未验证 提交 d6936dd5 编写于 作者: T Tyler James Leonhardt 提交者: GitHub

Add mechanism for snippets to overwrite Auto-closing pairs in some cases (#114235)

* Snippets and Auto-closing pairs play nicer

* move to DisposableStore
上级 2ca7b542
......@@ -16,6 +16,7 @@ import { ISnippetsService } from 'vs/workbench/contrib/snippets/browser/snippets
import { Snippet, SnippetSource } from 'vs/workbench/contrib/snippets/browser/snippetsFile';
import { isPatternInWord } from 'vs/base/common/filters';
import { StopWatch } from 'vs/base/common/stopwatch';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
export class SnippetCompletion implements CompletionItem {
......@@ -110,8 +111,27 @@ export class SnippetCompletionProvider implements CompletionItemProvider {
const prefixPos = position.column - (1 + start);
const prefixRestLen = snippet.prefixLow.length - prefixPos;
const endsWithPrefixRest = compareSubstring(lineContent, snippet.prefixLow, columnOffset, (columnOffset) + prefixRestLen, prefixPos, prefixPos + prefixRestLen);
const endColumn = endsWithPrefixRest === 0 ? position.column + prefixRestLen : position.column;
const replace = Range.fromPositions(position.delta(0, -prefixPos), { lineNumber: position.lineNumber, column: endColumn });
const startPosition = position.delta(0, -prefixPos);
let endColumn = endsWithPrefixRest === 0 ? position.column + prefixRestLen : position.column;
// First check if there is anything to the right of the cursor
if (columnOffset < lineContent.length) {
const autoClosingPairs = LanguageConfigurationRegistry.getAutoClosingPairs(languageId);
const standardAutoClosingPairConditionals = autoClosingPairs.autoClosingPairsCloseSingleChar.get(lineContent[columnOffset]);
// If the character to the right of the cursor is a closing character of an autoclosing pair
if (standardAutoClosingPairConditionals?.some(p =>
// and the start position is the opening character of an autoclosing pair
p.open === lineContent[startPosition.column - 1] &&
// and the snippet prefix contains the opening and closing pair at its edges
snippet.prefix.startsWith(p.open) &&
snippet.prefix[snippet.prefix.length - 1] === p.close)) {
// Eat the character that was likely inserted because of auto-closing pairs
endColumn++;
}
}
const replace = Range.fromPositions(startPosition, { lineNumber: position.lineNumber, column: endColumn });
const insert = replace.setEndPosition(position.lineNumber, position.column);
suggestions.push(new SnippetCompletion(snippet, { replace, insert }));
......
......@@ -13,6 +13,7 @@ import { ISnippetsService } from 'vs/workbench/contrib/snippets/browser/snippets
import { Snippet, SnippetSource } from 'vs/workbench/contrib/snippets/browser/snippetsFile';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { CompletionContext, CompletionTriggerKind } from 'vs/editor/common/modes';
import { DisposableStore } from 'vs/base/common/lifecycle';
class SimpleSnippetService implements ISnippetsService {
declare readonly _serviceBrand: undefined;
......@@ -35,6 +36,8 @@ class SimpleSnippetService implements ISnippetsService {
}
suite('SnippetsService', function () {
const disposableStore: DisposableStore = new DisposableStore();
const context: CompletionContext = { triggerKind: CompletionTriggerKind.Invoke };
suiteSetup(function () {
ModesRegistry.registerLanguage({
......@@ -43,9 +46,12 @@ suite('SnippetsService', function () {
});
});
suiteTeardown(function () {
disposableStore.dispose();
});
let modeService: ModeServiceImpl;
let snippetService: ISnippetsService;
let context: CompletionContext = { triggerKind: CompletionTriggerKind.Invoke };
setup(function () {
modeService = new ModeServiceImpl();
......@@ -68,7 +74,6 @@ suite('SnippetsService', function () {
)]);
});
test('snippet completions - simple', function () {
const provider = new SnippetCompletionProvider(modeService, snippetService);
......@@ -364,9 +369,10 @@ suite('SnippetsService', function () {
});
test('issue #61296: VS code freezes when editing CSS file with emoji', async function () {
let toDispose = LanguageConfigurationRegistry.register(modeService.getLanguageIdentifier('fooLang')!, {
disposableStore.add(LanguageConfigurationRegistry.register(modeService.getLanguageIdentifier('fooLang')!, {
wordPattern: /(#?-?\d*\.\d\w*%?)|(::?[\w-]*(?=[^,{;]*[,{]))|(([@#.!])?[\w-?]+%?|[@#!.])/g
});
}));
snippetService = new SimpleSnippetService([new Snippet(
['fooLang'],
'bug',
......@@ -383,8 +389,6 @@ suite('SnippetsService', function () {
let result = await provider.provideCompletionItems(model, new Position(1, 8), context)!;
assert.equal(result.suggestions.length, 1);
toDispose.dispose();
});
test('No snippets shown when triggering completions at whitespace on line that already has text #62335', async function () {
......@@ -502,4 +506,35 @@ suite('SnippetsService', function () {
assert.equal((first.range as any).insert.endColumn, 9);
assert.equal((first.range as any).replace.endColumn, 9);
});
test('Snippet will replace auto-closing pair if specified in prefix', async function () {
disposableStore.add(LanguageConfigurationRegistry.register(modeService.getLanguageIdentifier('fooLang')!, {
brackets: [
['{', '}'],
['[', ']'],
['(', ')'],
]
}));
snippetService = new SimpleSnippetService([new Snippet(
['fooLang'],
'PSCustomObject',
'[PSCustomObject]',
'',
'[PSCustomObject] @{ Key = Value }',
'',
SnippetSource.User
)]);
const provider = new SnippetCompletionProvider(modeService, snippetService);
let model = createTextModel('[psc]', undefined, modeService.getLanguageIdentifier('fooLang'));
let result = await provider.provideCompletionItems(model, new Position(1, 5), context)!;
assert.strictEqual(result.suggestions.length, 1);
let [first] = result.suggestions;
assert.strictEqual((first.range as any).insert.endColumn, 5);
// This is 6 because it should eat the `]` at the end of the text even if cursor is before it
assert.strictEqual((first.range as any).replace.endColumn, 6);
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册