diff --git a/packages/language-server/src/plugins/PluginHost.ts b/packages/language-server/src/plugins/PluginHost.ts index a4783a6a1..bbb3eac46 100644 --- a/packages/language-server/src/plugins/PluginHost.ts +++ b/packages/language-server/src/plugins/PluginHost.ts @@ -171,6 +171,22 @@ export class PluginHost implements LSProvider, OnWatchFileChanges { }); } + let itemDefaults: CompletionList['itemDefaults']; + if (completions.length === 1) { + itemDefaults = completions[0]?.result.itemDefaults; + } else { + // don't apply items default to the result of other plugins + for (const completion of completions) { + const itemDefaults = completion.result.itemDefaults; + if (!itemDefaults) { + continue; + } + completion.result.items.forEach((item) => { + item.commitCharacters ??= itemDefaults.commitCharacters; + }); + } + } + let flattenedCompletions = flatten( completions.map((completion) => completion.result.items) ); @@ -194,7 +210,10 @@ export class PluginHost implements LSProvider, OnWatchFileChanges { ); } - return CompletionList.create(flattenedCompletions, isIncomplete); + const result = CompletionList.create(flattenedCompletions, isIncomplete); + result.itemDefaults = itemDefaults; + + return result; } async resolveCompletion( diff --git a/packages/language-server/src/plugins/typescript/features/CompletionProvider.ts b/packages/language-server/src/plugins/typescript/features/CompletionProvider.ts index e7b5bec75..8e47b9b42 100644 --- a/packages/language-server/src/plugins/typescript/features/CompletionProvider.ts +++ b/packages/language-server/src/plugins/typescript/features/CompletionProvider.ts @@ -66,6 +66,12 @@ type LastCompletion = { completionList: AppCompletionList | null; }; +interface CommitCharactersOptions { + checkCommitCharacters: boolean; + defaultCommitCharacters?: string[]; + isNewIdentifierLocation?: boolean; +} + export class CompletionsProviderImpl implements CompletionsProvider { constructor( private readonly lsAndTsDocResolver: LSAndTSDocResolver, @@ -237,10 +243,8 @@ export class CompletionsProviderImpl implements CompletionsProvider { + item.commitCharacters ??= commitCharactersOptions.defaultCommitCharacters; + }); + } + } + this.lastCompletion = { key: document.getFilePath() || '', position, completionList }; return completionList; @@ -578,6 +603,7 @@ export class CompletionsProviderImpl implements CompletionsProvider ): AppCompletionItem | null { @@ -669,7 +695,7 @@ export class CompletionsProviderImpl implements CompletionsProvider { @@ -170,6 +170,34 @@ describe('CompletionProviderImpl', function () { }); } + it('provide completion with items default when supported', async () => { + const { completionProvider, document, lsConfigManager } = setup('completions.svelte'); + + lsConfigManager.updateClientCapabilities({ + textDocument: { + completion: { + completionList: { + itemDefaults: ['commitCharacters'] + } + } + } + }); + + const completions = await completionProvider.getCompletions( + document, + Position.create(0, 49), + { + triggerKind: CompletionTriggerKind.TriggerCharacter, + triggerCharacter: '.' + } + ); + + assert.deepStrictEqual(completions?.itemDefaults?.commitCharacters, ['.', ',', ';', '(']); + + const first = completions!.items[0]; + assert.strictEqual(first.commitCharacters, undefined); + }); + it('provides event completions', async () => { const { completionProvider, document } = setup('component-events-completion.svelte'); @@ -191,6 +219,7 @@ describe('CompletionProviderImpl', function () { assert.deepStrictEqual(eventCompletions, [ { + commitCharacters: [], detail: 'aa: CustomEvent', documentation: '', label: 'on:aa', @@ -199,6 +228,7 @@ describe('CompletionProviderImpl', function () { textEdit: undefined }, { + commitCharacters: [], detail: 'ab: MouseEvent', documentation: { kind: 'markdown', @@ -210,6 +240,7 @@ describe('CompletionProviderImpl', function () { textEdit: undefined }, { + commitCharacters: [], detail: 'ac: any', documentation: '', label: 'on:ac', @@ -309,6 +340,7 @@ describe('CompletionProviderImpl', function () { assert.deepStrictEqual(eventCompletions, [ { + commitCharacters: [], detail: 'aa: CustomEvent', documentation: '', label: 'on:aa', @@ -329,6 +361,7 @@ describe('CompletionProviderImpl', function () { } }, { + commitCharacters: [], detail: 'ab: MouseEvent', documentation: { kind: 'markdown', @@ -352,6 +385,7 @@ describe('CompletionProviderImpl', function () { } }, { + commitCharacters: [], detail: 'ac: any', documentation: '', label: 'on:ac', @@ -389,6 +423,7 @@ describe('CompletionProviderImpl', function () { assert.deepStrictEqual(eventCompletions, [ { + commitCharacters: [], detail: 'c: CustomEvent', documentation: { kind: 'markdown', @@ -417,6 +452,7 @@ describe('CompletionProviderImpl', function () { assert.deepStrictEqual(eventCompletions, [ { + commitCharacters: [], detail: 'event1: CustomEvent', documentation: '', label: 'on:event1', @@ -437,6 +473,7 @@ describe('CompletionProviderImpl', function () { } }, { + commitCharacters: [], detail: 'event2: CustomEvent', documentation: { kind: 'markdown', @@ -477,6 +514,7 @@ describe('CompletionProviderImpl', function () { assert.deepStrictEqual(eventCompletions, [ { + commitCharacters: [], detail: 'event1: CustomEvent | CustomEvent', label: 'on:event1', sortText: '-1', @@ -1101,6 +1139,7 @@ describe('CompletionProviderImpl', function () { assert.deepStrictEqual(slotLetCompletions, [ { + commitCharacters: [], detail: 'let1: boolean', documentation: '', label: 'let:let1', @@ -1121,6 +1160,7 @@ describe('CompletionProviderImpl', function () { } }, { + commitCharacters: [], detail: 'let2: string', documentation: { kind: 'markdown', @@ -1290,7 +1330,7 @@ describe('CompletionProviderImpl', function () { insertText: undefined, insertTextFormat: undefined, labelDetails: undefined, - commitCharacters: ['.', ',', ';', '('], + commitCharacters: [], textEdit: { newText: '@hi', range: {