@vue/language-service 2.2.0 → 2.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/language-blocks/zh-cn.json +6 -6
- package/data/model-modifiers/zh-cn.json +1 -1
- package/data/template/it.json +5 -5
- package/index.js +12 -8
- package/lib/ideFeatures/nameCasing.js +6 -6
- package/lib/plugins/css.js +59 -0
- package/lib/plugins/utils.d.ts +3 -0
- package/lib/plugins/utils.js +14 -0
- package/lib/plugins/vue-autoinsert-dotvalue.d.ts +0 -9
- package/lib/plugins/vue-autoinsert-dotvalue.js +31 -50
- package/lib/plugins/vue-autoinsert-self-closing.d.ts +2 -0
- package/lib/plugins/vue-autoinsert-self-closing.js +33 -0
- package/lib/plugins/vue-complete-define-assignment.js +6 -5
- package/lib/plugins/vue-directive-comments.d.ts +4 -0
- package/lib/plugins/vue-directive-comments.js +4 -0
- package/lib/plugins/vue-document-drop.js +5 -5
- package/lib/plugins/vue-document-links.js +5 -4
- package/lib/plugins/vue-extract-file.d.ts +2 -1
- package/lib/plugins/vue-extract-file.js +12 -7
- package/lib/plugins/vue-inlayhints.d.ts +1 -1
- package/lib/plugins/vue-inlayhints.js +11 -11
- package/lib/plugins/vue-sfc.js +48 -7
- package/lib/plugins/vue-template/autoinsert-self-closing-tags.d.ts +6 -0
- package/lib/plugins/vue-template/autoinsert-self-closing-tags.js +39 -0
- package/lib/plugins/vue-template/autoinsert-selfClosingTags.d.ts +1 -0
- package/lib/plugins/vue-template/autoinsert-selfClosingTags.js +3 -0
- package/lib/plugins/vue-template/autoinsert-selfclosing-tags.d.ts +1 -0
- package/lib/plugins/vue-template/autoinsert-selfclosing-tags.js +3 -0
- package/lib/plugins/vue-template.js +40 -50
- package/package.json +8 -7
|
@@ -45,14 +45,14 @@ function create(ts, getTsPluginClient) {
|
|
|
45
45
|
if (!importUri || !vueCompilerOptions.extensions.some(ext => importUri.endsWith(ext))) {
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
baseName = baseName.slice(0, baseName.lastIndexOf('.'));
|
|
50
|
-
const newName = (0, shared_1.capitalize)((0, shared_1.camelize)(baseName));
|
|
51
|
-
const sfc = root._sfc;
|
|
48
|
+
const { sfc } = root;
|
|
52
49
|
const script = sfc.scriptSetup ?? sfc.script;
|
|
53
50
|
if (!script) {
|
|
54
51
|
return;
|
|
55
52
|
}
|
|
53
|
+
let baseName = importUri.slice(importUri.lastIndexOf('/') + 1);
|
|
54
|
+
baseName = baseName.slice(0, baseName.lastIndexOf('.'));
|
|
55
|
+
const newName = (0, shared_1.capitalize)((0, shared_1.camelize)(baseName));
|
|
56
56
|
const additionalEdit = {};
|
|
57
57
|
const code = [...(0, language_core_1.forEachEmbeddedCode)(root)].find(code => code.id === (sfc.scriptSetup ? 'scriptsetup_raw' : 'script_raw'));
|
|
58
58
|
const lastImportNode = (0, vue_extract_file_1.getLastImportNode)(ts, script.ast);
|
|
@@ -91,7 +91,7 @@ function create(ts, getTsPluginClient) {
|
|
|
91
91
|
+ (lastImportNode ? '' : '\n'),
|
|
92
92
|
});
|
|
93
93
|
if (sfc.script) {
|
|
94
|
-
const edit = (0, vue_extract_file_1.createAddComponentToOptionEdit)(ts, sfc.script.ast, newName);
|
|
94
|
+
const edit = (0, vue_extract_file_1.createAddComponentToOptionEdit)(ts, sfc, sfc.script.ast, newName);
|
|
95
95
|
if (edit) {
|
|
96
96
|
additionalEdit.changes[embeddedDocumentUriStr].push({
|
|
97
97
|
range: {
|
|
@@ -24,12 +24,13 @@ function create() {
|
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
26
|
const result = [];
|
|
27
|
-
const
|
|
28
|
-
const
|
|
27
|
+
const { sfc } = root;
|
|
28
|
+
const codegen = language_core_1.tsCodegen.get(sfc);
|
|
29
|
+
const scopedClasses = codegen?.getGeneratedTemplate()?.scopedClasses ?? [];
|
|
29
30
|
const styleClasses = new Map();
|
|
30
31
|
const option = root.vueCompilerOptions.experimentalResolveStyleCssClasses;
|
|
31
|
-
for (let i = 0; i <
|
|
32
|
-
const style =
|
|
32
|
+
for (let i = 0; i < sfc.styles.length; i++) {
|
|
33
|
+
const style = sfc.styles[i];
|
|
33
34
|
if (option === 'always' || (option === 'scoped' && style.scoped)) {
|
|
34
35
|
for (const className of style.classNames) {
|
|
35
36
|
if (!styleClasses.has(className.text.slice(1))) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
|
|
2
|
+
import { Sfc } from '@vue/language-core';
|
|
2
3
|
import type * as ts from 'typescript';
|
|
3
4
|
export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
|
|
4
5
|
export declare function getLastImportNode(ts: typeof import('typescript'), sourceFile: ts.SourceFile): ts.Node | undefined;
|
|
5
|
-
export declare function createAddComponentToOptionEdit(ts: typeof import('typescript'), ast: ts.SourceFile, componentName: string): {
|
|
6
|
+
export declare function createAddComponentToOptionEdit(ts: typeof import('typescript'), sfc: Sfc, ast: ts.SourceFile, componentName: string): {
|
|
6
7
|
range: import("@vue/language-core").TextRange;
|
|
7
8
|
newText: string;
|
|
8
9
|
} | undefined;
|
|
@@ -11,13 +11,17 @@ function create(ts, getTsPluginClient) {
|
|
|
11
11
|
name: 'vue-extract-file',
|
|
12
12
|
capabilities: {
|
|
13
13
|
codeActionProvider: {
|
|
14
|
+
codeActionKinds: ['refactor'],
|
|
14
15
|
resolveProvider: true,
|
|
15
16
|
},
|
|
16
17
|
},
|
|
17
18
|
create(context) {
|
|
18
19
|
const tsPluginClient = getTsPluginClient?.(context);
|
|
19
20
|
return {
|
|
20
|
-
provideCodeActions(document, range,
|
|
21
|
+
provideCodeActions(document, range, ctx) {
|
|
22
|
+
if (ctx.only && !ctx.only.includes('refactor')) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
21
25
|
const startOffset = document.offsetAt(range.start);
|
|
22
26
|
const endOffset = document.offsetAt(range.end);
|
|
23
27
|
if (startOffset === endOffset) {
|
|
@@ -34,7 +38,7 @@ function create(ts, getTsPluginClient) {
|
|
|
34
38
|
if (!(root instanceof language_core_1.VueVirtualCode)) {
|
|
35
39
|
return;
|
|
36
40
|
}
|
|
37
|
-
const sfc = root
|
|
41
|
+
const { sfc } = root;
|
|
38
42
|
const script = sfc.scriptSetup ?? sfc.script;
|
|
39
43
|
if (!sfc.template || !script) {
|
|
40
44
|
return;
|
|
@@ -69,7 +73,7 @@ function create(ts, getTsPluginClient) {
|
|
|
69
73
|
if (!(root instanceof language_core_1.VueVirtualCode)) {
|
|
70
74
|
return codeAction;
|
|
71
75
|
}
|
|
72
|
-
const sfc = root
|
|
76
|
+
const { sfc } = root;
|
|
73
77
|
const script = sfc.scriptSetup ?? sfc.script;
|
|
74
78
|
if (!sfc.template || !script) {
|
|
75
79
|
return codeAction;
|
|
@@ -118,7 +122,7 @@ function create(ts, getTsPluginClient) {
|
|
|
118
122
|
},
|
|
119
123
|
];
|
|
120
124
|
if (sfc.script) {
|
|
121
|
-
const edit = createAddComponentToOptionEdit(ts, sfc.script.ast, newName);
|
|
125
|
+
const edit = createAddComponentToOptionEdit(ts, sfc, sfc.script.ast, newName);
|
|
122
126
|
if (edit) {
|
|
123
127
|
sfcEdits.push({
|
|
124
128
|
range: {
|
|
@@ -247,11 +251,12 @@ function getLastImportNode(ts, sourceFile) {
|
|
|
247
251
|
}
|
|
248
252
|
return lastImportNode;
|
|
249
253
|
}
|
|
250
|
-
function createAddComponentToOptionEdit(ts, ast, componentName) {
|
|
251
|
-
const
|
|
252
|
-
if (!exportDefault) {
|
|
254
|
+
function createAddComponentToOptionEdit(ts, sfc, ast, componentName) {
|
|
255
|
+
const scriptRanges = language_core_1.tsCodegen.get(sfc)?.getScriptRanges();
|
|
256
|
+
if (!scriptRanges?.exportDefault) {
|
|
253
257
|
return;
|
|
254
258
|
}
|
|
259
|
+
const { exportDefault } = scriptRanges;
|
|
255
260
|
// https://github.com/microsoft/TypeScript/issues/36174
|
|
256
261
|
const printer = ts.createPrinter();
|
|
257
262
|
if (exportDefault.componentsOption && exportDefault.componentsOptionNode) {
|
|
@@ -4,4 +4,4 @@ export declare function create(ts: typeof import('typescript')): LanguageService
|
|
|
4
4
|
/**
|
|
5
5
|
* Refactored from https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/script/definePropsDestructure.ts
|
|
6
6
|
*/
|
|
7
|
-
export declare function findDestructuredProps(ts: typeof import('typescript'), ast: ts.SourceFile, props:
|
|
7
|
+
export declare function findDestructuredProps(ts: typeof import('typescript'), ast: ts.SourceFile, props: MapIterator<string>): [ts.Identifier, boolean][];
|
|
@@ -26,17 +26,17 @@ function create(ts) {
|
|
|
26
26
|
return settings[key] ??= await context.env.getConfiguration?.(key) ?? false;
|
|
27
27
|
}
|
|
28
28
|
const result = [];
|
|
29
|
-
const codegen = language_core_1.tsCodegen.get(virtualCode.
|
|
29
|
+
const codegen = language_core_1.tsCodegen.get(virtualCode.sfc);
|
|
30
30
|
const inlayHints = [
|
|
31
|
-
...codegen?.
|
|
32
|
-
...codegen?.
|
|
31
|
+
...codegen?.getGeneratedTemplate()?.inlayHints ?? [],
|
|
32
|
+
...codegen?.getGeneratedScript()?.inlayHints ?? [],
|
|
33
33
|
];
|
|
34
|
-
const scriptSetupRanges = codegen?.
|
|
35
|
-
if (scriptSetupRanges?.defineProps?.destructured && virtualCode.
|
|
34
|
+
const scriptSetupRanges = codegen?.getScriptSetupRanges();
|
|
35
|
+
if (scriptSetupRanges?.defineProps?.destructured && virtualCode.sfc.scriptSetup?.ast) {
|
|
36
36
|
const setting = 'vue.inlayHints.destructuredProps';
|
|
37
37
|
const enabled = await getSettingEnabled(setting);
|
|
38
38
|
if (enabled) {
|
|
39
|
-
for (const [prop, isShorthand] of findDestructuredProps(ts, virtualCode.
|
|
39
|
+
for (const [prop, isShorthand] of findDestructuredProps(ts, virtualCode.sfc.scriptSetup.ast, scriptSetupRanges.defineProps.destructured.keys())) {
|
|
40
40
|
const name = prop.text;
|
|
41
41
|
const end = prop.getEnd();
|
|
42
42
|
const pos = isShorthand ? end : end - name.length;
|
|
@@ -51,9 +51,9 @@ function create(ts) {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
const blocks = [
|
|
54
|
-
virtualCode.
|
|
55
|
-
virtualCode.
|
|
56
|
-
virtualCode.
|
|
54
|
+
virtualCode.sfc.template,
|
|
55
|
+
virtualCode.sfc.script,
|
|
56
|
+
virtualCode.sfc.scriptSetup,
|
|
57
57
|
];
|
|
58
58
|
const start = document.offsetAt(range.start);
|
|
59
59
|
const end = document.offsetAt(range.end);
|
|
@@ -148,7 +148,7 @@ function findDestructuredProps(ts, ast, props) {
|
|
|
148
148
|
&& initializer
|
|
149
149
|
&& ts.isCallExpression(initializer)
|
|
150
150
|
&& initializer.expression.getText(ast) === 'defineProps';
|
|
151
|
-
for (const
|
|
151
|
+
for (const { id } of (0, index_1.collectIdentifiers)(ts, name)) {
|
|
152
152
|
if (isDefineProps) {
|
|
153
153
|
excludedIds.add(id);
|
|
154
154
|
}
|
|
@@ -163,7 +163,7 @@ function findDestructuredProps(ts, ast, props) {
|
|
|
163
163
|
registerLocalBinding(name);
|
|
164
164
|
}
|
|
165
165
|
for (const p of parameters) {
|
|
166
|
-
for (const
|
|
166
|
+
for (const { id } of (0, index_1.collectIdentifiers)(ts, p)) {
|
|
167
167
|
registerLocalBinding(id);
|
|
168
168
|
}
|
|
169
169
|
}
|
package/lib/plugins/vue-sfc.js
CHANGED
|
@@ -8,7 +8,7 @@ const vscode_uri_1 = require("vscode-uri");
|
|
|
8
8
|
const data_1 = require("./data");
|
|
9
9
|
let sfcDataProvider;
|
|
10
10
|
function create() {
|
|
11
|
-
const
|
|
11
|
+
const htmlService = (0, volar_service_html_1.create)({
|
|
12
12
|
documentSelector: ['vue-root-tags'],
|
|
13
13
|
useDefaultDataProvider: false,
|
|
14
14
|
getCustomData(context) {
|
|
@@ -19,7 +19,7 @@ function create() {
|
|
|
19
19
|
return await worker(document, context, async (root) => {
|
|
20
20
|
const formatSettings = await context.env.getConfiguration?.('html.format') ?? {};
|
|
21
21
|
const blockTypes = ['template', 'script', 'style'];
|
|
22
|
-
for (const customBlock of root.
|
|
22
|
+
for (const customBlock of root.sfc.customBlocks) {
|
|
23
23
|
blockTypes.push(customBlock.type);
|
|
24
24
|
}
|
|
25
25
|
return {
|
|
@@ -36,12 +36,19 @@ function create() {
|
|
|
36
36
|
},
|
|
37
37
|
});
|
|
38
38
|
return {
|
|
39
|
-
...
|
|
39
|
+
...htmlService,
|
|
40
40
|
name: 'vue-sfc',
|
|
41
|
+
capabilities: {
|
|
42
|
+
...htmlService.capabilities,
|
|
43
|
+
diagnosticProvider: {
|
|
44
|
+
interFileDependencies: false,
|
|
45
|
+
workspaceDiagnostics: false,
|
|
46
|
+
}
|
|
47
|
+
},
|
|
41
48
|
create(context) {
|
|
42
|
-
const
|
|
49
|
+
const htmlServiceInstance = htmlService.create(context);
|
|
43
50
|
return {
|
|
44
|
-
...
|
|
51
|
+
...htmlServiceInstance,
|
|
45
52
|
provideDocumentLinks: undefined,
|
|
46
53
|
async resolveEmbeddedCodeFormattingOptions(sourceScript, virtualCode, options) {
|
|
47
54
|
if (sourceScript.generated?.root instanceof language_core_1.VueVirtualCode) {
|
|
@@ -63,10 +70,44 @@ function create() {
|
|
|
63
70
|
}
|
|
64
71
|
return options;
|
|
65
72
|
},
|
|
73
|
+
provideDiagnostics(document, token) {
|
|
74
|
+
return worker(document, context, async (root) => {
|
|
75
|
+
const { vueSfc, sfc } = root;
|
|
76
|
+
if (!vueSfc) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const originalResult = await htmlServiceInstance.provideDiagnostics?.(document, token);
|
|
80
|
+
const sfcErrors = [];
|
|
81
|
+
const { template } = sfc;
|
|
82
|
+
const { startTagEnd = Infinity, endTagStart = -Infinity } = template ?? {};
|
|
83
|
+
for (const error of vueSfc.errors) {
|
|
84
|
+
if ('code' in error) {
|
|
85
|
+
const start = error.loc?.start.offset ?? 0;
|
|
86
|
+
const end = error.loc?.end.offset ?? 0;
|
|
87
|
+
if (end < startTagEnd || start >= endTagStart) {
|
|
88
|
+
sfcErrors.push({
|
|
89
|
+
range: {
|
|
90
|
+
start: document.positionAt(start),
|
|
91
|
+
end: document.positionAt(end),
|
|
92
|
+
},
|
|
93
|
+
severity: 1,
|
|
94
|
+
code: error.code,
|
|
95
|
+
source: 'vue',
|
|
96
|
+
message: error.message,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return [
|
|
102
|
+
...originalResult ?? [],
|
|
103
|
+
...sfcErrors
|
|
104
|
+
];
|
|
105
|
+
});
|
|
106
|
+
},
|
|
66
107
|
provideDocumentSymbols(document) {
|
|
67
108
|
return worker(document, context, root => {
|
|
68
109
|
const result = [];
|
|
69
|
-
const sfc = root
|
|
110
|
+
const { sfc } = root;
|
|
70
111
|
if (sfc.template) {
|
|
71
112
|
result.push({
|
|
72
113
|
name: 'template',
|
|
@@ -148,7 +189,7 @@ function create() {
|
|
|
148
189
|
});
|
|
149
190
|
},
|
|
150
191
|
async provideCompletionItems(document, position, context, token) {
|
|
151
|
-
const result = await
|
|
192
|
+
const result = await htmlServiceInstance.provideCompletionItems?.(document, position, context, token);
|
|
152
193
|
if (!result) {
|
|
153
194
|
return;
|
|
154
195
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { LanguageServiceContext, LanguageServicePluginInstance } from '@volar/language-service';
|
|
2
|
+
import * as html from 'vscode-html-languageservice';
|
|
3
|
+
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
4
|
+
export declare function provideAutoInsertSelfClosingTags(context: LanguageServiceContext, service: LanguageServicePluginInstance, document: TextDocument, position: html.Position, change: {
|
|
5
|
+
text: string;
|
|
6
|
+
}): Promise<">" | undefined>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.provideAutoInsertSelfClosingTags = provideAutoInsertSelfClosingTags;
|
|
4
|
+
const html = require("vscode-html-languageservice");
|
|
5
|
+
const vue_template_1 = require("../vue-template");
|
|
6
|
+
async function provideAutoInsertSelfClosingTags(context, service, document, position, change) {
|
|
7
|
+
if (document.languageId !== 'html') {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const enabled = await context.env.getConfiguration?.('vue.autoInsert.selfClosing') ?? true;
|
|
11
|
+
if (!enabled) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (change.text !== '/') {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const scanner = (0, vue_template_1.getScanner)(service, document, 'html');
|
|
18
|
+
if (!scanner) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const offset = document.offsetAt(position);
|
|
22
|
+
let token;
|
|
23
|
+
let inStartTag = false;
|
|
24
|
+
while ((token = scanner.scan()) !== html.TokenType.EOS) {
|
|
25
|
+
if (token === html.TokenType.StartTagOpen) {
|
|
26
|
+
inStartTag = true;
|
|
27
|
+
}
|
|
28
|
+
else if (token === html.TokenType.StartTagClose || token === html.TokenType.StartTagSelfClose) {
|
|
29
|
+
inStartTag = false;
|
|
30
|
+
}
|
|
31
|
+
else if (scanner.getTokenOffset() + 1 === offset) {
|
|
32
|
+
if (token === html.TokenType.Unknown) {
|
|
33
|
+
return '>';
|
|
34
|
+
}
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=autoinsert-self-closing-tags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -30,7 +30,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
30
30
|
let customData = [];
|
|
31
31
|
let extraCustomData = [];
|
|
32
32
|
let lastCompletionComponentNames = new Set();
|
|
33
|
-
const
|
|
33
|
+
const cachedPropInfos = new Map();
|
|
34
34
|
const onDidChangeCustomDataListeners = new Set();
|
|
35
35
|
const onDidChangeCustomData = (listener) => {
|
|
36
36
|
onDidChangeCustomDataListeners.add(listener);
|
|
@@ -131,7 +131,6 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
131
131
|
if (!context.project.vue) {
|
|
132
132
|
return;
|
|
133
133
|
}
|
|
134
|
-
const vueCompilerOptions = context.project.vue.compilerOptions;
|
|
135
134
|
let sync;
|
|
136
135
|
let currentVersion;
|
|
137
136
|
const uri = vscode_uri_1.URI.parse(document.uri);
|
|
@@ -141,7 +140,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
141
140
|
if (root instanceof language_core_1.VueVirtualCode) {
|
|
142
141
|
// #4298: Precompute HTMLDocument before provideHtmlData to avoid parseHTMLDocument requesting component names from tsserver
|
|
143
142
|
baseServiceInstance.provideCompletionItems?.(document, position, completionContext, token);
|
|
144
|
-
sync = (await provideHtmlData(
|
|
143
|
+
sync = (await provideHtmlData(sourceScript.id, root)).sync;
|
|
145
144
|
currentVersion = await sync();
|
|
146
145
|
}
|
|
147
146
|
let htmlComplete = await baseServiceInstance.provideCompletionItems?.(document, position, completionContext, token);
|
|
@@ -302,7 +301,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
302
301
|
}
|
|
303
302
|
const originalResult = await baseServiceInstance.provideDiagnostics?.(document, token);
|
|
304
303
|
const templateErrors = [];
|
|
305
|
-
const { template } = root.
|
|
304
|
+
const { template } = root.sfc;
|
|
306
305
|
if (template) {
|
|
307
306
|
for (const error of template.errors) {
|
|
308
307
|
onCompilerError(error, 1);
|
|
@@ -352,7 +351,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
352
351
|
if (!(root instanceof language_core_1.VueVirtualCode)) {
|
|
353
352
|
return;
|
|
354
353
|
}
|
|
355
|
-
const { template } = root.
|
|
354
|
+
const { template } = root.sfc;
|
|
356
355
|
if (!template) {
|
|
357
356
|
return;
|
|
358
357
|
}
|
|
@@ -378,7 +377,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
378
377
|
});
|
|
379
378
|
},
|
|
380
379
|
};
|
|
381
|
-
async function provideHtmlData(
|
|
380
|
+
async function provideHtmlData(sourceDocumentUri, vueCode) {
|
|
382
381
|
await (initializing ??= initialize());
|
|
383
382
|
const casing = await (0, nameCasing_1.getNameCasing)(context, sourceDocumentUri);
|
|
384
383
|
if (builtInData.tags) {
|
|
@@ -401,8 +400,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
401
400
|
const tagInfos = new Map();
|
|
402
401
|
let version = 0;
|
|
403
402
|
let components;
|
|
404
|
-
|
|
405
|
-
tsDocumentations.clear();
|
|
403
|
+
cachedPropInfos.clear();
|
|
406
404
|
updateExtraCustomData([
|
|
407
405
|
html.newHTMLDataProvider('vue-template-built-in', builtInData),
|
|
408
406
|
{
|
|
@@ -422,9 +420,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
422
420
|
})());
|
|
423
421
|
return [];
|
|
424
422
|
}
|
|
425
|
-
const scriptSetupRanges = vueCode.
|
|
426
|
-
? (0, language_core_1.parseScriptSetupRanges)(ts, vueCode._sfc.scriptSetup.ast, vueCompilerOptions)
|
|
427
|
-
: undefined;
|
|
423
|
+
const scriptSetupRanges = language_core_1.tsCodegen.get(vueCode.sfc)?.getScriptSetupRanges();
|
|
428
424
|
const names = new Set();
|
|
429
425
|
const tags = [];
|
|
430
426
|
for (const tag of components) {
|
|
@@ -436,7 +432,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
436
432
|
}
|
|
437
433
|
}
|
|
438
434
|
for (const binding of scriptSetupRanges?.bindings ?? []) {
|
|
439
|
-
const name = vueCode.
|
|
435
|
+
const name = vueCode.sfc.scriptSetup.content.slice(binding.range.start, binding.range.end);
|
|
440
436
|
if (casing.tag === types_1.TagNameCasing.Kebab) {
|
|
441
437
|
names.add((0, language_core_1.hyphenateTag)(name));
|
|
442
438
|
}
|
|
@@ -457,44 +453,24 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
457
453
|
if (!tagInfo) {
|
|
458
454
|
promises.push((async () => {
|
|
459
455
|
const attrs = await tsPluginClient?.getElementAttrs(vueCode.fileName, tag) ?? [];
|
|
460
|
-
const
|
|
456
|
+
const propInfos = await tsPluginClient?.getComponentProps(vueCode.fileName, tag) ?? [];
|
|
461
457
|
const events = await tsPluginClient?.getComponentEvents(vueCode.fileName, tag) ?? [];
|
|
458
|
+
const directives = await tsPluginClient?.getComponentDirectives(vueCode.fileName) ?? [];
|
|
462
459
|
tagInfos.set(tag, {
|
|
463
460
|
attrs,
|
|
464
|
-
|
|
461
|
+
propInfos: propInfos.filter(prop => !prop.name.startsWith('ref_')),
|
|
465
462
|
events,
|
|
463
|
+
directives,
|
|
466
464
|
});
|
|
467
465
|
version++;
|
|
468
466
|
})());
|
|
469
467
|
return [];
|
|
470
468
|
}
|
|
471
|
-
const { attrs,
|
|
472
|
-
const props =
|
|
469
|
+
const { attrs, propInfos, events, directives } = tagInfo;
|
|
470
|
+
const props = propInfos.map(prop => (0, language_core_1.hyphenateTag)(prop.name).startsWith('on-vnode-')
|
|
473
471
|
? 'onVue:' + prop.name.slice('onVnode'.length)
|
|
474
472
|
: prop.name);
|
|
475
473
|
const attributes = [];
|
|
476
|
-
const _tsCodegen = language_core_1.tsCodegen.get(vueCode._sfc);
|
|
477
|
-
if (_tsCodegen) {
|
|
478
|
-
if (!templateContextProps) {
|
|
479
|
-
promises.push((async () => {
|
|
480
|
-
templateContextProps = await tsPluginClient?.getTemplateContextProps(vueCode.fileName) ?? [];
|
|
481
|
-
version++;
|
|
482
|
-
})());
|
|
483
|
-
return [];
|
|
484
|
-
}
|
|
485
|
-
let ctxVars = [
|
|
486
|
-
..._tsCodegen.scriptRanges.get()?.bindings.map(({ range }) => vueCode._sfc.script.content.slice(range.start, range.end)) ?? [],
|
|
487
|
-
..._tsCodegen.scriptSetupRanges.get()?.bindings.map(({ range }) => vueCode._sfc.scriptSetup.content.slice(range.start, range.end)) ?? [],
|
|
488
|
-
...templateContextProps,
|
|
489
|
-
];
|
|
490
|
-
ctxVars = [...new Set(ctxVars)];
|
|
491
|
-
const dirs = ctxVars.map(language_core_1.hyphenateAttr).filter(v => v.startsWith('v-'));
|
|
492
|
-
for (const dir of dirs) {
|
|
493
|
-
attributes.push({
|
|
494
|
-
name: dir,
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
474
|
const propsSet = new Set(props);
|
|
499
475
|
for (const prop of [...props, ...attrs]) {
|
|
500
476
|
const isGlobal = !propsSet.has(prop);
|
|
@@ -515,13 +491,13 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
515
491
|
}
|
|
516
492
|
else {
|
|
517
493
|
const propName = name;
|
|
518
|
-
const
|
|
519
|
-
const propDescription = propsInfo.find(prop => {
|
|
494
|
+
const propInfo = propInfos.find(prop => {
|
|
520
495
|
const name = casing.attr === types_1.AttrNameCasing.Camel ? prop.name : (0, language_core_1.hyphenateAttr)(prop.name);
|
|
521
496
|
return name === propName;
|
|
522
|
-
})
|
|
523
|
-
|
|
524
|
-
|
|
497
|
+
});
|
|
498
|
+
const propKey = generateItemKey('componentProp', isGlobal ? '*' : tag, propName, propInfo?.deprecated);
|
|
499
|
+
if (propInfo) {
|
|
500
|
+
cachedPropInfos.set(propName, propInfo);
|
|
525
501
|
}
|
|
526
502
|
attributes.push({
|
|
527
503
|
name: propName,
|
|
@@ -546,6 +522,12 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
546
522
|
description: propKey,
|
|
547
523
|
});
|
|
548
524
|
}
|
|
525
|
+
for (const directive of directives) {
|
|
526
|
+
const name = (0, language_core_1.hyphenateAttr)(directive);
|
|
527
|
+
attributes.push({
|
|
528
|
+
name
|
|
529
|
+
});
|
|
530
|
+
}
|
|
549
531
|
const models = [];
|
|
550
532
|
for (const prop of [...props, ...attrs]) {
|
|
551
533
|
if (prop.startsWith('onUpdate:')) {
|
|
@@ -652,7 +634,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
652
634
|
const htmlDocumentations = new Map();
|
|
653
635
|
for (const item of completionList.items) {
|
|
654
636
|
const documentation = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
|
|
655
|
-
if (documentation && !isItemKey(documentation)
|
|
637
|
+
if (documentation && !isItemKey(documentation)) {
|
|
656
638
|
htmlDocumentations.set(item.label, documentation);
|
|
657
639
|
}
|
|
658
640
|
}
|
|
@@ -675,10 +657,12 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
675
657
|
}
|
|
676
658
|
const itemKeyStr = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
|
|
677
659
|
let parsedItemKey = itemKeyStr ? parseItemKey(itemKeyStr) : undefined;
|
|
660
|
+
let propInfo;
|
|
678
661
|
if (parsedItemKey) {
|
|
679
662
|
const documentations = [];
|
|
680
|
-
|
|
681
|
-
|
|
663
|
+
propInfo = cachedPropInfos.get(parsedItemKey.prop);
|
|
664
|
+
if (propInfo?.commentMarkdown) {
|
|
665
|
+
documentations.push(propInfo.commentMarkdown);
|
|
682
666
|
}
|
|
683
667
|
let { isEvent, propName } = getPropName(parsedItemKey);
|
|
684
668
|
if (isEvent) {
|
|
@@ -712,20 +696,25 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
712
696
|
type: 'componentProp',
|
|
713
697
|
tag: '^',
|
|
714
698
|
prop: propName,
|
|
699
|
+
deprecated: false,
|
|
715
700
|
leadingSlash: false
|
|
716
701
|
};
|
|
717
702
|
}
|
|
718
|
-
|
|
703
|
+
propInfo = cachedPropInfos.get(propName);
|
|
704
|
+
if (propInfo?.commentMarkdown) {
|
|
719
705
|
const originalDocumentation = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
|
|
720
706
|
item.documentation = {
|
|
721
707
|
kind: 'markdown',
|
|
722
708
|
value: [
|
|
723
|
-
|
|
709
|
+
propInfo.commentMarkdown,
|
|
724
710
|
originalDocumentation,
|
|
725
711
|
].filter(str => !!str).join('\n\n'),
|
|
726
712
|
};
|
|
727
713
|
}
|
|
728
714
|
}
|
|
715
|
+
if (propInfo?.deprecated) {
|
|
716
|
+
item.tags = [1];
|
|
717
|
+
}
|
|
729
718
|
const tokens = [];
|
|
730
719
|
if (item.kind === 10
|
|
731
720
|
&& lastCompletionComponentNames.has((0, language_core_1.hyphenateTag)(item.label))) {
|
|
@@ -850,8 +839,8 @@ function parseLabel(label) {
|
|
|
850
839
|
leadingSlash
|
|
851
840
|
};
|
|
852
841
|
}
|
|
853
|
-
function generateItemKey(type, tag, prop) {
|
|
854
|
-
return
|
|
842
|
+
function generateItemKey(type, tag, prop, deprecated) {
|
|
843
|
+
return `__VLS_data=${type},${tag},${prop},${Number(deprecated)}`;
|
|
855
844
|
}
|
|
856
845
|
function isItemKey(key) {
|
|
857
846
|
return key.startsWith('__VLS_data=');
|
|
@@ -864,6 +853,7 @@ function parseItemKey(key) {
|
|
|
864
853
|
type: strs[0],
|
|
865
854
|
tag: strs[1],
|
|
866
855
|
prop: strs[2],
|
|
856
|
+
deprecated: strs[3] === '1',
|
|
867
857
|
leadingSlash
|
|
868
858
|
};
|
|
869
859
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue/language-service",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"data",
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"@volar/language-service": "~2.4.11",
|
|
22
22
|
"@volar/typescript": "~2.4.11",
|
|
23
23
|
"@vue/compiler-dom": "^3.5.0",
|
|
24
|
-
"@vue/language-core": "2.2.
|
|
24
|
+
"@vue/language-core": "2.2.4",
|
|
25
25
|
"@vue/shared": "^3.5.0",
|
|
26
|
-
"@vue/typescript-plugin": "2.2.
|
|
27
|
-
"alien-signals": "^0.
|
|
26
|
+
"@vue/typescript-plugin": "2.2.4",
|
|
27
|
+
"alien-signals": "^1.0.3",
|
|
28
28
|
"path-browserify": "^1.0.1",
|
|
29
29
|
"volar-service-css": "0.0.62",
|
|
30
30
|
"volar-service-emmet": "0.0.62",
|
|
@@ -34,15 +34,16 @@
|
|
|
34
34
|
"volar-service-pug-beautify": "0.0.62",
|
|
35
35
|
"volar-service-typescript": "0.0.62",
|
|
36
36
|
"volar-service-typescript-twoslash-queries": "0.0.62",
|
|
37
|
+
"vscode-css-languageservice": "^6.3.1",
|
|
37
38
|
"vscode-html-languageservice": "^5.2.0",
|
|
38
39
|
"vscode-languageserver-textdocument": "^1.0.11",
|
|
39
40
|
"vscode-uri": "^3.0.8"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
|
-
"@types/node": "
|
|
43
|
-
"@types/path-browserify": "
|
|
43
|
+
"@types/node": "^22.10.4",
|
|
44
|
+
"@types/path-browserify": "^1.0.1",
|
|
44
45
|
"@volar/kit": "~2.4.11",
|
|
45
46
|
"vscode-languageserver-protocol": "^3.17.5"
|
|
46
47
|
},
|
|
47
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "c28986596935cb43979c9d437c25f292bdb36cef"
|
|
48
49
|
}
|