@vue/language-service 2.0.6 → 2.0.10

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 (34) hide show
  1. package/data/language-blocks/en.json +1 -1
  2. package/data/model-modifiers/ja.json +1 -1
  3. package/data/template/ja.json +1 -1
  4. package/index.d.ts +3 -2
  5. package/index.js +88 -23
  6. package/lib/ideFeatures/nameCasing.d.ts +2 -2
  7. package/lib/ideFeatures/nameCasing.js +23 -16
  8. package/lib/plugins/css.d.ts +2 -2
  9. package/lib/plugins/data.js +6 -3
  10. package/lib/plugins/vue-autoinsert-dotvalue.d.ts +5 -5
  11. package/lib/plugins/vue-autoinsert-dotvalue.js +37 -31
  12. package/lib/plugins/vue-autoinsert-parentheses.d.ts +2 -2
  13. package/lib/plugins/vue-autoinsert-parentheses.js +15 -6
  14. package/lib/plugins/vue-autoinsert-space.d.ts +2 -2
  15. package/lib/plugins/vue-autoinsert-space.js +7 -14
  16. package/lib/plugins/vue-codelens-references.d.ts +2 -2
  17. package/lib/plugins/vue-codelens-references.js +8 -4
  18. package/lib/plugins/vue-directive-comments.d.ts +2 -2
  19. package/lib/plugins/vue-directive-comments.js +4 -3
  20. package/lib/plugins/vue-document-drop.d.ts +2 -2
  21. package/lib/plugins/vue-document-drop.js +36 -14
  22. package/lib/plugins/vue-extract-file.d.ts +2 -2
  23. package/lib/plugins/vue-extract-file.js +32 -18
  24. package/lib/plugins/vue-sfc.d.ts +2 -2
  25. package/lib/plugins/vue-sfc.js +40 -35
  26. package/lib/plugins/vue-template.d.ts +3 -3
  27. package/lib/plugins/vue-template.js +86 -32
  28. package/lib/plugins/vue-toggle-v-bind-codeaction.d.ts +2 -2
  29. package/lib/plugins/vue-toggle-v-bind-codeaction.js +6 -3
  30. package/lib/plugins/vue-twoslash-queries.d.ts +2 -2
  31. package/lib/plugins/vue-twoslash-queries.js +9 -5
  32. package/lib/plugins/vue-visualize-hidden-callback-param.d.ts +2 -2
  33. package/lib/plugins/vue-visualize-hidden-callback-param.js +7 -4
  34. package/package.json +19 -19
@@ -6,45 +6,67 @@ const shared_1 = require("@vue/shared");
6
6
  const path = require("path-browserify");
7
7
  const vue_extract_file_1 = require("../plugins/vue-extract-file");
8
8
  const types_1 = require("../types");
9
- function create(ts) {
9
+ const getUserPreferences_1 = require("volar-service-typescript/lib/configs/getUserPreferences");
10
+ function create(ts, getTsPluginClient) {
10
11
  return {
11
12
  name: 'vue-document-drop',
12
13
  create(context) {
13
14
  let casing = types_1.TagNameCasing.Pascal; // TODO
15
+ const tsPluginClient = getTsPluginClient?.(context);
14
16
  return {
15
17
  async provideDocumentDropEdits(document, _position, dataTransfer) {
16
- if (document.languageId !== 'html')
18
+ if (document.languageId !== 'html') {
17
19
  return;
18
- const [virtualCode, sourceFile] = context.documents.getVirtualCodeByUri(document.uri);
19
- const vueVirtualCode = sourceFile?.generated?.code;
20
- if (!virtualCode || !(vueVirtualCode instanceof language_core_1.VueGeneratedCode))
20
+ }
21
+ const decoded = context.decodeEmbeddedDocumentUri(document.uri);
22
+ const sourceScript = decoded && context.language.scripts.get(decoded[0]);
23
+ const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
24
+ const vueVirtualCode = sourceScript?.generated?.root;
25
+ if (!sourceScript || !virtualCode || !(vueVirtualCode instanceof language_core_1.VueGeneratedCode)) {
21
26
  return;
27
+ }
22
28
  let importUri;
23
29
  for (const [mimeType, item] of dataTransfer) {
24
30
  if (mimeType === 'text/uri-list') {
25
31
  importUri = item.value;
26
32
  }
27
33
  }
28
- if (!importUri?.endsWith('.vue'))
34
+ if (!importUri?.endsWith('.vue')) {
29
35
  return;
36
+ }
30
37
  let baseName = importUri.substring(importUri.lastIndexOf('/') + 1);
31
38
  baseName = baseName.substring(0, baseName.lastIndexOf('.'));
32
39
  const newName = (0, shared_1.capitalize)((0, shared_1.camelize)(baseName));
33
40
  const { sfc } = vueVirtualCode;
34
41
  const script = sfc.scriptSetup ?? sfc.script;
35
- if (!script)
42
+ if (!script) {
36
43
  return;
44
+ }
37
45
  const additionalEdit = {};
38
46
  const code = [...(0, language_core_1.forEachEmbeddedCode)(vueVirtualCode)].find(code => code.id === (sfc.scriptSetup ? 'scriptSetupFormat' : 'scriptFormat'));
39
47
  const lastImportNode = (0, vue_extract_file_1.getLastImportNode)(ts, script.ast);
40
- let importPath = path.relative(path.dirname(document.uri), importUri)
41
- || importUri.substring(importUri.lastIndexOf('/') + 1);
42
- if (!importPath.startsWith('./') && !importPath.startsWith('../')) {
43
- importPath = './' + importPath;
48
+ const incomingFileName = context.env.typescript.uriToFileName(importUri);
49
+ let importPath;
50
+ const serviceScript = sourceScript.generated?.languagePlugin.typescript?.getServiceScript(vueVirtualCode);
51
+ if (tsPluginClient && serviceScript) {
52
+ const tsDocumentUri = context.encodeEmbeddedDocumentUri(sourceScript.id, serviceScript.code.id);
53
+ const tsDocument = context.documents.get(tsDocumentUri, serviceScript.code.languageId, serviceScript.code.snapshot);
54
+ const preferences = await (0, getUserPreferences_1.getUserPreferences)(context, tsDocument);
55
+ const importPathRequest = await tsPluginClient.getImportPathForFile(vueVirtualCode.fileName, incomingFileName, preferences);
56
+ if (importPathRequest) {
57
+ importPath = importPathRequest;
58
+ }
59
+ }
60
+ if (!importPath) {
61
+ importPath = path.relative(path.dirname(vueVirtualCode.fileName), incomingFileName)
62
+ || importUri.substring(importUri.lastIndexOf('/') + 1);
63
+ if (!importPath.startsWith('./') && !importPath.startsWith('../')) {
64
+ importPath = './' + importPath;
65
+ }
44
66
  }
45
67
  additionalEdit.changes ??= {};
46
- additionalEdit.changes[context.documents.getVirtualCodeUri(sourceFile.id, code.id)] = [];
47
- additionalEdit.changes[context.documents.getVirtualCodeUri(sourceFile.id, code.id)].push({
68
+ additionalEdit.changes[context.encodeEmbeddedDocumentUri(sourceScript.id, code.id)] = [];
69
+ additionalEdit.changes[context.encodeEmbeddedDocumentUri(sourceScript.id, code.id)].push({
48
70
  range: lastImportNode ? {
49
71
  start: script.ast.getLineAndCharacterOfPosition(lastImportNode.end),
50
72
  end: script.ast.getLineAndCharacterOfPosition(lastImportNode.end),
@@ -58,7 +80,7 @@ function create(ts) {
58
80
  if (sfc.script) {
59
81
  const edit = (0, vue_extract_file_1.createAddComponentToOptionEdit)(ts, sfc.script.ast, newName);
60
82
  if (edit) {
61
- additionalEdit.changes[context.documents.getVirtualCodeUri(sourceFile.id, code.id)].push({
83
+ additionalEdit.changes[context.encodeEmbeddedDocumentUri(sourceScript.id, code.id)].push({
62
84
  range: {
63
85
  start: document.positionAt(edit.range.start),
64
86
  end: document.positionAt(edit.range.end),
@@ -1,6 +1,6 @@
1
- import type { ServicePlugin } from '@volar/language-service';
1
+ import type { ServiceContext, LanguageServicePlugin } from '@volar/language-service';
2
2
  import type * as ts from 'typescript';
3
- export declare function create(ts: typeof import('typescript'), tsPluginClient?: typeof import('@vue/typescript-plugin/lib/client')): ServicePlugin;
3
+ export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: ServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
4
4
  export declare function getLastImportNode(ts: typeof import('typescript'), sourceFile: ts.SourceFile): ts.Node | undefined;
5
5
  export declare function createAddComponentToOptionEdit(ts: typeof import('typescript'), ast: ts.SourceFile, componentName: string): {
6
6
  range: import("@vue/language-core").TextRange;
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createAddComponentToOptionEdit = exports.getLastImportNode = exports.create = void 0;
4
4
  const language_core_1 = require("@vue/language-core");
5
5
  const unicodeReg = /\\u/g;
6
- function create(ts, tsPluginClient) {
6
+ function create(ts, getTsPluginClient) {
7
7
  return {
8
8
  name: 'vue-extract-file',
9
9
  create(context) {
10
+ const tsPluginClient = getTsPluginClient?.(context);
10
11
  return {
11
12
  async provideCodeActions(document, range, _context) {
12
13
  const startOffset = document.offsetAt(range.start);
@@ -14,16 +15,21 @@ function create(ts, tsPluginClient) {
14
15
  if (startOffset === endOffset) {
15
16
  return;
16
17
  }
17
- const [code, vueCode] = context.documents.getVirtualCodeByUri(document.uri);
18
- if (!(vueCode?.generated?.code instanceof language_core_1.VueGeneratedCode) || code?.id !== 'template')
18
+ const decoded = context.decodeEmbeddedDocumentUri(document.uri);
19
+ const sourceScript = decoded && context.language.scripts.get(decoded[0]);
20
+ const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
21
+ if (!(sourceScript?.generated?.root instanceof language_core_1.VueGeneratedCode) || virtualCode?.id !== 'template') {
19
22
  return;
20
- const { sfc } = vueCode.generated.code;
23
+ }
24
+ const { sfc } = sourceScript.generated.root;
21
25
  const script = sfc.scriptSetup ?? sfc.script;
22
- if (!sfc.template || !script)
26
+ if (!sfc.template || !script) {
23
27
  return;
28
+ }
24
29
  const templateCodeRange = selectTemplateCode(startOffset, endOffset, sfc.template);
25
- if (!templateCodeRange)
30
+ if (!templateCodeRange) {
26
31
  return;
32
+ }
27
33
  return [
28
34
  {
29
35
  title: 'Extract into new dumb component',
@@ -39,21 +45,27 @@ function create(ts, tsPluginClient) {
39
45
  async resolveCodeAction(codeAction) {
40
46
  const { uri, range, newName } = codeAction.data;
41
47
  const [startOffset, endOffset] = range;
42
- const [code, sourceFile] = context.documents.getVirtualCodeByUri(uri);
43
- if (!(sourceFile?.generated?.code instanceof language_core_1.VueGeneratedCode) || code?.id !== 'template')
48
+ const decoded = context.decodeEmbeddedDocumentUri(uri);
49
+ const sourceScript = decoded && context.language.scripts.get(decoded[0]);
50
+ const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
51
+ if (!(sourceScript?.generated?.root instanceof language_core_1.VueGeneratedCode) || virtualCode?.id !== 'template') {
44
52
  return codeAction;
45
- const document = context.documents.get(uri, code.languageId, code.snapshot);
46
- const sfcDocument = context.documents.get(sourceFile.id, sourceFile.languageId, sourceFile.snapshot);
47
- const { sfc } = sourceFile.generated.code;
53
+ }
54
+ const document = context.documents.get(uri, virtualCode.languageId, virtualCode.snapshot);
55
+ const sfcDocument = context.documents.get(sourceScript.id, sourceScript.languageId, sourceScript.snapshot);
56
+ const { sfc } = sourceScript.generated.root;
48
57
  const script = sfc.scriptSetup ?? sfc.script;
49
- if (!sfc.template || !script)
58
+ if (!sfc.template || !script) {
50
59
  return codeAction;
60
+ }
51
61
  const templateCodeRange = selectTemplateCode(startOffset, endOffset, sfc.template);
52
- if (!templateCodeRange)
62
+ if (!templateCodeRange) {
53
63
  return codeAction;
54
- const toExtract = await tsPluginClient?.collectExtractProps(sourceFile.generated.code.fileName, templateCodeRange) ?? [];
55
- if (!toExtract)
64
+ }
65
+ const toExtract = await tsPluginClient?.collectExtractProps(sourceScript.generated.root.fileName, templateCodeRange) ?? [];
66
+ if (!toExtract) {
56
67
  return codeAction;
68
+ }
57
69
  const templateInitialIndent = await context.env.getConfiguration('vue.format.template.initialIndent') ?? true;
58
70
  const scriptInitialIndent = await context.env.getConfiguration('vue.format.script.initialIndent') ?? false;
59
71
  const newUri = sfcDocument.uri.substring(0, sfcDocument.uri.lastIndexOf('/') + 1) + `${newName}.vue`;
@@ -114,7 +126,7 @@ function create(ts, tsPluginClient) {
114
126
  // editing vue sfc
115
127
  {
116
128
  textDocument: {
117
- uri: sourceFile.id,
129
+ uri: sourceScript.id,
118
130
  version: null,
119
131
  },
120
132
  edits: sfcEdits,
@@ -200,8 +212,9 @@ function selectTemplateCode(startOffset, endOffset, templateBlock) {
200
212
  }
201
213
  }
202
214
  function constructTag(name, attributes, initialIndent, content) {
203
- if (initialIndent)
215
+ if (initialIndent) {
204
216
  content = content.split('\n').map(line => `\t${line}`).join('\n');
217
+ }
205
218
  const attributesString = attributes.length ? ` ${attributes.join(' ')}` : '';
206
219
  return `<${name}${attributesString}>\n${content}\n</${name}>\n`;
207
220
  }
@@ -220,8 +233,9 @@ function getLastImportNode(ts, sourceFile) {
220
233
  exports.getLastImportNode = getLastImportNode;
221
234
  function createAddComponentToOptionEdit(ts, ast, componentName) {
222
235
  const exportDefault = language_core_1.scriptRanges.parseScriptRanges(ts, ast, false, true).exportDefault;
223
- if (!exportDefault)
236
+ if (!exportDefault) {
224
237
  return;
238
+ }
225
239
  // https://github.com/microsoft/TypeScript/issues/36174
226
240
  const printer = ts.createPrinter();
227
241
  if (exportDefault.componentsOption && exportDefault.componentsOptionNode) {
@@ -1,7 +1,7 @@
1
- import type { ServicePlugin } from '@volar/language-service';
1
+ import type { LanguageServicePlugin } from '@volar/language-service';
2
2
  import * as vue from '@vue/language-core';
3
3
  import type { TextDocument } from 'vscode-languageserver-textdocument';
4
4
  export interface Provide {
5
5
  'vue/vueFile': (document: TextDocument) => vue.VueGeneratedCode | undefined;
6
6
  }
7
- export declare function create(): ServicePlugin;
7
+ export declare function create(): LanguageServicePlugin;
@@ -12,34 +12,53 @@ function create() {
12
12
  create(context) {
13
13
  const htmlPlugin = (0, volar_service_html_1.create)({
14
14
  documentSelector: ['vue'],
15
- useCustomDataProviders: false,
15
+ useDefaultDataProvider: false,
16
+ getCustomData(context) {
17
+ sfcDataProvider ??= html.newHTMLDataProvider('vue', (0, data_1.loadLanguageBlocks)(context.env.locale ?? 'en'));
18
+ return [sfcDataProvider];
19
+ },
20
+ async getFormattingOptions(document, options, context) {
21
+ return await worker(document, async (vueCode) => {
22
+ const formatSettings = await context.env.getConfiguration?.('html.format') ?? {};
23
+ const blockTypes = ['template', 'script', 'style'];
24
+ for (const customBlock of vueCode.sfc.customBlocks) {
25
+ blockTypes.push(customBlock.type);
26
+ }
27
+ return {
28
+ ...options,
29
+ ...formatSettings,
30
+ wrapAttributes: 'auto',
31
+ unformatted: '',
32
+ contentUnformatted: blockTypes.join(','),
33
+ endWithNewline: options.insertFinalNewline ? true
34
+ : options.trimFinalNewlines ? false
35
+ : document.getText().endsWith('\n'),
36
+ };
37
+ }) ?? {};
38
+ },
16
39
  }).create(context);
17
- const htmlLanguageService = htmlPlugin.provide['html/languageService']();
18
- sfcDataProvider ??= html.newHTMLDataProvider('vue', (0, data_1.loadLanguageBlocks)(context.env.locale ?? 'en'));
19
- htmlLanguageService.setDataProviders(false, [sfcDataProvider]);
20
40
  return {
21
41
  ...htmlPlugin,
22
42
  provide: {
23
43
  'vue/vueFile': document => {
24
- return worker(document, (vueFile) => {
44
+ return worker(document, vueFile => {
25
45
  return vueFile;
26
46
  });
27
47
  },
28
48
  },
29
- async resolveEmbeddedCodeFormattingOptions(code, options) {
30
- const sourceFile = context.language.files.getByVirtualCode(code);
31
- if (sourceFile.generated?.code instanceof vue.VueGeneratedCode) {
32
- if (code.id === 'scriptFormat' || code.id === 'scriptSetupFormat') {
49
+ async resolveEmbeddedCodeFormattingOptions(sourceScript, virtualCode, options) {
50
+ if (sourceScript.generated?.root instanceof vue.VueGeneratedCode) {
51
+ if (virtualCode.id === 'scriptFormat' || virtualCode.id === 'scriptSetupFormat') {
33
52
  if (await context.env.getConfiguration?.('vue.format.script.initialIndent') ?? false) {
34
53
  options.initialIndentLevel++;
35
54
  }
36
55
  }
37
- else if (code.id.startsWith('style_')) {
56
+ else if (virtualCode.id.startsWith('style_')) {
38
57
  if (await context.env.getConfiguration?.('vue.format.style.initialIndent') ?? false) {
39
58
  options.initialIndentLevel++;
40
59
  }
41
60
  }
42
- else if (code.id === 'template') {
61
+ else if (virtualCode.id === 'template') {
43
62
  if (await context.env.getConfiguration?.('vue.format.template.initialIndent') ?? true) {
44
63
  options.initialIndentLevel++;
45
64
  }
@@ -49,7 +68,7 @@ function create() {
49
68
  },
50
69
  provideDocumentLinks: undefined,
51
70
  provideDocumentSymbols(document) {
52
- return worker(document, (vueSourceFile) => {
71
+ return worker(document, vueSourceFile => {
53
72
  const result = [];
54
73
  const descriptor = vueSourceFile.sfc;
55
74
  if (descriptor.template) {
@@ -96,10 +115,12 @@ function create() {
96
115
  }
97
116
  for (const style of descriptor.styles) {
98
117
  let name = 'style';
99
- if (style.scoped)
118
+ if (style.scoped) {
100
119
  name += ' scoped';
101
- if (style.module)
120
+ }
121
+ if (style.module) {
102
122
  name += ' module';
123
+ }
103
124
  result.push({
104
125
  name,
105
126
  kind: 2,
@@ -130,29 +151,13 @@ function create() {
130
151
  return result;
131
152
  });
132
153
  },
133
- provideDocumentFormattingEdits(document, range, options) {
134
- return worker(document, async (vueCode) => {
135
- const formatSettings = await context.env.getConfiguration?.('html.format') ?? {};
136
- const blockTypes = ['template', 'script', 'style'];
137
- for (const customBlock of vueCode.sfc.customBlocks) {
138
- blockTypes.push(customBlock.type);
139
- }
140
- return htmlLanguageService.format(document, range, {
141
- ...options,
142
- ...formatSettings,
143
- unformatted: '',
144
- contentUnformatted: blockTypes.join(','),
145
- endWithNewline: options.insertFinalNewline ? true
146
- : options.trimFinalNewlines ? false
147
- : document.getText().endsWith('\n'),
148
- });
149
- });
150
- },
151
154
  };
152
155
  function worker(document, callback) {
153
- const [vueFile] = context.documents.getVirtualCodeByUri(document.uri);
154
- if (vueFile instanceof vue.VueGeneratedCode) {
155
- return callback(vueFile);
156
+ const decoded = context.decodeEmbeddedDocumentUri(document.uri);
157
+ const sourceScript = decoded && context.language.scripts.get(decoded[0]);
158
+ const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
159
+ if (virtualCode instanceof vue.VueGeneratedCode) {
160
+ return callback(virtualCode);
156
161
  }
157
162
  }
158
163
  },
@@ -1,3 +1,3 @@
1
- import type { ServiceEnvironment } from '@volar/language-service';
2
- import { ServicePlugin, VueCompilerOptions } from '../types';
3
- export declare function create(mode: 'html' | 'pug', ts: typeof import('typescript'), getVueOptions: (env: ServiceEnvironment) => VueCompilerOptions, tsPluginClient?: typeof import('@vue/typescript-plugin/lib/client')): ServicePlugin;
1
+ import type { ServiceContext, ServiceEnvironment } from '@volar/language-service';
2
+ import { LanguageServicePlugin, VueCompilerOptions } from '../types';
3
+ export declare function create(mode: 'html' | 'pug', ts: typeof import('typescript'), getVueOptions: (env: ServiceEnvironment) => VueCompilerOptions, getTsPluginClient?: (context: ServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
@@ -10,9 +10,10 @@ const nameCasing_1 = require("../ideFeatures/nameCasing");
10
10
  const types_1 = require("../types");
11
11
  const data_1 = require("./data");
12
12
  const vscode_uri_1 = require("vscode-uri");
13
+ const common_1 = require("@vue/typescript-plugin/lib/common");
13
14
  let builtInData;
14
15
  let modelData;
15
- function create(mode, ts, getVueOptions, tsPluginClient) {
16
+ function create(mode, ts, getVueOptions, getTsPluginClient) {
16
17
  let customData = [];
17
18
  let extraCustomData = [];
18
19
  const onDidChangeCustomDataListeners = new Set();
@@ -41,6 +42,7 @@ function create(mode, ts, getVueOptions, tsPluginClient) {
41
42
  '@', // vue event shorthand
42
43
  ],
43
44
  create(context) {
45
+ const tsPluginClient = getTsPluginClient?.(context);
44
46
  const baseServiceInstance = baseService.create(context);
45
47
  const vueCompilerOptions = getVueOptions(context.env);
46
48
  builtInData ??= (0, data_1.loadTemplateData)(context.env.locale ?? 'en');
@@ -82,38 +84,46 @@ function create(mode, ts, getVueOptions, tsPluginClient) {
82
84
  disposable?.dispose();
83
85
  },
84
86
  async provideCompletionItems(document, position, completionContext, token) {
85
- if (!isSupportedDocument(document))
87
+ if (!isSupportedDocument(document)) {
86
88
  return;
89
+ }
87
90
  let sync;
88
91
  let currentVersion;
89
- const [_, sourceFile] = context.documents.getVirtualCodeByUri(document.uri);
90
- if (sourceFile?.generated?.code instanceof language_core_1.VueGeneratedCode) {
91
- sync = (await provideHtmlData(sourceFile.id, sourceFile.generated.code)).sync;
92
+ const decoded = context.decodeEmbeddedDocumentUri(document.uri);
93
+ const sourceScript = decoded && context.language.scripts.get(decoded[0]);
94
+ if (sourceScript?.generated?.root instanceof language_core_1.VueGeneratedCode) {
95
+ sync = (await provideHtmlData(sourceScript.id, sourceScript.generated.root)).sync;
92
96
  currentVersion = await sync();
93
97
  }
94
98
  let htmlComplete = await baseServiceInstance.provideCompletionItems?.(document, position, completionContext, token);
95
99
  while (currentVersion !== (currentVersion = await sync?.())) {
96
100
  htmlComplete = await baseServiceInstance.provideCompletionItems?.(document, position, completionContext, token);
97
101
  }
98
- if (!htmlComplete)
102
+ if (!htmlComplete) {
99
103
  return;
100
- if (sourceFile?.generated?.code instanceof language_core_1.VueGeneratedCode) {
101
- await afterHtmlCompletion(htmlComplete, context.documents.get(sourceFile.id, sourceFile.languageId, sourceFile.snapshot), sourceFile.generated.code);
104
+ }
105
+ if (sourceScript?.generated?.root instanceof language_core_1.VueGeneratedCode) {
106
+ await afterHtmlCompletion(htmlComplete, context.documents.get(sourceScript.id, sourceScript.languageId, sourceScript.snapshot), sourceScript.generated.root);
102
107
  }
103
108
  return htmlComplete;
104
109
  },
105
110
  async provideInlayHints(document) {
106
- if (!isSupportedDocument(document))
111
+ if (!isSupportedDocument(document)) {
107
112
  return;
113
+ }
108
114
  const enabled = await context.env.getConfiguration?.('vue.inlayHints.missingProps') ?? false;
109
- if (!enabled)
115
+ if (!enabled) {
110
116
  return;
117
+ }
111
118
  const result = [];
112
- const [virtualCode] = context.documents.getVirtualCodeByUri(document.uri);
113
- if (!virtualCode)
119
+ const decoded = context.decodeEmbeddedDocumentUri(document.uri);
120
+ const sourceScript = decoded && context.language.scripts.get(decoded[0]);
121
+ const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
122
+ if (!virtualCode) {
114
123
  return;
124
+ }
115
125
  for (const map of context.documents.getMaps(virtualCode)) {
116
- const code = context.language.files.get(map.sourceDocument.uri)?.generated?.code;
126
+ const code = context.language.scripts.get(map.sourceDocument.uri)?.generated?.root;
117
127
  const scanner = getScanner(baseServiceInstance, document);
118
128
  if (code instanceof language_core_1.VueGeneratedCode && scanner) {
119
129
  // visualize missing required props
@@ -203,23 +213,30 @@ function create(mode, ts, getVueOptions, tsPluginClient) {
203
213
  return result;
204
214
  },
205
215
  provideHover(document, position, token) {
206
- if (!isSupportedDocument(document))
216
+ if (!isSupportedDocument(document)) {
207
217
  return;
208
- if (context.documents.getVirtualCodeByUri(document.uri)[0])
218
+ }
219
+ if (context.decodeEmbeddedDocumentUri(document.uri)) {
209
220
  updateExtraCustomData([]);
221
+ }
210
222
  return baseServiceInstance.provideHover?.(document, position, token);
211
223
  },
212
224
  async provideDiagnostics(document, token) {
213
- if (!isSupportedDocument(document))
225
+ if (!isSupportedDocument(document)) {
214
226
  return;
227
+ }
215
228
  const originalResult = await baseServiceInstance.provideDiagnostics?.(document, token);
216
- const [virtualCode] = context.documents.getVirtualCodeByUri(document.uri);
217
- if (!virtualCode)
229
+ const decoded = context.decodeEmbeddedDocumentUri(document.uri);
230
+ const sourceScript = decoded && context.language.scripts.get(decoded[0]);
231
+ const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
232
+ if (!virtualCode) {
218
233
  return;
234
+ }
219
235
  for (const map of context.documents.getMaps(virtualCode)) {
220
- const code = context.language.files.get(map.sourceDocument.uri)?.generated?.code;
221
- if (!(code instanceof language_core_1.VueGeneratedCode))
236
+ const code = context.language.scripts.get(map.sourceDocument.uri)?.generated?.root;
237
+ if (!(code instanceof language_core_1.VueGeneratedCode)) {
222
238
  continue;
239
+ }
223
240
  const templateErrors = [];
224
241
  const { template } = code.sfc;
225
242
  if (template) {
@@ -253,18 +270,58 @@ function create(mode, ts, getVueOptions, tsPluginClient) {
253
270
  ];
254
271
  }
255
272
  },
273
+ provideDocumentSemanticTokens(document, range, legend) {
274
+ if (!isSupportedDocument(document)) {
275
+ return;
276
+ }
277
+ const languageService = context.inject('typescript/languageService');
278
+ if (!languageService) {
279
+ return;
280
+ }
281
+ const decoded = context.decodeEmbeddedDocumentUri(document.uri);
282
+ const sourceScript = decoded && context.language.scripts.get(decoded[0]);
283
+ if (!sourceScript
284
+ || !(sourceScript.generated?.root instanceof language_core_1.VueGeneratedCode)
285
+ || !sourceScript.generated.root.sfc.template) {
286
+ return [];
287
+ }
288
+ const { template } = sourceScript.generated.root.sfc;
289
+ const spans = common_1.getComponentSpans.call({
290
+ files: context.language.scripts,
291
+ languageService,
292
+ typescript: ts,
293
+ vueOptions: getVueOptions(context.env),
294
+ }, sourceScript.generated.root, template, {
295
+ start: document.offsetAt(range.start),
296
+ length: document.offsetAt(range.end) - document.offsetAt(range.start),
297
+ });
298
+ const classTokenIndex = legend.tokenTypes.indexOf('class');
299
+ return spans.map(span => {
300
+ const start = document.positionAt(span.start);
301
+ return [
302
+ start.line,
303
+ start.character,
304
+ span.length,
305
+ classTokenIndex,
306
+ 0,
307
+ ];
308
+ });
309
+ },
256
310
  };
257
311
  async function provideHtmlData(sourceDocumentUri, vueCode) {
258
312
  await (initializing ??= initialize());
259
313
  const casing = await (0, nameCasing_1.getNameCasing)(context, sourceDocumentUri, tsPluginClient);
260
314
  if (builtInData.tags) {
261
315
  for (const tag of builtInData.tags) {
262
- if (tag.name === 'slot')
316
+ if (tag.name === 'slot') {
263
317
  continue;
264
- if (tag.name === 'component')
318
+ }
319
+ if (tag.name === 'component') {
265
320
  continue;
266
- if (tag.name === 'template')
321
+ }
322
+ if (tag.name === 'template') {
267
323
  continue;
324
+ }
268
325
  if (casing.tag === types_1.TagNameCasing.Kebab) {
269
326
  tag.name = (0, language_core_1.hyphenateTag)(tag.name);
270
327
  }
@@ -324,10 +381,8 @@ function create(mode, ts, getVueOptions, tsPluginClient) {
324
381
  }
325
382
  return tags;
326
383
  },
327
- provideAttributes: (tag) => {
328
- tsPluginClient?.getTemplateContextProps;
329
- let failed = false;
330
- let tagInfo = tagInfos.get(tag);
384
+ provideAttributes: tag => {
385
+ const tagInfo = tagInfos.get(tag);
331
386
  if (!tagInfo) {
332
387
  promises.push((async () => {
333
388
  const attrs = await tsPluginClient?.getElementAttrs(vueCode.fileName, tag) ?? [];
@@ -342,9 +397,6 @@ function create(mode, ts, getVueOptions, tsPluginClient) {
342
397
  })());
343
398
  return [];
344
399
  }
345
- if (failed) {
346
- return [];
347
- }
348
400
  const { attrs, props, events } = tagInfo;
349
401
  const attributes = [];
350
402
  const _tsCodegen = language_core_1.tsCodegen.get(vueCode.sfc);
@@ -467,8 +519,9 @@ function create(mode, ts, getVueOptions, tsPluginClient) {
467
519
  const textWithoutModifier = replacement.text.split('.')[0];
468
520
  if (validModifiers && hasModifier) {
469
521
  for (const modifier in validModifiers) {
470
- if (modifiers.includes(modifier))
522
+ if (modifiers.includes(modifier)) {
471
523
  continue;
524
+ }
472
525
  const modifierDes = validModifiers[modifier];
473
526
  const insertText = textWithoutModifier + modifiers.slice(0, -1).map(m => '.' + m).join('') + '.' + modifier;
474
527
  const newItem = {
@@ -489,8 +542,9 @@ function create(mode, ts, getVueOptions, tsPluginClient) {
489
542
  }
490
543
  else if (hasModifier && isModel) {
491
544
  for (const modifier of modelData.globalAttributes ?? []) {
492
- if (modifiers.includes(modifier.name))
545
+ if (modifiers.includes(modifier.name)) {
493
546
  continue;
547
+ }
494
548
  const insertText = textWithoutModifier + modifiers.slice(0, -1).map(m => '.' + m).join('') + '.' + modifier.name;
495
549
  const newItem = {
496
550
  label: modifier.name,
@@ -1,2 +1,2 @@
1
- import type { ServicePlugin } from '@volar/language-service';
2
- export declare function create(ts: typeof import('typescript')): ServicePlugin;
1
+ import type { LanguageServicePlugin } from '@volar/language-service';
2
+ export declare function create(ts: typeof import('typescript')): LanguageServicePlugin;
@@ -10,16 +10,19 @@ function create(ts) {
10
10
  provideCodeActions(document, range, _context) {
11
11
  const startOffset = document.offsetAt(range.start);
12
12
  const endOffset = document.offsetAt(range.end);
13
- const [virtualCode] = context.documents.getVirtualCodeByUri(document.uri);
13
+ const decoded = context.decodeEmbeddedDocumentUri(document.uri);
14
+ const sourceScript = decoded && context.language.scripts.get(decoded[0]);
15
+ const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
14
16
  if (!(virtualCode instanceof language_core_1.VueGeneratedCode)) {
15
17
  return;
16
18
  }
17
19
  const { template } = virtualCode.sfc;
18
- if (!template?.ast)
20
+ if (!template?.ast) {
19
21
  return;
22
+ }
20
23
  const templateStartOffset = template.startTagEnd;
21
24
  const result = [];
22
- for (const node of (0, language_core_1.eachElementNode)(template.ast)) {
25
+ for (const node of (0, language_core_1.forEachElementNode)(template.ast)) {
23
26
  if (startOffset > templateStartOffset + node.loc.end.offset || endOffset < templateStartOffset + node.loc.start.offset) {
24
27
  return;
25
28
  }
@@ -1,2 +1,2 @@
1
- import type { ServicePlugin } from '@volar/language-service';
2
- export declare function create(ts: typeof import('typescript'), tsPluginClient?: typeof import('@vue/typescript-plugin/lib/client')): ServicePlugin;
1
+ import type { ServiceContext, LanguageServicePlugin } from '@volar/language-service';
2
+ export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: ServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;