@@ -99,6 +99,24 @@ module ErrorMessages = struct
99
99
100
100
let dict_expr_spread = " Dict literals do not support spread (`...`) yet."
101
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
+
102
120
let variant_ident =
103
121
" A polymorphic variant (e.g. #id) must start with an alphabetical letter \
104
122
or be a number (e.g. #742)"
@@ -1414,6 +1432,13 @@ and parse_record_pattern_row_field ~attrs p =
1414
1432
let optional = parse_optional_label p in
1415
1433
let pat = parse_pattern p in
1416
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)
1417
1442
| _ ->
1418
1443
( Ast_helper.Pat. var ~loc: label.loc ~attrs
1419
1444
(Location. mkloc (Longident. last label.txt) label.loc),
@@ -3062,6 +3087,19 @@ and parse_braced_or_record_expr p =
3062
3087
in
3063
3088
Parser. expect Rbrace p;
3064
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
3065
3103
| _ -> (
3066
3104
let tag = if p.mode = ParseForTypeChecker then Some " js" else None in
3067
3105
let constant =
@@ -3155,6 +3193,28 @@ and parse_braced_or_record_expr p =
3155
3193
in
3156
3194
Parser. expect Rbrace p;
3157
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)
3158
3218
(* error case *)
3159
3219
| Lident _ ->
3160
3220
if p.prev_end_pos.pos_lnum < p.start_pos.pos_lnum then (
@@ -3297,6 +3357,12 @@ and parse_record_expr_row_with_string_key p :
3297
3357
Parser. next p;
3298
3358
let field_expr = parse_expr p in
3299
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 }
3300
3366
| _ ->
3301
3367
Some
3302
3368
{
@@ -3326,6 +3392,13 @@ and parse_record_expr_row p :
3326
3392
let optional = parse_optional_label p in
3327
3393
let field_expr = parse_expr p in
3328
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}
3329
3402
| _ ->
3330
3403
let value = Ast_helper.Exp. ident ~loc: field.loc ~attrs field in
3331
3404
let value =
@@ -3385,6 +3458,12 @@ and parse_dict_expr_row p =
3385
3458
Parser. next p;
3386
3459
let fieldExpr = parse_expr p in
3387
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)
3388
3467
| _ -> Some (field, Ast_helper.Exp. ident ~loc: field.loc field))
3389
3468
| _ -> None
3390
3469
@@ -3889,12 +3968,42 @@ and parse_argument2 p : argument option =
3889
3968
in
3890
3969
Some {label; expr}
3891
3970
| Colon ->
3971
+ let colon_start = p.start_pos in
3892
3972
Parser. next p;
3893
- let typ = parse_typ_expr p in
3894
- let loc = mk_loc start_pos p.prev_end_pos in
3895
- let expr = Ast_helper.Exp. constraint_ ~loc ident_expr typ in
3896
- Some
3897
- {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}
3898
4007
| _ ->
3899
4008
Some
3900
4009
{
@@ -4791,7 +4900,13 @@ and parse_string_field_declaration p =
4791
4900
let name_end_pos = p.end_pos in
4792
4901
Parser. next p;
4793
4902
let field_name = Location. mkloc name (mk_loc name_start_pos name_end_pos) in
4794
- 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);
4795
4910
let typ = parse_poly_type_expr p in
4796
4911
Some (Parsetree. Otag (field_name, attrs, typ))
4797
4912
| DotDotDot ->
@@ -4804,7 +4919,13 @@ and parse_string_field_declaration p =
4804
4919
(Diagnostics. message (ErrorMessages. object_quoted_field_name name));
4805
4920
Parser. next p;
4806
4921
let field_name = Location. mkloc name name_loc in
4807
- 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);
4808
4929
let typ = parse_poly_type_expr p in
4809
4930
Some (Parsetree. Otag (field_name, attrs, typ))
4810
4931
| _token -> None
@@ -4833,6 +4954,14 @@ and parse_field_declaration ?current_type_name_path ?inline_types_context p =
4833
4954
extend_current_type_name_path current_type_name_path name.txt
4834
4955
in
4835
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
4836
4965
| _ ->
4837
4966
Ast_helper.Typ. constr ~loc: name.loc {name with txt = Lident name.txt} []
4838
4967
in
@@ -4874,6 +5003,11 @@ and parse_field_declaration_region ?current_type_name_path ?inline_types_context
4874
5003
| Colon ->
4875
5004
Parser. next p;
4876
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
4877
5011
| _ ->
4878
5012
Ast_helper.Typ. constr ~loc: name.loc ~attrs
4879
5013
{name with txt = Lident name.txt}
0 commit comments