Skip to content

Sync latest syntax #5761

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions jscomp/napkin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@

- Add support for empty record literal `{}` for records with only optional fields, and type definition of empty record (e.g. `type empty = {}`) https://github.com/rescript-lang/syntax/pull/632

- Support the use of spread anywhere in list creation (e.g. `list{...x, 1, ...y, ...z}). https://github.com/rescript-lang/syntax/pull/692

- Add support for the argument of `@react.component` to set a props type from the outside. https://github.com/rescript-lang/syntax/pull/699

#### :bug: Bug Fix

- Fix issue in formatting JSX spread props https://github.com/rescript-lang/syntax/pull/644
Expand All @@ -44,6 +48,9 @@
- Fix issue where certain JSX expressions would be formatted differenctly in compiler 10.1.0-rc.1 https://github.com/rescript-lang/syntax/issues/675
- Fix issue where printing nested pipe discards await https://github.com/rescript-lang/syntax/issues/687
- Fix issue where the JSX key type is not an optional string https://github.com/rescript-lang/syntax/pull/693
- Fix issue where the JSX fragment without children build error https://github.com/rescript-lang/syntax/pull/704
- Fix issue where async as an id cannot be used with application and labelled arguments https://github.com/rescript-lang/syntax/issues/707


#### :eyeglasses: Spec Compliance

Expand Down
224 changes: 192 additions & 32 deletions lib/4.06.1/unstable/js_compiler.ml
Original file line number Diff line number Diff line change
Expand Up @@ -47769,6 +47769,8 @@ val isBlockExpr : Parsetree.expression -> bool
val isTemplateLiteral : Parsetree.expression -> bool
val hasTemplateLiteralAttr : Parsetree.attributes -> bool

val isSpreadBeltListConcat : Parsetree.expression -> bool

val collectOrPatternChain : Parsetree.pattern -> Parsetree.pattern list

val processBracesAttr :
Expand Down Expand Up @@ -48412,6 +48414,25 @@ let isTemplateLiteral expr =
| Pexp_constant _ when hasTemplateLiteralAttr expr.pexp_attributes -> true
| _ -> false

let hasSpreadAttr attrs =
List.exists
(fun attr ->
match attr with
| {Location.txt = "res.spread"}, _ -> true
| _ -> false)
attrs

let isSpreadBeltListConcat expr =
match expr.pexp_desc with
| Pexp_ident
{
txt =
Longident.Ldot
(Longident.Ldot (Longident.Lident "Belt", "List"), "concatMany");
} ->
hasSpreadAttr expr.pexp_attributes
| _ -> false

(* Blue | Red | Green -> [Blue; Red; Green] *)
let collectOrPatternChain pat =
let rec loop pattern chain =
Expand Down Expand Up @@ -54273,6 +54294,9 @@ and printExpression ~customLayout (e : Parsetree.expression) cmtTbl =
])
| extension ->
printExtension ~customLayout ~atModuleLvl:false extension cmtTbl)
| Pexp_apply (e, [(Nolabel, {pexp_desc = Pexp_array subLists})])
when ParsetreeViewer.isSpreadBeltListConcat e ->
printBeltListConcatApply ~customLayout subLists cmtTbl
| Pexp_apply _ ->
if ParsetreeViewer.isUnaryExpression e then
printUnaryExpression ~customLayout e cmtTbl
Expand Down Expand Up @@ -55061,6 +55085,63 @@ and printBinaryExpression ~customLayout (expr : Parsetree.expression) cmtTbl =
])
| _ -> Doc.nil

and printBeltListConcatApply ~customLayout subLists cmtTbl =
let makeSpreadDoc commaBeforeSpread = function
| Some expr ->
Doc.concat
[
commaBeforeSpread;
Doc.dotdotdot;
(let doc = printExpressionWithComments ~customLayout expr cmtTbl in
match Parens.expr expr with
| Parens.Parenthesized -> addParens doc
| Braced braces -> printBraces doc expr braces
| Nothing -> doc);
]
| None -> Doc.nil
in
let makeSubListDoc (expressions, spread) =
let commaBeforeSpread =
match expressions with
| [] -> Doc.nil
| _ -> Doc.concat [Doc.text ","; Doc.line]
in
let spreadDoc = makeSpreadDoc commaBeforeSpread spread in
Doc.concat
[
Doc.join
~sep:(Doc.concat [Doc.text ","; Doc.line])
(List.map
(fun expr ->
let doc =
printExpressionWithComments ~customLayout expr cmtTbl
in
match Parens.expr expr with
| Parens.Parenthesized -> addParens doc
| Braced braces -> printBraces doc expr braces
| Nothing -> doc)
expressions);
spreadDoc;
]
in
Doc.group
(Doc.concat
[
Doc.text "list{";
Doc.indent
(Doc.concat
[
Doc.softLine;
Doc.join
~sep:(Doc.concat [Doc.text ","; Doc.line])
(List.map makeSubListDoc
(List.map ParsetreeViewer.collectListExpressions subLists));
]);
Doc.trailingComma;
Doc.softLine;
Doc.rbrace;
])

(* callExpr(arg1, arg2) *)
and printPexpApply ~customLayout expr cmtTbl =
match expr.pexp_desc with
Expand Down Expand Up @@ -271777,6 +271858,25 @@ let hasAttr (loc, _) = loc.txt = "react.component"
let hasAttrOnBinding {pvb_attributes} =
List.find_opt hasAttr pvb_attributes <> None

let coreTypeOfAttrs attributes =
List.find_map
(fun ({txt}, payload) ->
match (txt, payload) with
| "react.component", PTyp coreType -> Some coreType
| _ -> None)
attributes

let typVarsOfCoreType {ptyp_desc} =
match ptyp_desc with
| Ptyp_constr (_, coreTypes) ->
List.filter
(fun {ptyp_desc} ->
match ptyp_desc with
| Ptyp_var _ -> true
| _ -> false)
coreTypes
| _ -> []

let raiseError ~loc msg = Location.raise_errorf ~loc msg

let raiseErrorMultipleReactComponent ~loc =
Expand Down Expand Up @@ -273296,13 +273396,30 @@ let makeTypeDecls propsName loc namedTypeList =
~kind:(Ptype_record labelDeclList);
]

let makeTypeDeclsWithCoreType propsName loc coreType typVars =
[
Type.mk ~loc {txt = propsName; loc} ~kind:Ptype_abstract
~params:(typVars |> List.map (fun v -> (v, Invariant)))
~manifest:coreType;
]

(* type props<'x, 'y, ...> = { x: 'x, y?: 'y, ... } *)
let makePropsRecordType propsName loc namedTypeList =
Str.type_ Nonrecursive (makeTypeDecls propsName loc namedTypeList)
let makePropsRecordType ~coreTypeOfAttr ~typVarsOfCoreType propsName loc
namedTypeList =
Str.type_ Nonrecursive
(match coreTypeOfAttr with
| None -> makeTypeDecls propsName loc namedTypeList
| Some coreType ->
makeTypeDeclsWithCoreType propsName loc coreType typVarsOfCoreType)

(* type props<'x, 'y, ...> = { x: 'x, y?: 'y, ... } *)
let makePropsRecordTypeSig propsName loc namedTypeList =
Sig.type_ Nonrecursive (makeTypeDecls propsName loc namedTypeList)
let makePropsRecordTypeSig ~coreTypeOfAttr ~typVarsOfCoreType propsName loc
namedTypeList =
Sig.type_ Nonrecursive
(match coreTypeOfAttr with
| None -> makeTypeDecls propsName loc namedTypeList
| Some coreType ->
makeTypeDeclsWithCoreType propsName loc coreType typVarsOfCoreType)

let transformUppercaseCall3 ~config modulePath mapper jsxExprLoc callExprLoc
attrs callArguments =
Expand Down Expand Up @@ -273396,7 +273513,7 @@ let transformUppercaseCall3 ~config modulePath mapper jsxExprLoc callExprLoc
(Exp.ident
{
loc = Location.none;
txt = Ldot (Lident "React", "createElementWithKey");
txt = Ldot (Lident "JsxPPXReactSupport", "createElementWithKey");
})
[key; (nolabel, makeID); (nolabel, props)]
| None, [] ->
Expand All @@ -273409,7 +273526,8 @@ let transformUppercaseCall3 ~config modulePath mapper jsxExprLoc callExprLoc
(Exp.ident
{
loc = Location.none;
txt = Ldot (Lident "React", "createElementVariadicWithKey");
txt =
Ldot (Lident "JsxPPXReactSupport", "createElementVariadicWithKey");
})
[key; (nolabel, makeID); (nolabel, props); (nolabel, children)]
| Some children, [] ->
Expand Down Expand Up @@ -273718,6 +273836,12 @@ let transformStructureItem ~config mapper item =
config.hasReactComponent <- true;
check_string_int_attribute_iter.structure_item
check_string_int_attribute_iter item;
let coreTypeOfAttr = React_jsx_common.coreTypeOfAttrs pval_attributes in
let typVarsOfCoreType =
coreTypeOfAttr
|> Option.map React_jsx_common.typVarsOfCoreType
|> Option.value ~default:[]
in
let rec getPropTypes types ({ptyp_loc; ptyp_desc} as fullType) =
match ptyp_desc with
| Ptyp_arrow (name, type_, ({ptyp_desc = Ptyp_arrow _} as rest))
Expand All @@ -273734,11 +273858,17 @@ let transformStructureItem ~config mapper item =
let retPropsType =
Typ.constr ~loc:pstr_loc
(Location.mkloc (Lident "props") pstr_loc)
(makePropsTypeParams namedTypeList)
(match coreTypeOfAttr with
| None -> makePropsTypeParams namedTypeList
| Some _ -> (
match typVarsOfCoreType with
| [] -> []
| _ -> [Typ.any ()]))
in
(* type props<'x, 'y> = { x: 'x, y?: 'y, ... } *)
let propsRecordType =
makePropsRecordType "props" pstr_loc namedTypeList
makePropsRecordType ~coreTypeOfAttr ~typVarsOfCoreType "props"
pstr_loc namedTypeList
in
(* can't be an arrow because it will defensively uncurry *)
let newExternalType =
Expand Down Expand Up @@ -273772,6 +273902,14 @@ let transformStructureItem ~config mapper item =
React_jsx_common.raiseErrorMultipleReactComponent ~loc:pstr_loc
else (
config.hasReactComponent <- true;
let coreTypeOfAttr =
React_jsx_common.coreTypeOfAttrs binding.pvb_attributes
in
let typVarsOfCoreType =
coreTypeOfAttr
|> Option.map React_jsx_common.typVarsOfCoreType
|> Option.value ~default:[]
in
let bindingLoc = binding.pvb_loc in
let bindingPatLoc = binding.pvb_pat.ppat_loc in
let binding =
Expand Down Expand Up @@ -273962,7 +274100,8 @@ let transformStructureItem ~config mapper item =
let vbMatchList = List.map vbMatch namedArgWithDefaultValueList in
(* type props = { ... } *)
let propsRecordType =
makePropsRecordType "props" pstr_loc namedTypeList
makePropsRecordType ~coreTypeOfAttr ~typVarsOfCoreType "props"
pstr_loc namedTypeList
in
let innerExpression =
Exp.apply
Expand All @@ -273974,19 +274113,23 @@ let transformStructureItem ~config mapper item =
[(Nolabel, Exp.ident (Location.mknoloc @@ Lident "ref"))]
| false -> [])
in
let makePropsPattern = function
| [] -> Pat.var @@ Location.mknoloc "props"
| _ ->
Pat.constraint_
(Pat.var @@ Location.mknoloc "props")
(Typ.constr (Location.mknoloc @@ Lident "props") [Typ.any ()])
in
let fullExpression =
(* React component name should start with uppercase letter *)
(* let make = { let \"App" = props => make(props); \"App" } *)
(* let make = React.forwardRef({
let \"App" = (props, ref) => make({...props, ref: @optional (Js.Nullabel.toOption(ref))})
})*)
Exp.fun_ nolabel None
(match namedTypeList with
| [] -> Pat.var @@ Location.mknoloc "props"
| _ ->
Pat.constraint_
(Pat.var @@ Location.mknoloc "props")
(Typ.constr (Location.mknoloc @@ Lident "props") [Typ.any ()]))
(match coreTypeOfAttr with
| None -> makePropsPattern namedTypeList
| Some _ -> makePropsPattern typVarsOfCoreType)
(if hasForwardRef then
Exp.fun_ nolabel None
(Pat.var @@ Location.mknoloc "ref")
Expand Down Expand Up @@ -274090,8 +274233,15 @@ let transformStructureItem ~config mapper item =
(Pat.constraint_ recordPattern
(Typ.constr ~loc:emptyLoc
{txt = Lident "props"; loc = emptyLoc}
(makePropsTypeParams ~stripExplicitOption:true
~stripExplicitJsNullableOfRef:hasForwardRef namedTypeList)))
(match coreTypeOfAttr with
| None ->
makePropsTypeParams ~stripExplicitOption:true
~stripExplicitJsNullableOfRef:hasForwardRef
namedTypeList
| Some _ -> (
match typVarsOfCoreType with
| [] -> []
| _ -> [Typ.any ()]))))
expression
in
(* let make = ({id, name, ...}: props<'id, 'name, ...>) => { ... } *)
Expand Down Expand Up @@ -274167,6 +274317,12 @@ let transformSignatureItem ~config _mapper item =
check_string_int_attribute_iter.signature_item
check_string_int_attribute_iter item;
let hasForwardRef = ref false in
let coreTypeOfAttr = React_jsx_common.coreTypeOfAttrs pval_attributes in
let typVarsOfCoreType =
coreTypeOfAttr
|> Option.map React_jsx_common.typVarsOfCoreType
|> Option.value ~default:[]
in
let rec getPropTypes types ({ptyp_loc; ptyp_desc} as fullType) =
match ptyp_desc with
| Ptyp_arrow (name, type_, ({ptyp_desc = Ptyp_arrow _} as rest))
Expand All @@ -274189,10 +274345,16 @@ let transformSignatureItem ~config _mapper item =
let retPropsType =
Typ.constr
(Location.mkloc (Lident "props") psig_loc)
(makePropsTypeParams namedTypeList)
(match coreTypeOfAttr with
| None -> makePropsTypeParams namedTypeList
| Some _ -> (
match typVarsOfCoreType with
| [] -> []
| _ -> [Typ.any ()]))
in
let propsRecordType =
makePropsRecordTypeSig "props" psig_loc
makePropsRecordTypeSig ~coreTypeOfAttr ~typVarsOfCoreType "props"
psig_loc
((* If there is Nolabel arg, regard the type as ref in forwardRef *)
(if !hasForwardRef then [(true, "ref", [], refType Location.none)]
else [])
Expand Down Expand Up @@ -274301,24 +274463,22 @@ let expr ~config mapper expression =
Exp.ident ~loc {loc; txt = Ldot (Lident "React", "fragment")}
in
let childrenExpr = transformChildrenIfList ~mapper listItems in
let recordOfChildren children =
Exp.record [(Location.mknoloc (Lident "children"), children)] None
in
let args =
[
(nolabel, fragment);
(match config.mode with
| "automatic" ->
| "automatic" -> (
( nolabel,
Exp.record
[
( Location.mknoloc @@ Lident "children",
match childrenExpr with
| {pexp_desc = Pexp_array children} -> (
match children with
| [] -> emptyRecord ~loc:Location.none
| [child] -> child
| _ -> childrenExpr)
| _ -> childrenExpr );
]
None )
match childrenExpr with
| {pexp_desc = Pexp_array children} -> (
match children with
| [] -> emptyRecord ~loc:Location.none
| [child] -> recordOfChildren child
| _ -> recordOfChildren childrenExpr)
| _ -> recordOfChildren childrenExpr ))
| "classic" | _ -> (nolabel, childrenExpr));
]
in
Expand Down
Loading