Skip to content

Commit

Permalink
Merge pull request #138974 from microsoft/joh/fix/138707
Browse files Browse the repository at this point in the history
be more strict when suggesting snippets at word ends
  • Loading branch information
jrieken committed Dec 15, 2021
2 parents 8e7b278 + 6d1c824 commit bfb6730
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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;
Expand All @@ -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)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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);
});
Expand Down Expand Up @@ -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();
});
});

0 comments on commit bfb6730

Please sign in to comment.