@@ -99,6 +99,24 @@ module ErrorMessages = struct
9999
100100 let dict_expr_spread = " Dict literals do not support spread (`...`) yet."
101101
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+
102120 let variant_ident =
103121 " A polymorphic variant (e.g. #id) must start with an alphabetical letter \
104122 or be a number (e.g. #742)"
@@ -1414,6 +1432,13 @@ and parse_record_pattern_row_field ~attrs p =
14141432 let optional = parse_optional_label p in
14151433 let pat = parse_pattern p in
14161434 (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)
14171442 | _ ->
14181443 ( Ast_helper.Pat. var ~loc: label.loc ~attrs
14191444 (Location. mkloc (Longident. last label.txt) label.loc),
@@ -3062,6 +3087,19 @@ and parse_braced_or_record_expr p =
30623087 in
30633088 Parser. expect Rbrace p;
30643089 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
30653103 | _ -> (
30663104 let tag = if p.mode = ParseForTypeChecker then Some " js" else None in
30673105 let constant =
@@ -3155,6 +3193,28 @@ and parse_braced_or_record_expr p =
31553193 in
31563194 Parser. expect Rbrace p;
31573195 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)
31583218 (* error case *)
31593219 | Lident _ ->
31603220 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 :
32973357 Parser. next p;
32983358 let field_expr = parse_expr p in
32993359 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 }
33003366 | _ ->
33013367 Some
33023368 {
@@ -3326,6 +3392,13 @@ and parse_record_expr_row p :
33263392 let optional = parse_optional_label p in
33273393 let field_expr = parse_expr p in
33283394 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}
33293402 | _ ->
33303403 let value = Ast_helper.Exp. ident ~loc: field.loc ~attrs field in
33313404 let value =
@@ -3385,6 +3458,12 @@ and parse_dict_expr_row p =
33853458 Parser. next p;
33863459 let fieldExpr = parse_expr p in
33873460 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)
33883467 | _ -> Some (field, Ast_helper.Exp. ident ~loc: field.loc field))
33893468 | _ -> None
33903469
@@ -3889,12 +3968,42 @@ and parse_argument2 p : argument option =
38893968 in
38903969 Some {label; expr}
38913970 | Colon ->
3971+ let colon_start = p.start_pos in
38923972 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}
38984007 | _ ->
38994008 Some
39004009 {
@@ -4791,7 +4900,13 @@ and parse_string_field_declaration p =
47914900 let name_end_pos = p.end_pos in
47924901 Parser. next p;
47934902 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);
47954910 let typ = parse_poly_type_expr p in
47964911 Some (Parsetree. Otag (field_name, attrs, typ))
47974912 | DotDotDot ->
@@ -4804,7 +4919,13 @@ and parse_string_field_declaration p =
48044919 (Diagnostics. message (ErrorMessages. object_quoted_field_name name));
48054920 Parser. next p;
48064921 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);
48084929 let typ = parse_poly_type_expr p in
48094930 Some (Parsetree. Otag (field_name, attrs, typ))
48104931 | _token -> None
@@ -4833,6 +4954,14 @@ and parse_field_declaration ?current_type_name_path ?inline_types_context p =
48334954 extend_current_type_name_path current_type_name_path name.txt
48344955 in
48354956 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
48364965 | _ ->
48374966 Ast_helper.Typ. constr ~loc: name.loc {name with txt = Lident name.txt} []
48384967 in
@@ -4874,6 +5003,11 @@ and parse_field_declaration_region ?current_type_name_path ?inline_types_context
48745003 | Colon ->
48755004 Parser. next p;
48765005 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
48775011 | _ ->
48785012 Ast_helper.Typ. constr ~loc: name.loc ~attrs
48795013 {name with txt = Lident name.txt}
0 commit comments