From b22a6714c9cbf4f11e01c1af21533a165c8836f8 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 2 May 2023 11:43:47 -0700 Subject: [PATCH] JSX namespace names should not be considered expressions --- src/compiler/checker.ts | 23 +++++++++++++++---- src/compiler/emitter.ts | 15 ++++++++---- src/compiler/parser.ts | 12 ++++++---- src/compiler/types.ts | 14 +++++------ src/compiler/utilities.ts | 22 ++++++++++++------ src/compiler/utilitiesPublic.ts | 1 - src/services/signatureHelp.ts | 3 ++- src/services/utilities.ts | 3 ++- .../reference/api/tsserverlibrary.d.ts | 8 +++---- tests/baselines/reference/api/typescript.d.ts | 8 +++---- ...NamespaceNamesQuestionableForms.errors.txt | 17 ++++++++++---- ...checkJsxNamespaceNamesQuestionableForms.js | 3 ++- ...JsxNamespaceNamesQuestionableForms.symbols | 2 ++ ...ckJsxNamespaceNamesQuestionableForms.types | 8 +++---- .../jsxInvalidEsprimaTestSuite.errors.txt | 17 ++++++++++---- .../reference/jsxInvalidEsprimaTestSuite.js | 3 ++- .../jsxInvalidEsprimaTestSuite.symbols | 3 ++- .../jsxInvalidEsprimaTestSuite.types | 8 +++---- ...eNotComparedToNonMatchingIndexSignature.js | 16 +++++++++++++ ...omparedToNonMatchingIndexSignature.symbols | 23 +++++++++++++++++++ ...tComparedToNonMatchingIndexSignature.types | 23 +++++++++++++++++++ ...NotComparedToNonMatchingIndexSignature.tsx | 12 ++++++++++ 22 files changed, 186 insertions(+), 58 deletions(-) create mode 100644 tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.js create mode 100644 tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.symbols create mode 100644 tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.types create mode 100644 tests/cases/compiler/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1bb5c6a297765..0da35600a6087 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -776,6 +776,7 @@ import { JSDocVariadicType, JsxAttribute, JsxAttributeLike, + JsxAttributeName, JsxAttributes, JsxChild, JsxClosingElement, @@ -17006,19 +17007,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getLiteralTypeFromPropertyName(name: PropertyName) { + function getLiteralTypeFromPropertyName(name: PropertyName | JsxAttributeName) { if (isPrivateIdentifier(name)) { return neverType; } - return isIdentifier(name) ? getStringLiteralType(unescapeLeadingUnderscores(name.escapedText)) : - getRegularTypeOfLiteralType(isComputedPropertyName(name) ? checkComputedPropertyName(name) : checkExpression(name)); + if (isNumericLiteral(name)) { + return getRegularTypeOfLiteralType(checkExpression(name)); + } + if (isComputedPropertyName(name)) { + return getRegularTypeOfLiteralType(checkComputedPropertyName(name)); + } + const propertyName = getPropertyNameForPropertyNameNode(name); + if (propertyName !== undefined) { + return getStringLiteralType(unescapeLeadingUnderscores(propertyName)); + } + if (isExpression(name)) { + return getRegularTypeOfLiteralType(checkExpression(name)); + } + return neverType; } function getLiteralTypeFromProperty(prop: Symbol, include: TypeFlags, includeNonPublic?: boolean) { if (includeNonPublic || !(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier)) { let type = getSymbolLinks(getLateBoundSymbol(prop)).nameType; if (!type) { - const name = getNameOfDeclaration(prop.valueDeclaration) as PropertyName; + const name = getNameOfDeclaration(prop.valueDeclaration) as PropertyName | JsxAttributeName; type = prop.escapedName === InternalSymbolName.Default ? getStringLiteralType("default") : name && getLiteralTypeFromPropertyName(name) || (!isKnownSymbol(prop) ? getStringLiteralType(symbolName(prop)) : undefined); } @@ -32621,7 +32634,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (getJsxNamespaceContainerForImplicitImport(node)) { return true; // factory is implicitly jsx/jsxdev - assume it fits the bill, since we don't strongly look for the jsx/jsxs/jsxDEV factory APIs anywhere else (at least not yet) } - const tagType = isJsxOpeningElement(node) || isJsxSelfClosingElement(node) && !isJsxIntrinsicTagName(node.tagName) ? checkExpression(node.tagName) : undefined; + const tagType = (isJsxOpeningElement(node) || isJsxSelfClosingElement(node)) && !(isJsxIntrinsicTagName(node.tagName) || isJsxNamespacedName(node.tagName)) ? checkExpression(node.tagName) : undefined; if (!tagType) { return true; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index da4f3f56fa5e7..6f34ec688fc63 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -179,6 +179,7 @@ import { getSyntheticLeadingComments, getSyntheticTrailingComments, getTextOfJSDocComment, + getTextOfJsxNamespacedName, getTrailingCommentRanges, getTrailingSemicolonDeferringWriter, getTransformers, @@ -228,6 +229,7 @@ import { isJSDocLikeText, isJsonSourceFile, isJsxClosingElement, + isJsxNamespacedName, isJsxOpeningElement, isKeyword, isLet, @@ -2066,6 +2068,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return emitJsxSpreadAttribute(node as JsxSpreadAttribute); case SyntaxKind.JsxExpression: return emitJsxExpression(node as JsxExpression); + case SyntaxKind.JsxNamespacedName: + return emitJsxNamespacedName(node as JsxNamespacedName); // Clauses case SyntaxKind.CaseClause: @@ -2283,8 +2287,6 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return emitJsxSelfClosingElement(node as JsxSelfClosingElement); case SyntaxKind.JsxFragment: return emitJsxFragment(node as JsxFragment); - case SyntaxKind.JsxNamespacedName: - return emitJsxNamespacedName(node as JsxNamespacedName); // Synthesized list case SyntaxKind.SyntaxList: @@ -5528,7 +5530,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return node; } - function getTextOfNode(node: Identifier | PrivateIdentifier | LiteralExpression, includeTrivia?: boolean): string { + function getTextOfNode(node: Identifier | PrivateIdentifier | LiteralExpression | JsxNamespacedName, includeTrivia?: boolean): string { if (isGeneratedIdentifier(node) || isGeneratedPrivateIdentifier(node)) { return generateName(node); } @@ -5542,6 +5544,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return idText(node); } } + else if (isJsxNamespacedName(node)) { + if (!canUseSourceFile || getSourceFileOfNode(node) !== getOriginalNode(sourceFile)) { + return getTextOfJsxNamespacedName(node); + } + } else { Debug.assertNode(node, isLiteralExpression); // not strictly necessary if (!canUseSourceFile) { @@ -5554,7 +5561,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined, jsxAttributeEscape: boolean): string { if (node.kind === SyntaxKind.StringLiteral && (node as StringLiteral).textSourceNode) { const textSourceNode = (node as StringLiteral).textSourceNode!; - if (isIdentifier(textSourceNode) || isPrivateIdentifier(textSourceNode) || isNumericLiteral(textSourceNode)) { + if (isIdentifier(textSourceNode) || isPrivateIdentifier(textSourceNode) || isNumericLiteral(textSourceNode) || isJsxNamespacedName(textSourceNode)) { const text = isNumericLiteral(textSourceNode) ? textSourceNode.text : getTextOfNode(textSourceNode); return jsxAttributeEscape ? `"${escapeJsxAttributeString(text)}"` : neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? `"${escapeString(text)}"` : diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index fb31e3dbdc518..0b3e415f1193d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -147,6 +147,7 @@ import { isJSDocNullableType, isJSDocReturnTag, isJSDocTypeTag, + isJsxNamespacedName, isJsxOpeningElement, isJsxOpeningFragment, isKeyword, @@ -228,7 +229,6 @@ import { JsxSelfClosingElement, JsxSpreadAttribute, JsxTagNameExpression, - JsxTagNamePropertyAccess, JsxText, JsxTokenSyntaxKind, LabeledStatement, @@ -6112,11 +6112,15 @@ namespace Parser { // primaryExpression in the form of an identifier and "this" keyword // We can't just simply use parseLeftHandSideExpressionOrHigher because then we will start consider class,function etc as a keyword // We only want to consider "this" as a primaryExpression - let expression: JsxTagNameExpression = parseJsxTagName(); + const initialExpression = parseJsxTagName(); + if (isJsxNamespacedName(initialExpression)) { + return initialExpression; // `a:b.c` is invalid syntax, don't even look for the `.` if we parse `a:b`, and let `parseAttribute` report "unexpected :" instead. + } + let expression: PropertyAccessExpression | Identifier | ThisExpression = initialExpression; while (parseOptional(SyntaxKind.DotToken)) { - expression = finishNode(factoryCreatePropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false)), pos) as JsxTagNamePropertyAccess; + expression = finishNode(factoryCreatePropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false)), pos); } - return expression; + return expression as JsxTagNameExpression; } function parseJsxTagName(): Identifier | JsxNamespacedName | ThisExpression { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c97bbaffa2834..dd25737a4c575 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1722,11 +1722,9 @@ export type PropertyName = Identifier | StringLiteral | NumericLiteral | Compute export type MemberName = Identifier | PrivateIdentifier; export type DeclarationName = - | Identifier - | PrivateIdentifier + | PropertyName + | JsxAttributeName | StringLiteralLike - | NumericLiteral - | ComputedPropertyName | ElementAccessExpression | BindingPattern | EntityNameExpression; @@ -2332,7 +2330,7 @@ export interface LiteralTypeNode extends TypeNode { export interface StringLiteral extends LiteralExpression, Declaration { readonly kind: SyntaxKind.StringLiteral; - /** @internal */ readonly textSourceNode?: Identifier | StringLiteralLike | NumericLiteral | PrivateIdentifier; // Allows a StringLiteral to get its text from another node (used by transforms). + /** @internal */ readonly textSourceNode?: Identifier | StringLiteralLike | NumericLiteral | PrivateIdentifier | JsxNamespacedName; // Allows a StringLiteral to get its text from another node (used by transforms). /** * Note: this is only set when synthesizing a node, not during parsing. * @@ -2342,7 +2340,7 @@ export interface StringLiteral extends LiteralExpression, Declaration { } export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral; -export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; +export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName; export interface TemplateLiteralTypeNode extends TypeNode { kind: SyntaxKind.TemplateLiteralType, @@ -3191,7 +3189,7 @@ export type JsxTagNameExpression = ; export interface JsxTagNamePropertyAccess extends PropertyAccessExpression { - readonly expression: JsxTagNameExpression; + readonly expression: Identifier | ThisExpression | JsxTagNamePropertyAccess; } export interface JsxAttributes extends PrimaryExpression, Declaration { @@ -3200,7 +3198,7 @@ export interface JsxAttributes extends PrimaryExpression, Declaration { readonly parent: JsxOpeningLikeElement; } -export interface JsxNamespacedName extends PrimaryExpression { +export interface JsxNamespacedName extends Node { readonly kind: SyntaxKind.JsxNamespacedName; readonly name: Identifier; readonly namespace: Identifier; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index fde771ab80db5..c6ac49373efb3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -293,6 +293,7 @@ import { isJSDocTypeTag, isJsxChild, isJsxFragment, + isJsxNamespacedName, isJsxOpeningLikeElement, isJsxText, isLeftHandSideExpression, @@ -2024,7 +2025,7 @@ export function isComputedNonLiteralName(name: PropertyName): boolean { } /** @internal */ -export function tryGetTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral): __String | undefined { +export function tryGetTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral | JsxAttributeName): __String | undefined { switch (name.kind) { case SyntaxKind.Identifier: case SyntaxKind.PrivateIdentifier: @@ -2036,13 +2037,15 @@ export function tryGetTextOfPropertyName(name: PropertyName | NoSubstitutionTemp case SyntaxKind.ComputedPropertyName: if (isStringOrNumericLiteralLike(name.expression)) return escapeLeadingUnderscores(name.expression.text); return undefined; + case SyntaxKind.JsxNamespacedName: + return getEscapedTextOfJsxNamespacedName(name); default: return Debug.assertNever(name); } } /** @internal */ -export function getTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral): __String { +export function getTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral | JsxAttributeName): __String { return Debug.checkDefined(tryGetTextOfPropertyName(name)); } @@ -3074,7 +3077,7 @@ export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNam } /** @internal */ -export function getInvokedExpression(node: CallLikeExpression): Expression { +export function getInvokedExpression(node: CallLikeExpression): Expression | JsxTagNameExpression { switch (node.kind) { case SyntaxKind.TaggedTemplateExpression: return node.tag; @@ -4954,7 +4957,7 @@ export function isDynamicName(name: DeclarationName): boolean { } /** @internal */ -export function getPropertyNameForPropertyNameNode(name: PropertyName): __String | undefined { +export function getPropertyNameForPropertyNameNode(name: PropertyName | JsxAttributeName): __String | undefined { switch (name.kind) { case SyntaxKind.Identifier: case SyntaxKind.PrivateIdentifier: @@ -4974,6 +4977,8 @@ export function getPropertyNameForPropertyNameNode(name: PropertyName): __String return nameExpression.operand.text as __String; } return undefined; + case SyntaxKind.JsxNamespacedName: + return getEscapedTextOfJsxNamespacedName(name); default: return Debug.assertNever(name); } @@ -4993,12 +4998,12 @@ export function isPropertyNameLiteral(node: Node): node is PropertyNameLiteral { } /** @internal */ export function getTextOfIdentifierOrLiteral(node: PropertyNameLiteral | PrivateIdentifier): string { - return isMemberName(node) ? idText(node) : node.text; + return isMemberName(node) ? idText(node) : isJsxNamespacedName(node) ? getTextOfJsxNamespacedName(node) : node.text; } /** @internal */ export function getEscapedTextOfIdentifierOrLiteral(node: PropertyNameLiteral): __String { - return isMemberName(node) ? node.escapedText : escapeLeadingUnderscores(node.text); + return isMemberName(node) ? node.escapedText : isJsxNamespacedName(node) ? getEscapedTextOfJsxNamespacedName(node) : escapeLeadingUnderscores(node.text); } /** @internal */ @@ -7025,7 +7030,7 @@ export function isPropertyAccessEntityNameExpression(node: Node): node is Proper } /** @internal */ -export function tryGetPropertyAccessOrIdentifierToString(expr: Expression): string | undefined { +export function tryGetPropertyAccessOrIdentifierToString(expr: Expression | JsxTagNameExpression): string | undefined { if (isPropertyAccessExpression(expr)) { const baseStr = tryGetPropertyAccessOrIdentifierToString(expr.expression); if (baseStr !== undefined) { @@ -7041,6 +7046,9 @@ export function tryGetPropertyAccessOrIdentifierToString(expr: Expression): stri else if (isIdentifier(expr)) { return unescapeLeadingUnderscores(expr.escapedText); } + else if (isJsxNamespacedName(expr)) { + return getTextOfJsxNamespacedName(expr); + } return undefined; } diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 3767bcc3f1118..4d0220bdf4308 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -1941,7 +1941,6 @@ function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean { case SyntaxKind.JsxElement: case SyntaxKind.JsxSelfClosingElement: case SyntaxKind.JsxFragment: - case SyntaxKind.JsxNamespacedName: case SyntaxKind.TaggedTemplateExpression: case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.ParenthesizedExpression: diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index e5a48acc64076..9d3c350943987 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -55,6 +55,7 @@ import { isTemplateSpan, isTemplateTail, isTransientSymbol, + JsxTagNameExpression, last, lastOrUndefined, ListFormat, @@ -599,7 +600,7 @@ function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, return children[indexOfOpenerToken + 1]; } -function getExpressionFromInvocation(invocation: CallInvocation | TypeArgsInvocation): Expression { +function getExpressionFromInvocation(invocation: CallInvocation | TypeArgsInvocation): Expression | JsxTagNameExpression { return invocation.kind === InvocationKind.Call ? getInvokedExpression(invocation.node) : invocation.called; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index d7c8149609b0c..be896d9d5ca4a 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -261,6 +261,7 @@ import { JsTyping, JsxEmit, JsxOpeningLikeElement, + JsxTagNameExpression, LabeledStatement, LanguageServiceHost, last, @@ -617,7 +618,7 @@ function selectTagNameOfJsxOpeningLikeElement(node: JsxOpeningLikeElement) { return node.tagName; } -function isCalleeWorker(node: Node, pred: (node: Node) => node is T, calleeSelector: (node: T) => Expression, includeElementAccess: boolean, skipPastOuterExpressions: boolean) { +function isCalleeWorker(node: Node, pred: (node: Node) => node is T, calleeSelector: (node: T) => Expression | JsxTagNameExpression, includeElementAccess: boolean, skipPastOuterExpressions: boolean) { let target = includeElementAccess ? climbPastPropertyOrElementAccess(node) : climbPastPropertyAccess(node); if (skipPastOuterExpressions) { target = skipOuterExpressions(target); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ee5fed651ed51..870d881644902 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4691,7 +4691,7 @@ declare namespace ts { type EntityName = Identifier | QualifiedName; type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier; type MemberName = Identifier | PrivateIdentifier; - type DeclarationName = Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern | EntityNameExpression; + type DeclarationName = PropertyName | JsxAttributeName | StringLiteralLike | ElementAccessExpression | BindingPattern | EntityNameExpression; interface Declaration extends Node { _declarationBrand: any; } @@ -5038,7 +5038,7 @@ declare namespace ts { readonly kind: SyntaxKind.StringLiteral; } type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral; - type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; + type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName; interface TemplateLiteralTypeNode extends TypeNode { kind: SyntaxKind.TemplateLiteralType; readonly head: TemplateHead; @@ -5397,14 +5397,14 @@ declare namespace ts { type JsxAttributeName = Identifier | JsxNamespacedName; type JsxTagNameExpression = Identifier | ThisExpression | JsxTagNamePropertyAccess | JsxNamespacedName; interface JsxTagNamePropertyAccess extends PropertyAccessExpression { - readonly expression: JsxTagNameExpression; + readonly expression: Identifier | ThisExpression | JsxTagNamePropertyAccess; } interface JsxAttributes extends PrimaryExpression, Declaration { readonly properties: NodeArray; readonly kind: SyntaxKind.JsxAttributes; readonly parent: JsxOpeningLikeElement; } - interface JsxNamespacedName extends PrimaryExpression { + interface JsxNamespacedName extends Node { readonly kind: SyntaxKind.JsxNamespacedName; readonly name: Identifier; readonly namespace: Identifier; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index debe70be3206c..862560ba05a7d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -644,7 +644,7 @@ declare namespace ts { type EntityName = Identifier | QualifiedName; type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier; type MemberName = Identifier | PrivateIdentifier; - type DeclarationName = Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern | EntityNameExpression; + type DeclarationName = PropertyName | JsxAttributeName | StringLiteralLike | ElementAccessExpression | BindingPattern | EntityNameExpression; interface Declaration extends Node { _declarationBrand: any; } @@ -991,7 +991,7 @@ declare namespace ts { readonly kind: SyntaxKind.StringLiteral; } type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral; - type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; + type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName; interface TemplateLiteralTypeNode extends TypeNode { kind: SyntaxKind.TemplateLiteralType; readonly head: TemplateHead; @@ -1350,14 +1350,14 @@ declare namespace ts { type JsxAttributeName = Identifier | JsxNamespacedName; type JsxTagNameExpression = Identifier | ThisExpression | JsxTagNamePropertyAccess | JsxNamespacedName; interface JsxTagNamePropertyAccess extends PropertyAccessExpression { - readonly expression: JsxTagNameExpression; + readonly expression: Identifier | ThisExpression | JsxTagNamePropertyAccess; } interface JsxAttributes extends PrimaryExpression, Declaration { readonly properties: NodeArray; readonly kind: SyntaxKind.JsxAttributes; readonly parent: JsxOpeningLikeElement; } - interface JsxNamespacedName extends PrimaryExpression { + interface JsxNamespacedName extends Node { readonly kind: SyntaxKind.JsxNamespacedName; readonly name: Identifier; readonly namespace: Identifier; diff --git a/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.errors.txt b/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.errors.txt index 55a28e9330031..e28775c6cedbd 100644 --- a/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.errors.txt +++ b/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.errors.txt @@ -1,7 +1,10 @@ -tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,2): error TS2633: JSX property access expressions cannot include JSX namespace names +tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,5): error TS1003: Identifier expected. +tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,13): error TS1005: '>' expected. +tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,14): error TS2304: Cannot find name 'x'. +tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,16): error TS1109: Expression expected. -==== tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx (1 errors) ==== +==== tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx (4 errors) ==== declare namespace JSX { interface IntrinsicElements { 'this:b': any; @@ -14,6 +17,12 @@ tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,2): e ; ; - ~~~ -!!! error TS2633: JSX property access expressions cannot include JSX namespace names + ~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: '>' expected. + ~ +!!! error TS2304: Cannot find name 'x'. + ~ +!!! error TS1109: Expression expected. ; \ No newline at end of file diff --git a/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.js b/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.js index 6189a8f9d78c8..c523d4cf657ed 100644 --- a/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.js +++ b/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.js @@ -15,5 +15,6 @@ declare namespace JSX { //// [checkJsxNamespaceNamesQuestionableForms.jsx] ; -; +; +x > ; ; diff --git a/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.symbols b/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.symbols index 9f2a5cb77ceef..fce449b99ec07 100644 --- a/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.symbols +++ b/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.symbols @@ -22,4 +22,6 @@ declare namespace JSX { ; ; +>x : Symbol(x, Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 11, 5)) + ; diff --git a/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.types b/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.types index ea6728210b671..c031735d567bb 100644 --- a/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.types +++ b/tests/baselines/reference/checkJsxNamespaceNamesQuestionableForms.types @@ -24,15 +24,15 @@ declare namespace JSX { >b : any ; -> : any ->b:c.x : any +>b : any >c : any ->x : any ->b:c.x : any +>x : true >b : any >c : any +>x> : boolean >x : any +> : any ; > : any diff --git a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt index f332ade0a3d52..e45de4c04c971 100644 --- a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt +++ b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt @@ -74,7 +74,10 @@ tests/cases/conformance/jsx/5.tsx(1,5): error TS1005: '' expected. +tests/cases/conformance/jsx/9.tsx(1,14): error TS2304: Cannot find name 'c'. +tests/cases/conformance/jsx/9.tsx(1,16): error TS1109: Expression expected. ==== tests/cases/conformance/jsx/1.tsx (3 errors) ==== @@ -125,10 +128,16 @@ tests/cases/conformance/jsx/9.tsx(1,2): error TS2633: JSX property access expres ; ~ !!! error TS17002: Expected corresponding JSX closing tag for 'a:b'. -==== tests/cases/conformance/jsx/9.tsx (1 errors) ==== +==== tests/cases/conformance/jsx/9.tsx (4 errors) ==== ; - ~~~ -!!! error TS2633: JSX property access expressions cannot include JSX namespace names + ~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: '>' expected. + ~ +!!! error TS2304: Cannot find name 'c'. + ~ +!!! error TS1109: Expression expected. ==== tests/cases/conformance/jsx/10.tsx (6 errors) ==== ; ~ diff --git a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js index 8c1d7dea1c27c..be3f6cdf424f4 100644 --- a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js +++ b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js @@ -92,7 +92,8 @@ a / > ; //// [8.jsx] ; //// [9.jsx] -; +; +c > ; //// [10.jsx] ; c > ; diff --git a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.symbols b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.symbols index b3363ce0ef4aa..68db01b40500b 100644 --- a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.symbols +++ b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.symbols @@ -28,8 +28,9 @@ declare var React: any; ; === tests/cases/conformance/jsx/9.tsx === - ; +>c : Symbol(c, Decl(9.tsx, 0, 5)) + === tests/cases/conformance/jsx/10.tsx === ; >c : Symbol(c, Decl(10.tsx, 0, 5)) diff --git a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.types b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.types index e3bb4ff69559f..2aeb5e436858b 100644 --- a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.types +++ b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.types @@ -58,15 +58,15 @@ declare var React: any; === tests/cases/conformance/jsx/9.tsx === ; -> : any ->a:b.c : any +>a : any >b : any ->c : any ->a:b.c : any +>c : true >a : any >b : any +>c> : boolean >c : any +> : any === tests/cases/conformance/jsx/10.tsx === ; diff --git a/tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.js b/tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.js new file mode 100644 index 0000000000000..4118c9ea70e77 --- /dev/null +++ b/tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.js @@ -0,0 +1,16 @@ +//// [jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx] +/// + +declare module "react" { + interface Attributes { + [key: `do-${string}`]: Function; + "ns:thing"?: string; + } +} + +export const tag =
+ +//// [jsxNamespacedNameNotComparedToNonMatchingIndexSignature.js] +import { jsx as _jsx } from "react/jsx-runtime"; +/// +export const tag = _jsx("div", { "ns:thing": "a" }); diff --git a/tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.symbols b/tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.symbols new file mode 100644 index 0000000000000..6dd3a53559111 --- /dev/null +++ b/tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.symbols @@ -0,0 +1,23 @@ +=== tests/cases/compiler/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx === +/// + +declare module "react" { +>"react" : Symbol(React, Decl(react16.d.ts, 110, 19), Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 0, 0)) + + interface Attributes { +>Attributes : Symbol(Attributes, Decl(react16.d.ts, 128, 34), Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 2, 24)) + + [key: `do-${string}`]: Function; +>key : Symbol(key, Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 4, 9)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + "ns:thing"?: string; +>"ns:thing" : Symbol(Attributes["ns:thing"], Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 4, 40)) + } +} + +export const tag =
+>tag : Symbol(tag, Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 9, 12)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114)) +>ns:thing : Symbol(ns:thing, Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 9, 23)) + diff --git a/tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.types b/tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.types new file mode 100644 index 0000000000000..76c0d7cbf00c3 --- /dev/null +++ b/tests/baselines/reference/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.types @@ -0,0 +1,23 @@ +=== tests/cases/compiler/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx === +/// + +declare module "react" { +>"react" : typeof import("react") + + interface Attributes { + [key: `do-${string}`]: Function; +>key : `do-${string}` + + "ns:thing"?: string; +>"ns:thing" : string + } +} + +export const tag =
+>tag : JSX.Element +>
: JSX.Element +>div : any +>ns:thing : string +>ns : error +>thing : error + diff --git a/tests/cases/compiler/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx b/tests/cases/compiler/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx new file mode 100644 index 0000000000000..7e840d2a1963a --- /dev/null +++ b/tests/cases/compiler/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx @@ -0,0 +1,12 @@ +// @jsx: react-jsx +// @target: esnext +/// + +declare module "react" { + interface Attributes { + [key: `do-${string}`]: Function; + "ns:thing"?: string; + } +} + +export const tag =
\ No newline at end of file