Get completion of JSX attributes type when tag name is a property access expression
This commit is contained in:
parent
ef25b25c1f
commit
0290e20b8e
2 changed files with 59 additions and 6 deletions
|
@ -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:
|
||||||
|
|
44
tests/cases/fourslash/tsxCompletion14.ts
Normal file
44
tests/cases/fourslash/tsxCompletion14.ts
Normal 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");
|
Loading…
Reference in a new issue