Don't trigger parameter hints when completing empty method

Fixes #64023
This commit is contained in:
Matt Bierner
2018-11-29 12:03:36 -08:00
parent f2348199e0
commit e42051996b
4 changed files with 29 additions and 15 deletions

View File

@@ -455,8 +455,11 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider
if (detail && item.useCodeSnippet) {
const shouldCompleteFunction = await this.isValidFunctionCompletionContext(filepath, item.position, token);
if (shouldCompleteFunction) {
item.insertText = snippetForFunctionCall(item, detail.displayParts);
commands.push({ title: 'triggerParameterHints', command: 'editor.action.triggerParameterHints' });
const { snippet, parameterCount } = snippetForFunctionCall(item, detail.displayParts);
item.insertText = snippet;
if (parameterCount > 0) {
commands.push({ title: 'triggerParameterHints', command: 'editor.action.triggerParameterHints' });
}
}
}

View File

@@ -66,6 +66,7 @@ export class DisplayPartKind {
public static readonly functionName = 'functionName';
public static readonly methodName = 'methodName';
public static readonly parameterName = 'parameterName';
public static readonly propertyName = 'propertyName';
public static readonly punctuation = 'punctuation';
public static readonly text = 'text';
}

View File

@@ -14,7 +14,7 @@ suite('typescript function call snippets', () => {
snippetForFunctionCall(
{ label: 'abc', },
[]
).value,
).snippet.value,
'abc()$0');
});
@@ -23,7 +23,7 @@ suite('typescript function call snippets', () => {
snippetForFunctionCall(
{ label: 'abc', insertText: 'def' },
[]
).value,
).snippet.value,
'def()$0');
});
@@ -32,7 +32,7 @@ suite('typescript function call snippets', () => {
snippetForFunctionCall(
{ label: 'abc', insertText: new vscode.SnippetString('bla()$0') },
[]
).value,
).snippet.value,
'bla()$0');
});
@@ -41,7 +41,7 @@ suite('typescript function call snippets', () => {
snippetForFunctionCall(
{ label: 'abc', insertText: new vscode.SnippetString('bla()$0') },
[]
).value,
).snippet.value,
'bla()$0');
});
@@ -50,7 +50,7 @@ suite('typescript function call snippets', () => {
snippetForFunctionCall(
{ label: 'activate' },
[{ "text": "function", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "activate", "kind": "text" }, { "text": "(", "kind": "punctuation" }, { "text": "context", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "vscode", "kind": "aliasName" }, { "text": ".", "kind": "punctuation" }, { "text": "ExtensionContext", "kind": "interfaceName" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "void", "kind": "keyword" }]
).value,
).snippet.value,
'activate(${1:context})$0');
});
@@ -59,7 +59,7 @@ suite('typescript function call snippets', () => {
snippetForFunctionCall(
{ label: 'foo' },
[{ "text": "function", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "foo", "kind": "functionName" }, { "text": "(", "kind": "punctuation" }, { "text": "a", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "string", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "b", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "c", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "boolean", "kind": "keyword" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "void", "kind": "keyword" }]
).value,
).snippet.value,
'foo(${1:a}, ${2:b}, ${3:c})$0');
});
@@ -68,7 +68,7 @@ suite('typescript function call snippets', () => {
snippetForFunctionCall(
{ label: 'foo' },
[{ "text": "function", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "foo", "kind": "functionName" }, { "text": "(", "kind": "punctuation" }, { "text": "a", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "string", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "...", "kind": "punctuation" }, { "text": "rest", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "any", "kind": "keyword" }, { "text": "[", "kind": "punctuation" }, { "text": "]", "kind": "punctuation" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "void", "kind": "keyword" }]
).value,
).snippet.value,
'foo(${1:a}$2)$0');
});
@@ -77,7 +77,7 @@ suite('typescript function call snippets', () => {
snippetForFunctionCall(
{ label: 'foo' },
[{ "text": "function", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "foo", "kind": "functionName" }, { "text": "(", "kind": "punctuation" }, { "text": "a", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "(", "kind": "punctuation" }, { "text": "x", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": ")", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "=>", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "{", "kind": "punctuation" }, { "text": "\n", "kind": "lineBreak" }, { "text": " ", "kind": "space" }, { "text": "f", "kind": "propertyName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "(", "kind": "punctuation" }, { "text": ")", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "=>", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "void", "kind": "keyword" }, { "text": ";", "kind": "punctuation" }, { "text": "\n", "kind": "lineBreak" }, { "text": "}", "kind": "punctuation" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "b", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "{", "kind": "punctuation" }, { "text": "\n", "kind": "lineBreak" }, { "text": " ", "kind": "space" }, { "text": "f", "kind": "propertyName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "(", "kind": "punctuation" }, { "text": ")", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "=>", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "void", "kind": "keyword" }, { "text": ";", "kind": "punctuation" }, { "text": "\n", "kind": "lineBreak" }, { "text": "}", "kind": "punctuation" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "void", "kind": "keyword" }]
).value,
).snippet.value,
'foo(${1:a}, ${2:b})$0');
});
@@ -86,7 +86,7 @@ suite('typescript function call snippets', () => {
snippetForFunctionCall(
{ label: 'foo' },
[{ "text": "function", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "foo", "kind": "functionName" }, { "text": "(", "kind": "punctuation" }, { "text": "a", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "{", "kind": "punctuation" }, { "text": "\n", "kind": "lineBreak" }, { "text": " ", "kind": "space" }, { "text": "f", "kind": "propertyName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "(", "kind": "punctuation" }, { "text": "b", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": ")", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "=>", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": ";", "kind": "punctuation" }, { "text": "\n", "kind": "lineBreak" }, { "text": "}", "kind": "punctuation" }]
).value,
).snippet.value,
'foo(${1:a})$0');
});
@@ -95,7 +95,16 @@ suite('typescript function call snippets', () => {
snippetForFunctionCall(
{ label: 'foo' },
[{ "text": "(", "kind": "punctuation" }, { "text": "method", "kind": "text" }, { "text": ")", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "Array", "kind": "localName" }, { "text": "<", "kind": "punctuation" }, { "text": "{", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "dispose", "kind": "methodName" }, { "text": "(", "kind": "punctuation" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "any", "kind": "keyword" }, { "text": ";", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "}", "kind": "punctuation" }, { "text": ">", "kind": "punctuation" }, { "text": ".", "kind": "punctuation" }, { "text": "foo", "kind": "methodName" }, { "text": "(", "kind": "punctuation" }, { "text": "searchElement", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "{", "kind": "punctuation" }, { "text": "\n", "kind": "lineBreak" }, { "text": " ", "kind": "space" }, { "text": "dispose", "kind": "methodName" }, { "text": "(", "kind": "punctuation" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "any", "kind": "keyword" }, { "text": ";", "kind": "punctuation" }, { "text": "\n", "kind": "lineBreak" }, { "text": "}", "kind": "punctuation" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "fromIndex", "kind": "parameterName" }, { "text": "?", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }]
).value,
).snippet.value,
'foo(${1:searchElement}$2)$0');
});
test('Should complete property names', async () => {
assert.strictEqual(
snippetForFunctionCall(
{ label: 'methoda' },
[{ "text": "(", "kind": "punctuation" }, { "text": "method", "kind": "text" }, { "text": ")", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "methoda", "kind": "propertyName" }, { "text": "(", "kind": "punctuation" }, { "text": "x", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "void", "kind": "keyword" }]
).snippet.value,
'methoda(${1:x})$0');
});
});

View File

@@ -10,9 +10,9 @@ import * as PConst from '../protocol.const';
export function snippetForFunctionCall(
item: { insertText?: string | vscode.SnippetString; label: string; },
displayParts: ReadonlyArray<Proto.SymbolDisplayPart>
): vscode.SnippetString {
): { snippet: vscode.SnippetString, parameterCount: number } {
if (item.insertText && typeof item.insertText !== 'string') {
return item.insertText;
return { snippet: item.insertText, parameterCount: 0 };
}
const parameterListParts = getParameterListParts(displayParts, item.label);
@@ -23,7 +23,7 @@ export function snippetForFunctionCall(
}
snippet.appendText(')');
snippet.appendTabstop(0);
return snippet;
return { snippet, parameterCount: parameterListParts.parts.length + (parameterListParts.hasOptionalParameters ? 1 : 0) };
}
function appendJoinedPlaceholders(
@@ -59,6 +59,7 @@ function getParameterListParts(
case PConst.DisplayPartKind.methodName:
case PConst.DisplayPartKind.functionName:
case PConst.DisplayPartKind.text:
case PConst.DisplayPartKind.propertyName:
if (part.text === label && parenCount === 0) {
isInMethod = true;
}