Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support attributes/doc-comments on record type fields. #1817

Merged
merged 2 commits into from Feb 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
76 changes: 62 additions & 14 deletions formatTest/typeCheckedTests/expected_output/attributes.re
Expand Up @@ -256,8 +256,7 @@ let showLets = () =>
*/
[@moduleItemAttribute]
class boxA ('a) (init: 'a) =
[@onReturnClassExpr]
{
[@onReturnClassExpr] {
/**Floating comment text should be removed*/;
/**Floating comment text should be removed*/;
pub pr = init + init + init;
Expand All @@ -267,20 +266,17 @@ class boxA ('a) (init: 'a) =
* In non-curried sugar, the class_expr still sticks to "the simple thing".
*/
class boxB ('a) (init: 'a) =
[@stillOnTheReturnBecauseItsSimple]
Copy link
Member Author

@jordwalke jordwalke Feb 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found the formatting change in this diff to be a slight improvement, especially if we were to allow omitting the brackets:

@attr {
  bracedExpression
}

I imagine it could be pretty easily used to embed query languages for things like graphQL:

@query {
   friends: {
      
   },
   otherField: {

   }
}

{
[@stillOnTheReturnBecauseItsSimple] {
pub pr = init + init + init;
};

/* To be able to put an attribute on just the return in that case, use
* parens. */
[@onBoxC x; y]
class boxC ('a) =
[@onEntireFunction]
(
[@onEntireFunction] (
fun (init: 'a) =>
[@onReturnClassExpr]
{
[@onReturnClassExpr] {
pub pr = init + init + init;
}
);
Expand Down Expand Up @@ -464,8 +460,10 @@ external foo : bool => bool = "";
external readFileSync :
(
~name: string,
[@bs.string]
[ | `utf8 | [@bs.as "ascii"] `my_name]
[@bs.string] [
| `utf8
| [@bs.as "ascii"] `my_name
]
) =>
string =
"";
Expand All @@ -474,8 +472,7 @@ external readFileSync :
external readFileSync2 :
(
~name: string,
[@bs.string]
[
[@bs.string] [
| [@bs.as "ascii"] `utf8
| [@bs.as "ascii"] `my_name
]
Expand Down Expand Up @@ -513,8 +510,9 @@ external debounce :
(
int,
[@bs.meth] (unit => unit),
[@bs.meth]
(unit => [@bs.meth] (unit => unit))
[@bs.meth] (
unit => [@bs.meth] (unit => unit)
)
) =>
[@bs.meth] (unit => unit) =
"";
Expand Down Expand Up @@ -570,3 +568,53 @@ let x = 5;
/* Type */
[@haha: option(int)]
let x = 5;

/* Record item attributes */
type t_ = {
/** Comment attribute on record item */
x: int,
};

type tt = {
[@attr "on record field"]
x: int,
};

type ttt = {
[@attr "on record field"]
x: [@attr "on type itself"] int,
};

type tttt = {
/** Comment attribute on record item */
x: int,
[@regularAttribute "on next item"]
y: int,
};

type ttttt = {
[@attr "moved to first row"] [@attr]
x: int,
};

type tttttt = {
[@attr "testing with mutable field"]
mutable x: int,
};

let tmp =
/** On if statement */
(if (true) {true} else {false});

type foo =
option(
[@foo
[
"how does this break",
"when long enough",
]
] (
[@bar] (int => int),
[@baz] (int => int),
),
);
28 changes: 28 additions & 0 deletions formatTest/typeCheckedTests/expected_output/attributes.rei
Expand Up @@ -45,3 +45,31 @@ external createCompositeElementInternalHack :
) =>
reactElement =
"createElement";

/* Record item attributes */
type t_ = {
/** Comment attribute on record item */
x: int,
};

type tt = {
[@attr "on record field"]
x: int,
};

type ttt = {
[@attr "on record field"]
x: [@attr "on type itself"] int,
};

type tttt = {
/** Comment attribute on record item */
x: int,
[@regularAttribute "on next item"]
y: int,
};

type ttttt = {
[@attr "moved to first row"] [@attr]
x: int,
};
52 changes: 52 additions & 0 deletions formatTest/typeCheckedTests/input/attributes.re
Expand Up @@ -424,3 +424,55 @@ let x = 5;
/* Type */
[@haha: option(int)]
let x = 5;

/* Record item attributes */

type t_ = {
/** Comment attribute on record item */
x: int
};

type tt = {
[@attr "on record field"]
x: int
};

type ttt = {
[@attr "on record field"]
x: [@attr "on type itself"] int
};

type tttt = {
/** Comment attribute on record item */
x: int,
[@regularAttribute "on next item"]
y: int
};

type ttttt = [@attr "moved to first row"] {
[@attr]
x: int
};

type tttttt = {
[@attr "testing with mutable field"]
mutable x: int
};


let tmp = {
/** On if statement */
if (true) {
true
} else {
false
};
};

type foo =
option(
[@foo ["how does this break", "when long enough"]] (
[@bar] (int => int),
[@baz] (int => int),
),
);
30 changes: 30 additions & 0 deletions formatTest/typeCheckedTests/input/attributes.rei
Expand Up @@ -37,3 +37,33 @@ external createClassInternalHack : (t('classSpec)) => reactClass =
external createCompositeElementInternalHack :
(reactClass, t({.. reasonProps : 'props}), array(reactElement)) => reactElement =
"createElement";


/* Record item attributes */

type t_ = {
/** Comment attribute on record item */
x: int
};

type tt = {
[@attr "on record field"]
x: int
};

type ttt = {
[@attr "on record field"]
x: [@attr "on type itself"] int
};

type tttt = {
/** Comment attribute on record item */
x: int,
[@regularAttribute "on next item"]
y: int
};

type ttttt = [@attr "moved to first row"] {
[@attr]
x: int
};
9 changes: 5 additions & 4 deletions formatTest/unit_tests/expected_output/typeDeclarations.re
Expand Up @@ -74,8 +74,10 @@ type foo = option([@foo] ((int, int) => int));
/* tuple */
type foo =
option(
[@foo]
([@bar] (int => int), [@baz] (int => int)),
[@foo] (
[@bar] (int => int),
[@baz] (int => int),
),
);

type foo =
Expand All @@ -85,8 +87,7 @@ type foo =

type foo =
option(
[@foo]
(
[@foo] (
[@bar] string,
[@baz] (int => int),
[@qux] string,
Expand Down
29 changes: 8 additions & 21 deletions src/reason-parser/reason_parser.mly
Expand Up @@ -488,7 +488,7 @@ let syntax_error_typ loc msg =
if !Reason_config.recoverable then
Typ.extension ~loc (Syntax_util.syntax_error_extension_node loc msg)
else
syntax_error ()
raise (Syntaxerr.Error(Syntaxerr.Not_expecting (loc, msg)))

let syntax_error_mod loc msg =
if !Reason_config.recoverable then
Expand Down Expand Up @@ -920,9 +920,9 @@ let ensureTagsAreEqual startTag endTag loc =
"Start tag <%s> does not match end tag </%s>" startTag endTag

let prepare_immutable_labels labels =
let prepare (label, attr) =
let prepare label =
if label.pld_mutable == Mutable then syntax_error();
(label.pld_name.txt, attr, label.pld_type)
(label.pld_name.txt, label.pld_attributes, label.pld_type)
in
List.map prepare labels

Expand All @@ -943,19 +943,6 @@ let only_core_type t startp endp =
let loc = mklocation startp endp in
raiseSyntaxErrorFromSyntaxUtils loc "Record type is not allowed"

let only_labels l =
let rec loop label_declarations result =
match label_declarations with
| hd :: tail ->
let (l, a) = hd in
if (List.length a > 0) then
syntax_error ()
else
loop tail (result @ [l] )
| [] -> result
in
loop l []

let doc_loc = {txt = "ocaml.doc"; loc = Location.none}

let doc_attr text loc =
Expand Down Expand Up @@ -3670,7 +3657,7 @@ type_other_kind:
| EQUAL only_core_type(core_type) EQUAL DOTDOT
{ (Ptype_open, Public, Some $2) }
| EQUAL only_core_type(core_type) EQUAL private_flag LBRACE label_declarations RBRACE
{ (Ptype_record (only_labels $6), $4, Some $2) }
{ (Ptype_record $6, $4, Some $2) }
;

type_variables_with_variance_comma_list:
Expand Down Expand Up @@ -3776,11 +3763,11 @@ constructor_arguments:
label_declaration:
| item_attributes mutable_flag as_loc(LIDENT)
{ let loc = mklocation $symbolstartpos $endpos in
(Type.field $3 (mkct $3) ~mut:$2 ~loc, $1)
Type.field $3 (mkct $3) ~attrs:$1 ~mut:$2 ~loc
}
| item_attributes mutable_flag as_loc(LIDENT) COLON poly_type
{ let loc = mklocation $symbolstartpos $endpos in
(Type.field $3 $5 ~mut:$2 ~loc, $1)
Type.field $3 $5 ~attrs:$1 ~mut:$2 ~loc
}
;

Expand All @@ -3792,7 +3779,7 @@ string_literal_lbl:
{
let loc = mklocation $symbolstartpos $endpos in
let (s, _) = $2 in
(Type.field (mkloc s loc) $4 ~loc, $1)
Type.field (mkloc s loc) $4 ~attrs:$1 ~loc
}
;

Expand Down Expand Up @@ -4168,7 +4155,7 @@ object_record_type:
| LBRACE RBRACE
{ syntax_error () }
| LBRACE label_declarations RBRACE
{ Record_type (only_labels $2) }
{ Record_type $2 }
| LBRACE DOT string_literal_lbls RBRACE
{ (* `{. "foo": bar}` -> `Js.t({. foo: bar})` *)
let loc = mklocation $symbolstartpos $endpos in
Expand Down