提交 d5843e55 编写于 作者: M Matt Bierner

Fix bug for generating snippet if the object type contained a method signature

上级 1755715a
...@@ -632,7 +632,6 @@ export function snippetForFunctionCall( ...@@ -632,7 +632,6 @@ export function snippetForFunctionCall(
let hasAddedParameters = false; let hasAddedParameters = false;
const snippet = new vscode.SnippetString(); const snippet = new vscode.SnippetString();
const methodName = displayParts.find(part => part.kind === 'methodName');
if (item.insertText) { if (item.insertText) {
if (typeof item.insertText === 'string') { if (typeof item.insertText === 'string') {
snippet.appendText(item.insertText); snippet.appendText(item.insertText);
...@@ -640,17 +639,18 @@ export function snippetForFunctionCall( ...@@ -640,17 +639,18 @@ export function snippetForFunctionCall(
return item.insertText; return item.insertText;
} }
} else { } else {
snippet.appendText((methodName && methodName.text) || item.label); snippet.appendText(item.label);
} }
snippet.appendText('('); snippet.appendText('(');
const functionSignatureDisplayParts = getFunctionSignatureDisplayParts(displayParts, item.label);
let parenCount = 0; let parenCount = 0;
let i = 0; let i = 0;
for (; i < displayParts.length; ++i) { for (; i < functionSignatureDisplayParts.length; ++i) {
const part = displayParts[i]; const part = functionSignatureDisplayParts[i];
// Only take top level paren names // Only take top level paren names
if (part.kind === 'parameterName' && parenCount === 1) { if (part.kind === 'parameterName' && parenCount === 1) {
const next = displayParts[i + 1]; const next = functionSignatureDisplayParts[i + 1];
// Skip optional parameters // Skip optional parameters
const nameIsFollowedByOptionalIndicator = next && next.text === '?'; const nameIsFollowedByOptionalIndicator = next && next.text === '?';
if (!nameIsFollowedByOptionalIndicator) { if (!nameIsFollowedByOptionalIndicator) {
...@@ -684,6 +684,43 @@ export function snippetForFunctionCall( ...@@ -684,6 +684,43 @@ export function snippetForFunctionCall(
return snippet; return snippet;
} }
function getFunctionSignatureDisplayParts(
displayParts: ReadonlyArray<Proto.SymbolDisplayPart>,
label: string,
): ReadonlyArray<Proto.SymbolDisplayPart> {
let start: number | undefined;
let end: number | undefined;
let index = 0;
let nestingLevel = 0;
for (; index < displayParts.length; ++index) {
const part = displayParts[index];
if (part.kind === 'methodName' || part.kind === 'functionName' || part.kind === 'text' && part.text === label) {
if (nestingLevel === 0) {
start = index;
}
} else if (part.kind === 'punctuation') {
switch (part.text) {
case '(':
++nestingLevel;
break;
case ')':
--nestingLevel;
if (nestingLevel <= 0) {
end = index;
}
break;
}
}
}
if (typeof start === 'number' && typeof end === 'number') {
return displayParts.slice(start, end);
}
return [];
}
function shouldExcludeCompletionEntry( function shouldExcludeCompletionEntry(
element: Proto.CompletionEntry, element: Proto.CompletionEntry,
completionConfiguration: CompletionConfiguration completionConfiguration: CompletionConfiguration
......
...@@ -81,7 +81,7 @@ suite('typescript function call snippets', () => { ...@@ -81,7 +81,7 @@ suite('typescript function call snippets', () => {
'foo(${1:a}, ${2:b})$0'); 'foo(${1:a}, ${2:b})$0');
}); });
test('Should skip over return type', async () => { test('Should skip over return type while extracting parameters', async () => {
assert.strictEqual( assert.strictEqual(
snippetForFunctionCall( snippetForFunctionCall(
{ label: 'foo' }, { label: 'foo' },
...@@ -89,4 +89,13 @@ suite('typescript function call snippets', () => { ...@@ -89,4 +89,13 @@ suite('typescript function call snippets', () => {
).value, ).value,
'foo(${1:a})$0'); 'foo(${1:a})$0');
}); });
test('Should skip over prefix type while extracting parameters', async () => {
assert.strictEqual(
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,
'foo(${1:searchElement}$2)$0');
});
}); });
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册