From c5713c1a1089c98fafa6ab3642660ce87900a09d Mon Sep 17 00:00:00 2001 From: Mathias Picker Date: Sat, 6 Dec 2025 18:52:30 +0100 Subject: [PATCH 1/3] only create objects for completion items for svelte syntax once --- .../plugins/svelte/features/getCompletions.ts | 87 +++++++++++-------- 1 file changed, 51 insertions(+), 36 deletions(-) diff --git a/packages/language-server/src/plugins/svelte/features/getCompletions.ts b/packages/language-server/src/plugins/svelte/features/getCompletions.ts index 99259ba94..94f73100b 100644 --- a/packages/language-server/src/plugins/svelte/features/getCompletions.ts +++ b/packages/language-server/src/plugins/svelte/features/getCompletions.ts @@ -109,6 +109,48 @@ function getEventModifierCompletion(attributeContext: AttributeContext): Complet return CompletionList.create(items); } +const atCompletionItems = createCompletionItems([ + { tag: 'html', label: 'html' }, + { tag: 'debug', label: 'debug' }, + { tag: 'const', label: 'const' }, + { tag: 'render', label: 'render' }, + { tag: 'attach', label: 'attach' } +]); + +const hashtagCompletionItems = createCompletionItems([ + { tag: 'if', label: 'if', insertText: 'if $1}\n\t$2\n{/if' }, + { tag: 'each', label: 'each', insertText: 'each $1 as $2}\n\t$3\n{/each' }, + { + tag: 'await', + label: 'await :then', + insertText: 'await $1}\n\t$2\n{:then $3} \n\t$4\n{/await' + }, + { + tag: 'await', + label: 'await then', + insertText: 'await $1 then $2}\n\t$3\n{/await' + }, + { tag: 'key', label: 'key', insertText: 'key $1}\n\t$2\n{/key' }, + { tag: 'snippet', label: 'snippet', insertText: 'snippet $1($2)}\n\t$3\n{/snippet' } +]); + +const beginningAwaitOpenCompletionItems = createCompletionItems([ + { tag: 'await', label: 'then' }, + { tag: 'await', label: 'catch' } +]); + +const beginningEachOpenCompletionItems = createCompletionItems([{ tag: 'each', label: 'else' }]); + +const beginningIfOpenCompletionItems = createCompletionItems([ + { tag: 'if', label: 'else' }, + { tag: 'if', label: 'else if' } +]); + +const endAwaitOpenCompletionItems = createCompletionItems([{ tag: 'await', label: 'await' }]); +const endEachOpenCompletionItems = createCompletionItems([{ tag: 'each', label: 'each' }]); +const endIfOpenCompletionItems = createCompletionItems([{ tag: 'if', label: 'if' }]); +const endKeyOpenCompletionItems = createCompletionItems([{ tag: 'key', label: 'key' }]); + /** * Get completions with regard to trigger character. */ @@ -118,46 +160,19 @@ function getCompletionsWithRegardToTriggerCharacter( offset: number ) { if (triggerCharacter === '@') { - return createCompletionItems([ - { tag: 'html', label: 'html' }, - { tag: 'debug', label: 'debug' }, - { tag: 'const', label: 'const' }, - { tag: 'render', label: 'render' }, - { tag: 'attach', label: 'attach' } - ]); + return atCompletionItems; } if (triggerCharacter === '#') { - return createCompletionItems([ - { tag: 'if', label: 'if', insertText: 'if $1}\n\t$2\n{/if' }, - { tag: 'each', label: 'each', insertText: 'each $1 as $2}\n\t$3\n{/each' }, - { - tag: 'await', - label: 'await :then', - insertText: 'await $1}\n\t$2\n{:then $3} \n\t$4\n{/await' - }, - { - tag: 'await', - label: 'await then', - insertText: 'await $1 then $2}\n\t$3\n{/await' - }, - { tag: 'key', label: 'key', insertText: 'key $1}\n\t$2\n{/key' }, - { tag: 'snippet', label: 'snippet', insertText: 'snippet $1($2)}\n\t$3\n{/snippet' } - ]); + return hashtagCompletionItems; } if (triggerCharacter === ':') { return showCompletionWithRegardsToOpenedTags( { - awaitOpen: createCompletionItems([ - { tag: 'await', label: 'then' }, - { tag: 'await', label: 'catch' } - ]), - eachOpen: createCompletionItems([{ tag: 'each', label: 'else' }]), - ifOpen: createCompletionItems([ - { tag: 'if', label: 'else' }, - { tag: 'if', label: 'else if' } - ]) + awaitOpen: beginningAwaitOpenCompletionItems, + eachOpen: beginningEachOpenCompletionItems, + ifOpen: beginningIfOpenCompletionItems }, svelteDoc, offset @@ -167,10 +182,10 @@ function getCompletionsWithRegardToTriggerCharacter( if (triggerCharacter === '/') { return showCompletionWithRegardsToOpenedTags( { - awaitOpen: createCompletionItems([{ tag: 'await', label: 'await' }]), - eachOpen: createCompletionItems([{ tag: 'each', label: 'each' }]), - ifOpen: createCompletionItems([{ tag: 'if', label: 'if' }]), - keyOpen: createCompletionItems([{ tag: 'key', label: 'key' }]) + awaitOpen: endAwaitOpenCompletionItems, + eachOpen: endEachOpenCompletionItems, + ifOpen: endIfOpenCompletionItems, + keyOpen: endKeyOpenCompletionItems }, svelteDoc, offset From c8488fa0b3589bec2496156cb18b2a5b0abc2d30 Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Sat, 6 Dec 2025 18:56:02 +0100 Subject: [PATCH 2/3] Optimize completion items handling for Svelte syntax --- .changeset/sharp-jeans-attack.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sharp-jeans-attack.md diff --git a/.changeset/sharp-jeans-attack.md b/.changeset/sharp-jeans-attack.md new file mode 100644 index 000000000..607bfe61b --- /dev/null +++ b/.changeset/sharp-jeans-attack.md @@ -0,0 +1,5 @@ +--- +"svelte-language-server": patch +--- + +[perf]: avoid re-reacting completion items for svelte syntax every time `getCompletionsWithRegardToTriggerCharacter` is called From 97f761bfb1db361a1ae34d8dff0ed336447b1d62 Mon Sep 17 00:00:00 2001 From: Mathias Picker Date: Sun, 7 Dec 2025 11:45:31 +0100 Subject: [PATCH 3/3] format --- .changeset/sharp-jeans-attack.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/sharp-jeans-attack.md b/.changeset/sharp-jeans-attack.md index 607bfe61b..f93abbe73 100644 --- a/.changeset/sharp-jeans-attack.md +++ b/.changeset/sharp-jeans-attack.md @@ -1,5 +1,5 @@ --- -"svelte-language-server": patch +'svelte-language-server': patch --- [perf]: avoid re-reacting completion items for svelte syntax every time `getCompletionsWithRegardToTriggerCharacter` is called