Skip to content

Commit 5ce8a8d

Browse files
committed
cleanup
1 parent 659a349 commit 5ce8a8d

9 files changed

+89
-65
lines changed

compiler/syntax/src/res_core.ml

Lines changed: 43 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,26 @@ module ErrorMessages = struct
150150
let multiple_inline_record_definitions_at_same_path =
151151
"Only one inline record definition is allowed per record field. This \
152152
defines more than one inline record."
153+
154+
let keyword_field_in_expr keyword_txt =
155+
"Cannot use keyword `"
156+
^ keyword_txt
157+
^ "` as a record field name. Suggestion: rename it (e.g. `"
158+
^ keyword_txt ^ "_`)"
159+
160+
let keyword_field_in_pattern keyword_txt =
161+
"Cannot use keyword `"
162+
^ keyword_txt
163+
^ "` here. Keywords are not allowed as record field names."
164+
165+
let keyword_field_in_type keyword_txt =
166+
"Cannot use keyword `"
167+
^ keyword_txt
168+
^ "` as a record field name. Suggestion: rename it (e.g. `"
169+
^ keyword_txt
170+
^ "_`)\n If you need the field to be \""
171+
^ keyword_txt ^ "\" at runtime, annotate the field: `@as(\""
172+
^ keyword_txt ^ "\") " ^ keyword_txt ^ "_ : ...`"
153173
end
154174

155175
module InExternal = struct
@@ -398,8 +418,17 @@ let build_longident words =
398418
| [] -> assert false
399419
| hd :: tl -> List.fold_left (fun p s -> Longident.Ldot (p, s)) (Lident hd) tl
400420

401-
(* Recovers a keyword used as field name if it's probable that it's a full
402-
field name (not punning etc), by checking if there's a colon after it. *)
421+
(* Emit a keyword-as-field diagnostic for the current token using a context-specific
422+
message builder. *)
423+
let emit_keyword_field_error (p : Parser.t) ~mk_message =
424+
let keyword_txt = Token.to_string p.token in
425+
let keyword_start = p.Parser.start_pos in
426+
let keyword_end = p.Parser.end_pos in
427+
Parser.err ~start_pos:keyword_start ~end_pos:keyword_end p
428+
(Diagnostics.message (mk_message keyword_txt))
429+
430+
(* Recovers a keyword used as field name if it's probable that it's a full
431+
field name (not punning etc), by checking if there's a colon after it. *)
403432
let recover_keyword_field_name_if_probably_field p ~mk_message :
404433
(string * Location.t) option =
405434
if
@@ -408,13 +437,9 @@ let recover_keyword_field_name_if_probably_field p ~mk_message :
408437
Parser.next st;
409438
st.Parser.token = Colon)
410439
then (
411-
let keyword_txt = Token.to_string p.token in
412-
let keyword_start = p.Parser.start_pos in
413-
let keyword_end = p.Parser.end_pos in
414-
Parser.err ~start_pos:keyword_start ~end_pos:keyword_end p
415-
(Diagnostics.message (mk_message keyword_txt));
416-
let loc = mk_loc keyword_start keyword_end in
417-
let recovered_field_name = keyword_txt ^ "_" in
440+
emit_keyword_field_error p ~mk_message;
441+
let loc = mk_loc p.Parser.start_pos p.Parser.end_pos in
442+
let recovered_field_name = Token.to_string p.token ^ "_" in
418443
Parser.next p;
419444
Some (recovered_field_name, loc))
420445
else None
@@ -1402,28 +1427,16 @@ and parse_record_pattern_row p =
14021427
if Token.is_keyword p.token then (
14031428
match
14041429
recover_keyword_field_name_if_probably_field p
1405-
~mk_message:(fun keyword_txt ->
1406-
"Cannot use keyword `" ^ keyword_txt
1407-
^ "` here. Keywords are not allowed as record field names.")
1430+
~mk_message:ErrorMessages.keyword_field_in_pattern
14081431
with
14091432
| Some (recovered_field_name, loc) ->
14101433
Parser.expect Colon p;
14111434
let optional = parse_optional_label p in
14121435
let pat = parse_pattern p in
1413-
let field =
1414-
Location.mkloc (Longident.Lident recovered_field_name) loc
1415-
in
1436+
let field = Location.mkloc (Longident.Lident recovered_field_name) loc in
14161437
Some (false, PatField {lid = field; x = pat; opt = optional})
14171438
| None ->
1418-
let keyword_txt = Token.to_string p.token in
1419-
let keyword_start = p.Parser.start_pos in
1420-
let keyword_end = p.Parser.end_pos in
1421-
let message =
1422-
"Cannot use keyword `" ^ keyword_txt
1423-
^ "` here. Keywords are not allowed as record field names."
1424-
in
1425-
Parser.err ~start_pos:keyword_start ~end_pos:keyword_end p
1426-
(Diagnostics.message message);
1439+
emit_keyword_field_error p ~mk_message:ErrorMessages.keyword_field_in_pattern;
14271440
None)
14281441
else None
14291442

@@ -2974,10 +2987,7 @@ and parse_braced_or_record_expr p =
29742987
| token when Token.is_keyword token -> (
29752988
match
29762989
recover_keyword_field_name_if_probably_field p
2977-
~mk_message:(fun keyword_txt ->
2978-
"Cannot use keyword `" ^ keyword_txt
2979-
^ "` as a record field name. Suggestion: rename it (e.g. `"
2980-
^ keyword_txt ^ "_`)")
2990+
~mk_message:ErrorMessages.keyword_field_in_expr
29812991
with
29822992
| Some (recovered_field_name, loc) ->
29832993
Parser.expect Colon p;
@@ -3314,30 +3324,16 @@ and parse_record_expr_row p :
33143324
if Token.is_keyword p.token then (
33153325
match
33163326
recover_keyword_field_name_if_probably_field p
3317-
~mk_message:(fun keyword_txt ->
3318-
"Cannot use keyword `" ^ keyword_txt
3319-
^ "` as a record field name. Suggestion: rename it (e.g. `"
3320-
^ keyword_txt ^ "_`)")
3327+
~mk_message:ErrorMessages.keyword_field_in_expr
33213328
with
33223329
| Some (recovered_field_name, loc) ->
33233330
Parser.expect Colon p;
33243331
let optional = parse_optional_label p in
33253332
let field_expr = parse_expr p in
3326-
let field =
3327-
Location.mkloc (Longident.Lident recovered_field_name) loc
3328-
in
3333+
let field = Location.mkloc (Longident.Lident recovered_field_name) loc in
33293334
Some {lid = field; x = field_expr; opt = optional}
33303335
| None ->
3331-
let keyword_txt = Token.to_string p.token in
3332-
let keyword_start = p.Parser.start_pos in
3333-
let keyword_end = p.Parser.end_pos in
3334-
let message =
3335-
"Cannot use keyword `" ^ keyword_txt
3336-
^ "` as a record field name. Suggestion: rename it (e.g. `"
3337-
^ keyword_txt ^ "_`)"
3338-
in
3339-
Parser.err ~start_pos:keyword_start ~end_pos:keyword_end p
3340-
(Diagnostics.message message);
3336+
emit_keyword_field_error p ~mk_message:ErrorMessages.keyword_field_in_expr;
33413337
None)
33423338
else None
33433339

@@ -4839,12 +4835,7 @@ and parse_field_declaration_region ?current_type_name_path ?inline_types_context
48394835
if Token.is_keyword p.token then (
48404836
match
48414837
recover_keyword_field_name_if_probably_field p
4842-
~mk_message:(fun keyword_txt ->
4843-
"Cannot use keyword `" ^ keyword_txt
4844-
^ "` as a record field name. Suggestion: rename it (e.g. `"
4845-
^ keyword_txt ^ "_`)\n" ^ " If you need the field to be \""
4846-
^ keyword_txt ^ "\" at runtime, annotate the field: `@as(\""
4847-
^ keyword_txt ^ "\") " ^ keyword_txt ^ "_ : ...`")
4838+
~mk_message:ErrorMessages.keyword_field_in_type
48484839
with
48494840
| Some (recovered_field_name, name_loc) ->
48504841
let optional = parse_optional_label p in
@@ -4856,18 +4847,7 @@ and parse_field_declaration_region ?current_type_name_path ?inline_types_context
48564847
let name = Location.mkloc recovered_field_name name_loc in
48574848
Some (Ast_helper.Type.field ~attrs ~loc ~mut ~optional name typ)
48584849
| None ->
4859-
let keyword_txt = Token.to_string p.token in
4860-
let keyword_start = p.Parser.start_pos in
4861-
let keyword_end = p.Parser.end_pos in
4862-
let message =
4863-
"Cannot use keyword `" ^ keyword_txt
4864-
^ "` as a record field name. Suggestion: rename it (e.g. `"
4865-
^ keyword_txt ^ "_`)\n" ^ " If you need the field to be \""
4866-
^ keyword_txt ^ "\" at runtime, annotate the field: `@as(\""
4867-
^ keyword_txt ^ "\") " ^ keyword_txt ^ "_ : ...`"
4868-
in
4869-
Parser.err ~start_pos:keyword_start ~end_pos:keyword_end p
4870-
(Diagnostics.message message);
4850+
emit_keyword_field_error p ~mk_message:ErrorMessages.keyword_field_in_type;
48714851
None)
48724852
else (
48734853
if attrs <> [] then

tests/syntax_tests/data/parsing/errors/structure/expected/recordFieldKeywordInExpr.res.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77

88
Cannot use keyword `type` as a record field name. Suggestion: rename it (e.g. `type_`)
99

10-
let r = { type = 1 }
10+
let r = { type_ = 1 }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
Syntax error!
3+
syntax_tests/data/parsing/errors/structure/recordFieldKeywordInExpr2.res:1:16-19
4+
5+
1 │ let r = {a: 1, type: 2}
6+
2 │
7+
8+
Cannot use keyword `type` as a record field name. Suggestion: rename it (e.g. `type_`)
9+
10+
let r = { a = 1; type_ = 2 }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
Syntax error!
3+
syntax_tests/data/parsing/errors/structure/recordFieldKeywordInPattern2.res:1:12-15
4+
5+
1 │ let {a: _, type: x} = r
6+
2 │
7+
8+
Cannot use keyword `type` here. Keywords are not allowed as record field names.
9+
10+
let { a = _; type_ = x } = r

tests/syntax_tests/data/parsing/errors/structure/expected/recordFieldKeywordInType.res.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313

1414
type nonrec r = {
1515
id: string ;
16-
type: int }
16+
type_: int }
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
Syntax error!
3+
syntax_tests/data/parsing/errors/structure/recordFieldKeywordInType2.res:3:3-6
4+
5+
1 │ type r = {
6+
2 │ id: string,
7+
3 │ type: int,
8+
4 │ x: bool,
9+
5 │ }
10+
11+
Cannot use keyword `type` as a record field name. Suggestion: rename it (e.g. `type_`)
12+
If you need the field to be "type" at runtime, annotate the field: `@as("type") type_ : ...`
13+
14+
type nonrec r = {
15+
id: string ;
16+
type_: int ;
17+
x: bool }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let r = {a: 1, type: 2}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let {a: _, type: x} = r
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type r = {
2+
id: string,
3+
type: int,
4+
x: bool,
5+
}

0 commit comments

Comments
 (0)