Skip to content

Commit a6b84a2

Browse files
gkzmeta-codesync[bot]
authored andcommitted
[flow][enums] Parse and error on enum string literal member names
Summary: Flow enums currently only support identifier member names (e.g. `A = "a"`). This change parses string literal member names (e.g. `'MAIN' = "MAIN"`) so that users get a proper error message instead of a confusing parse failure, and so we can parse TS enums that support this. The validation layer errors with a "non-identifier member name" message. Changelog: [internal] Reviewed By: SamChou19815 Differential Revision: D98588604 fbshipit-source-id: 37388b54e9e5bc91f7eabdf3c00e9019566eddb1
1 parent 9c81517 commit a6b84a2

Some content is hidden

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

41 files changed

+811
-170
lines changed

rust_port/crates/flow_parser/src/ast.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2348,6 +2348,22 @@ pub mod statement {
23482348
pub mod enum_declaration {
23492349
use super::*;
23502350

2351+
#[derive(
2352+
Debug,
2353+
Clone,
2354+
PartialEq,
2355+
Eq,
2356+
Hash,
2357+
PartialOrd,
2358+
Ord,
2359+
serde::Serialize,
2360+
serde::Deserialize
2361+
)]
2362+
pub enum MemberName<M: Dupe> {
2363+
Identifier(Identifier<M, M>),
2364+
StringLiteral(M, super::super::StringLiteral<M>),
2365+
}
2366+
23512367
#[derive(
23522368
Debug,
23532369
Clone,
@@ -2361,7 +2377,7 @@ pub mod statement {
23612377
)]
23622378
pub struct DefaultedMember<M: Dupe> {
23632379
pub loc: M,
2364-
pub id: Identifier<M, M>,
2380+
pub id: MemberName<M>,
23652381
}
23662382

23672383
#[derive(
@@ -2377,7 +2393,7 @@ pub mod statement {
23772393
)]
23782394
pub struct InitializedMember<I, M: Dupe> {
23792395
pub loc: M,
2380-
pub id: Identifier<M, M>,
2396+
pub id: MemberName<M>,
23812397
pub init: (M, I),
23822398
}
23832399

rust_port/crates/flow_parser/src/ast_utils.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,3 +1400,12 @@ pub fn export_specifiers_has_value_export<M: Dupe, T: Dupe>(
14001400
== statement::ExportKind::ExportValue
14011401
})
14021402
}
1403+
1404+
pub fn string_of_enum_member_name<M: Dupe>(
1405+
id: &statement::enum_declaration::MemberName<M>,
1406+
) -> &str {
1407+
match id {
1408+
statement::enum_declaration::MemberName::Identifier(ident) => &ident.name,
1409+
statement::enum_declaration::MemberName::StringLiteral(_, lit) => &lit.value,
1410+
}
1411+
}

rust_port/crates/flow_parser/src/ast_visitor.rs

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,6 +1564,23 @@ pub trait AstVisitor<'ast, Loc: Dupe, Type: Dupe = Loc, C = &'ast Loc, E = !> {
15641564
map_enum_bigint_member_default(self, member)
15651565
}
15661566

1567+
fn enum_member_name(
1568+
&mut self,
1569+
id: &'ast ast::statement::enum_declaration::MemberName<Loc>,
1570+
) -> Result<(), E> {
1571+
enum_member_name_default(self, id)
1572+
}
1573+
1574+
fn map_enum_member_name(
1575+
&mut self,
1576+
id: &'ast ast::statement::enum_declaration::MemberName<Loc>,
1577+
) -> ast::statement::enum_declaration::MemberName<Loc>
1578+
where
1579+
Loc: Dupe,
1580+
{
1581+
map_enum_member_name_default(self, id)
1582+
}
1583+
15671584
fn enum_member_identifier(&mut self, id: &'ast ast::Identifier<Loc, Loc>) -> Result<(), E> {
15681585
enum_member_identifier_default(self, id)
15691586
}
@@ -9465,7 +9482,7 @@ pub fn enum_defaulted_member_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
94659482
member: &'ast ast::statement::enum_declaration::DefaultedMember<Loc>,
94669483
) -> Result<(), E> {
94679484
let ast::statement::enum_declaration::DefaultedMember { loc: _, id } = member;
9468-
visitor.enum_member_identifier(id)?;
9485+
visitor.enum_member_name(id)?;
94699486
Ok(())
94709487
}
94719488

@@ -9474,7 +9491,7 @@ pub fn map_enum_defaulted_member_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
94749491
member: &'ast ast::statement::enum_declaration::DefaultedMember<Loc>,
94759492
) -> ast::statement::enum_declaration::DefaultedMember<Loc> {
94769493
let ast::statement::enum_declaration::DefaultedMember { loc, id } = member;
9477-
let id_ = visitor.map_enum_member_identifier(id);
9494+
let id_ = visitor.map_enum_member_name(id);
94789495
ast::statement::enum_declaration::DefaultedMember {
94799496
loc: loc.dupe(),
94809497
id: id_,
@@ -9493,7 +9510,7 @@ pub fn enum_boolean_member_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
94939510
id,
94949511
init: (_, init_val),
94959512
} = member;
9496-
visitor.enum_member_identifier(id)?;
9513+
visitor.enum_member_name(id)?;
94979514
visitor.boolean_literal(init_val)?;
94989515
Ok(())
94999516
}
@@ -9506,7 +9523,7 @@ pub fn map_enum_boolean_member_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
95069523
>,
95079524
) -> ast::statement::enum_declaration::InitializedMember<ast::BooleanLiteral<Loc>, Loc> {
95089525
let ast::statement::enum_declaration::InitializedMember { loc, id, init } = member;
9509-
let id_ = visitor.map_enum_member_identifier(id);
9526+
let id_ = visitor.map_enum_member_name(id);
95109527
let (init_loc, init_lit) = init;
95119528
let init_lit_ = visitor.map_boolean_literal(init_lit);
95129529
ast::statement::enum_declaration::InitializedMember {
@@ -9525,7 +9542,7 @@ pub fn enum_number_member_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
95259542
id,
95269543
init: (_, init_val),
95279544
} = member;
9528-
visitor.enum_member_identifier(id)?;
9545+
visitor.enum_member_name(id)?;
95299546
visitor.number_literal(init_val)?;
95309547
Ok(())
95319548
}
@@ -9535,7 +9552,7 @@ pub fn map_enum_number_member_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
95359552
member: &'ast ast::statement::enum_declaration::InitializedMember<ast::NumberLiteral<Loc>, Loc>,
95369553
) -> ast::statement::enum_declaration::InitializedMember<ast::NumberLiteral<Loc>, Loc> {
95379554
let ast::statement::enum_declaration::InitializedMember { loc, id, init } = member;
9538-
let id_ = visitor.map_enum_member_identifier(id);
9555+
let id_ = visitor.map_enum_member_name(id);
95399556
let (init_loc, init_lit) = init;
95409557
let init_lit_ = visitor.map_number_literal(init_lit);
95419558
ast::statement::enum_declaration::InitializedMember {
@@ -9554,7 +9571,7 @@ pub fn enum_string_member_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
95549571
id,
95559572
init: (_, init_val),
95569573
} = member;
9557-
visitor.enum_member_identifier(id)?;
9574+
visitor.enum_member_name(id)?;
95589575
visitor.string_literal(init_val)?;
95599576
Ok(())
95609577
}
@@ -9564,7 +9581,7 @@ pub fn map_enum_string_member_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
95649581
member: &'ast ast::statement::enum_declaration::InitializedMember<ast::StringLiteral<Loc>, Loc>,
95659582
) -> ast::statement::enum_declaration::InitializedMember<ast::StringLiteral<Loc>, Loc> {
95669583
let ast::statement::enum_declaration::InitializedMember { loc, id, init } = member;
9567-
let id_ = visitor.map_enum_member_identifier(id);
9584+
let id_ = visitor.map_enum_member_name(id);
95689585
let (init_loc, init_lit) = init;
95699586
let init_lit_ = visitor.map_string_literal(init_lit);
95709587
ast::statement::enum_declaration::InitializedMember {
@@ -9583,7 +9600,7 @@ pub fn enum_bigint_member_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
95839600
id,
95849601
init: (_, init_val),
95859602
} = member;
9586-
visitor.enum_member_identifier(id)?;
9603+
visitor.enum_member_name(id)?;
95879604
visitor.bigint_literal(init_val)?;
95889605
Ok(())
95899606
}
@@ -9593,7 +9610,7 @@ pub fn map_enum_bigint_member_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
95939610
member: &'ast ast::statement::enum_declaration::InitializedMember<ast::BigIntLiteral<Loc>, Loc>,
95949611
) -> ast::statement::enum_declaration::InitializedMember<ast::BigIntLiteral<Loc>, Loc> {
95959612
let ast::statement::enum_declaration::InitializedMember { loc, id, init } = member;
9596-
let id_ = visitor.map_enum_member_identifier(id);
9613+
let id_ = visitor.map_enum_member_name(id);
95979614
let (init_loc, init_lit) = init;
95989615
let init_lit_ = visitor.map_bigint_literal(init_lit);
95999616
ast::statement::enum_declaration::InitializedMember {
@@ -9603,6 +9620,40 @@ pub fn map_enum_bigint_member_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
96039620
}
96049621
}
96059622

9623+
pub fn enum_member_name_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
9624+
visitor: &mut (impl AstVisitor<'ast, Loc, Type, C, E> + ?Sized),
9625+
id: &'ast ast::statement::enum_declaration::MemberName<Loc>,
9626+
) -> Result<(), E> {
9627+
match id {
9628+
ast::statement::enum_declaration::MemberName::Identifier(ident) => {
9629+
visitor.enum_member_identifier(ident)?;
9630+
}
9631+
ast::statement::enum_declaration::MemberName::StringLiteral(_, lit) => {
9632+
visitor.string_literal(lit)?;
9633+
}
9634+
}
9635+
Ok(())
9636+
}
9637+
9638+
pub fn map_enum_member_name_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
9639+
visitor: &mut (impl AstVisitor<'ast, Loc, Type, C, E> + ?Sized),
9640+
id: &'ast ast::statement::enum_declaration::MemberName<Loc>,
9641+
) -> ast::statement::enum_declaration::MemberName<Loc> {
9642+
match id {
9643+
ast::statement::enum_declaration::MemberName::Identifier(ident) => {
9644+
ast::statement::enum_declaration::MemberName::Identifier(
9645+
visitor.map_enum_member_identifier(ident),
9646+
)
9647+
}
9648+
ast::statement::enum_declaration::MemberName::StringLiteral(loc, lit) => {
9649+
ast::statement::enum_declaration::MemberName::StringLiteral(
9650+
loc.dupe(),
9651+
visitor.map_string_literal(lit),
9652+
)
9653+
}
9654+
}
9655+
}
9656+
96069657
pub fn enum_member_identifier_default<'ast, Loc: Dupe, Type: Dupe, C, E>(
96079658
visitor: &mut (impl AstVisitor<'ast, Loc, Type, C, E> + ?Sized),
96089659
id: &'ast ast::Identifier<Loc, Loc>,

rust_port/crates/flow_parser/src/enum_parser.rs

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use flow_data_structure_wrapper::smol_str::FlowSmolStr;
1313
use crate::ast::BigIntLiteral;
1414
use crate::ast::BooleanLiteral;
1515
use crate::ast::Comment;
16-
use crate::ast::Identifier;
1716
use crate::ast::IdentifierInner;
1817
use crate::ast::NumberLiteral;
1918
use crate::ast::StringLiteral;
@@ -188,23 +187,40 @@ fn member_init(env: &mut ParserEnv) -> Result<Init, Rollback> {
188187
}
189188
}
190189

191-
fn member_raw(env: &mut ParserEnv) -> Result<(Loc, (Identifier<Loc, Loc>, Init)), Rollback> {
190+
fn member_raw(
191+
env: &mut ParserEnv,
192+
) -> Result<(Loc, (statement::enum_declaration::MemberName<Loc>, Init)), Rollback> {
192193
with_loc(None, env, |env| {
193-
let id = parser_common::identifier_name(env)?;
194+
let id = match peek::token(env) {
195+
TokenKind::TString(str_loc, value, raw, octal) => {
196+
let str_loc = str_loc.dupe();
197+
let value = value.to_owned();
198+
let raw = raw.to_owned();
199+
if *octal {
200+
env.strict_error(ParseError::StrictOctalLiteral)?;
201+
}
202+
eat::token(env)?;
203+
statement::enum_declaration::MemberName::StringLiteral(
204+
str_loc,
205+
StringLiteral {
206+
value,
207+
raw,
208+
comments: None,
209+
},
210+
)
211+
}
212+
_ => statement::enum_declaration::MemberName::Identifier(
213+
parser_common::identifier_name(env)?,
214+
),
215+
};
194216
let init = match peek::token(env) {
195217
TokenKind::TAssign => {
196218
expect::token(env, TokenKind::TAssign)?;
197219
member_init(env)?
198220
}
199221
TokenKind::TColon => {
200-
let IdentifierInner {
201-
loc: _,
202-
name: member_name,
203-
comments: _,
204-
} = id.deref();
205-
env.error(ParseError::EnumInvalidInitializerSeparator {
206-
member_name: member_name.as_str().to_owned(),
207-
})?;
222+
let member_name = ast_utils::string_of_enum_member_name(&id).to_owned();
223+
env.error(ParseError::EnumInvalidInitializerSeparator { member_name })?;
208224
expect::token(env, TokenKind::TColon)?;
209225
member_init(env)?
210226
}
@@ -221,11 +237,7 @@ fn enum_member(
221237
explicit_type: Option<ExplicitType>,
222238
) -> Result<(), Rollback> {
223239
let (member_loc, (id, init)) = member_raw(env)?;
224-
let IdentifierInner {
225-
loc: _id_loc,
226-
name: member_name,
227-
comments: _,
228-
} = id.deref();
240+
let member_name = ast_utils::string_of_enum_member_name(&id);
229241

230242
/* if we parsed an empty name, something has gone wrong and we should abort analysis */
231243
if member_name.is_empty() {
@@ -275,7 +287,7 @@ fn enum_member(
275287
ParseError::EnumInvalidMemberInitializer {
276288
enum_name: enum_name.to_owned(),
277289
explicit_type,
278-
member_name: member_name.as_str().to_owned(),
290+
member_name: member_name.to_owned(),
279291
},
280292
)?;
281293
}

rust_port/crates/flow_parser/src/estree_translator.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3686,6 +3686,16 @@ fn enum_body(
36863686
comments,
36873687
} = body;
36883688

3689+
let enum_member_name = |id: &ast::statement::enum_declaration::MemberName<Loc>| -> Value {
3690+
match id {
3691+
ast::statement::enum_declaration::MemberName::Identifier(ident) => {
3692+
identifier(offset_table, config, ident)
3693+
}
3694+
ast::statement::enum_declaration::MemberName::StringLiteral(loc, sl) => {
3695+
string_literal(offset_table, config, loc, sl)
3696+
}
3697+
}
3698+
};
36893699
let enum_member = |member: &Member<Loc>| -> Value {
36903700
match member {
36913701
Member::BooleanMember(member) => node(
@@ -3695,7 +3705,7 @@ fn enum_body(
36953705
&member.loc,
36963706
None,
36973707
vec![
3698-
("id", identifier(offset_table, config, &member.id)),
3708+
("id", enum_member_name(&member.id)),
36993709
(
37003710
"init",
37013711
boolean_literal(offset_table, config, &member.init.0, &member.init.1),
@@ -3709,7 +3719,7 @@ fn enum_body(
37093719
&member.loc,
37103720
None,
37113721
vec![
3712-
("id", identifier(offset_table, config, &member.id)),
3722+
("id", enum_member_name(&member.id)),
37133723
(
37143724
"init",
37153725
number_literal(offset_table, config, &member.init.0, &member.init.1),
@@ -3723,7 +3733,7 @@ fn enum_body(
37233733
&member.loc,
37243734
None,
37253735
vec![
3726-
("id", identifier(offset_table, config, &member.id)),
3736+
("id", enum_member_name(&member.id)),
37273737
(
37283738
"init",
37293739
string_literal(offset_table, config, &member.init.0, &member.init.1),
@@ -3737,7 +3747,7 @@ fn enum_body(
37373747
&member.loc,
37383748
None,
37393749
vec![
3740-
("id", identifier(offset_table, config, &member.id)),
3750+
("id", enum_member_name(&member.id)),
37413751
(
37423752
"init",
37433753
bigint_literal(offset_table, config, &member.init.0, &member.init.1),
@@ -3750,7 +3760,7 @@ fn enum_body(
37503760
"EnumDefaultedMember",
37513761
&member.loc,
37523762
None,
3753-
vec![("id", identifier(offset_table, config, &member.id))],
3763+
vec![("id", enum_member_name(&member.id))],
37543764
),
37553765
}
37563766
};
@@ -3785,15 +3795,6 @@ fn enum_declaration(
37853795
loc: &Loc,
37863796
enum_decl: &ast::statement::EnumDeclaration<Loc, Loc>,
37873797
) -> Value {
3788-
// and enum_declaration (loc, { Statement.EnumDeclaration.id; body; const_; comments }) =
3789-
// let props = [("id", identifier id); ("body", enum_body body)] in
3790-
// let props =
3791-
// if const_ then
3792-
// ("const", bool true) :: props
3793-
// else
3794-
// props
3795-
// in
3796-
// node ?comments "EnumDeclaration" loc props
37973798
let mut props = vec![
37983799
("id", identifier(offset_table, config, &enum_decl.id)),
37993800
("body", enum_body(offset_table, config, &enum_decl.body)),

0 commit comments

Comments
 (0)