Get completion of JSX attributes type when tag name is a property access expression

This commit is contained in:
Kanchalai Tanglertsampan 2017-02-21 10:54:28 -08:00
parent ef25b25c1f
commit 0290e20b8e
2 changed files with 59 additions and 6 deletions

View file

@ -898,8 +898,8 @@ namespace ts.Completions {
return undefined; return undefined;
} }
const { parent, kind } = contextToken; let parent = contextToken.parent;
if (kind === SyntaxKind.DotToken) { if (contextToken.kind === SyntaxKind.DotToken) {
if (parent.kind === SyntaxKind.PropertyAccessExpression) { if (parent.kind === SyntaxKind.PropertyAccessExpression) {
node = (<PropertyAccessExpression>contextToken.parent).expression; node = (<PropertyAccessExpression>contextToken.parent).expression;
isRightOfDot = true; isRightOfDot = true;
@ -915,16 +915,24 @@ namespace ts.Completions {
} }
} }
else if (sourceFile.languageVariant === LanguageVariant.JSX) { else if (sourceFile.languageVariant === LanguageVariant.JSX) {
switch (contextToken.parent.kind) { // <UI.Test /* completion position */ />
// If the tagname is a property access expression, we will then walk up to the top most of property access expression.
// Then, try to get a JSX container and its associated attributes type.
if (parent && parent.kind === SyntaxKind.PropertyAccessExpression) {
contextToken = parent;
parent = parent.parent;
}
switch (parent.kind) {
case SyntaxKind.JsxClosingElement: case SyntaxKind.JsxClosingElement:
if (kind === SyntaxKind.SlashToken) { if (contextToken.kind === SyntaxKind.SlashToken) {
isStartingCloseTag = true; isStartingCloseTag = true;
location = contextToken; location = contextToken;
} }
break; break;
case SyntaxKind.BinaryExpression: case SyntaxKind.BinaryExpression:
if (!((contextToken.parent as BinaryExpression).left.flags & NodeFlags.ThisNodeHasError)) { if (!((parent as BinaryExpression).left.flags & NodeFlags.ThisNodeHasError)) {
// It has a left-hand side, so we're not in an opening JSX tag. // It has a left-hand side, so we're not in an opening JSX tag.
break; break;
} }
@ -933,7 +941,7 @@ namespace ts.Completions {
case SyntaxKind.JsxSelfClosingElement: case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxElement: case SyntaxKind.JsxElement:
case SyntaxKind.JsxOpeningElement: case SyntaxKind.JsxOpeningElement:
if (kind === SyntaxKind.LessThanToken) { if (contextToken.kind === SyntaxKind.LessThanToken) {
isRightOfOpenTag = true; isRightOfOpenTag = true;
location = contextToken; location = contextToken;
} }
@ -1401,6 +1409,7 @@ namespace ts.Completions {
case SyntaxKind.LessThanSlashToken: case SyntaxKind.LessThanSlashToken:
case SyntaxKind.SlashToken: case SyntaxKind.SlashToken:
case SyntaxKind.Identifier: case SyntaxKind.Identifier:
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.JsxAttributes: case SyntaxKind.JsxAttributes:
case SyntaxKind.JsxAttribute: case SyntaxKind.JsxAttribute:
case SyntaxKind.JsxSpreadAttribute: case SyntaxKind.JsxSpreadAttribute:

View file

@ -0,0 +1,44 @@
/// <reference path='fourslash.ts' />
//@module: commonjs
//@jsx: preserve
//// declare module JSX {
//// interface Element { }
//// interface IntrinsicElements {
//// }
//// interface ElementAttributesProperty { props; }
//// }
//@Filename: exporter.tsx
//// export class Thing { props: { ONE: string; TWO: number } }
//// export module M {
//// export declare function SFCComp(props: { Three: number; Four: string }): JSX.Element;
//// }
//@Filename: file.tsx
//// import * as Exp from './exporter';
//// var x1 = <Exp.Thing /*1*/ />;
//// var x2 = <Exp.M.SFCComp /*2*/ />;
//// var x3 = <Exp.Thing /*3*/ ></Exp.Thing>;
//// var x4 = <Exp.M.SFCComp /*4*/ ></Exp.M.SFCComp>;
goTo.marker("1");
verify.completionListCount(2);
verify.completionListContains('ONE');
verify.completionListContains('TWO');
goTo.marker("2");
verify.completionListCount(2);
verify.completionListContains("Three");
verify.completionListContains("Four");
goTo.marker("3");
verify.completionListCount(2);
verify.completionListContains('ONE');
verify.completionListContains('TWO');
goTo.marker("4");
verify.completionListCount(2);
verify.completionListContains("Three");
verify.completionListContains("Four");