@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.
@@ -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 lspConverters_js_1 = require("volar-service-typescript/lib/utils/lspConverters.js");
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
- let htmlData = [];
68
+ const defaultDataProvider = html.getDefaultHTMLDataProvider();
69
+ let htmlData = [defaultDataProvider];
68
70
  let modulePathCache;
69
71
  const onDidChangeCustomDataListeners = new Set();
70
- const onDidChangeCustomData = (listener) => {
71
- onDidChangeCustomDataListeners.add(listener);
72
- return {
73
- dispose() {
74
- onDidChangeCustomDataListeners.delete(listener);
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 (cached) {
103
- return vscode_uri_1.URI.file(cached).toString();
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
- return (0, volar_service_html_1.resolveReference)(ref, baseUri, context.env.workspaceFolders);
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.sfc.template?.ast;
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.sfc);
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 = defaultHTMLProvider.provideTags()
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 defaultHtmlTags = new Map();
190
- for (const tag of defaultHTMLProvider.provideTags()) {
191
- defaultHtmlTags.set(tag.name, tag);
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, lspConverters_js_1.convertCompletionInfo)(ts, autoImport, document, position, entry => entry.data);
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, lspConverters_js_1.applyCompletionEntryDetails)(ts, item, details, sourceDocument, fileName => vscode_uri_1.URI.file(fileName), () => undefined);
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.sfc.template?.ast;
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
- return { result, ...lastSync };
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
- let elements;
506
- let directives;
507
- let values;
508
- const tasks = [];
509
- const tagDataMap = new Map();
510
- updateExtraCustomData([
511
- {
512
- getId: () => 'vue-template',
513
- isApplicable: () => true,
514
- provideTags: () => {
515
- const { components, elements } = getComponentsAndElements();
516
- const codegen = language_core_1.tsCodegen.get(root.sfc);
517
- const names = new Set();
518
- const tags = [];
519
- for (const tag of builtInData?.tags ?? []) {
520
- tags.push({
521
- ...tag,
522
- name: tagNameCasing === 0 /* TagNameCasing.Kebab */ ? (0, language_core_1.hyphenateTag)(tag.name) : tag.name,
523
- });
524
- }
525
- for (const tag of components) {
526
- names.add(tagNameCasing === 0 /* TagNameCasing.Kebab */ ? (0, language_core_1.hyphenateTag)(tag) : tag);
527
- }
528
- for (const tag of elements) {
529
- names.add(tag);
530
- }
531
- if (codegen) {
532
- for (const name of [
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
- return tags;
551
- },
552
- provideAttributes: tag => {
553
- const directives = getDirectives();
554
- const { attrs, meta } = getTagData(tag);
555
- const attributes = [];
556
- let addPlainAttrs = false;
557
- let addVBinds = false;
558
- let addVBindShorthands = false;
559
- let addVOns = false;
560
- let addVOnShorthands = false;
561
- if (!hint) {
562
- addVBindShorthands = true;
563
- addVOnShorthands = true;
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
- else if (hint === ':') {
566
- addVBindShorthands = true;
583
+ if (attr.name === 'ref' || attr.name.startsWith('v-')) {
584
+ attributes.push(attr);
585
+ continue;
567
586
  }
568
- else if (hint === '@') {
569
- addVOnShorthands = true;
587
+ if (addPlainAttrs) {
588
+ attributes.push({ ...attr, name: attr.name });
570
589
  }
571
- else {
572
- addPlainAttrs = true;
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
- for (const attr of builtInData?.globalAttributes ?? []) {
579
- if (attr.name === 'is' && tag.toLowerCase() !== 'component') {
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
- for (const [propName, propMeta] of [
597
- ...meta?.props.map(prop => [prop.name, prop]) ?? [],
598
- ...attrs.map(attr => [attr.name, undefined]),
599
- ]) {
600
- if (propName.match(EVENT_PROP_REGEX)) {
601
- let labelName = propName.slice(2);
602
- labelName = labelName.charAt(0).toLowerCase() + labelName.slice(1);
603
- if (attrNameCasing === 0 /* AttrNameCasing.Kebab */) {
604
- labelName = (0, language_core_1.hyphenateAttr)(labelName);
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 + eventName,
653
- description: event && createDescription(event),
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 + eventName,
659
- description: event && createDescription(event),
615
+ name: DIRECTIVE_V_ON + labelName,
616
+ description: propInfo?.description,
660
617
  });
661
618
  }
662
619
  }
663
- for (const directive of directives) {
664
- attributes.push({
665
- name: (0, language_core_1.hyphenateAttr)(directive),
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: label,
678
- description: propMeta && createDescription(propMeta),
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: label,
689
- description: createDescription(event),
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
- return attributes;
694
- },
695
- provideValues: (tag, attr) => {
696
- return getAttrValues(tag, attr).map(value => ({ name: value }));
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 createDescription(meta) {
720
- if (mode === 'hover') {
721
- // dedupe from TS hover
722
- return;
723
- }
724
- let description = meta?.description ?? '';
725
- for (const tag of meta.tags) {
726
- description += `\n\n*@${tag.name}* ${tag.text ?? ''}`;
727
- }
728
- if (!description) {
729
- return;
730
- }
731
- return {
732
- kind: 'markdown',
733
- value: description,
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
- function getAttrValues(tag, attr) {
737
- if (!values) {
738
- values = [];
739
- tasks.push((async () => {
740
- if (tag === 'slot' && attr === 'name') {
741
- values = await tsserver.getComponentSlots(root.fileName) ?? [];
742
- }
743
- version++;
744
- })());
745
- }
746
- return values;
747
- }
748
- function getTagData(tag) {
749
- let data = tagDataMap.get(tag);
750
- if (!data) {
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 updateExtraCustomData(newData) {
785
+ function updateHtmlData(newData) {
837
786
  htmlData = newData;
838
787
  onDidChangeCustomDataListeners.forEach(l => l());
839
788
  }