diff --git a/CHANGELOG.md b/CHANGELOG.md index bf61f0caab..0fd519622e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ #### :nail_care: Polish +- Allow skipping the leading pipe in variant definition with a leading constructor with an attribute. https://github.com/rescript-lang/rescript/pull/7782 + #### :house: Internal # 12.0.0-beta.6 diff --git a/compiler/syntax/src/res_core.ml b/compiler/syntax/src/res_core.ml index ab9d0d4cee..1cfb842cbd 100644 --- a/compiler/syntax/src/res_core.ml +++ b/compiler/syntax/src/res_core.ml @@ -5044,7 +5044,7 @@ and parse_type_representation ?current_type_name_path ?inline_types_context p = in let kind = match p.Parser.token with - | Bar | Uident _ | DocComment _ -> + | Bar | Uident _ | DocComment _ | At -> Parsetree.Ptype_variant (parse_type_constructor_declarations p) | Lbrace -> Parsetree.Ptype_record @@ -5602,6 +5602,36 @@ and parse_type_equation_and_representation ?current_type_name_path | Bar | DotDot | DocComment _ -> let priv, kind = parse_type_representation p in (None, priv, kind) + | At -> ( + (* Attribute can start a variant constructor or a type manifest. + Look ahead past attributes; if a constructor-like token follows (Uident not immediately + followed by a Dot, or DotDotDot/Bar/DocComment), treat as variant; otherwise manifest *) + let is_variant_after_attrs = + Parser.lookahead p (fun state -> + ignore (parse_attributes state); + match state.Parser.token with + | Uident _ -> ( + Parser.next state; + match state.Parser.token with + | Dot -> false + | _ -> true) + | DotDotDot | Bar | DocComment _ -> true + | _ -> false) + in + if is_variant_after_attrs then + let priv, kind = parse_type_representation p in + (None, priv, kind) + else + let manifest = Some (parse_typ_expr p) in + match p.Parser.token with + | Equal -> + Parser.next p; + let priv, kind = + parse_type_representation ?current_type_name_path + ?inline_types_context p + in + (manifest, priv, kind) + | _ -> (manifest, Public, Parsetree.Ptype_abstract)) | _ -> ( let manifest = Some (parse_typ_expr p) in match p.Parser.token with diff --git a/tests/syntax_tests/data/parsing/grammar/typedefinition/expected/missingPipeBeforeConstructorAttribute.res.txt b/tests/syntax_tests/data/parsing/grammar/typedefinition/expected/missingPipeBeforeConstructorAttribute.res.txt new file mode 100644 index 0000000000..97b97b4f45 --- /dev/null +++ b/tests/syntax_tests/data/parsing/grammar/typedefinition/expected/missingPipeBeforeConstructorAttribute.res.txt @@ -0,0 +1,2 @@ +type nonrec t = + | One [@as {js|one|js}] \ No newline at end of file diff --git a/tests/syntax_tests/data/parsing/grammar/typedefinition/missingPipeBeforeConstructorAttribute.res b/tests/syntax_tests/data/parsing/grammar/typedefinition/missingPipeBeforeConstructorAttribute.res new file mode 100644 index 0000000000..18b270836e --- /dev/null +++ b/tests/syntax_tests/data/parsing/grammar/typedefinition/missingPipeBeforeConstructorAttribute.res @@ -0,0 +1,2 @@ +type t = @as("one") One + diff --git a/tests/syntax_tests/data/printer/typeDef/expected/missingPipeBeforeConstructorAttribute.res.txt b/tests/syntax_tests/data/printer/typeDef/expected/missingPipeBeforeConstructorAttribute.res.txt new file mode 100644 index 0000000000..8c18eb4753 --- /dev/null +++ b/tests/syntax_tests/data/printer/typeDef/expected/missingPipeBeforeConstructorAttribute.res.txt @@ -0,0 +1 @@ +type t = | @as("one") One diff --git a/tests/syntax_tests/data/printer/typeDef/missingPipeBeforeConstructorAttribute.res b/tests/syntax_tests/data/printer/typeDef/missingPipeBeforeConstructorAttribute.res new file mode 100644 index 0000000000..18b270836e --- /dev/null +++ b/tests/syntax_tests/data/printer/typeDef/missingPipeBeforeConstructorAttribute.res @@ -0,0 +1,2 @@ +type t = @as("one") One +