Skip to content

Commit a4132f5

Browse files
Andaristiisaduan
andauthored
Port JSX fragment checking changes (#1053)
Co-authored-by: Isabel Duan <[email protected]>
1 parent 14e44b1 commit a4132f5

10 files changed

+272
-172
lines changed

internal/ast/utilities.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2774,9 +2774,19 @@ func GetLanguageVariant(scriptKind core.ScriptKind) core.LanguageVariant {
27742774

27752775
func IsCallLikeExpression(node *Node) bool {
27762776
switch node.Kind {
2777-
case KindJsxOpeningElement, KindJsxSelfClosingElement, KindCallExpression, KindNewExpression,
2777+
case KindJsxOpeningElement, KindJsxSelfClosingElement, KindJsxOpeningFragment, KindCallExpression, KindNewExpression,
27782778
KindTaggedTemplateExpression, KindDecorator:
27792779
return true
2780+
case KindBinaryExpression:
2781+
return node.AsBinaryExpression().OperatorToken.Kind == KindInstanceOfKeyword
2782+
}
2783+
return false
2784+
}
2785+
2786+
func IsJsxCallLike(node *Node) bool {
2787+
switch node.Kind {
2788+
case KindJsxOpeningElement, KindJsxSelfClosingElement, KindJsxOpeningFragment:
2789+
return true
27802790
}
27812791
return false
27822792
}
@@ -3422,6 +3432,8 @@ func GetInvokedExpression(node *Node) *Node {
34223432
return node.TagName()
34233433
case KindBinaryExpression:
34243434
return node.AsBinaryExpression().Right
3435+
case KindJsxOpeningFragment:
3436+
return node
34253437
default:
34263438
return node.Expression()
34273439
}

internal/checker/checker.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ type Checker struct {
701701
permissiveMapper *TypeMapper
702702
emptyObjectType *Type
703703
emptyJsxObjectType *Type
704+
emptyFreshJsxObjectType *Type
704705
emptyTypeLiteralType *Type
705706
unknownEmptyObjectType *Type
706707
unknownUnionType *Type
@@ -967,6 +968,7 @@ func NewChecker(program Program) *Checker {
967968
c.permissiveMapper = newFunctionTypeMapper(c.permissiveMapperWorker)
968969
c.emptyObjectType = c.newAnonymousType(nil /*symbol*/, nil, nil, nil, nil)
969970
c.emptyJsxObjectType = c.newAnonymousType(nil /*symbol*/, nil, nil, nil, nil)
971+
c.emptyFreshJsxObjectType = c.newAnonymousType(nil /*symbol*/, nil, nil, nil, nil)
970972
c.emptyTypeLiteralType = c.newAnonymousType(c.newSymbol(ast.SymbolFlagsTypeLiteral, ast.InternalSymbolNameType), nil, nil, nil, nil)
971973
c.unknownEmptyObjectType = c.newAnonymousType(nil /*symbol*/, nil, nil, nil, nil)
972974
c.unknownUnionType = c.createUnknownUnionType()
@@ -8057,7 +8059,7 @@ func (c *Checker) resolveSignature(node *ast.Node, candidatesOutArray *[]*Signat
80578059
return c.resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode)
80588060
case ast.KindDecorator:
80598061
return c.resolveDecorator(node, candidatesOutArray, checkMode)
8060-
case ast.KindJsxOpeningElement, ast.KindJsxSelfClosingElement:
8062+
case ast.KindJsxOpeningFragment, ast.KindJsxOpeningElement, ast.KindJsxSelfClosingElement:
80618063
return c.resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode)
80628064
case ast.KindBinaryExpression:
80638065
return c.resolveInstanceofExpression(node, candidatesOutArray, checkMode)
@@ -8435,7 +8437,7 @@ func (c *Checker) resolveCall(node *ast.Node, signatures []*Signature, candidate
84358437
reportErrors := !c.isInferencePartiallyBlocked && candidatesOutArray == nil
84368438
var s CallState
84378439
s.node = node
8438-
if !isDecorator && !isInstanceof && !isSuperCall(node) {
8440+
if !isDecorator && !isInstanceof && !isSuperCall(node) && !ast.IsJsxOpeningFragment(node) {
84398441
s.typeArguments = node.TypeArguments()
84408442
// We already perform checking on the type arguments on the class declaration itself.
84418443
if isTaggedTemplate || isJsxOpeningOrSelfClosingElement || node.Expression().Kind != ast.KindSuperKeyword {
@@ -8529,7 +8531,7 @@ func (c *Checker) resolveCall(node *ast.Node, signatures []*Signature, candidate
85298531
if headMessage == nil && isInstanceof {
85308532
headMessage = diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_assignable_to_the_first_argument_of_the_right_hand_side_s_Symbol_hasInstance_method
85318533
}
8532-
c.reportCallResolutionErrors(&s, signatures, headMessage)
8534+
c.reportCallResolutionErrors(node, &s, signatures, headMessage)
85338535
}
85348536
return result
85358537
}
@@ -8711,6 +8713,9 @@ func (c *Checker) getImplementationSignature(signature *Signature) *Signature {
87118713
}
87128714

87138715
func (c *Checker) hasCorrectArity(node *ast.Node, args []*ast.Node, signature *Signature, signatureHelpTrailingComma bool) bool {
8716+
if ast.IsJsxOpeningFragment(node) {
8717+
return true
8718+
}
87148719
var argCount int
87158720
callIsIncomplete := false
87168721
// In incomplete call we want to be lenient when we have too few arguments
@@ -8856,8 +8861,8 @@ func (c *Checker) checkTypeArguments(signature *Signature, typeArgumentNodes []*
88568861
}
88578862

88588863
func (c *Checker) isSignatureApplicable(node *ast.Node, args []*ast.Node, signature *Signature, relation *Relation, checkMode CheckMode, reportErrors bool, inferenceContext *InferenceContext, diagnosticOutput *[]*ast.Diagnostic) bool {
8859-
if ast.IsJsxOpeningLikeElement(node) {
8860-
return c.checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors, diagnosticOutput)
8864+
if ast.IsJsxCallLike(node) {
8865+
return c.checkApplicableSignatureForJsxCallLikeElement(node, signature, relation, checkMode, reportErrors, diagnosticOutput)
88618866
}
88628867
thisType := c.getThisTypeOfSignature(signature)
88638868
if thisType != nil && thisType != c.voidType && !(ast.IsNewExpression(node) || ast.IsCallExpression(node) && isSuperProperty(node.Expression())) {
@@ -9251,7 +9256,7 @@ func (c *Checker) tryGetRestTypeOfSignature(signature *Signature) *Type {
92519256
return c.getIndexTypeOfType(restType, c.numberType)
92529257
}
92539258

9254-
func (c *Checker) reportCallResolutionErrors(s *CallState, signatures []*Signature, headMessage *diagnostics.Message) {
9259+
func (c *Checker) reportCallResolutionErrors(node *ast.Node, s *CallState, signatures []*Signature, headMessage *diagnostics.Message) {
92559260
switch {
92569261
case len(s.candidatesForArgumentError) != 0:
92579262
last := s.candidatesForArgumentError[len(s.candidatesForArgumentError)-1]
@@ -9275,7 +9280,7 @@ func (c *Checker) reportCallResolutionErrors(s *CallState, signatures []*Signatu
92759280
c.diagnostics.Add(c.getArgumentArityError(s.node, []*Signature{s.candidateForArgumentArityError}, s.args, headMessage))
92769281
case s.candidateForTypeArgumentError != nil:
92779282
c.checkTypeArguments(s.candidateForTypeArgumentError, s.node.TypeArguments(), true /*reportErrors*/, headMessage)
9278-
default:
9283+
case !ast.IsJsxOpeningFragment(node):
92799284
signaturesWithCorrectTypeArgumentArity := core.Filter(signatures, func(sig *Signature) bool {
92809285
return c.hasCorrectTypeArgumentArity(sig, s.typeArguments)
92819286
})
@@ -26940,10 +26945,15 @@ func (c *Checker) markJsxAliasReferenced(node *ast.Node /*JsxOpeningLikeElement
2694026945
if ast.IsJsxOpeningLikeElement(node) {
2694126946
jsxFactoryLocation = node.TagName()
2694226947
}
26943-
// allow null as jsxFragmentFactory
26948+
shouldFactoryRefErr := c.compilerOptions.Jsx != core.JsxEmitPreserve && c.compilerOptions.Jsx != core.JsxEmitReactNative
26949+
// #38720/60122, allow null as jsxFragmentFactory
2694426950
var jsxFactorySym *ast.Symbol
2694526951
if !(ast.IsJsxOpeningFragment(node) && jsxFactoryNamespace == "null") {
26946-
jsxFactorySym = c.resolveName(jsxFactoryLocation, jsxFactoryNamespace, ast.SymbolFlagsValue, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/)
26952+
flags := ast.SymbolFlagsValue
26953+
if !shouldFactoryRefErr {
26954+
flags &= ^ast.SymbolFlagsEnum
26955+
}
26956+
jsxFactorySym = c.resolveName(jsxFactoryLocation, jsxFactoryNamespace, flags, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/)
2694726957
}
2694826958
if jsxFactorySym != nil {
2694926959
// Mark local symbol as referenced here because it might not have been marked
@@ -26954,12 +26964,16 @@ func (c *Checker) markJsxAliasReferenced(node *ast.Node /*JsxOpeningLikeElement
2695426964
c.markAliasSymbolAsReferenced(jsxFactorySym)
2695526965
}
2695626966
}
26957-
// For JsxFragment, mark jsx pragma as referenced via resolveName
26967+
// if JsxFragment, additionally mark jsx pragma as referenced, since `getJsxNamespace` above would have resolved to only the fragment factory if they are distinct
2695826968
if ast.IsJsxOpeningFragment(node) {
2695926969
file := ast.GetSourceFileOfNode(node)
2696026970
localJsxNamespace := c.getLocalJsxNamespace(file)
2696126971
if localJsxNamespace != "" {
26962-
c.resolveName(jsxFactoryLocation, localJsxNamespace, ast.SymbolFlagsValue, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/)
26972+
flags := ast.SymbolFlagsValue
26973+
if !shouldFactoryRefErr {
26974+
flags &= ^ast.SymbolFlagsEnum
26975+
}
26976+
c.resolveName(jsxFactoryLocation, localJsxNamespace, flags, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/)
2696326977
}
2696426978
}
2696526979
}
@@ -28218,6 +28232,9 @@ func (c *Checker) getContextualImportAttributeType(node *ast.Node) *Type {
2821828232
// Returns the effective arguments for an expression that works like a function invocation.
2821928233
func (c *Checker) getEffectiveCallArguments(node *ast.Node) []*ast.Node {
2822028234
switch {
28235+
case ast.IsJsxOpeningFragment(node):
28236+
// This attributes Type does not include a children property yet, the same way a fragment created with <React.Fragment> does not at this stage
28237+
return []*ast.Node{c.createSyntheticExpression(node, c.emptyFreshJsxObjectType, false, nil)}
2822128238
case ast.IsTaggedTemplateExpression(node):
2822228239
template := node.AsTaggedTemplateExpression().Template
2822328240
firstArg := c.createSyntheticExpression(template, c.getGlobalTemplateStringsArrayType(), false, nil)

0 commit comments

Comments
 (0)