-
Notifications
You must be signed in to change notification settings - Fork 470
Add loc to each props in JSX4 #5937
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
Changes from 9 commits
f0507b7
588acf8
13d148a
81f3dfd
12a59aa
ced073d
b825937
41382f7
10421cd
b19e8c9
b381364
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -242,9 +242,9 @@ let recordFromProps ~loc ~removeKey callArguments = | |
(* let make = ({id, name, children}: props<'id, 'name, 'children>) *) | ||
let makePropsTypeParamsTvar namedTypeList = | ||
namedTypeList | ||
|> List.filter_map (fun (_isOptional, label, _, _interiorType) -> | ||
|> List.filter_map (fun (_isOptional, label, _, loc, _interiorType) -> | ||
if label = "key" then None | ||
else Some (Typ.var @@ safeTypeFromValue (Labelled label))) | ||
else Some (Typ.var ~loc @@ safeTypeFromValue (Labelled label))) | ||
|
||
let stripOption coreType = | ||
match coreType with | ||
|
@@ -268,7 +268,7 @@ let stripJsNullable coreType = | |
let makePropsTypeParams ?(stripExplicitOption = false) | ||
?(stripExplicitJsNullableOfRef = false) namedTypeList = | ||
namedTypeList | ||
|> List.filter_map (fun (isOptional, label, _, interiorType) -> | ||
|> List.filter_map (fun (isOptional, label, _, loc, interiorType) -> | ||
if label = "key" then None | ||
(* TODO: Worth thinking how about "ref_" or "_ref" usages *) | ||
else if label = "ref" then | ||
|
@@ -277,7 +277,7 @@ let makePropsTypeParams ?(stripExplicitOption = false) | |
For example, if JSX ppx is used for React Native, type would be different. | ||
*) | ||
match interiorType with | ||
| {ptyp_desc = Ptyp_var "ref"} -> Some (refType Location.none) | ||
| {ptyp_desc = Ptyp_var "ref"} -> Some (refType loc) | ||
| _ -> | ||
(* Strip explicit Js.Nullable.t in case of forwardRef *) | ||
if stripExplicitJsNullableOfRef then stripJsNullable interiorType | ||
|
@@ -287,21 +287,44 @@ let makePropsTypeParams ?(stripExplicitOption = false) | |
else if isOptional && stripExplicitOption then stripOption interiorType | ||
else Some interiorType) | ||
|
||
let makeLabelDecls ~loc namedTypeList = | ||
namedTypeList | ||
|> List.map (fun (isOptional, label, attrs, interiorType) -> | ||
if label = "key" then | ||
Type.field ~loc ~attrs:(optionalAttrs @ attrs) {txt = label; loc} | ||
interiorType | ||
else if isOptional then | ||
Type.field ~loc ~attrs:(optionalAttrs @ attrs) {txt = label; loc} | ||
(Typ.var @@ safeTypeFromValue @@ Labelled label) | ||
else | ||
Type.field ~loc ~attrs {txt = label; loc} | ||
(Typ.var @@ safeTypeFromValue @@ Labelled label)) | ||
let makeLabelDecls namedTypeList = | ||
let rec mem_label ((_, la, _, _, _) as x) = function | ||
| [] -> false | ||
| (_, lb, _, _, _) :: l -> compare lb la = 0 || mem_label x l | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, it's way faster if one annotated that it's a string |
||
in | ||
let rec duplicated = function | ||
| [] -> None | ||
| hd :: tl -> if mem_label hd tl then Some hd else duplicated tl | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you throw an error right here, then you don't need anything else below. For perf, there are cases with several hundred props, in ReScript-react. This is quadratic, and happens only once when the big type is declared, but does not affect using the function. So I think it's OK. |
||
in | ||
(* Check if there are duplicated props in the namedTypeList without making list relocation. *) | ||
let duplicatedProp = namedTypeList |> duplicated in | ||
match duplicatedProp with | ||
| Some _ -> ( | ||
(* If there are duplicated props, then find the one from the last. *) | ||
let duplicatedPropAtLast = namedTypeList |> List.rev |> duplicated in | ||
match duplicatedPropAtLast with | ||
| Some (_, label, _, loc, _) -> | ||
React_jsx_common.raiseError ~loc "JSX: found the duplicated prop `%s`" | ||
label | ||
| None -> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic is a bit unclear. If one throws an error above as soon as a duplicate is found, then this logic is not needed at all. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The logics after duplicated fn are to look for the duplicated prop in backward. If we get a duplicated prop's label and loc, then we can show the error msg pointing the last one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think showing the first duplicated one is ok. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Otherwise, just reverse then iterate. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How does it look? b381364 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks great thanks. |
||
(* Never reach here *) | ||
React_jsx_common.raiseError ~loc:Location.none | ||
"JSX: found the duplicated prop") | ||
| None -> | ||
namedTypeList | ||
|> List.map (fun (isOptional, label, attrs, loc, interiorType) -> | ||
if label = "key" then | ||
Type.field ~loc ~attrs:(optionalAttrs @ attrs) {txt = label; loc} | ||
interiorType | ||
else if isOptional then | ||
Type.field ~loc ~attrs:(optionalAttrs @ attrs) {txt = label; loc} | ||
(Typ.var @@ safeTypeFromValue @@ Labelled label) | ||
else | ||
Type.field ~loc ~attrs {txt = label; loc} | ||
(Typ.var @@ safeTypeFromValue @@ Labelled label)) | ||
|
||
let makeTypeDecls propsName loc namedTypeList = | ||
let labelDeclList = makeLabelDecls ~loc namedTypeList in | ||
let labelDeclList = makeLabelDecls namedTypeList in | ||
(* 'id, 'className, ... *) | ||
let params = | ||
makePropsTypeParamsTvar namedTypeList | ||
|
@@ -702,17 +725,22 @@ let argToType ~newtypes ~(typeConstraints : core_type option) types | |
in | ||
match (type_, name, default) with | ||
| Some type_, name, _ when isOptional name -> | ||
(true, getLabel name, attrs, {type_ with ptyp_attributes = optionalAttrs}) | ||
( true, | ||
getLabel name, | ||
attrs, | ||
loc, | ||
{type_ with ptyp_attributes = optionalAttrs} ) | ||
:: types | ||
| Some type_, name, _ -> (false, getLabel name, attrs, type_) :: types | ||
| Some type_, name, _ -> (false, getLabel name, attrs, loc, type_) :: types | ||
| None, name, _ when isOptional name -> | ||
( true, | ||
getLabel name, | ||
attrs, | ||
loc, | ||
Typ.var ~loc ~attrs:optionalAttrs (safeTypeFromValue name) ) | ||
:: types | ||
| None, name, _ when isLabelled name -> | ||
(false, getLabel name, attrs, Typ.var ~loc (safeTypeFromValue name)) | ||
(false, getLabel name, attrs, loc, Typ.var ~loc (safeTypeFromValue name)) | ||
:: types | ||
| _ -> types | ||
|
||
|
@@ -721,10 +749,12 @@ let argWithDefaultValue (name, default, _, _, _, _) = | |
| Some default when isOptional name -> Some (getLabel name, default) | ||
| _ -> None | ||
|
||
let argToConcreteType types (name, attrs, _loc, type_) = | ||
let argToConcreteType types (name, attrs, loc, type_) = | ||
match name with | ||
| name when isLabelled name -> (false, getLabel name, attrs, type_) :: types | ||
| name when isOptional name -> (true, getLabel name, attrs, type_) :: types | ||
| name when isLabelled name -> | ||
(false, getLabel name, attrs, loc, type_) :: types | ||
| name when isOptional name -> | ||
(true, getLabel name, attrs, loc, type_) :: types | ||
| _ -> types | ||
|
||
let check_string_int_attribute_iter = | ||
|
@@ -1306,7 +1336,8 @@ let transformSignatureItem ~config _mapper item = | |
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)] | ||
(if !hasForwardRef then | ||
[(true, "ref", [], Location.none, refType Location.none)] | ||
else []) | ||
@ namedTypeList) | ||
in | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,7 @@ | ||
@@jsxConfig({version: 4, mode: "automatic"}) | ||
|
||
module C0 = { | ||
type props<'priority, 'text> = { | ||
priority: 'priority, | ||
text?: 'text, | ||
} | ||
type props<'priority, 'text> = {priority: 'priority, text?: 'text} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wonder why this PR change leads to remove the trailing comma. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably formatted differently now because of the loc changes. |
||
|
||
@react.component | ||
let make = ({priority: _, ?text, _}: props<'priority, 'text>) => { | ||
|
@@ -23,10 +20,7 @@ module C0 = { | |
} | ||
|
||
module C1 = { | ||
type props<'priority, 'text> = { | ||
priority: 'priority, | ||
text?: 'text, | ||
} | ||
type props<'priority, 'text> = {priority: 'priority, text?: 'text} | ||
|
||
@react.component | ||
let make = ({priority: p, ?text, _}: props<'priority, 'text>) => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,2 @@ | ||
type props<'x, 'ref> = { | ||
x: 'x, | ||
ref?: 'ref, | ||
} | ||
type props<'x, 'ref> = {x: 'x, ref?: 'ref} | ||
let make: React.componentLike<props<string, ReactDOM.Ref.currentDomRef>, React.element> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is not needed anymore right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, I will revert it.