@vue/language-service 3.2.9 → 3.3.1
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/lib/nameCasing.js +1 -1
- package/lib/plugins/css.js +1 -1
- package/lib/plugins/vue-autoinsert-dotvalue.js +2 -2
- package/lib/plugins/vue-compiler-dom-errors.js +1 -1
- package/lib/plugins/vue-component-semantic-tokens.js +1 -1
- package/lib/plugins/vue-document-drop.js +6 -14
- package/lib/plugins/vue-document-highlights.js +1 -1
- package/lib/plugins/vue-extract-file.d.ts +2 -2
- package/lib/plugins/vue-extract-file.js +16 -16
- package/lib/plugins/vue-inlayhints.js +7 -7
- package/lib/plugins/vue-missing-props-hints.d.ts +1 -1
- package/lib/plugins/vue-missing-props-hints.js +60 -129
- package/lib/plugins/vue-scoped-class-links.js +4 -4
- package/lib/plugins/vue-sfc.js +21 -21
- package/lib/plugins/vue-suggest-define-assignment.js +20 -46
- package/lib/plugins/vue-template-ref-links.js +4 -4
- package/lib/plugins/vue-template.js +270 -321
- package/package.json +6 -5
|
@@ -40,7 +40,7 @@ const language_core_1 = require("@vue/language-core");
|
|
|
40
40
|
const shared_1 = require("@vue/shared");
|
|
41
41
|
const volar_service_html_1 = require("volar-service-html");
|
|
42
42
|
const volar_service_pug_1 = require("volar-service-pug");
|
|
43
|
-
const
|
|
43
|
+
const lspConverters_1 = require("volar-service-typescript/lib/utils/lspConverters");
|
|
44
44
|
const html = __importStar(require("vscode-html-languageservice"));
|
|
45
45
|
const vscode_uri_1 = require("vscode-uri");
|
|
46
46
|
const data_1 = require("../data");
|
|
@@ -61,69 +61,64 @@ const V_BIND_SHORTHAND = ':';
|
|
|
61
61
|
const DIRECTIVE_V_FOR_NAME = 'v-for';
|
|
62
62
|
// Templates
|
|
63
63
|
const V_FOR_SNIPPET = '="${1:value} in ${2:source}"';
|
|
64
|
+
let customData;
|
|
64
65
|
let builtInData;
|
|
65
66
|
let modelData;
|
|
66
67
|
function create(ts, languageId, tsserver) {
|
|
67
|
-
|
|
68
|
+
const defaultDataProvider = html.getDefaultHTMLDataProvider();
|
|
69
|
+
let htmlData = [defaultDataProvider];
|
|
68
70
|
let modulePathCache;
|
|
69
71
|
const onDidChangeCustomDataListeners = new Set();
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const getDocumentContext = context => ({
|
|
79
|
-
resolveReference(ref, base) {
|
|
80
|
-
let baseUri = vscode_uri_1.URI.parse(base);
|
|
81
|
-
const decoded = context.decodeEmbeddedDocumentUri(baseUri);
|
|
82
|
-
if (decoded) {
|
|
83
|
-
baseUri = decoded[0];
|
|
84
|
-
}
|
|
85
|
-
if (modulePathCache
|
|
86
|
-
&& baseUri.scheme === 'file'
|
|
87
|
-
&& !ref.startsWith('./')
|
|
88
|
-
&& !ref.startsWith('../')) {
|
|
89
|
-
const map = modulePathCache;
|
|
90
|
-
if (!map.has(ref)) {
|
|
91
|
-
const fileName = baseUri.fsPath.replace(/\\/g, '/');
|
|
92
|
-
const promise = tsserver.resolveModuleName(fileName, ref);
|
|
93
|
-
map.set(ref, promise);
|
|
94
|
-
if (promise instanceof Promise) {
|
|
95
|
-
promise.then(res => map.set(ref, res));
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
const cached = modulePathCache.get(ref);
|
|
99
|
-
if (cached instanceof Promise) {
|
|
100
|
-
throw cached;
|
|
72
|
+
const serviceOptions = {
|
|
73
|
+
useDefaultDataProvider: false,
|
|
74
|
+
getDocumentContext: context => ({
|
|
75
|
+
resolveReference(ref, base) {
|
|
76
|
+
let baseUri = vscode_uri_1.URI.parse(base);
|
|
77
|
+
const decoded = context.decodeEmbeddedDocumentUri(baseUri);
|
|
78
|
+
if (decoded) {
|
|
79
|
+
baseUri = decoded[0];
|
|
101
80
|
}
|
|
102
|
-
if (
|
|
103
|
-
|
|
81
|
+
if (modulePathCache
|
|
82
|
+
&& baseUri.scheme === 'file'
|
|
83
|
+
&& !ref.startsWith('./')
|
|
84
|
+
&& !ref.startsWith('../')) {
|
|
85
|
+
const map = modulePathCache;
|
|
86
|
+
if (!map.has(ref)) {
|
|
87
|
+
const fileName = baseUri.fsPath.replace(/\\/g, '/');
|
|
88
|
+
const promise = tsserver.resolveModuleName(fileName, ref);
|
|
89
|
+
map.set(ref, promise);
|
|
90
|
+
if (promise instanceof Promise) {
|
|
91
|
+
promise.then(res => map.set(ref, res));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const cached = modulePathCache.get(ref);
|
|
95
|
+
if (cached instanceof Promise) {
|
|
96
|
+
throw cached;
|
|
97
|
+
}
|
|
98
|
+
if (cached) {
|
|
99
|
+
return vscode_uri_1.URI.file(cached).toString();
|
|
100
|
+
}
|
|
104
101
|
}
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
return (0, volar_service_html_1.resolveReference)(ref, baseUri, context.env.workspaceFolders);
|
|
103
|
+
},
|
|
104
|
+
}),
|
|
105
|
+
getCustomData() {
|
|
106
|
+
return customData?.length ? htmlData.concat(customData) : htmlData;
|
|
107
|
+
},
|
|
108
|
+
onDidChangeCustomData(listener) {
|
|
109
|
+
onDidChangeCustomDataListeners.add(listener);
|
|
110
|
+
return {
|
|
111
|
+
dispose() {
|
|
112
|
+
onDidChangeCustomDataListeners.delete(listener);
|
|
113
|
+
},
|
|
114
|
+
};
|
|
107
115
|
},
|
|
108
|
-
}
|
|
109
|
-
const defaultHTMLProvider = html.getDefaultHTMLDataProvider();
|
|
116
|
+
};
|
|
110
117
|
const baseService = languageId === 'jade'
|
|
111
|
-
? (0, volar_service_pug_1.create)(
|
|
112
|
-
useDefaultDataProvider: false,
|
|
113
|
-
getDocumentContext,
|
|
114
|
-
getCustomData() {
|
|
115
|
-
return htmlData;
|
|
116
|
-
},
|
|
117
|
-
onDidChangeCustomData,
|
|
118
|
-
})
|
|
118
|
+
? (0, volar_service_pug_1.create)(serviceOptions)
|
|
119
119
|
: (0, volar_service_html_1.create)({
|
|
120
|
+
...serviceOptions,
|
|
120
121
|
documentSelector: ['html', 'markdown'],
|
|
121
|
-
useDefaultDataProvider: false,
|
|
122
|
-
getDocumentContext,
|
|
123
|
-
getCustomData() {
|
|
124
|
-
return htmlData;
|
|
125
|
-
},
|
|
126
|
-
onDidChangeCustomData,
|
|
127
122
|
});
|
|
128
123
|
return {
|
|
129
124
|
name: `vue-template (${languageId})`,
|
|
@@ -145,7 +140,7 @@ function create(ts, languageId, tsserver) {
|
|
|
145
140
|
htmlService.parseHTMLDocument = document => {
|
|
146
141
|
const info = (0, utils_1.resolveEmbeddedCode)(context, document.uri);
|
|
147
142
|
if (info?.code.id === 'template') {
|
|
148
|
-
const templateAst = info.root.
|
|
143
|
+
const templateAst = info.root.ir.template?.ast;
|
|
149
144
|
if (templateAst) {
|
|
150
145
|
let text = document.getText();
|
|
151
146
|
for (const node of (0, language_core_1.forEachInterpolationNode)(templateAst)) {
|
|
@@ -164,13 +159,13 @@ function create(ts, languageId, tsserver) {
|
|
|
164
159
|
htmlService.format = (document, range, options) => {
|
|
165
160
|
let voidElements;
|
|
166
161
|
const info = (0, utils_1.resolveEmbeddedCode)(context, document.uri);
|
|
167
|
-
const codegen = info && language_core_1.tsCodegen.get(info.root.
|
|
162
|
+
const codegen = info && language_core_1.tsCodegen.get(info.root.ir);
|
|
168
163
|
if (codegen) {
|
|
169
164
|
const componentNames = new Set([
|
|
170
165
|
...codegen.getImportedComponents(),
|
|
171
166
|
...codegen.getSetupExposed(),
|
|
172
167
|
]);
|
|
173
|
-
voidElements =
|
|
168
|
+
voidElements = defaultDataProvider.provideTags()
|
|
174
169
|
.filter(tag => tag.void)
|
|
175
170
|
.map(tag => tag.name)
|
|
176
171
|
.filter(tag => !componentNames.has(tag) && !componentNames.has((0, shared_1.capitalize)(tag)));
|
|
@@ -186,9 +181,9 @@ function create(ts, languageId, tsserver) {
|
|
|
186
181
|
const vBindModifiers = extractDirectiveModifiers(builtInData.globalAttributes?.find(x => x.name === 'v-bind'));
|
|
187
182
|
const vModelModifiers = extractModelModifiers(modelData.globalAttributes);
|
|
188
183
|
const transformedItems = new WeakSet();
|
|
189
|
-
const
|
|
190
|
-
for (const tag of
|
|
191
|
-
|
|
184
|
+
const defaultTags = new Map();
|
|
185
|
+
for (const tag of defaultDataProvider.provideTags()) {
|
|
186
|
+
defaultTags.set(tag.name, tag);
|
|
192
187
|
}
|
|
193
188
|
let lastCompletionDocument;
|
|
194
189
|
return {
|
|
@@ -206,7 +201,7 @@ function create(ts, languageId, tsserver) {
|
|
|
206
201
|
}
|
|
207
202
|
const prevText = document.getText({ start: { line: 0, character: 0 }, end: position });
|
|
208
203
|
const hint = prevText.match(/(\S)[\S]*$/)?.[1];
|
|
209
|
-
const { result: htmlCompletion, info: { tagNameCasing, components, }, } = await runWithVueDataProvider(info.script.id, info.root, hint, 'completion', () => baseServiceInstance.provideCompletionItems(document, position, completionContext, token));
|
|
204
|
+
const { result: htmlCompletion, info: { tagNameCasing, components, }, } = await runWithVueDataProvider(info.script.id, info.root, document.offsetAt(position), hint, 'completion', () => baseServiceInstance.provideCompletionItems(document, position, completionContext, token));
|
|
210
205
|
const componentSet = new Set(components);
|
|
211
206
|
if (!htmlCompletion) {
|
|
212
207
|
return;
|
|
@@ -233,7 +228,7 @@ function create(ts, languageId, tsserver) {
|
|
|
233
228
|
if (!autoImport) {
|
|
234
229
|
continue;
|
|
235
230
|
}
|
|
236
|
-
const tsCompletion = (0,
|
|
231
|
+
const tsCompletion = (0, lspConverters_1.convertCompletionInfo)(ts, autoImport, document, position, entry => entry.data);
|
|
237
232
|
const placeholder = htmlCompletion.items[autoImportPlaceholderIndex];
|
|
238
233
|
for (const tsItem of tsCompletion.items) {
|
|
239
234
|
if (placeholder.textEdit) {
|
|
@@ -309,7 +304,7 @@ function create(ts, languageId, tsserver) {
|
|
|
309
304
|
const embeddedDocument = context.documents.get(embeddedUri, virtualCode.languageId, virtualCode.snapshot);
|
|
310
305
|
const map = context.language.maps.get(virtualCode, sourceScript);
|
|
311
306
|
item = (0, language_service_1.transformCompletionItem)(item, embeddedRange => (0, featureWorkers_1.getSourceRange)([sourceDocument, embeddedDocument, map], embeddedRange), embeddedDocument, context);
|
|
312
|
-
(0,
|
|
307
|
+
(0, lspConverters_1.applyCompletionEntryDetails)(ts, item, details, sourceDocument, fileName => vscode_uri_1.URI.file(fileName), () => undefined);
|
|
313
308
|
transformedItems.add(item);
|
|
314
309
|
}
|
|
315
310
|
}
|
|
@@ -328,8 +323,8 @@ function create(ts, languageId, tsserver) {
|
|
|
328
323
|
if (info?.code.id !== 'template') {
|
|
329
324
|
return;
|
|
330
325
|
}
|
|
331
|
-
let { result: htmlHover, } = await runWithVueDataProvider(info.script.id, info.root, undefined, 'hover', () => baseServiceInstance.provideHover(document, position, token));
|
|
332
|
-
const templateAst = info.root.
|
|
326
|
+
let { result: htmlHover, } = await runWithVueDataProvider(info.script.id, info.root, document.offsetAt(position), undefined, 'hover', () => baseServiceInstance.provideHover(document, position, token));
|
|
327
|
+
const templateAst = info.root.ir.template?.ast;
|
|
333
328
|
const enabledRichMessage = await context.env.getConfiguration?.('vue.hover.rich');
|
|
334
329
|
if (!templateAst || !enabledRichMessage || (htmlHover && hasContents(htmlHover.contents))) {
|
|
335
330
|
return htmlHover;
|
|
@@ -470,231 +465,222 @@ function create(ts, languageId, tsserver) {
|
|
|
470
465
|
}
|
|
471
466
|
}
|
|
472
467
|
},
|
|
473
|
-
provideDocumentSymbols(document, token) {
|
|
474
|
-
if (document.languageId !== languageId) {
|
|
475
|
-
return;
|
|
476
|
-
}
|
|
477
|
-
const info = (0, utils_1.resolveEmbeddedCode)(context, document.uri);
|
|
478
|
-
if (info?.code.id !== 'template') {
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
updateExtraCustomData([
|
|
482
|
-
defaultHTMLProvider,
|
|
483
|
-
]);
|
|
484
|
-
return baseServiceInstance.provideDocumentSymbols?.(document, token);
|
|
485
|
-
},
|
|
486
468
|
};
|
|
487
|
-
async function runWithVueDataProvider(sourceDocumentUri, root, hint, mode, fn) {
|
|
469
|
+
async function runWithVueDataProvider(sourceDocumentUri, root, position, hint, mode, fn) {
|
|
488
470
|
// #4298: Precompute HTMLDocument before provideHtmlData to avoid parseHTMLDocument requesting component names from tsserver
|
|
489
471
|
await fn();
|
|
490
|
-
const { sync } = await provideHtmlData(sourceDocumentUri, root, hint, mode);
|
|
472
|
+
const { sync } = await provideHtmlData(sourceDocumentUri, root, position, hint, mode);
|
|
491
473
|
let lastSync = await sync();
|
|
492
474
|
let result = await fn();
|
|
493
475
|
while (lastSync.version !== (lastSync = await sync()).version) {
|
|
494
476
|
result = await fn();
|
|
495
477
|
}
|
|
496
|
-
|
|
478
|
+
updateHtmlData([
|
|
479
|
+
defaultDataProvider,
|
|
480
|
+
]);
|
|
481
|
+
return {
|
|
482
|
+
result,
|
|
483
|
+
...lastSync,
|
|
484
|
+
};
|
|
497
485
|
}
|
|
498
|
-
async function provideHtmlData(sourceDocumentUri, root, hint, mode) {
|
|
486
|
+
async function provideHtmlData(sourceDocumentUri, root, position, hint, mode) {
|
|
499
487
|
const [tagNameCasing, attrNameCasing] = await Promise.all([
|
|
500
488
|
(0, nameCasing_1.getTagNameCasing)(context, sourceDocumentUri),
|
|
501
489
|
(0, nameCasing_1.getAttrNameCasing)(context, sourceDocumentUri),
|
|
502
490
|
]);
|
|
491
|
+
customData ??= await getCustomData();
|
|
492
|
+
const tasks = [];
|
|
503
493
|
let version = 0;
|
|
504
494
|
let components;
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
for (const
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
...codegen.getImportedComponents(),
|
|
534
|
-
...codegen.getSetupExposed(),
|
|
535
|
-
]) {
|
|
536
|
-
names.add(tagNameCasing === 0 /* TagNameCasing.Kebab */ ? (0, language_core_1.hyphenateTag)(name) : name);
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
const added = new Set(tags.map(t => t.name));
|
|
540
|
-
for (const name of names) {
|
|
541
|
-
if (!added.has(name)) {
|
|
542
|
-
const defaultTag = defaultHtmlTags.get(name);
|
|
543
|
-
tags.push({
|
|
544
|
-
...defaultTag,
|
|
545
|
-
name,
|
|
546
|
-
attributes: [],
|
|
547
|
-
});
|
|
548
|
-
}
|
|
495
|
+
const provideTags = createProvider({
|
|
496
|
+
async fetch() {
|
|
497
|
+
const res = await Promise.all([
|
|
498
|
+
tsserver.getComponentNames(root.fileName),
|
|
499
|
+
tsserver.getElementNames(root.fileName),
|
|
500
|
+
]);
|
|
501
|
+
components = res[0] ?? [];
|
|
502
|
+
return {
|
|
503
|
+
components,
|
|
504
|
+
elements: res[1] ?? [],
|
|
505
|
+
};
|
|
506
|
+
},
|
|
507
|
+
provide({ components, elements }) {
|
|
508
|
+
const codegen = language_core_1.tsCodegen.get(root.ir);
|
|
509
|
+
const names = new Set();
|
|
510
|
+
const tags = new Map();
|
|
511
|
+
for (const tag of components) {
|
|
512
|
+
names.add(tagNameCasing === 0 /* TagNameCasing.Kebab */ ? (0, language_core_1.hyphenateTag)(tag) : tag);
|
|
513
|
+
}
|
|
514
|
+
for (const tag of elements) {
|
|
515
|
+
names.add(tag);
|
|
516
|
+
}
|
|
517
|
+
if (codegen) {
|
|
518
|
+
for (const name of [
|
|
519
|
+
...codegen.getImportedComponents(),
|
|
520
|
+
...codegen.getSetupExposed(),
|
|
521
|
+
]) {
|
|
522
|
+
names.add(tagNameCasing === 0 /* TagNameCasing.Kebab */ ? (0, language_core_1.hyphenateTag)(name) : name);
|
|
549
523
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
524
|
+
}
|
|
525
|
+
for (const name of names) {
|
|
526
|
+
tags.set(name, {
|
|
527
|
+
...defaultTags.get(name),
|
|
528
|
+
name,
|
|
529
|
+
attributes: [],
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
for (const tag of builtInData?.tags ?? []) {
|
|
533
|
+
const name = tagNameCasing === 0 /* TagNameCasing.Kebab */ ? (0, language_core_1.hyphenateTag)(tag.name) : tag.name;
|
|
534
|
+
tags.set(name, {
|
|
535
|
+
...tag,
|
|
536
|
+
name,
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
return [...tags.values()];
|
|
540
|
+
},
|
|
541
|
+
});
|
|
542
|
+
const provideAttributes = createProvider({
|
|
543
|
+
async fetch(tag) {
|
|
544
|
+
const res = await Promise.all([
|
|
545
|
+
tsserver.getElementAttrs(root.fileName, tag),
|
|
546
|
+
tsserver.getComponentProps(root.fileName, position),
|
|
547
|
+
tsserver.getComponentDirectives(root.fileName),
|
|
548
|
+
]);
|
|
549
|
+
return {
|
|
550
|
+
attrs: res[0] ?? [],
|
|
551
|
+
props: res[1] ?? [],
|
|
552
|
+
directives: res[2] ?? [],
|
|
553
|
+
};
|
|
554
|
+
},
|
|
555
|
+
provide({ attrs, props, directives }, tag) {
|
|
556
|
+
const attributes = [];
|
|
557
|
+
let addPlainAttrs = false;
|
|
558
|
+
let addVBinds = false;
|
|
559
|
+
let addVBindShorthands = false;
|
|
560
|
+
let addVOns = false;
|
|
561
|
+
let addVOnShorthands = false;
|
|
562
|
+
if (!hint) {
|
|
563
|
+
addVBindShorthands = true;
|
|
564
|
+
addVOnShorthands = true;
|
|
565
|
+
}
|
|
566
|
+
else if (hint === ':') {
|
|
567
|
+
addVBindShorthands = true;
|
|
568
|
+
}
|
|
569
|
+
else if (hint === '@') {
|
|
570
|
+
addVOnShorthands = true;
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
addPlainAttrs = true;
|
|
574
|
+
addVBinds = true;
|
|
575
|
+
addVOns = true;
|
|
576
|
+
addVBindShorthands = true;
|
|
577
|
+
addVOnShorthands = true;
|
|
578
|
+
}
|
|
579
|
+
for (const attr of builtInData?.globalAttributes ?? []) {
|
|
580
|
+
if (attr.name === 'is' && tag.toLowerCase() !== 'component') {
|
|
581
|
+
continue;
|
|
564
582
|
}
|
|
565
|
-
|
|
566
|
-
|
|
583
|
+
if (attr.name === 'ref' || attr.name.startsWith('v-')) {
|
|
584
|
+
attributes.push(attr);
|
|
585
|
+
continue;
|
|
567
586
|
}
|
|
568
|
-
|
|
569
|
-
|
|
587
|
+
if (addPlainAttrs) {
|
|
588
|
+
attributes.push({ ...attr, name: attr.name });
|
|
570
589
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
addVBinds = true;
|
|
574
|
-
addVOns = true;
|
|
575
|
-
addVBindShorthands = true;
|
|
576
|
-
addVOnShorthands = true;
|
|
590
|
+
if (addVBindShorthands) {
|
|
591
|
+
attributes.push({ ...attr, name: V_BIND_SHORTHAND + attr.name });
|
|
577
592
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
continue;
|
|
581
|
-
}
|
|
582
|
-
if (attr.name === 'ref' || attr.name.startsWith('v-')) {
|
|
583
|
-
attributes.push(attr);
|
|
584
|
-
continue;
|
|
585
|
-
}
|
|
586
|
-
if (addPlainAttrs) {
|
|
587
|
-
attributes.push({ ...attr, name: attr.name });
|
|
588
|
-
}
|
|
589
|
-
if (addVBindShorthands) {
|
|
590
|
-
attributes.push({ ...attr, name: V_BIND_SHORTHAND + attr.name });
|
|
591
|
-
}
|
|
592
|
-
if (addVBinds) {
|
|
593
|
-
attributes.push({ ...attr, name: DIRECTIVE_V_BIND + attr.name });
|
|
594
|
-
}
|
|
593
|
+
if (addVBinds) {
|
|
594
|
+
attributes.push({ ...attr, name: DIRECTIVE_V_BIND + attr.name });
|
|
595
595
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
])
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
if (addVOnShorthands) {
|
|
607
|
-
attributes.push({
|
|
608
|
-
name: V_ON_SHORTHAND + labelName,
|
|
609
|
-
description: propMeta && createDescription(propMeta),
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
if (addVOns) {
|
|
613
|
-
attributes.push({
|
|
614
|
-
name: DIRECTIVE_V_ON + labelName,
|
|
615
|
-
description: propMeta && createDescription(propMeta),
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
else {
|
|
620
|
-
const labelName = attrNameCasing === 1 /* AttrNameCasing.Camel */ ? propName : (0, language_core_1.hyphenateAttr)(propName);
|
|
621
|
-
const propMeta2 = meta?.props.find(prop => {
|
|
622
|
-
const name = attrNameCasing === 1 /* AttrNameCasing.Camel */ ? prop.name : (0, language_core_1.hyphenateAttr)(prop.name);
|
|
623
|
-
return name === labelName;
|
|
624
|
-
});
|
|
625
|
-
const isBoolean = propMeta2?.type === 'boolean' || propMeta2?.type.startsWith('boolean ');
|
|
626
|
-
if (addPlainAttrs) {
|
|
627
|
-
attributes.push({
|
|
628
|
-
name: labelName,
|
|
629
|
-
description: propMeta2 && createDescription(propMeta2),
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
if (addVBindShorthands) {
|
|
633
|
-
attributes.push({
|
|
634
|
-
name: V_BIND_SHORTHAND + labelName,
|
|
635
|
-
description: propMeta2 && createDescription(propMeta2),
|
|
636
|
-
valueSet: isBoolean ? 'v' : undefined,
|
|
637
|
-
});
|
|
638
|
-
}
|
|
639
|
-
if (addVBinds) {
|
|
640
|
-
attributes.push({
|
|
641
|
-
name: DIRECTIVE_V_BIND + labelName,
|
|
642
|
-
description: propMeta2 && createDescription(propMeta2),
|
|
643
|
-
valueSet: isBoolean ? 'v' : undefined,
|
|
644
|
-
});
|
|
645
|
-
}
|
|
596
|
+
}
|
|
597
|
+
for (const [propName, propInfo] of [
|
|
598
|
+
...props.map(prop => [prop.name, prop]),
|
|
599
|
+
...attrs.map(attr => [attr.name, attr]),
|
|
600
|
+
]) {
|
|
601
|
+
if (propName.match(EVENT_PROP_REGEX)) {
|
|
602
|
+
let labelName = propName.slice(2);
|
|
603
|
+
labelName = labelName.charAt(0).toLowerCase() + labelName.slice(1);
|
|
604
|
+
if (attrNameCasing === 0 /* AttrNameCasing.Kebab */) {
|
|
605
|
+
labelName = (0, language_core_1.hyphenateAttr)(labelName);
|
|
646
606
|
}
|
|
647
|
-
}
|
|
648
|
-
for (const event of meta?.events ?? []) {
|
|
649
|
-
const eventName = attrNameCasing === 1 /* AttrNameCasing.Camel */ ? event.name : (0, language_core_1.hyphenateAttr)(event.name);
|
|
650
607
|
if (addVOnShorthands) {
|
|
651
608
|
attributes.push({
|
|
652
|
-
name: V_ON_SHORTHAND +
|
|
653
|
-
description:
|
|
609
|
+
name: V_ON_SHORTHAND + labelName,
|
|
610
|
+
description: propInfo?.description,
|
|
654
611
|
});
|
|
655
612
|
}
|
|
656
613
|
if (addVOns) {
|
|
657
614
|
attributes.push({
|
|
658
|
-
name: DIRECTIVE_V_ON +
|
|
659
|
-
description:
|
|
615
|
+
name: DIRECTIVE_V_ON + labelName,
|
|
616
|
+
description: propInfo?.description,
|
|
660
617
|
});
|
|
661
618
|
}
|
|
662
619
|
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
});
|
|
667
|
-
}
|
|
668
|
-
for (const [propName, propMeta] of [
|
|
669
|
-
...meta?.props.map(prop => [prop.name, prop]) ?? [],
|
|
670
|
-
...attrs.map(attr => [attr.name, undefined]),
|
|
671
|
-
]) {
|
|
672
|
-
if (propName.startsWith(UPDATE_PROP_PREFIX)) {
|
|
673
|
-
const model = propName.slice(UPDATE_PROP_PREFIX.length);
|
|
674
|
-
const label = DIRECTIVE_V_MODEL
|
|
675
|
-
+ (attrNameCasing === 1 /* AttrNameCasing.Camel */ ? model : (0, language_core_1.hyphenateAttr)(model));
|
|
620
|
+
else {
|
|
621
|
+
const labelName = attrNameCasing === 1 /* AttrNameCasing.Camel */ ? propName : (0, language_core_1.hyphenateAttr)(propName);
|
|
622
|
+
if (addPlainAttrs) {
|
|
676
623
|
attributes.push({
|
|
677
|
-
name:
|
|
678
|
-
description:
|
|
624
|
+
name: labelName,
|
|
625
|
+
description: propInfo?.description,
|
|
626
|
+
valueSet: propInfo?.boolean ? 'v' : undefined,
|
|
679
627
|
});
|
|
680
628
|
}
|
|
681
|
-
|
|
682
|
-
for (const event of meta?.events ?? []) {
|
|
683
|
-
if (event.name.startsWith(UPDATE_EVENT_PREFIX)) {
|
|
684
|
-
const model = event.name.slice(UPDATE_EVENT_PREFIX.length);
|
|
685
|
-
const label = DIRECTIVE_V_MODEL
|
|
686
|
-
+ (attrNameCasing === 1 /* AttrNameCasing.Camel */ ? model : (0, language_core_1.hyphenateAttr)(model));
|
|
629
|
+
if (addVBindShorthands) {
|
|
687
630
|
attributes.push({
|
|
688
|
-
name:
|
|
689
|
-
description:
|
|
631
|
+
name: V_BIND_SHORTHAND + labelName,
|
|
632
|
+
description: propInfo?.description,
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
if (addVBinds) {
|
|
636
|
+
attributes.push({
|
|
637
|
+
name: DIRECTIVE_V_BIND + labelName,
|
|
638
|
+
description: propInfo?.description,
|
|
690
639
|
});
|
|
691
640
|
}
|
|
692
641
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
642
|
+
if (propName.startsWith(UPDATE_PROP_PREFIX)) {
|
|
643
|
+
const model = propName.slice(UPDATE_PROP_PREFIX.length);
|
|
644
|
+
const label = DIRECTIVE_V_MODEL
|
|
645
|
+
+ (attrNameCasing === 1 /* AttrNameCasing.Camel */ ? model : (0, language_core_1.hyphenateAttr)(model));
|
|
646
|
+
attributes.push({
|
|
647
|
+
name: label,
|
|
648
|
+
description: propInfo?.description,
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
for (const directive of directives) {
|
|
653
|
+
attributes.push({
|
|
654
|
+
name: (0, language_core_1.hyphenateAttr)(directive),
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
// dedupe from tsserver
|
|
658
|
+
if (mode === 'hover') {
|
|
659
|
+
for (const item of attributes) {
|
|
660
|
+
item.description = undefined;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
return attributes;
|
|
664
|
+
},
|
|
665
|
+
});
|
|
666
|
+
const provideValues = createProvider({
|
|
667
|
+
async fetch(tag, attr) {
|
|
668
|
+
if (tag === 'slot' && attr === 'name') {
|
|
669
|
+
return await tsserver.getComponentSlots(root.fileName) ?? [];
|
|
670
|
+
}
|
|
671
|
+
return [];
|
|
672
|
+
},
|
|
673
|
+
provide(values) {
|
|
674
|
+
return values.map(value => ({ name: value }));
|
|
675
|
+
},
|
|
676
|
+
});
|
|
677
|
+
updateHtmlData([
|
|
678
|
+
{
|
|
679
|
+
getId: () => 'vue-template',
|
|
680
|
+
isApplicable: () => true,
|
|
681
|
+
provideTags,
|
|
682
|
+
provideAttributes,
|
|
683
|
+
provideValues,
|
|
698
684
|
},
|
|
699
685
|
{
|
|
700
686
|
getId: () => 'vue-auto-imports',
|
|
@@ -716,79 +702,42 @@ function create(ts, languageId, tsserver) {
|
|
|
716
702
|
};
|
|
717
703
|
},
|
|
718
704
|
};
|
|
719
|
-
function
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
705
|
+
function createProvider(options) {
|
|
706
|
+
let status = 'idle';
|
|
707
|
+
let data;
|
|
708
|
+
return (...args) => {
|
|
709
|
+
if (status === 'idle') {
|
|
710
|
+
status = 'pending';
|
|
711
|
+
tasks.push((async () => {
|
|
712
|
+
data = await options.fetch(...args);
|
|
713
|
+
status = 'done';
|
|
714
|
+
version++;
|
|
715
|
+
})());
|
|
716
|
+
}
|
|
717
|
+
else if (status === 'done') {
|
|
718
|
+
return options.provide(data, ...args);
|
|
719
|
+
}
|
|
720
|
+
return [];
|
|
734
721
|
};
|
|
735
722
|
}
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
data = { attrs: [], meta: undefined };
|
|
752
|
-
tagDataMap.set(tag, data);
|
|
753
|
-
tasks.push((async () => {
|
|
754
|
-
tagDataMap.set(tag, {
|
|
755
|
-
attrs: await tsserver.getElementAttrs(root.fileName, tag) ?? [],
|
|
756
|
-
meta: await tsserver.getComponentMeta(root.fileName, tag),
|
|
757
|
-
});
|
|
758
|
-
version++;
|
|
759
|
-
})());
|
|
760
|
-
}
|
|
761
|
-
return data;
|
|
762
|
-
}
|
|
763
|
-
function getDirectives() {
|
|
764
|
-
if (!directives) {
|
|
765
|
-
directives = [];
|
|
766
|
-
tasks.push((async () => {
|
|
767
|
-
directives = await tsserver.getComponentDirectives(root.fileName) ?? [];
|
|
768
|
-
version++;
|
|
769
|
-
})());
|
|
770
|
-
}
|
|
771
|
-
return directives;
|
|
772
|
-
}
|
|
773
|
-
function getComponentsAndElements() {
|
|
774
|
-
if (!components || !elements) {
|
|
775
|
-
components = [];
|
|
776
|
-
elements = [];
|
|
777
|
-
tasks.push((async () => {
|
|
778
|
-
const res = await Promise.all([
|
|
779
|
-
tsserver.getComponentNames(root.fileName),
|
|
780
|
-
tsserver.getElementNames(root.fileName),
|
|
781
|
-
]);
|
|
782
|
-
components = res[0] ?? [];
|
|
783
|
-
elements = res[1] ?? [];
|
|
784
|
-
version++;
|
|
785
|
-
})());
|
|
723
|
+
}
|
|
724
|
+
async function getCustomData() {
|
|
725
|
+
const paths = await context.env.getConfiguration?.('html.customData') ?? [];
|
|
726
|
+
const customData = [];
|
|
727
|
+
for (const path of paths) {
|
|
728
|
+
for (const workspaceFolder of context.env.workspaceFolders) {
|
|
729
|
+
const uri = vscode_uri_1.Utils.resolvePath(workspaceFolder, path);
|
|
730
|
+
const text = await context.env.fs?.readFile(uri) ?? '';
|
|
731
|
+
try {
|
|
732
|
+
const data = JSON.parse(text);
|
|
733
|
+
customData.push(html.newHTMLDataProvider(path, data));
|
|
734
|
+
}
|
|
735
|
+
catch (error) {
|
|
736
|
+
console.error(error);
|
|
737
|
+
}
|
|
786
738
|
}
|
|
787
|
-
return {
|
|
788
|
-
components,
|
|
789
|
-
elements,
|
|
790
|
-
};
|
|
791
739
|
}
|
|
740
|
+
return customData;
|
|
792
741
|
}
|
|
793
742
|
function addDirectiveModifiers(list, item, document) {
|
|
794
743
|
const replacement = getReplacement(item, document);
|
|
@@ -833,7 +782,7 @@ function create(ts, languageId, tsserver) {
|
|
|
833
782
|
}
|
|
834
783
|
},
|
|
835
784
|
};
|
|
836
|
-
function
|
|
785
|
+
function updateHtmlData(newData) {
|
|
837
786
|
htmlData = newData;
|
|
838
787
|
onDidChangeCustomDataListeners.forEach(l => l());
|
|
839
788
|
}
|