Merge pull request #20941 from mariusschulz/stringCompletionsForIndexedAccessTypes

Return string completions for indexed access types
This commit is contained in:
Daniel Rosenwasser
2018-01-06 21:07:00 -08:00
committed by GitHub
5 changed files with 31 additions and 8 deletions

View File

@@ -4403,7 +4403,7 @@ namespace ts {
return node.kind === SyntaxKind.RegularExpressionLiteral;
}
export function isNoSubstitutionTemplateLiteral(node: Node): node is LiteralExpression {
export function isNoSubstitutionTemplateLiteral(node: Node): node is NoSubstitutionTemplateLiteral {
return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}

View File

@@ -264,7 +264,8 @@ namespace ts.Completions {
// }
// let a: A;
// a['/*completion position*/']
return getStringLiteralCompletionEntriesFromElementAccess(node.parent, typeChecker, compilerOptions.target, log);
const type = typeChecker.getTypeAtLocation(node.parent.expression);
return getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess(node, type, typeChecker, compilerOptions.target, log);
}
else if (node.parent.kind === SyntaxKind.ImportDeclaration || node.parent.kind === SyntaxKind.ExportDeclaration
|| isRequireCall(node.parent, /*checkArgumentIsStringLiteral*/ false) || isImportCall(node.parent)
@@ -278,6 +279,16 @@ namespace ts.Completions {
const entries = PathCompletions.getStringLiteralCompletionsFromModuleNames(node, compilerOptions, host, typeChecker);
return pathCompletionsInfo(entries);
}
else if (isIndexedAccessTypeNode(node.parent.parent)) {
// Get all apparent property names
// i.e. interface Foo {
// foo: string;
// bar: string;
// }
// let x: Foo["/*completion position*/"]
const type = typeChecker.getTypeFromTypeNode(node.parent.parent.objectType);
return getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess(node, type, typeChecker, compilerOptions.target, log);
}
else {
const argumentInfo = SignatureHelp.getImmediatelyContainingArgumentInfo(node, position, sourceFile);
if (argumentInfo) {
@@ -334,11 +345,10 @@ namespace ts.Completions {
return undefined;
}
function getStringLiteralCompletionEntriesFromElementAccess(node: ElementAccessExpression, typeChecker: TypeChecker, target: ScriptTarget, log: Log): CompletionInfo | undefined {
const type = typeChecker.getTypeAtLocation(node.expression);
function getStringLiteralCompletionEntriesFromElementAccessOrIndexedAccess(stringLiteralNode: StringLiteral | NoSubstitutionTemplateLiteral, type: Type, typeChecker: TypeChecker, target: ScriptTarget, log: Log): CompletionInfo | undefined {
const entries: CompletionEntry[] = [];
if (type) {
getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, node, /*performCharacterChecks*/ false, typeChecker, target, log, /*allowStringLiteral*/ true);
getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, stringLiteralNode, /*performCharacterChecks*/ false, typeChecker, target, log, /*allowStringLiteral*/ true);
if (entries.length) {
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: true, entries };
}
@@ -1583,7 +1593,7 @@ namespace ts.Completions {
switch (contextToken.kind) {
case SyntaxKind.OpenParenToken:
case SyntaxKind.CommaToken:
return isConstructorDeclaration(contextToken.parent) && contextToken.parent;
return isConstructorDeclaration(contextToken.parent) && contextToken.parent;
default:
if (isConstructorParameterCompletion(contextToken)) {

View File

@@ -2912,7 +2912,7 @@ declare namespace ts {
function isStringLiteral(node: Node): node is StringLiteral;
function isJsxText(node: Node): node is JsxText;
function isRegularExpressionLiteral(node: Node): node is RegularExpressionLiteral;
function isNoSubstitutionTemplateLiteral(node: Node): node is LiteralExpression;
function isNoSubstitutionTemplateLiteral(node: Node): node is NoSubstitutionTemplateLiteral;
function isTemplateHead(node: Node): node is TemplateHead;
function isTemplateMiddle(node: Node): node is TemplateMiddle;
function isTemplateTail(node: Node): node is TemplateTail;

View File

@@ -2965,7 +2965,7 @@ declare namespace ts {
function isStringLiteral(node: Node): node is StringLiteral;
function isJsxText(node: Node): node is JsxText;
function isRegularExpressionLiteral(node: Node): node is RegularExpressionLiteral;
function isNoSubstitutionTemplateLiteral(node: Node): node is LiteralExpression;
function isNoSubstitutionTemplateLiteral(node: Node): node is NoSubstitutionTemplateLiteral;
function isTemplateHead(node: Node): node is TemplateHead;
function isTemplateMiddle(node: Node): node is TemplateMiddle;
function isTemplateTail(node: Node): node is TemplateTail;

View File

@@ -0,0 +1,13 @@
/// <reference path='fourslash.ts'/>
////interface Foo {
//// foo: string;
//// bar: string;
////}
////
////let x: Foo["/*1*/"]
goTo.marker("1");
verify.completionListContains("foo");
verify.completionListContains("bar");
verify.completionListCount(2);