Merge pull request #7645 from Microsoft/fix7637
Fix #7637: treat jsx tag names as expressions
This commit is contained in:
commit
b07eb63000
|
@ -9033,7 +9033,12 @@ namespace ts {
|
|||
checkJsxOpeningLikeElement(node.openingElement);
|
||||
|
||||
// Perform resolution on the closing tag so that rename/go to definition/etc work
|
||||
getJsxTagSymbol(node.closingElement);
|
||||
if (isJsxIntrinsicIdentifier(node.closingElement.tagName)) {
|
||||
getIntrinsicTagSymbol(node.closingElement);
|
||||
}
|
||||
else {
|
||||
checkExpression(node.closingElement.tagName);
|
||||
}
|
||||
|
||||
// Check children
|
||||
for (const child of node.children) {
|
||||
|
@ -9143,18 +9148,6 @@ namespace ts {
|
|||
return jsxTypes[name];
|
||||
}
|
||||
|
||||
function getJsxTagSymbol(node: JsxOpeningLikeElement | JsxClosingElement): Symbol {
|
||||
if (isJsxIntrinsicIdentifier(node.tagName)) {
|
||||
return getIntrinsicTagSymbol(node);
|
||||
}
|
||||
else if (node.tagName.kind === SyntaxKind.Identifier) {
|
||||
return resolveEntityName(node.tagName, SymbolFlags.Value | SymbolFlags.Alias);
|
||||
}
|
||||
else {
|
||||
return checkExpression(node.tagName).symbol;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up an intrinsic tag name and returns a symbol that either points to an intrinsic
|
||||
* property (in which case nodeLinks.jsxFlags will be IntrinsicNamedElement) or an intrinsic
|
||||
|
@ -16211,12 +16204,6 @@ namespace ts {
|
|||
meaning |= SymbolFlags.Alias;
|
||||
return resolveEntityName(<EntityName>entityName, meaning);
|
||||
}
|
||||
else if ((entityName.parent.kind === SyntaxKind.JsxOpeningElement) ||
|
||||
(entityName.parent.kind === SyntaxKind.JsxSelfClosingElement) ||
|
||||
(entityName.parent.kind === SyntaxKind.JsxClosingElement)) {
|
||||
|
||||
return getJsxTagSymbol(<JsxOpeningLikeElement>entityName.parent);
|
||||
}
|
||||
else if (isExpression(entityName)) {
|
||||
if (nodeIsMissing(entityName)) {
|
||||
// Missing entity name.
|
||||
|
@ -16224,6 +16211,10 @@ namespace ts {
|
|||
}
|
||||
|
||||
if (entityName.kind === SyntaxKind.Identifier) {
|
||||
if (isJSXTagName(entityName) && isJsxIntrinsicIdentifier(<Identifier>entityName)) {
|
||||
return getIntrinsicTagSymbol(<JsxOpeningLikeElement>entityName.parent);
|
||||
}
|
||||
|
||||
// Include aliases in the meaning, this ensures that we do not follow aliases to where they point and instead
|
||||
// return the alias symbol.
|
||||
const meaning: SymbolFlags = SymbolFlags.Value | SymbolFlags.Alias;
|
||||
|
|
|
@ -953,6 +953,16 @@ namespace ts {
|
|||
return node.kind === SyntaxKind.ElementAccessExpression;
|
||||
}
|
||||
|
||||
export function isJSXTagName(node: Node) {
|
||||
const parent = node.parent;
|
||||
if (parent.kind === SyntaxKind.JsxOpeningElement ||
|
||||
parent.kind === SyntaxKind.JsxSelfClosingElement ||
|
||||
parent.kind === SyntaxKind.JsxClosingElement) {
|
||||
return (<JsxOpeningLikeElement>parent).tagName === node;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isExpression(node: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SuperKeyword:
|
||||
|
@ -994,9 +1004,9 @@ namespace ts {
|
|||
while (node.parent.kind === SyntaxKind.QualifiedName) {
|
||||
node = node.parent;
|
||||
}
|
||||
return node.parent.kind === SyntaxKind.TypeQuery;
|
||||
return node.parent.kind === SyntaxKind.TypeQuery || isJSXTagName(node);
|
||||
case SyntaxKind.Identifier:
|
||||
if (node.parent.kind === SyntaxKind.TypeQuery) {
|
||||
if (node.parent.kind === SyntaxKind.TypeQuery || isJSXTagName(node)) {
|
||||
return true;
|
||||
}
|
||||
// fall through
|
||||
|
|
|
@ -178,8 +178,10 @@ var x =
|
|||
>constructor : Symbol(unknown)
|
||||
|
||||
<Namespace.Component />;
|
||||
>Namespace : Symbol(Namespace, Decl(jsxReactTestSuite.tsx, 6, 11))
|
||||
|
||||
<Namespace.DeepNamespace.Component />;
|
||||
>Namespace : Symbol(Namespace, Decl(jsxReactTestSuite.tsx, 6, 11))
|
||||
|
||||
<Component { ... x } y
|
||||
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
|
||||
|
|
|
@ -235,11 +235,14 @@ var x =
|
|||
|
||||
<Namespace.Component />;
|
||||
><Namespace.Component /> : any
|
||||
>Namespace.Component : any
|
||||
>Namespace : any
|
||||
>Component : any
|
||||
|
||||
<Namespace.DeepNamespace.Component />;
|
||||
><Namespace.DeepNamespace.Component /> : any
|
||||
>Namespace.DeepNamespace.Component : any
|
||||
>Namespace.DeepNamespace : any
|
||||
>Namespace : any
|
||||
>DeepNamespace : any
|
||||
>Component : any
|
||||
|
|
|
@ -5,6 +5,6 @@ function Test() { }
|
|||
|
||||
<Test></Test>
|
||||
><Test></Test> : any
|
||||
>Test : any
|
||||
>Test : any
|
||||
>Test : () => void
|
||||
>Test : () => void
|
||||
|
||||
|
|
|
@ -47,5 +47,7 @@ var d = <Other />;
|
|||
|
||||
var e = <Dotted.Name />;
|
||||
>e : Symbol(e, Decl(tsxElementResolution.tsx, 23, 3))
|
||||
>Dotted.Name : Symbol(Dotted.Name, Decl(tsxElementResolution.tsx, 12, 15))
|
||||
>Dotted : Symbol(Dotted, Decl(tsxElementResolution.tsx, 10, 14))
|
||||
>Name : Symbol(Dotted.Name, Decl(tsxElementResolution.tsx, 12, 15))
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ var d = <Other />;
|
|||
var e = <Dotted.Name />;
|
||||
>e : any
|
||||
><Dotted.Name /> : any
|
||||
>Dotted : any
|
||||
>Name : any
|
||||
>Dotted.Name : typeof Dotted.Name
|
||||
>Dotted : typeof Dotted
|
||||
>Name : typeof Dotted.Name
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ import s2 = require('elements2');
|
|||
>s2 : Symbol(s2, Decl(consumer.tsx, 2, 33))
|
||||
|
||||
<s1.MyElement />;
|
||||
>s1.MyElement : Symbol(s1.MyElement, Decl(file.tsx, 6, 28))
|
||||
>s1 : Symbol(s1, Decl(consumer.tsx, 0, 0))
|
||||
>MyElement : Symbol(s1.MyElement, Decl(file.tsx, 6, 28))
|
||||
|
||||
=== tests/cases/conformance/jsx/file.tsx ===
|
||||
|
|
|
@ -9,8 +9,9 @@ import s2 = require('elements2');
|
|||
|
||||
<s1.MyElement />;
|
||||
><s1.MyElement /> : JSX.Element
|
||||
>s1 : any
|
||||
>MyElement : any
|
||||
>s1.MyElement : typeof s1.MyElement
|
||||
>s1 : typeof s1
|
||||
>MyElement : typeof s1.MyElement
|
||||
|
||||
=== tests/cases/conformance/jsx/file.tsx ===
|
||||
|
||||
|
|
|
@ -59,6 +59,8 @@ module M {
|
|||
>S.Bar : Symbol(S.Bar, Decl(file.tsx, 8, 18))
|
||||
>S : Symbol(S, Decl(file.tsx, 7, 39), Decl(file.tsx, 18, 14))
|
||||
>Bar : Symbol(S.Bar, Decl(file.tsx, 8, 18))
|
||||
>S.Bar : Symbol(S.Bar, Decl(file.tsx, 8, 18))
|
||||
>S : Symbol(S, Decl(file.tsx, 7, 39), Decl(file.tsx, 18, 14))
|
||||
>Bar : Symbol(S.Bar, Decl(file.tsx, 8, 18))
|
||||
}
|
||||
|
||||
|
|
|
@ -67,8 +67,9 @@ module M {
|
|||
>S : typeof S
|
||||
>Bar : typeof S.Bar
|
||||
><S.Bar /> : JSX.Element
|
||||
>S : any
|
||||
>Bar : any
|
||||
>S.Bar : typeof S.Bar
|
||||
>S : typeof S
|
||||
>Bar : typeof S.Bar
|
||||
}
|
||||
|
||||
module M {
|
||||
|
|
|
@ -16,4 +16,18 @@ declare module A.B.C {
|
|||
}
|
||||
|
||||
<A.B.C.D>foo</A . B . C.D>
|
||||
>A.B.C.D : Symbol(A.B.C.D, Decl(file.tsx, 5, 5))
|
||||
>A.B.C : Symbol(A.B.C, Decl(file.tsx, 4, 19))
|
||||
>A.B : Symbol(A.B, Decl(file.tsx, 4, 17))
|
||||
>A : Symbol(A, Decl(file.tsx, 2, 1))
|
||||
>B : Symbol(A.B, Decl(file.tsx, 4, 17))
|
||||
>C : Symbol(A.B.C, Decl(file.tsx, 4, 19))
|
||||
>D : Symbol(A.B.C.D, Decl(file.tsx, 5, 5))
|
||||
>A . B . C.D : Symbol(A.B.C.D, Decl(file.tsx, 5, 5))
|
||||
>A . B . C : Symbol(A.B.C, Decl(file.tsx, 4, 19))
|
||||
>A . B : Symbol(A.B, Decl(file.tsx, 4, 17))
|
||||
>A : Symbol(A, Decl(file.tsx, 2, 1))
|
||||
>B : Symbol(A.B, Decl(file.tsx, 4, 17))
|
||||
>C : Symbol(A.B.C, Decl(file.tsx, 4, 19))
|
||||
>D : Symbol(A.B.C.D, Decl(file.tsx, 5, 5))
|
||||
|
||||
|
|
|
@ -17,12 +17,18 @@ declare module A.B.C {
|
|||
|
||||
<A.B.C.D>foo</A . B . C.D>
|
||||
><A.B.C.D>foo</A . B . C.D> : JSX.Element
|
||||
>A : any
|
||||
>B : any
|
||||
>C : any
|
||||
>A.B.C.D : any
|
||||
>A.B.C : typeof A.B.C
|
||||
>A.B : typeof A.B
|
||||
>A : typeof A
|
||||
>B : typeof A.B
|
||||
>C : typeof A.B.C
|
||||
>D : any
|
||||
>A : any
|
||||
>B : any
|
||||
>C : any
|
||||
>A . B . C.D : any
|
||||
>A . B . C : typeof A.B.C
|
||||
>A . B : typeof A.B
|
||||
>A : typeof A
|
||||
>B : typeof A.B
|
||||
>C : typeof A.B.C
|
||||
>D : any
|
||||
|
||||
|
|
11
tests/cases/fourslash/findReferencesJSXTagName2.ts
Normal file
11
tests/cases/fourslash/findReferencesJSXTagName2.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @Filename: index.tsx
|
||||
////const /*1*/obj = {Component: () => <div/>};
|
||||
////const element = </*2*/obj.Component/>;
|
||||
|
||||
goTo.marker("1");
|
||||
verify.referencesCountIs(2);
|
||||
|
||||
goTo.marker("2");
|
||||
verify.referencesCountIs(2);
|
Loading…
Reference in a new issue