mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-07 14:34:35 -06:00
Merge pull request #13364 from Microsoft/string_literal_completions_fix
String literal completions: Use call signature only if we are *immediately* in a call expression
This commit is contained in:
commit
df8cb9d2c3
@ -15,7 +15,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Array that is only intended to be pushed to, never read. */
|
||||
interface Push<T> {
|
||||
export interface Push<T> {
|
||||
push(value: T): void;
|
||||
}
|
||||
|
||||
@ -357,7 +357,7 @@ namespace ts {
|
||||
* Then it computes the set of parent folders for 'directory' that should have the same module resolution result
|
||||
* and for every parent folder in set it adds entry: parent -> module resolution. .
|
||||
* Lets say we first directory name: /a/b/c/d/e and resolution result is: /a/b/bar.ts.
|
||||
* Set of parent folders that should have the same result will be:
|
||||
* Set of parent folders that should have the same result will be:
|
||||
* [
|
||||
* /a/b/c/d, /a/b/c, /a/b
|
||||
* ]
|
||||
@ -391,7 +391,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getCommonPrefix(directory: Path, resolution: string) {
|
||||
if (resolution === undefined) {
|
||||
return undefined;
|
||||
@ -1022,7 +1022,7 @@ namespace ts {
|
||||
|
||||
/**
|
||||
* Represents result of search. Normally when searching among several alternatives we treat value `undefined` as indicator
|
||||
* that search fails and we should try another option.
|
||||
* that search fails and we should try another option.
|
||||
* However this does not allow us to represent final result that should be used instead of further searching (i.e. a final result that was found in cache).
|
||||
* SearchResult is used to deal with this issue, its values represents following outcomes:
|
||||
* - undefined - not found, continue searching
|
||||
@ -1030,7 +1030,7 @@ namespace ts {
|
||||
* - { value: <some-value> } - found - stop searching
|
||||
*/
|
||||
type SearchResult<T> = { value: T | undefined } | undefined;
|
||||
|
||||
|
||||
/**
|
||||
* Wraps value to SearchResult.
|
||||
* @returns undefined if value is undefined or { value } otherwise
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
/// <reference path='../compiler/utilities.ts' />
|
||||
|
||||
/* @internal */
|
||||
namespace ts.Completions {
|
||||
export function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo {
|
||||
export function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo | undefined {
|
||||
if (isInReferenceComment(sourceFile, position)) {
|
||||
return getTripleSlashReferenceCompletion(sourceFile, position);
|
||||
}
|
||||
@ -134,7 +132,7 @@ namespace ts.Completions {
|
||||
return uniqueNames;
|
||||
}
|
||||
|
||||
function getStringLiteralCompletionEntries(sourceFile: SourceFile, position: number) {
|
||||
function getStringLiteralCompletionEntries(sourceFile: SourceFile, position: number): CompletionInfo | undefined {
|
||||
const node = findPrecedingToken(position, sourceFile);
|
||||
if (!node || node.kind !== SyntaxKind.StringLiteral) {
|
||||
return undefined;
|
||||
@ -174,7 +172,7 @@ namespace ts.Completions {
|
||||
return getStringLiteralCompletionEntriesFromModuleNames(<StringLiteral>node);
|
||||
}
|
||||
else {
|
||||
const argumentInfo = SignatureHelp.getContainingArgumentInfo(node, position, sourceFile);
|
||||
const argumentInfo = SignatureHelp.getImmediatelyContainingArgumentInfo(node, position, sourceFile);
|
||||
if (argumentInfo) {
|
||||
// Get string literal completions from specialized signatures of the target
|
||||
// i.e. declare function f(a: 'A');
|
||||
@ -188,7 +186,7 @@ namespace ts.Completions {
|
||||
}
|
||||
}
|
||||
|
||||
function getStringLiteralCompletionEntriesFromPropertyAssignment(element: ObjectLiteralElement) {
|
||||
function getStringLiteralCompletionEntriesFromPropertyAssignment(element: ObjectLiteralElement): CompletionInfo | undefined {
|
||||
const type = typeChecker.getContextualType((<ObjectLiteralExpression>element.parent));
|
||||
const entries: CompletionEntry[] = [];
|
||||
if (type) {
|
||||
@ -199,7 +197,7 @@ namespace ts.Completions {
|
||||
}
|
||||
}
|
||||
|
||||
function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo: SignatureHelp.ArgumentListInfo) {
|
||||
function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo: SignatureHelp.ArgumentListInfo): CompletionInfo | undefined {
|
||||
const candidates: Signature[] = [];
|
||||
const entries: CompletionEntry[] = [];
|
||||
|
||||
@ -219,7 +217,7 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getStringLiteralCompletionEntriesFromElementAccess(node: ElementAccessExpression) {
|
||||
function getStringLiteralCompletionEntriesFromElementAccess(node: ElementAccessExpression): CompletionInfo | undefined {
|
||||
const type = typeChecker.getTypeAtLocation(node.expression);
|
||||
const entries: CompletionEntry[] = [];
|
||||
if (type) {
|
||||
@ -231,7 +229,7 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getStringLiteralCompletionEntriesFromContextualType(node: StringLiteral) {
|
||||
function getStringLiteralCompletionEntriesFromContextualType(node: StringLiteral): CompletionInfo | undefined {
|
||||
const type = typeChecker.getContextualType(node);
|
||||
if (type) {
|
||||
const entries: CompletionEntry[] = [];
|
||||
@ -243,7 +241,7 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function addStringLiteralCompletionsFromType(type: Type, result: CompletionEntry[]): void {
|
||||
function addStringLiteralCompletionsFromType(type: Type, result: Push<CompletionEntry>): void {
|
||||
if (type && type.flags & TypeFlags.TypeParameter) {
|
||||
type = typeChecker.getApparentType(type);
|
||||
}
|
||||
@ -251,18 +249,18 @@ namespace ts.Completions {
|
||||
return;
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
forEach((<UnionType>type).types, t => addStringLiteralCompletionsFromType(t, result));
|
||||
}
|
||||
else {
|
||||
if (type.flags & TypeFlags.StringLiteral) {
|
||||
result.push({
|
||||
name: (<LiteralType>type).text,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
kind: ScriptElementKind.variableElement,
|
||||
sortText: "0"
|
||||
});
|
||||
for (const t of (<UnionType>type).types) {
|
||||
addStringLiteralCompletionsFromType(t, result);
|
||||
}
|
||||
}
|
||||
else if (type.flags & TypeFlags.StringLiteral) {
|
||||
result.push({
|
||||
name: (<LiteralType>type).text,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
kind: ScriptElementKind.variableElement,
|
||||
sortText: "0"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getStringLiteralCompletionEntriesFromModuleNames(node: StringLiteral): CompletionInfo {
|
||||
|
||||
@ -260,7 +260,7 @@ namespace ts.SignatureHelp {
|
||||
* Returns relevant information for the argument list and the current argument if we are
|
||||
* in the argument of an invocation; returns undefined otherwise.
|
||||
*/
|
||||
function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo {
|
||||
export function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo {
|
||||
if (node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) {
|
||||
const callExpression = <CallExpression>node.parent;
|
||||
// There are 3 cases to handle:
|
||||
|
||||
12
tests/cases/fourslash/completionForStringLiteral6.ts
Normal file
12
tests/cases/fourslash/completionForStringLiteral6.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface Foo {
|
||||
//// x: "abc" | "def";
|
||||
////}
|
||||
////function bar(f: Foo) { };
|
||||
////bar({x: "/**/"});
|
||||
|
||||
goTo.marker();
|
||||
verify.completionListContains("abc");
|
||||
verify.completionListContains("def");
|
||||
verify.completionListCount(2);
|
||||
@ -129,7 +129,7 @@ function dir(dirPath: string, spec?: string, options?: any) {
|
||||
function deleteFolderRecursive(dirPath: string) {
|
||||
if (fs.existsSync(dirPath)) {
|
||||
fs.readdirSync(dirPath).forEach((file) => {
|
||||
const curPath = path.join(path, file);
|
||||
const curPath = path.join(dirPath, file);
|
||||
if (fs.statSync(curPath).isDirectory()) { // recurse
|
||||
deleteFolderRecursive(curPath);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user