@@ -97,6 +97,26 @@ module ErrorMessages = struct
97
97
...b}` wouldn't make sense, as `b` would override every field of `a` \
98
98
anyway."
99
99
100
+ let dict_expr_spread = " Dict literals do not support spread (`...`) yet."
101
+
102
+ let record_field_missing_colon =
103
+ " Records use `:` when assigning fields. Example: `{field: value}`"
104
+
105
+ let record_pattern_field_missing_colon =
106
+ " Record patterns use `:` when matching fields. Example: `{field: value}`"
107
+
108
+ let record_type_field_missing_colon =
109
+ " Record fields in type declarations use `:`. Example: `{field: string}`"
110
+
111
+ let dict_field_missing_colon =
112
+ " Dict entries use `:` to separate keys from values. Example: `{\" k\" : v}`"
113
+
114
+ let labelled_argument_missing_equal =
115
+ " Use `=` to pass a labelled argument. Example: `~label=value`"
116
+
117
+ let optional_labelled_argument_missing_equal =
118
+ " Optional labelled arguments use `=?`. Example: `~label=?value`"
119
+
100
120
let variant_ident =
101
121
" A polymorphic variant (e.g. #id) must start with an alphabetical letter \
102
122
or be a number (e.g. #742)"
@@ -1412,6 +1432,13 @@ and parse_record_pattern_row_field ~attrs p =
1412
1432
let optional = parse_optional_label p in
1413
1433
let pat = parse_pattern p in
1414
1434
(pat, optional)
1435
+ | Equal ->
1436
+ Parser. err ~start_pos: p.start_pos ~end_pos: p.end_pos p
1437
+ (Diagnostics. message ErrorMessages. record_pattern_field_missing_colon);
1438
+ Parser. next p;
1439
+ let optional = parse_optional_label p in
1440
+ let pat = parse_pattern p in
1441
+ (pat, optional)
1415
1442
| _ ->
1416
1443
( Ast_helper.Pat. var ~loc: label.loc ~attrs
1417
1444
(Location. mkloc (Longident. last label.txt) label.loc),
@@ -3060,6 +3087,19 @@ and parse_braced_or_record_expr p =
3060
3087
in
3061
3088
Parser. expect Rbrace p;
3062
3089
expr
3090
+ | Equal ->
3091
+ Parser. err ~start_pos: p.start_pos ~end_pos: p.end_pos p
3092
+ (Diagnostics. message ErrorMessages. record_field_missing_colon);
3093
+ Parser. next p;
3094
+ let field_expr = parse_expr p in
3095
+ Parser. optional p Comma |> ignore;
3096
+ let expr =
3097
+ parse_record_expr_with_string_keys ~start_pos
3098
+ {Parsetree. lid = field; x = field_expr; opt = false }
3099
+ p
3100
+ in
3101
+ Parser. expect Rbrace p;
3102
+ expr
3063
3103
| _ -> (
3064
3104
let tag = if p.mode = ParseForTypeChecker then Some " js" else None in
3065
3105
let constant =
@@ -3153,6 +3193,28 @@ and parse_braced_or_record_expr p =
3153
3193
in
3154
3194
Parser. expect Rbrace p;
3155
3195
expr)
3196
+ | Equal -> (
3197
+ Parser. err ~start_pos: p.start_pos ~end_pos: p.end_pos p
3198
+ (Diagnostics. message ErrorMessages. record_field_missing_colon);
3199
+ Parser. next p;
3200
+ let optional = parse_optional_label p in
3201
+ let field_expr = parse_expr p in
3202
+ match p.Parser. token with
3203
+ | Rbrace ->
3204
+ Parser. next p;
3205
+ let loc = mk_loc start_pos p.prev_end_pos in
3206
+ Ast_helper.Exp. record ~loc
3207
+ [{lid = path_ident; x = field_expr; opt = optional}]
3208
+ None
3209
+ | _ ->
3210
+ Parser. expect Comma p;
3211
+ let expr =
3212
+ parse_record_expr ~start_pos
3213
+ [{lid = path_ident; x = field_expr; opt = optional}]
3214
+ p
3215
+ in
3216
+ Parser. expect Rbrace p;
3217
+ expr)
3156
3218
(* error case *)
3157
3219
| Lident _ ->
3158
3220
if p.prev_end_pos.pos_lnum < p.start_pos.pos_lnum then (
@@ -3295,6 +3357,12 @@ and parse_record_expr_row_with_string_key p :
3295
3357
Parser. next p;
3296
3358
let field_expr = parse_expr p in
3297
3359
Some {lid = field; x = field_expr; opt = false }
3360
+ | Equal ->
3361
+ Parser. err ~start_pos: p.start_pos ~end_pos: p.end_pos p
3362
+ (Diagnostics. message ErrorMessages. record_field_missing_colon);
3363
+ Parser. next p;
3364
+ let field_expr = parse_expr p in
3365
+ Some {lid = field; x = field_expr; opt = false }
3298
3366
| _ ->
3299
3367
Some
3300
3368
{
@@ -3324,6 +3392,13 @@ and parse_record_expr_row p :
3324
3392
let optional = parse_optional_label p in
3325
3393
let field_expr = parse_expr p in
3326
3394
Some {lid = field; x = field_expr; opt = optional}
3395
+ | Equal ->
3396
+ Parser. err ~start_pos: p.start_pos ~end_pos: p.end_pos p
3397
+ (Diagnostics. message ErrorMessages. record_field_missing_colon);
3398
+ Parser. next p;
3399
+ let optional = parse_optional_label p in
3400
+ let field_expr = parse_expr p in
3401
+ Some {lid = field; x = field_expr; opt = optional}
3327
3402
| _ ->
3328
3403
let value = Ast_helper.Exp. ident ~loc: field.loc ~attrs field in
3329
3404
let value =
@@ -3368,6 +3443,12 @@ and parse_record_expr_row p :
3368
3443
3369
3444
and parse_dict_expr_row p =
3370
3445
match p.Parser. token with
3446
+ | DotDotDot ->
3447
+ Parser. err p (Diagnostics. message ErrorMessages. dict_expr_spread);
3448
+ Parser. next p;
3449
+ (* Parse the expr so it's consumed *)
3450
+ let _spread_expr = parse_constrained_or_coerced_expr p in
3451
+ None
3371
3452
| String s -> (
3372
3453
let loc = mk_loc p.start_pos p.end_pos in
3373
3454
Parser. next p;
@@ -3377,6 +3458,12 @@ and parse_dict_expr_row p =
3377
3458
Parser. next p;
3378
3459
let fieldExpr = parse_expr p in
3379
3460
Some (field, fieldExpr)
3461
+ | Equal ->
3462
+ Parser. err ~start_pos: p.start_pos ~end_pos: p.end_pos p
3463
+ (Diagnostics. message ErrorMessages. dict_field_missing_colon);
3464
+ Parser. next p;
3465
+ let fieldExpr = parse_expr p in
3466
+ Some (field, fieldExpr)
3380
3467
| _ -> Some (field, Ast_helper.Exp. ident ~loc: field.loc field))
3381
3468
| _ -> None
3382
3469
@@ -3881,12 +3968,42 @@ and parse_argument2 p : argument option =
3881
3968
in
3882
3969
Some {label; expr}
3883
3970
| Colon ->
3971
+ let colon_start = p.start_pos in
3884
3972
Parser. next p;
3885
- let typ = parse_typ_expr p in
3886
- let loc = mk_loc start_pos p.prev_end_pos in
3887
- let expr = Ast_helper.Exp. constraint_ ~loc ident_expr typ in
3888
- Some
3889
- {label = Asttypes. Labelled {txt = ident; loc = named_arg_loc}; expr}
3973
+ let colon_end = p.prev_end_pos in
3974
+ if Grammar. is_typ_expr_start p.Parser. token then
3975
+ let typ = parse_typ_expr p in
3976
+ let loc = mk_loc start_pos p.prev_end_pos in
3977
+ let expr = Ast_helper.Exp. constraint_ ~loc ident_expr typ in
3978
+ Some
3979
+ {label = Asttypes. Labelled {txt = ident; loc = named_arg_loc}; expr}
3980
+ else
3981
+ let label, expr =
3982
+ match p.Parser. token with
3983
+ | Question ->
3984
+ Parser. err ~start_pos: colon_start ~end_pos: colon_end p
3985
+ (Diagnostics. message
3986
+ ErrorMessages. optional_labelled_argument_missing_equal);
3987
+ Parser. next p;
3988
+ let expr = parse_constrained_or_coerced_expr p in
3989
+ (Asttypes. Optional {txt = ident; loc = named_arg_loc}, expr)
3990
+ | _ ->
3991
+ Parser. err ~start_pos: colon_start ~end_pos: colon_end p
3992
+ (Diagnostics. message
3993
+ ErrorMessages. labelled_argument_missing_equal);
3994
+ let expr =
3995
+ match p.Parser. token with
3996
+ | Underscore
3997
+ when not (is_es6_arrow_expression ~in_ternary: false p) ->
3998
+ let loc = mk_loc p.start_pos p.end_pos in
3999
+ Parser. next p;
4000
+ Ast_helper.Exp. ident ~loc
4001
+ (Location. mkloc (Longident. Lident " _" ) loc)
4002
+ | _ -> parse_constrained_or_coerced_expr p
4003
+ in
4004
+ (Asttypes. Labelled {txt = ident; loc = named_arg_loc}, expr)
4005
+ in
4006
+ Some {label; expr}
3890
4007
| _ ->
3891
4008
Some
3892
4009
{
@@ -4783,7 +4900,13 @@ and parse_string_field_declaration p =
4783
4900
let name_end_pos = p.end_pos in
4784
4901
Parser. next p;
4785
4902
let field_name = Location. mkloc name (mk_loc name_start_pos name_end_pos) in
4786
- Parser. expect ~grammar: Grammar. TypeExpression Colon p;
4903
+ (match p.Parser. token with
4904
+ | Colon -> Parser. next p
4905
+ | Equal ->
4906
+ Parser. err ~start_pos: p.start_pos ~end_pos: p.end_pos p
4907
+ (Diagnostics. message ErrorMessages. record_type_field_missing_colon);
4908
+ Parser. next p
4909
+ | _ -> Parser. expect ~grammar: Grammar. TypeExpression Colon p);
4787
4910
let typ = parse_poly_type_expr p in
4788
4911
Some (Parsetree. Otag (field_name, attrs, typ))
4789
4912
| DotDotDot ->
@@ -4796,7 +4919,13 @@ and parse_string_field_declaration p =
4796
4919
(Diagnostics. message (ErrorMessages. object_quoted_field_name name));
4797
4920
Parser. next p;
4798
4921
let field_name = Location. mkloc name name_loc in
4799
- Parser. expect ~grammar: Grammar. TypeExpression Colon p;
4922
+ (match p.Parser. token with
4923
+ | Colon -> Parser. next p
4924
+ | Equal ->
4925
+ Parser. err ~start_pos: p.start_pos ~end_pos: p.end_pos p
4926
+ (Diagnostics. message ErrorMessages. record_type_field_missing_colon);
4927
+ Parser. next p
4928
+ | _ -> Parser. expect ~grammar: Grammar. TypeExpression Colon p);
4800
4929
let typ = parse_poly_type_expr p in
4801
4930
Some (Parsetree. Otag (field_name, attrs, typ))
4802
4931
| _token -> None
@@ -4825,6 +4954,14 @@ and parse_field_declaration ?current_type_name_path ?inline_types_context p =
4825
4954
extend_current_type_name_path current_type_name_path name.txt
4826
4955
in
4827
4956
parse_poly_type_expr ?current_type_name_path ?inline_types_context p
4957
+ | Equal ->
4958
+ Parser. err ~start_pos: p.start_pos ~end_pos: p.end_pos p
4959
+ (Diagnostics. message ErrorMessages. record_type_field_missing_colon);
4960
+ Parser. next p;
4961
+ let current_type_name_path =
4962
+ extend_current_type_name_path current_type_name_path name.txt
4963
+ in
4964
+ parse_poly_type_expr ?current_type_name_path ?inline_types_context p
4828
4965
| _ ->
4829
4966
Ast_helper.Typ. constr ~loc: name.loc {name with txt = Lident name.txt} []
4830
4967
in
@@ -4866,6 +5003,11 @@ and parse_field_declaration_region ?current_type_name_path ?inline_types_context
4866
5003
| Colon ->
4867
5004
Parser. next p;
4868
5005
parse_poly_type_expr ?current_type_name_path ?inline_types_context p
5006
+ | Equal ->
5007
+ Parser. err ~start_pos: p.start_pos ~end_pos: p.end_pos p
5008
+ (Diagnostics. message ErrorMessages. record_type_field_missing_colon);
5009
+ Parser. next p;
5010
+ parse_poly_type_expr ?current_type_name_path ?inline_types_context p
4869
5011
| _ ->
4870
5012
Ast_helper.Typ. constr ~loc: name.loc ~attrs
4871
5013
{name with txt = Lident name.txt}
0 commit comments