Fix attribute completion following JSX exprs

This commit is contained in:
Ryan Cavanaugh
2015-07-01 15:00:06 -07:00
parent b2a871dcfb
commit f465d99492
4 changed files with 60 additions and 25 deletions

View File

@@ -3009,6 +3009,7 @@ namespace ts {
function tryGetGlobalSymbols(): boolean {
let objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken);
let jsxContainer = tryGetContainingJsxElement(contextToken);
if (objectLikeContainer) {
// Object literal expression, look up possible property names from contextual type
isMemberCompletion = true;
@@ -3059,30 +3060,22 @@ namespace ts {
}
return true;
}
else if (getAncestor(contextToken, SyntaxKind.JsxElement) || getAncestor(contextToken, SyntaxKind.JsxSelfClosingElement)) {
// Go up until we hit either the element or expression
let jsxNode = contextToken;
else if(jsxContainer) {
let attrsType: Type;
if (jsxContainer.kind === SyntaxKind.JsxSelfClosingElement) {
// Cursor is inside a JSX self-closing element
attrsType = typeChecker.getJsxElementAttributesType(<JsxSelfClosingElement>jsxContainer);
}
else if(jsxContainer.kind === SyntaxKind.JsxOpeningElement) {
// Cursor is inside a JSX element
attrsType = typeChecker.getJsxElementAttributesType(<JsxOpeningElement>jsxContainer);
}
while (jsxNode) {
if (jsxNode.kind === SyntaxKind.JsxExpression) {
// Defer to global completion if we're inside an {expression}
break;
} else if (jsxNode.kind === SyntaxKind.JsxSelfClosingElement || jsxNode.kind === SyntaxKind.JsxElement) {
let attrsType: Type;
if (jsxNode.kind === SyntaxKind.JsxSelfClosingElement) {
// Cursor is inside a JSX self-closing element
attrsType = typeChecker.getJsxElementAttributesType(<JsxSelfClosingElement>jsxNode);
}
else {
Debug.assert(jsxNode.kind === SyntaxKind.JsxElement);
// Cursor is inside a JSX element
attrsType = typeChecker.getJsxElementAttributesType((<JsxElement>jsxNode).openingElement);
}
symbols = typeChecker.getPropertiesOfType(attrsType);
isMemberCompletion = true;
return true;
}
jsxNode = jsxNode.parent;
if (attrsType) {
symbols = typeChecker.getPropertiesOfType(attrsType);
isMemberCompletion = true;
isNewIdentifierLocation = false;
return true;
}
}
@@ -3268,6 +3261,36 @@ namespace ts {
return undefined;
}
function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement {
if (contextToken) {
let parent = contextToken.parent;
switch(contextToken.kind) {
case SyntaxKind.LessThanSlashToken:
case SyntaxKind.SlashToken:
case SyntaxKind.Identifier:
if(parent && (parent.kind === SyntaxKind.JsxSelfClosingElement || parent.kind === SyntaxKind.JsxOpeningElement)) {
return <JsxOpeningLikeElement>parent;
}
break;
case SyntaxKind.CloseBraceToken:
// The context token is the closing } of an attribute, which means
// its parent is a JsxExpression, whose parent is a JsxAttribute,
// whose parent is a JsxOpeningLikeElement
if(parent &&
parent.kind === SyntaxKind.JsxExpression &&
parent.parent &&
parent.parent.kind === SyntaxKind.JsxAttribute) {
return <JsxOpeningLikeElement>parent.parent.parent;
}
break;
}
}
return undefined;
}
function isFunction(kind: SyntaxKind): boolean {
switch (kind) {
case SyntaxKind.FunctionExpression:

View File

@@ -8,6 +8,5 @@
//// public foo3() { }
////}
debugger;
goTo.marker("1");
edit.insert(" + 1");

View File

@@ -7,7 +7,7 @@
//// v = 2;
////>>>>>>> Branch - a
////}
debugger;
var c = classification;
verify.syntacticClassificationsAre(
c.keyword("class"), c.className("C"), c.punctuation("{"),

View File

@@ -0,0 +1,13 @@
/// <reference path='fourslash.ts' />
//@Filename: file.tsx
//// declare module JSX {
//// interface Element { }
//// interface IntrinsicElements {
//// div: { one; two; }
//// }
//// }
//// <div one={1} /**//>;
goTo.marker();
verify.completionListContains('two');