be more strict when suggesting snippets at word ends,...

be more strict when suggesting snippets at word ends, https://github.com/microsoft/vscode/issues/138707
上级 7db1a2b8
......@@ -17,6 +17,7 @@ import { Snippet, SnippetSource } from 'vs/workbench/contrib/snippets/browser/sn
import { isPatternInWord } from 'vs/base/common/filters';
import { StopWatch } from 'vs/base/common/stopwatch';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { getWordAtText } from 'vs/editor/common/model/wordHelper';
export class SnippetCompletion implements CompletionItem {
......@@ -70,6 +71,7 @@ export class SnippetCompletionProvider implements CompletionItemProvider {
const snippets = new Set(await this._snippets.getSnippets(languageId));
const lineContentLow = model.getLineContent(position.lineNumber).toLowerCase();
const wordUntil = model.getWordUntilPosition(position).word.toLowerCase();
const suggestions: SnippetCompletion[] = [];
const columnOffset = position.column - 1;
......@@ -78,6 +80,13 @@ export class SnippetCompletionProvider implements CompletionItemProvider {
for (const snippet of snippets) {
const snippetPrefixWord = getWordAtText(1, LanguageConfigurationRegistry.getWordDefinition(languageId), snippet.prefixLow, 0);
if (wordUntil && snippetPrefixWord && !isPatternInWord(wordUntil, 0, wordUntil.length, snippet.prefixLow, 0, snippet.prefixLow.length)) {
// when at a word the snippet prefix must match
continue;
}
for (let pos = Math.max(0, columnOffset - snippet.prefixLow.length); pos < lineContentLow.length; pos++) {
if (context.triggerKind === CompletionTriggerKind.TriggerCharacter && !snippet.prefixLow.startsWith(triggerCharacterLow)) {
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { SnippetCompletionProvider } from 'vs/workbench/contrib/snippets/browser/snippetCompletionProvider';
import { SnippetCompletion, SnippetCompletionProvider } from 'vs/workbench/contrib/snippets/browser/snippetCompletionProvider';
import { Position } from 'vs/editor/common/core/position';
import { ModesRegistry } from 'vs/editor/common/modes/modesRegistry';
import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
......@@ -91,12 +91,17 @@ suite('SnippetsService', function () {
});
});
test('snippet completions - simple 2', function () {
test('snippet completions - simple 2', async function () {
const provider = new SnippetCompletionProvider(modeService, snippetService);
const model = disposables.add(createTextModel('hello ', undefined, 'fooLang'));
return provider.provideCompletionItems(model, new Position(1, 6), context)!.then(result => {
await provider.provideCompletionItems(model, new Position(1, 6) /* hello| */, context)!.then(result => {
assert.strictEqual(result.incomplete, undefined);
assert.strictEqual(result.suggestions.length, 0);
});
await provider.provideCompletionItems(model, new Position(1, 7) /* hello |*/, context)!.then(result => {
assert.strictEqual(result.incomplete, undefined);
assert.strictEqual(result.suggestions.length, 2);
});
......@@ -640,4 +645,67 @@ suite('SnippetsService', function () {
assert.strictEqual(result.suggestions.length, 1);
model.dispose();
});
test('Snippet suggestions are too eager #138707 (word)', async function () {
snippetService = new SimpleSnippetService([
new Snippet(['fooLang'], 'tys', 'tys', '', 'value', '', SnippetSource.User),
new Snippet(['fooLang'], 'hell_or_tell', 'hell_or_tell', '', 'value', '', SnippetSource.User),
new Snippet(['fooLang'], '^y', '^y', '', 'value', '', SnippetSource.User),
]);
const provider = new SnippetCompletionProvider(modeService, snippetService);
let model = createTextModel('\'hellot\'', undefined, 'fooLang');
let result = await provider.provideCompletionItems(
model,
new Position(1, 8),
{ triggerKind: CompletionTriggerKind.Invoke }
)!;
assert.strictEqual(result.suggestions.length, 2);
assert.strictEqual((<SnippetCompletion>result.suggestions[0]).label.label, '^y');
assert.strictEqual((<SnippetCompletion>result.suggestions[1]).label.label, 'hell_or_tell');
model.dispose();
});
test('Snippet suggestions are too eager #138707 (no word)', async function () {
snippetService = new SimpleSnippetService([
new Snippet(['fooLang'], 'tys', 'tys', '', 'value', '', SnippetSource.User),
new Snippet(['fooLang'], 't', 't', '', 'value', '', SnippetSource.User),
new Snippet(['fooLang'], '^y', '^y', '', 'value', '', SnippetSource.User),
]);
const provider = new SnippetCompletionProvider(modeService, snippetService);
let model = createTextModel(')*&^', undefined, 'fooLang');
let result = await provider.provideCompletionItems(
model,
new Position(1, 5),
{ triggerKind: CompletionTriggerKind.Invoke }
)!;
assert.strictEqual(result.suggestions.length, 1);
assert.strictEqual((<SnippetCompletion>result.suggestions[0]).label.label, '^y');
model.dispose();
});
test('Snippet suggestions are too eager #138707 (word/word)', async function () {
snippetService = new SimpleSnippetService([
new Snippet(['fooLang'], 'async arrow function', 'async arrow function', '', 'value', '', SnippetSource.User),
new Snippet(['fooLang'], 'foobarrrrrr', 'foobarrrrrr', '', 'value', '', SnippetSource.User),
]);
const provider = new SnippetCompletionProvider(modeService, snippetService);
let model = createTextModel('foobar', undefined, 'fooLang');
let result = await provider.provideCompletionItems(
model,
new Position(1, 7),
{ triggerKind: CompletionTriggerKind.Invoke }
)!;
assert.strictEqual(result.suggestions.length, 1);
assert.strictEqual((<SnippetCompletion>result.suggestions[0]).label.label, 'foobarrrrrr');
model.dispose();
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册