Skip to content

Commit 89babe5

Browse files
metaduvfacebook-github-bot
authored andcommitted
Include Const values in decl output (gated with flag)
Summary: Added an option to also include const values (including enums) in the output of ext_decl. * For literals, it outputs a normalize form (null, false, true, numbers and a single quoted string). * For all complex initializers it simply slices the source text and trims it Reviewed By: nt591 Differential Revision: D52605538 fbshipit-source-id: 71771515efa535b0fec29d853a875fb8d313c845
1 parent 5ea5278 commit 89babe5

File tree

61 files changed

+437
-155
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+437
-155
lines changed

hphp/hack/hhi/ext_decl.hhi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ namespace HH {
8585
type ExtDeclFileConst = shape(
8686
'name' => string,
8787
'type' => TypeExpr,
88+
?'value' => string,
8889
);
8990

9091
type ExtDeclModule = shape(
@@ -125,6 +126,7 @@ namespace HH {
125126
'name' => string,
126127
'type' => TypeExpr,
127128
?'is_abstract' => bool,
129+
?'value' => string,
128130
);
129131

130132
// https://github.com/facebook/hhvm/issues/5594

hphp/hack/src/decl/decl_pos_utils.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ struct
383383
scc_name = positioned_id scc.scc_name;
384384
scc_type = ty scc.scc_type;
385385
scc_refs = scc.scc_refs;
386+
scc_value = scc.scc_value;
386387
}
387388

388389
and shallow_typeconst stc =

hphp/hack/src/decl/direct_decl_smart_constructors.rs

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,47 @@ impl<'a, 'o, 't, S: SourceTextAllocator<'t, 'a>> DirectDeclSmartConstructors<'a,
13761376
Some(self.alloc(aast::Expr((), pos, expr_)))
13771377
}
13781378

1379+
fn node_to_str(&self, node: Node<'a>, semicolon: Node<'a>) -> &'a str {
1380+
let expr = self.node_to_expr(node);
1381+
match expr {
1382+
// Only some nodes have a simple translate to an expression
1383+
// Since some nodes *are* expressions, we prefer to write the
1384+
// to_string logic once for expressions
1385+
Some(expr) => self.expr_to_str(expr),
1386+
1387+
// This is usually complex shapes / vec / dict etc. and the
1388+
// actual value is NOT in the nodes so we have to yank the text
1389+
None => self
1390+
.str_from_utf8(self.source_text_at_pos(Pos::from_lnum_bol_offset(
1391+
self.arena,
1392+
self.filename,
1393+
self.get_pos(node).to_start_and_end_lnum_bol_offset().1,
1394+
self.get_pos(semicolon).to_start_and_end_lnum_bol_offset().0,
1395+
)))
1396+
.trim(),
1397+
}
1398+
}
1399+
1400+
fn expr_to_str(&self, expr: &aast::Expr<'a, (), ()>) -> &'a str {
1401+
match expr.2 {
1402+
// Simple literals (99% of the cases)
1403+
aast::Expr_::Int(s) => s,
1404+
aast::Expr_::Float(s) => s,
1405+
aast::Expr_::String(s) => {
1406+
// Always use single quotes for strings
1407+
bumpalo::format!(in self.arena, "'{}'", s).into_bump_str()
1408+
}
1409+
aast::Expr_::True => "true",
1410+
aast::Expr_::False => "false",
1411+
aast::Expr_::Null => "null",
1412+
1413+
// Default to actual text
1414+
// ... VariableExpression, BinaryExpression, SubscriptExpression,
1415+
// FunctionCallExpression, ConditionalExpression ...
1416+
_ => self.str_from_utf8(self.source_text_at_pos(expr.1)),
1417+
}
1418+
}
1419+
13791420
fn node_to_non_ret_ty(&self, node: Node<'a>) -> Option<&'a Ty<'a>> {
13801421
self.node_to_ty_(node, false)
13811422
}
@@ -3947,12 +3988,18 @@ impl<'a, 'o, 't, S: SourceTextAllocator<'t, 'a>> FlattenSmartConstructors
39473988
let ty = ty
39483989
.or_else(|| self.infer_const(name, initializer))
39493990
.unwrap_or(TANY);
3991+
39503992
Some(Node::Const(self.alloc(
39513993
shallow_decl_defs::ShallowClassConst {
39523994
abstract_,
39533995
name: id.into(),
39543996
type_: ty,
39553997
refs,
3998+
value: if self.opts.include_assignment_values {
3999+
Some(self.node_to_str(initializer, semicolon))
4000+
} else {
4001+
None
4002+
},
39564003
},
39574004
)))
39584005
}
@@ -3978,8 +4025,18 @@ impl<'a, 'o, 't, S: SourceTextAllocator<'t, 'a>> FlattenSmartConstructors
39784025
.node_to_ty(hint)
39794026
.or_else(|| self.infer_const(name, initializer))
39804027
.unwrap_or_else(|| self.tany_with_pos(id_pos));
4028+
4029+
let const_decl = ConstDecl {
4030+
pos,
4031+
type_: ty,
4032+
value: if self.opts.include_assignment_values {
4033+
Some(self.node_to_str(initializer, semicolon))
4034+
} else {
4035+
None
4036+
},
4037+
};
39814038
let this = Rc::make_mut(&mut self.state);
3982-
this.add_const(id, this.alloc(ConstDecl { pos, type_: ty }));
4039+
this.add_const(id, this.alloc(const_decl));
39834040
}
39844041
}
39854042
_ => {}
@@ -4972,7 +5029,7 @@ impl<'a, 'o, 't, S: SourceTextAllocator<'t, 'a>> FlattenSmartConstructors
49725029
name: Self::Output,
49735030
_equal: Self::Output,
49745031
value: Self::Output,
4975-
_semicolon: Self::Output,
5032+
semicolon: Self::Output,
49765033
) -> Self::Output {
49775034
let refs = self.stop_accumulating_const_refs();
49785035
let id = match self.expect_name(name) {
@@ -4988,6 +5045,11 @@ impl<'a, 'o, 't, S: SourceTextAllocator<'t, 'a>> FlattenSmartConstructors
49885045
.infer_const(name, value)
49895046
.unwrap_or_else(|| self.tany_with_pos(id.0)),
49905047
refs,
5048+
value: if self.opts.include_assignment_values {
5049+
Some(self.node_to_str(value, semicolon))
5050+
} else {
5051+
None
5052+
},
49915053
}),
49925054
)
49935055
}
@@ -5160,8 +5222,8 @@ impl<'a, 'o, 't, S: SourceTextAllocator<'t, 'a>> FlattenSmartConstructors
51605222
modifiers: Self::Output,
51615223
type_: Self::Output,
51625224
name: Self::Output,
5163-
_initializer: Self::Output,
5164-
_semicolon: Self::Output,
5225+
initializer: Self::Output,
5226+
semicolon: Self::Output,
51655227
) -> Self::Output {
51665228
let refs = self.stop_accumulating_const_refs();
51675229
let name = match self.expect_name(name) {
@@ -5203,6 +5265,11 @@ impl<'a, 'o, 't, S: SourceTextAllocator<'t, 'a>> FlattenSmartConstructors
52035265
name: name.into(),
52045266
type_,
52055267
refs,
5268+
value: if self.opts.include_assignment_values {
5269+
Some(self.node_to_str(initializer, semicolon))
5270+
} else {
5271+
None
5272+
},
52065273
}))
52075274
}
52085275

hphp/hack/src/decl/shallow_decl_defs.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,9 @@ type shallow_class_const = {
182182
(** This is a list of all scope-resolution operators "A::B" that are mentioned in the const initializer,
183183
for members of regular-enums and enum-class-enums to detect circularity of initializers.
184184
We don't yet have a similar mechanism for top-level const initializers. *)
185+
scc_value: string option;
186+
(** If DeclParserConfig option include_assignment_values is true,
187+
The string value for the constant *)
185188
}
186189
[@@deriving eq, show]
187190

hphp/hack/src/decl/shallow_decl_defs.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ type shallow_class_const = {
8383
scc_name: Typing_defs.pos_id;
8484
scc_type: decl_ty;
8585
scc_refs: Typing_defs.class_const_ref list;
86+
scc_value: string option;
8687
}
8788
[@@deriving eq, show]
8889

hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ mod ffi {
109109
enable_xhp_class_modifier: bool,
110110
php5_compat_mode: bool,
111111
hhvm_compat_mode: bool,
112+
include_assignment_values: bool,
112113
}
113114

114115
pub struct DeclsAndBlob {
@@ -247,13 +248,15 @@ mod ffi {
247248
pub struct ExtDeclFileConst {
248249
name: String,
249250
type_: String,
251+
value: String,
250252
}
251253

252254
#[derive(Debug, PartialEq)]
253255
pub struct ExtDeclClassConst {
254256
name: String,
255257
type_: String,
256258
is_abstract: bool,
259+
value: String,
257260
}
258261
pub struct ExtDeclClassConstVec {
259262
pub vec: Vec<ExtDeclClassConst>,
@@ -713,6 +716,7 @@ pub fn parse_decls(
713716
enable_xhp_class_modifier: config.enable_xhp_class_modifier,
714717
php5_compat_mode: config.php5_compat_mode,
715718
hhvm_compat_mode: config.hhvm_compat_mode,
719+
include_assignment_values: config.include_assignment_values,
716720
keep_user_attributes: true,
717721
..Default::default()
718722
};

hphp/hack/src/hackc/ffi_bridge/ext_decl.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ pub fn get_file_consts(parsed_file: &ParsedFile<'_>, name: &str) -> Vec<ExtDeclF
7676
.map(|(cname, decl)| ExtDeclFileConst {
7777
name: fmt_type(cname),
7878
type_: extract_type_name(decl.type_),
79+
value: str_or_empty(decl.value),
7980
})
8081
.collect()
8182
}
@@ -399,6 +400,7 @@ fn get_consts(consts: &[&ShallowClassConst<'_>], name: &str) -> Vec<ExtDeclClass
399400
name: fmt_type(c.name.1),
400401
type_: extract_type_name(c.type_),
401402
is_abstract: c.abstract_ != ClassConstKind::CCConcrete,
403+
value: str_or_empty(c.value),
402404
})
403405
.collect()
404406
}

hphp/hack/src/hackrs/ty/decl/from_oxidized.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ impl<R: Reason> From<&obr::shallow_decl_defs::ShallowClassConst<'_>>
356356
name: scc.name.into(),
357357
ty: scc.type_.into(),
358358
refs: slice(scc.refs),
359+
value: scc.value.map(Into::into),
359360
}
360361
}
361362
}
@@ -513,6 +514,7 @@ impl<R: Reason> From<&obr::shallow_decl_defs::ConstDecl<'_>> for shallow::ConstD
513514
Self {
514515
pos: x.pos.into(),
515516
ty: x.type_.into(),
517+
value: x.value.map(Into::into),
516518
}
517519
}
518520
}

hphp/hack/src/hackrs/ty/decl/shallow.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ pub struct ShallowClassConst<R: Reason> {
6767
/// to detect circularity of initializers. We don't yet have a similar mechanism
6868
/// for top-level const initializers.
6969
pub refs: Box<[ClassConstRef]>,
70+
71+
/// If DeclParserConfig option include_assignment_values is true,
72+
/// The string value for the constant
73+
pub value: Option<String>,
7074
}
7175

7276
walkable!(ShallowClassConst<R> => [ty]);

hphp/hack/src/hackrs/ty/decl/to_oxidized.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,12 +654,14 @@ impl<'a, R: Reason> ToOxidized<'a> for shallow::ShallowClassConst<R> {
654654
name,
655655
ty,
656656
refs,
657+
value,
657658
} = self;
658659
arena.alloc(obr::shallow_decl_defs::ShallowClassConst {
659660
abstract_: *kind,
660661
name: name.to_oxidized(arena),
661662
type_: ty.to_oxidized(arena),
662663
refs: refs.to_oxidized(arena),
664+
value: value.as_deref().to_oxidized(arena),
663665
})
664666
}
665667
}
@@ -839,10 +841,11 @@ impl<'a, R: Reason> ToOxidized<'a> for shallow::ConstDecl<R> {
839841
type Output = &'a obr::shallow_decl_defs::ConstDecl<'a>;
840842

841843
fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
842-
let Self { pos, ty } = self;
844+
let Self { pos, ty, value } = self;
843845
arena.alloc(obr::shallow_decl_defs::ConstDecl {
844846
pos: pos.to_oxidized(arena),
845847
type_: ty.to_oxidized(arena),
848+
value: value.as_deref().to_oxidized(arena),
846849
})
847850
}
848851
}

0 commit comments

Comments
 (0)