From a5924046c2f6481c0cb1508b30e1abf177202b78 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 13 Dec 2021 10:59:55 +0100 Subject: [PATCH] fix word-word case, https://github.com/microsoft/vscode/issues/138846 --- .../browser/snippetCompletionProvider.ts | 9 +++++-- .../test/browser/snippetsService.test.ts | 27 ++++++++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts b/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts index 74103ead7b3..24b7cf9fdd9 100644 --- a/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts +++ b/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts @@ -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 { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; +import { getWordAtText } from 'vs/editor/common/model/wordHelper'; export class SnippetCompletion implements CompletionItem { @@ -68,6 +69,7 @@ export class SnippetCompletionProvider implements CompletionItemProvider { const sw = new StopWatch(true); const languageId = this._getLanguageIdAtPosition(model, position); + const languageConfig = this._languageConfigurationService.getLanguageConfiguration(languageId); const snippets = new Set(await this._snippets.getSnippets(languageId)); const lineContentLow = model.getLineContent(position.lineNumber).toLowerCase(); @@ -78,9 +80,12 @@ export class SnippetCompletionProvider implements CompletionItemProvider { const triggerCharacterLow = context.triggerCharacter?.toLowerCase() ?? ''; + for (const snippet of snippets) { - if (wordUntil && snippet.prefixLow.length < wordUntil.length && !isPatternInWord(snippet.prefixLow, 0, snippet.prefixLow.length, wordUntil, 0, wordUntil.length)) { + const word = getWordAtText(1, languageConfig.getWordDefinition(), snippet.prefixLow, 0); + + if (wordUntil && word && !isPatternInWord(wordUntil, 0, wordUntil.length, snippet.prefixLow, 0, snippet.prefixLow.length)) { // when at a word the snippet prefix must match continue; } @@ -104,7 +109,7 @@ export class SnippetCompletionProvider implements CompletionItemProvider { // First check if there is anything to the right of the cursor if (columnOffset < lineContentLow.length) { - const autoClosingPairs = this._languageConfigurationService.getLanguageConfiguration(languageId).getAutoClosingPairs(); + const autoClosingPairs = languageConfig.getAutoClosingPairs(); const standardAutoClosingPairConditionals = autoClosingPairs.autoClosingPairsCloseSingleChar.get(lineContentLow[columnOffset]); // If the character to the right of the cursor is a closing character of an autoclosing pair if (standardAutoClosingPairConditionals?.some(p => diff --git a/src/vs/workbench/contrib/snippets/test/browser/snippetsService.test.ts b/src/vs/workbench/contrib/snippets/test/browser/snippetsService.test.ts index a5ce99557d1..19ff77081f7 100644 --- a/src/vs/workbench/contrib/snippets/test/browser/snippetsService.test.ts +++ b/src/vs/workbench/contrib/snippets/test/browser/snippetsService.test.ts @@ -650,7 +650,7 @@ suite('SnippetsService', function () { test('Snippet suggestions are too eager #138707 (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'], 'hell_or_tell', 'hell_or_tell', '', 'value', '', SnippetSource.User), new Snippet(['fooLang'], '^y', '^y', '', 'value', '', SnippetSource.User), ]); @@ -663,8 +663,9 @@ suite('SnippetsService', function () { { triggerKind: CompletionTriggerKind.Invoke } )!; - assert.strictEqual(result.suggestions.length, 1); - assert.strictEqual((result.suggestions[0]).label.label, 't'); + assert.strictEqual(result.suggestions.length, 2); + assert.strictEqual((result.suggestions[0]).label.label, '^y'); + assert.strictEqual((result.suggestions[1]).label.label, 'hell_or_tell'); model.dispose(); }); @@ -688,4 +689,24 @@ suite('SnippetsService', function () { assert.strictEqual((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(languageService, snippetService, new TestLanguageConfigurationService()); + 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((result.suggestions[0]).label.label, 'foobarrrrrr'); + model.dispose(); + }); });