Skip to content

Commit a69f992

Browse files
gkzfacebook-github-bot
authored andcommitted
[flow][enums] Allow for negative Flow Enums number values
Summary: Changelog: [feature] Negative Flow Enums number values are now allowed. This has been requested by users multiple times. Reviewed By: SamChou19815 Differential Revision: D55774625 fbshipit-source-id: 5fbbfd226647658eec9eb7348b8ca63ec32f4eb1
1 parent 786fcb9 commit a69f992

11 files changed

+241
-14
lines changed

src/parser/enum_parser.ml

+27-14
Original file line numberDiff line numberDiff line change
@@ -64,24 +64,37 @@ end = struct
6464
true
6565
| _ -> false
6666

67+
let number_init env loc ~neg ~leading ~kind ~raw =
68+
let value = Parse.number env kind raw in
69+
let (value, raw) =
70+
if neg then
71+
(-.value, "-" ^ raw)
72+
else
73+
(value, raw)
74+
in
75+
let trailing = Eat.trailing_comments env in
76+
if end_of_member_init env then
77+
NumberInit
78+
( loc,
79+
{
80+
NumberLiteral.value;
81+
raw;
82+
comments = Flow_ast_utils.mk_comments_opt ~leading ~trailing ();
83+
}
84+
)
85+
else
86+
InvalidInit loc
87+
6788
let member_init env =
6889
let loc = Peek.loc env in
6990
let leading = Peek.comments env in
7091
match Peek.token env with
71-
| T_NUMBER { kind; raw } ->
72-
let value = Parse.number env kind raw in
73-
let trailing = Eat.trailing_comments env in
74-
if end_of_member_init env then
75-
NumberInit
76-
( loc,
77-
{
78-
NumberLiteral.value;
79-
raw;
80-
comments = Flow_ast_utils.mk_comments_opt ~leading ~trailing ();
81-
}
82-
)
83-
else
84-
InvalidInit loc
92+
| T_MINUS ->
93+
Eat.token env;
94+
(match Peek.token env with
95+
| T_NUMBER { kind; raw } -> number_init env loc ~neg:true ~leading ~kind ~raw
96+
| _ -> InvalidInit loc)
97+
| T_NUMBER { kind; raw } -> number_init env loc ~neg:false ~leading ~kind ~raw
8598
| T_STRING (loc, value, raw, octal) ->
8699
if octal then strict_error env Parse_error.StrictOctalLiteral;
87100
Eat.token env;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
enum E {
2+
A = -true,
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"enums": true
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"errors":[
3+
{
4+
"loc":{"source":null,"start":{"line":2,"column":6},"end":{"line":2,"column":7}},
5+
"message":"The enum member initializer for `A` needs to be a literal (either a boolean, number, or string) in enum `E`."
6+
},
7+
{
8+
"loc":{"source":null,"start":{"line":2,"column":7},"end":{"line":2,"column":11}},
9+
"message":"Unexpected token `true`, expected the token `,`"
10+
},
11+
{
12+
"loc":{"source":null,"start":{"line":2,"column":11},"end":{"line":2,"column":12}},
13+
"message":"Unexpected token `,`, expected an identifier"
14+
}
15+
],
16+
"type":"Program",
17+
"loc":{"source":null,"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
18+
"range":[0,23],
19+
"body":[
20+
{
21+
"type":"EnumDeclaration",
22+
"loc":{"source":null,"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
23+
"range":[0,23],
24+
"id":{
25+
"type":"Identifier",
26+
"loc":{"source":null,"start":{"line":1,"column":5},"end":{"line":1,"column":6}},
27+
"range":[5,6],
28+
"name":"E",
29+
"typeAnnotation":null,
30+
"optional":false
31+
},
32+
"body":{
33+
"type":"EnumStringBody",
34+
"loc":{"source":null,"start":{"line":1,"column":7},"end":{"line":3,"column":1}},
35+
"range":[7,23],
36+
"members":[],
37+
"explicitType":false,
38+
"hasUnknownMembers":false
39+
}
40+
}
41+
],
42+
"comments":[]
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
enum E of number {
2+
A = -1,
3+
B = -2,
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"enums": true
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"type":"Program",
3+
"loc":{"source":null,"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
4+
"range":[0,40],
5+
"body":[
6+
{
7+
"type":"EnumDeclaration",
8+
"loc":{"source":null,"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
9+
"range":[0,40],
10+
"id":{
11+
"type":"Identifier",
12+
"loc":{"source":null,"start":{"line":1,"column":5},"end":{"line":1,"column":6}},
13+
"range":[5,6],
14+
"name":"E",
15+
"typeAnnotation":null,
16+
"optional":false
17+
},
18+
"body":{
19+
"type":"EnumNumberBody",
20+
"loc":{"source":null,"start":{"line":1,"column":7},"end":{"line":4,"column":1}},
21+
"range":[7,40],
22+
"members":[
23+
{
24+
"type":"EnumNumberMember",
25+
"loc":{"source":null,"start":{"line":2,"column":2},"end":{"line":2,"column":8}},
26+
"range":[21,27],
27+
"id":{
28+
"type":"Identifier",
29+
"loc":{"source":null,"start":{"line":2,"column":2},"end":{"line":2,"column":3}},
30+
"range":[21,22],
31+
"name":"A",
32+
"typeAnnotation":null,
33+
"optional":false
34+
},
35+
"init":{
36+
"type":"Literal",
37+
"loc":{"source":null,"start":{"line":2,"column":6},"end":{"line":2,"column":7}},
38+
"range":[25,26],
39+
"value":-1,
40+
"raw":"-1"
41+
}
42+
},
43+
{
44+
"type":"EnumNumberMember",
45+
"loc":{"source":null,"start":{"line":3,"column":2},"end":{"line":3,"column":8}},
46+
"range":[31,37],
47+
"id":{
48+
"type":"Identifier",
49+
"loc":{"source":null,"start":{"line":3,"column":2},"end":{"line":3,"column":3}},
50+
"range":[31,32],
51+
"name":"B",
52+
"typeAnnotation":null,
53+
"optional":false
54+
},
55+
"init":{
56+
"type":"Literal",
57+
"loc":{"source":null,"start":{"line":3,"column":6},"end":{"line":3,"column":7}},
58+
"range":[35,36],
59+
"value":-2,
60+
"raw":"-2"
61+
}
62+
}
63+
],
64+
"explicitType":true,
65+
"hasUnknownMembers":false
66+
}
67+
}
68+
],
69+
"comments":[]
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
enum E {
2+
A = -1,
3+
B = -2,
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"enums": true
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"type":"Program",
3+
"loc":{"source":null,"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
4+
"range":[0,30],
5+
"body":[
6+
{
7+
"type":"EnumDeclaration",
8+
"loc":{"source":null,"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
9+
"range":[0,30],
10+
"id":{
11+
"type":"Identifier",
12+
"loc":{"source":null,"start":{"line":1,"column":5},"end":{"line":1,"column":6}},
13+
"range":[5,6],
14+
"name":"E",
15+
"typeAnnotation":null,
16+
"optional":false
17+
},
18+
"body":{
19+
"type":"EnumNumberBody",
20+
"loc":{"source":null,"start":{"line":1,"column":7},"end":{"line":4,"column":1}},
21+
"range":[7,30],
22+
"members":[
23+
{
24+
"type":"EnumNumberMember",
25+
"loc":{"source":null,"start":{"line":2,"column":2},"end":{"line":2,"column":8}},
26+
"range":[11,17],
27+
"id":{
28+
"type":"Identifier",
29+
"loc":{"source":null,"start":{"line":2,"column":2},"end":{"line":2,"column":3}},
30+
"range":[11,12],
31+
"name":"A",
32+
"typeAnnotation":null,
33+
"optional":false
34+
},
35+
"init":{
36+
"type":"Literal",
37+
"loc":{"source":null,"start":{"line":2,"column":6},"end":{"line":2,"column":7}},
38+
"range":[15,16],
39+
"value":-1,
40+
"raw":"-1"
41+
}
42+
},
43+
{
44+
"type":"EnumNumberMember",
45+
"loc":{"source":null,"start":{"line":3,"column":2},"end":{"line":3,"column":8}},
46+
"range":[21,27],
47+
"id":{
48+
"type":"Identifier",
49+
"loc":{"source":null,"start":{"line":3,"column":2},"end":{"line":3,"column":3}},
50+
"range":[21,22],
51+
"name":"B",
52+
"typeAnnotation":null,
53+
"optional":false
54+
},
55+
"init":{
56+
"type":"Literal",
57+
"loc":{"source":null,"start":{"line":3,"column":6},"end":{"line":3,"column":7}},
58+
"range":[25,26],
59+
"value":-2,
60+
"raw":"-2"
61+
}
62+
}
63+
],
64+
"explicitType":false,
65+
"hasUnknownMembers":false
66+
}
67+
}
68+
],
69+
"comments":[]
70+
}

tests/enums/negative.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Negative numbers
2+
enum N {
3+
A = -1,
4+
B = -2,
5+
}
6+
7+
{
8+
const x = N.A; // OK
9+
x as N; // OK
10+
N.cast(-1) as N | void; // OK
11+
}

0 commit comments

Comments
 (0)