@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.
Files changed (30) hide show
  1. package/data/language-blocks/zh-cn.json +6 -6
  2. package/data/model-modifiers/zh-cn.json +1 -1
  3. package/data/template/it.json +5 -5
  4. package/index.js +12 -8
  5. package/lib/ideFeatures/nameCasing.js +6 -6
  6. package/lib/plugins/css.js +59 -0
  7. package/lib/plugins/utils.d.ts +3 -0
  8. package/lib/plugins/utils.js +14 -0
  9. package/lib/plugins/vue-autoinsert-dotvalue.d.ts +0 -9
  10. package/lib/plugins/vue-autoinsert-dotvalue.js +31 -50
  11. package/lib/plugins/vue-autoinsert-self-closing.d.ts +2 -0
  12. package/lib/plugins/vue-autoinsert-self-closing.js +33 -0
  13. package/lib/plugins/vue-complete-define-assignment.js +6 -5
  14. package/lib/plugins/vue-directive-comments.d.ts +4 -0
  15. package/lib/plugins/vue-directive-comments.js +4 -0
  16. package/lib/plugins/vue-document-drop.js +5 -5
  17. package/lib/plugins/vue-document-links.js +5 -4
  18. package/lib/plugins/vue-extract-file.d.ts +2 -1
  19. package/lib/plugins/vue-extract-file.js +12 -7
  20. package/lib/plugins/vue-inlayhints.d.ts +1 -1
  21. package/lib/plugins/vue-inlayhints.js +11 -11
  22. package/lib/plugins/vue-sfc.js +48 -7
  23. package/lib/plugins/vue-template/autoinsert-self-closing-tags.d.ts +6 -0
  24. package/lib/plugins/vue-template/autoinsert-self-closing-tags.js +39 -0
  25. package/lib/plugins/vue-template/autoinsert-selfClosingTags.d.ts +1 -0
  26. package/lib/plugins/vue-template/autoinsert-selfClosingTags.js +3 -0
  27. package/lib/plugins/vue-template/autoinsert-selfclosing-tags.d.ts +1 -0
  28. package/lib/plugins/vue-template/autoinsert-selfclosing-tags.js +3 -0
  29. package/lib/plugins/vue-template.js +40 -50
  30. 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
- let baseName = importUri.slice(importUri.lastIndexOf('/') + 1);
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 codegen = language_core_1.tsCodegen.get(root._sfc);
28
- const scopedClasses = codegen?.generatedTemplate.get()?.scopedClasses ?? [];
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 < root._sfc.styles.length; i++) {
32
- const style = root._sfc.styles[i];
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, _context) {
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._sfc;
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._sfc;
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 exportDefault = language_core_1.scriptRanges.parseScriptRanges(ts, ast, false, true).exportDefault;
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: Set<string>): [ts.Identifier, boolean][];
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._sfc);
29
+ const codegen = language_core_1.tsCodegen.get(virtualCode.sfc);
30
30
  const inlayHints = [
31
- ...codegen?.generatedTemplate.get()?.inlayHints ?? [],
32
- ...codegen?.generatedScript.get()?.inlayHints ?? [],
31
+ ...codegen?.getGeneratedTemplate()?.inlayHints ?? [],
32
+ ...codegen?.getGeneratedScript()?.inlayHints ?? [],
33
33
  ];
34
- const scriptSetupRanges = codegen?.scriptSetupRanges.get();
35
- if (scriptSetupRanges?.defineProps?.destructured && virtualCode._sfc.scriptSetup?.ast) {
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._sfc.scriptSetup.ast, scriptSetupRanges.defineProps.destructured)) {
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._sfc.template,
55
- virtualCode._sfc.script,
56
- virtualCode._sfc.scriptSetup,
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 [id] of (0, index_1.collectIdentifiers)(ts, name)) {
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 [id] of (0, index_1.collectIdentifiers)(ts, p)) {
166
+ for (const { id } of (0, index_1.collectIdentifiers)(ts, p)) {
167
167
  registerLocalBinding(id);
168
168
  }
169
169
  }
@@ -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 htmlPlugin = (0, volar_service_html_1.create)({
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._sfc.customBlocks) {
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
- ...htmlPlugin,
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 htmlPluginInstance = htmlPlugin.create(context);
49
+ const htmlServiceInstance = htmlService.create(context);
43
50
  return {
44
- ...htmlPluginInstance,
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._sfc;
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 htmlPluginInstance.provideCompletionItems?.(document, position, context, token);
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,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=autoinsert-selfClosingTags.js.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=autoinsert-selfclosing-tags.js.map
@@ -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 tsDocumentations = new Map();
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(vueCompilerOptions, sourceScript.id, root)).sync;
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._sfc;
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._sfc;
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(vueCompilerOptions, sourceDocumentUri, vueCode) {
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
- let templateContextProps;
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._sfc.scriptSetup
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._sfc.scriptSetup.content.slice(binding.range.start, binding.range.end);
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 propsInfo = await tsPluginClient?.getComponentProps(vueCode.fileName, tag) ?? [];
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
- propsInfo: propsInfo.filter(prop => !prop.name.startsWith('ref_')),
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, propsInfo, events } = tagInfo;
472
- const props = propsInfo.map(prop => (0, language_core_1.hyphenateTag)(prop.name).startsWith('on-vnode-')
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 propKey = generateItemKey('componentProp', isGlobal ? '*' : tag, propName);
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
- })?.commentMarkdown;
523
- if (propDescription) {
524
- tsDocumentations.set(propName, propDescription);
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) && item.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
- if (tsDocumentations.has(parsedItemKey.prop)) {
681
- documentations.push(tsDocumentations.get(parsedItemKey.prop));
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
- if (tsDocumentations.has(propName)) {
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
- tsDocumentations.get(propName),
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 '__VLS_data=' + type + ',' + tag + ',' + prop;
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.0",
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.0",
24
+ "@vue/language-core": "2.2.4",
25
25
  "@vue/shared": "^3.5.0",
26
- "@vue/typescript-plugin": "2.2.0",
27
- "alien-signals": "^0.4.9",
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": "latest",
43
- "@types/path-browserify": "latest",
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": "5babca774658d4b9afbe877ac7c8cafdaecf2c3e"
48
+ "gitHead": "c28986596935cb43979c9d437c25f292bdb36cef"
48
49
  }