From 531ed688cc77f1d091729851c627ad224168dd2c Mon Sep 17 00:00:00 2001 From: KazariEX <1364035137@qq.com> Date: Sun, 15 Dec 2024 01:32:52 +0800 Subject: [PATCH 1/4] fix: align the completion of built-in directive modifiers with TS behavior --- .../lib/plugins/vue-template.ts | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/packages/language-service/lib/plugins/vue-template.ts b/packages/language-service/lib/plugins/vue-template.ts index a66adbd8c0..32360ba112 100644 --- a/packages/language-service/lib/plugins/vue-template.ts +++ b/packages/language-service/lib/plugins/vue-template.ts @@ -702,22 +702,27 @@ export function create( function afterHtmlCompletion(completionList: vscode.CompletionList, document: TextDocument) { - const replacement = getReplacement(completionList, document); - - if (replacement) { + do { + const replacement = getReplacement(completionList, document); + if (!replacement) { + break; + } - const isEvent = replacement.text.startsWith('v-on:') || replacement.text.startsWith('@'); - const isProp = replacement.text.startsWith('v-bind:') || replacement.text.startsWith(':'); - const isModel = replacement.text.startsWith('v-model:') || replacement.text.split('.')[0] === 'v-model'; const hasModifier = replacement.text.includes('.'); + if (!hasModifier) { + break; + } + + const [text, ...modifiers] = replacement.text.split('.'); + const isEvent = text.startsWith('v-on:') || text === 'v-on' || text.startsWith('@'); + const isProp = text.startsWith('v-bind:') || text === 'v-bind' || text.startsWith(':'); + const isModel = text.startsWith('v-model:') || text === 'v-model'; const validModifiers = isEvent ? eventModifiers : isProp ? propModifiers : undefined; - const modifiers = replacement.text.split('.').slice(1); - const textWithoutModifier = replacement.text.split('.')[0]; - if (validModifiers && hasModifier) { + if (validModifiers) { for (const modifier in validModifiers) { @@ -725,14 +730,14 @@ export function create( continue; } - const modifierDes = validModifiers[modifier]; - const insertText = textWithoutModifier + modifiers.slice(0, -1).map(m => '.' + m).join('') + '.' + modifier; + const description = validModifiers[modifier]; + const insertText = text + modifiers.slice(0, -1).map(m => '.' + m).join('') + '.' + modifier; const newItem: html.CompletionItem = { label: modifier, filterText: insertText, documentation: { kind: 'markdown', - value: modifierDes, + value: description, }, textEdit: { range: replacement.textEdit.range, @@ -744,7 +749,7 @@ export function create( completionList.items.push(newItem); } } - else if (hasModifier && isModel) { + else if (isModel) { for (const modifier of modelData.globalAttributes ?? []) { @@ -752,7 +757,7 @@ export function create( continue; } - const insertText = textWithoutModifier + modifiers.slice(0, -1).map(m => '.' + m).join('') + '.' + modifier.name; + const insertText = text + modifiers.slice(0, -1).map(m => '.' + m).join('') + '.' + modifier.name; const newItem: html.CompletionItem = { label: modifier.name, filterText: insertText, @@ -771,7 +776,8 @@ export function create( completionList.items.push(newItem); } } - } + + } while(0); completionList.items = completionList.items.filter(item => !specialTags.has(parseLabel(item.label).name)); From e169f20397cae031ec5d8e859760bcc1e32f68b8 Mon Sep 17 00:00:00 2001 From: KazariEX <1364035137@qq.com> Date: Sun, 15 Dec 2024 01:39:45 +0800 Subject: [PATCH 2/4] chore: lint [skip ci] --- packages/language-service/lib/plugins/vue-template.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/language-service/lib/plugins/vue-template.ts b/packages/language-service/lib/plugins/vue-template.ts index 32360ba112..f1ff1a74a6 100644 --- a/packages/language-service/lib/plugins/vue-template.ts +++ b/packages/language-service/lib/plugins/vue-template.ts @@ -776,8 +776,7 @@ export function create( completionList.items.push(newItem); } } - - } while(0); + } while (0); completionList.items = completionList.items.filter(item => !specialTags.has(parseLabel(item.label).name)); From 98e06560120e5c1d6f8f7dc8cddf61098e9fa10b Mon Sep 17 00:00:00 2001 From: KazariEX <1364035137@qq.com> Date: Sun, 15 Dec 2024 02:05:47 +0800 Subject: [PATCH 3/4] refactor: renaming --- .../lib/plugins/vue-template.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/language-service/lib/plugins/vue-template.ts b/packages/language-service/lib/plugins/vue-template.ts index f1ff1a74a6..81f0992191 100644 --- a/packages/language-service/lib/plugins/vue-template.ts +++ b/packages/language-service/lib/plugins/vue-template.ts @@ -107,8 +107,8 @@ export function create( // https://vuejs.org/api/built-in-directives.html#v-on // https://vuejs.org/api/built-in-directives.html#v-bind - const eventModifiers: Record = {}; - const propModifiers: Record = {}; + const vOnModifiers: Record = {}; + const vBindModifiers: Record = {}; const vOn = builtInData.globalAttributes?.find(x => x.name === 'v-on'); const vBind = builtInData.globalAttributes?.find(x => x.name === 'v-bind'); @@ -119,8 +119,8 @@ export function create( .split('\n').slice(2, -1); for (let text of modifiers) { text = text.slice(' - `.'.length); - const [name, disc] = text.split('` - '); - eventModifiers[name] = disc; + const [name, desc] = text.split('` - '); + vOnModifiers[name] = desc; } } if (vBind) { @@ -130,8 +130,8 @@ export function create( .split('\n').slice(2, -1); for (let text of modifiers) { text = text.slice(' - `.'.length); - const [name, disc] = text.split('` - '); - propModifiers[name] = disc; + const [name, desc] = text.split('` - '); + vBindModifiers[name] = desc; } } @@ -714,12 +714,12 @@ export function create( } const [text, ...modifiers] = replacement.text.split('.'); - const isEvent = text.startsWith('v-on:') || text === 'v-on' || text.startsWith('@'); - const isProp = text.startsWith('v-bind:') || text === 'v-bind' || text.startsWith(':'); - const isModel = text.startsWith('v-model:') || text === 'v-model'; + const isVOn = text === 'v-on' || text.startsWith('v-on:') || text.startsWith('@'); + const isVBind = text === 'v-bind' || text.startsWith('v-bind:') || text.startsWith(':'); + const isVModel = text === 'v-model' || text.startsWith('v-model:'); const validModifiers = - isEvent ? eventModifiers - : isProp ? propModifiers + isVOn ? vOnModifiers + : isVBind ? vBindModifiers : undefined; if (validModifiers) { @@ -749,7 +749,7 @@ export function create( completionList.items.push(newItem); } } - else if (isModel) { + else if (isVModel) { for (const modifier of modelData.globalAttributes ?? []) { From 40ebb9acbb9517583bcd108a2ba1256d81f3ed84 Mon Sep 17 00:00:00 2001 From: KazariEX <1364035137@qq.com> Date: Sun, 15 Dec 2024 13:01:35 +0800 Subject: [PATCH 4/4] fix: don't provide modifier completion for `@` and `:` --- packages/language-service/lib/plugins/vue-template.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/language-service/lib/plugins/vue-template.ts b/packages/language-service/lib/plugins/vue-template.ts index 81f0992191..1598744e02 100644 --- a/packages/language-service/lib/plugins/vue-template.ts +++ b/packages/language-service/lib/plugins/vue-template.ts @@ -714,9 +714,9 @@ export function create( } const [text, ...modifiers] = replacement.text.split('.'); - const isVOn = text === 'v-on' || text.startsWith('v-on:') || text.startsWith('@'); - const isVBind = text === 'v-bind' || text.startsWith('v-bind:') || text.startsWith(':'); - const isVModel = text === 'v-model' || text.startsWith('v-model:'); + const isVOn = text.startsWith('v-on:') || text.startsWith('@') && text.length > 1; + const isVBind = text.startsWith('v-bind:') || text.startsWith(':') && text.length > 1; + const isVModel = text.startsWith('v-model:') || text === 'v-model'; const validModifiers = isVOn ? vOnModifiers : isVBind ? vBindModifiers