Merge pull request #7645 from Microsoft/fix7637

Fix #7637: treat jsx tag names as expressions
This commit is contained in:
Mohamed Hegazy 2016-03-23 11:04:37 -07:00
commit b07eb63000
14 changed files with 81 additions and 35 deletions

View file

@ -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;

View file

@ -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

View file

@ -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))

View file

@ -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

View file

@ -5,6 +5,6 @@ function Test() { }
<Test></Test>
><Test></Test> : any
>Test : any
>Test : any
>Test : () => void
>Test : () => void

View file

@ -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))

View file

@ -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

View file

@ -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 ===

View file

@ -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 ===

View file

@ -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))
}

View file

@ -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 {

View file

@ -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))

View file

@ -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

View 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);