@vue/language-service 2.2.10 → 3.0.0-alpha.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.
package/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  export * from '@volar/language-service';
2
2
  export * from '@vue/language-core';
3
- export * from './lib/ideFeatures/nameCasing';
3
+ export * from './lib/nameCasing';
4
4
  export * from './lib/types';
5
5
  import type { LanguageServicePlugin } from '@volar/language-service';
6
- import { VueCompilerOptions } from '@vue/language-core';
6
+ import { type VueCompilerOptions } from '@vue/language-core';
7
7
  declare module '@volar/language-service' {
8
8
  interface ProjectContext {
9
9
  vue?: {
@@ -11,7 +11,8 @@ declare module '@volar/language-service' {
11
11
  };
12
12
  }
13
13
  }
14
- export declare function getFullLanguageServicePlugins(ts: typeof import('typescript'), { disableAutoImportCache }?: {
15
- disableAutoImportCache?: boolean;
16
- }): LanguageServicePlugin<any>[];
17
- export declare function getHybridModeLanguageServicePlugins(ts: typeof import('typescript'), getTsPluginClient: typeof import("@vue/typescript-plugin/lib/client")): LanguageServicePlugin<any>[];
14
+ export declare function getFullLanguageServicePlugins(ts: typeof import('typescript')): LanguageServicePlugin<any>[];
15
+ import type * as ts from 'typescript';
16
+ export declare function getHybridModeLanguageServicePlugins(ts: typeof import('typescript'), tsPluginClient: (import('@vue/typescript-plugin/lib/requests').Requests & {
17
+ getDocumentHighlights: (fileName: string, position: number) => Promise<ts.DocumentHighlights[] | null>;
18
+ }) | undefined): LanguageServicePlugin<any>[];
package/index.js CHANGED
@@ -19,7 +19,7 @@ exports.getFullLanguageServicePlugins = getFullLanguageServicePlugins;
19
19
  exports.getHybridModeLanguageServicePlugins = getHybridModeLanguageServicePlugins;
20
20
  __exportStar(require("@volar/language-service"), exports);
21
21
  __exportStar(require("@vue/language-core"), exports);
22
- __exportStar(require("./lib/ideFeatures/nameCasing"), exports);
22
+ __exportStar(require("./lib/nameCasing"), exports);
23
23
  __exportStar(require("./lib/types"), exports);
24
24
  const types_1 = require("./lib/types");
25
25
  const volar_service_emmet_1 = require("volar-service-emmet");
@@ -32,12 +32,15 @@ const syntactic_1 = require("volar-service-typescript/lib/plugins/syntactic");
32
32
  const css_1 = require("./lib/plugins/css");
33
33
  const vue_autoinsert_dotvalue_1 = require("./lib/plugins/vue-autoinsert-dotvalue");
34
34
  const vue_autoinsert_space_1 = require("./lib/plugins/vue-autoinsert-space");
35
+ const vue_compiler_dom_errors_1 = require("./lib/plugins/vue-compiler-dom-errors");
35
36
  const vue_complete_define_assignment_1 = require("./lib/plugins/vue-complete-define-assignment");
36
37
  const vue_directive_comments_1 = require("./lib/plugins/vue-directive-comments");
37
38
  const vue_document_drop_1 = require("./lib/plugins/vue-document-drop");
39
+ const vue_document_highlights_1 = require("./lib/plugins/vue-document-highlights");
38
40
  const vue_document_links_1 = require("./lib/plugins/vue-document-links");
39
41
  const vue_extract_file_1 = require("./lib/plugins/vue-extract-file");
40
42
  const vue_inlayhints_1 = require("./lib/plugins/vue-inlayhints");
43
+ const vue_missing_props_hints_1 = require("./lib/plugins/vue-missing-props-hints");
41
44
  const vue_sfc_1 = require("./lib/plugins/vue-sfc");
42
45
  const vue_template_1 = require("./lib/plugins/vue-template");
43
46
  const vue_twoslash_queries_1 = require("./lib/plugins/vue-twoslash-queries");
@@ -49,14 +52,15 @@ const getComponentEvents_1 = require("@vue/typescript-plugin/lib/requests/getCom
49
52
  const getComponentNames_1 = require("@vue/typescript-plugin/lib/requests/getComponentNames");
50
53
  const getComponentProps_1 = require("@vue/typescript-plugin/lib/requests/getComponentProps");
51
54
  const getElementAttrs_1 = require("@vue/typescript-plugin/lib/requests/getElementAttrs");
55
+ const getElementNames_1 = require("@vue/typescript-plugin/lib/requests/getElementNames");
52
56
  const getImportPathForFile_1 = require("@vue/typescript-plugin/lib/requests/getImportPathForFile");
53
57
  const getPropertiesAtLocation_1 = require("@vue/typescript-plugin/lib/requests/getPropertiesAtLocation");
54
58
  const vscode_uri_1 = require("vscode-uri");
55
- const nameCasing_1 = require("./lib/ideFeatures/nameCasing");
56
- function getFullLanguageServicePlugins(ts, { disableAutoImportCache } = {}) {
59
+ const nameCasing_1 = require("./lib/nameCasing");
60
+ function getFullLanguageServicePlugins(ts) {
57
61
  const plugins = [
58
- ...(0, volar_service_typescript_1.create)(ts, { disableAutoImportCache }),
59
- ...getCommonLanguageServicePlugins(ts, getTsPluginClientForLSP)
62
+ ...(0, volar_service_typescript_1.create)(ts),
63
+ ...getCommonLanguageServicePlugins(ts, getTsPluginClientForLSP),
60
64
  ];
61
65
  for (let i = 0; i < plugins.length; i++) {
62
66
  const plugin = plugins[i];
@@ -102,28 +106,31 @@ function getFullLanguageServicePlugins(ts, { disableAutoImportCache } = {}) {
102
106
  };
103
107
  return {
104
108
  async collectExtractProps(...args) {
105
- return await collectExtractProps_1.collectExtractProps.apply(requestContext, args);
109
+ return collectExtractProps_1.collectExtractProps.apply(requestContext, args);
106
110
  },
107
111
  async getPropertiesAtLocation(...args) {
108
- return await getPropertiesAtLocation_1.getPropertiesAtLocation.apply(requestContext, args);
112
+ return getPropertiesAtLocation_1.getPropertiesAtLocation.apply(requestContext, args);
109
113
  },
110
114
  async getImportPathForFile(...args) {
111
- return await getImportPathForFile_1.getImportPathForFile.apply(requestContext, args);
115
+ return getImportPathForFile_1.getImportPathForFile.apply(requestContext, args);
112
116
  },
113
117
  async getComponentEvents(...args) {
114
- return await getComponentEvents_1.getComponentEvents.apply(requestContext, args);
118
+ return getComponentEvents_1.getComponentEvents.apply(requestContext, args);
115
119
  },
116
120
  async getComponentDirectives(...args) {
117
- return await getComponentDirectives_1.getComponentDirectives.apply(requestContext, args);
121
+ return getComponentDirectives_1.getComponentDirectives.apply(requestContext, args);
118
122
  },
119
123
  async getComponentNames(...args) {
120
- return await getComponentNames_1.getComponentNames.apply(requestContext, args);
124
+ return getComponentNames_1.getComponentNames.apply(requestContext, args);
121
125
  },
122
126
  async getComponentProps(...args) {
123
- return await getComponentProps_1.getComponentProps.apply(requestContext, args);
127
+ return getComponentProps_1.getComponentProps.apply(requestContext, args);
124
128
  },
125
129
  async getElementAttrs(...args) {
126
- return await getElementAttrs_1.getElementAttrs.apply(requestContext, args);
130
+ return getElementAttrs_1.getElementAttrs.apply(requestContext, args);
131
+ },
132
+ async getElementNames(...args) {
133
+ return getElementNames_1.getElementNames.apply(requestContext, args);
127
134
  },
128
135
  async getQuickInfoAtPosition(fileName, position) {
129
136
  const languageService = context.getLanguageService();
@@ -132,8 +139,7 @@ function getFullLanguageServicePlugins(ts, { disableAutoImportCache } = {}) {
132
139
  if (!sourceScript) {
133
140
  return;
134
141
  }
135
- const document = context.documents.get(uri, sourceScript.languageId, sourceScript.snapshot);
136
- const hover = await languageService.getHover(uri, document.positionAt(position));
142
+ const hover = await languageService.getHover(uri, position);
137
143
  let text = '';
138
144
  if (typeof hover?.contents === 'string') {
139
145
  text = hover.contents;
@@ -161,12 +167,15 @@ function getFullLanguageServicePlugins(ts, { disableAutoImportCache } = {}) {
161
167
  };
162
168
  }
163
169
  }
164
- function getHybridModeLanguageServicePlugins(ts, getTsPluginClient) {
170
+ function getHybridModeLanguageServicePlugins(ts, tsPluginClient) {
165
171
  const plugins = [
166
172
  (0, syntactic_1.create)(ts),
167
173
  (0, docCommentTemplate_1.create)(ts),
168
- ...getCommonLanguageServicePlugins(ts, () => getTsPluginClient)
174
+ ...getCommonLanguageServicePlugins(ts, () => tsPluginClient)
169
175
  ];
176
+ if (tsPluginClient) {
177
+ plugins.push((0, vue_document_highlights_1.create)(tsPluginClient.getDocumentHighlights));
178
+ }
170
179
  for (const plugin of plugins) {
171
180
  // avoid affecting TS plugin
172
181
  delete plugin.capabilities.semanticTokensProvider;
@@ -179,12 +188,14 @@ function getCommonLanguageServicePlugins(ts, getTsPluginClient) {
179
188
  (0, css_1.create)(),
180
189
  (0, volar_service_pug_beautify_1.create)(),
181
190
  (0, volar_service_json_1.create)(),
182
- (0, vue_template_1.create)('html', ts, getTsPluginClient),
183
- (0, vue_template_1.create)('pug', ts, getTsPluginClient),
191
+ (0, vue_template_1.create)('html', getTsPluginClient),
192
+ (0, vue_template_1.create)('pug', getTsPluginClient),
193
+ (0, vue_missing_props_hints_1.create)(getTsPluginClient),
194
+ (0, vue_compiler_dom_errors_1.create)(),
184
195
  (0, vue_sfc_1.create)(),
185
196
  (0, vue_twoslash_queries_1.create)(getTsPluginClient),
186
- (0, vue_document_links_1.create)(),
187
197
  (0, vue_document_drop_1.create)(ts, getTsPluginClient),
198
+ (0, vue_document_links_1.create)(),
188
199
  (0, vue_complete_define_assignment_1.create)(),
189
200
  (0, vue_autoinsert_dotvalue_1.create)(ts, getTsPluginClient),
190
201
  (0, vue_autoinsert_space_1.create)(),
@@ -23,55 +23,67 @@ function create() {
23
23
  return diagnostics;
24
24
  },
25
25
  /**
26
- * If the editing position is within the virtual code and navigation is enabled,
27
- * skip the CSS renaming feature.
26
+ * If the position is within the virtual code and navigation is enabled,
27
+ * skip the CSS navigation feature.
28
28
  */
29
+ provideReferences(document, position) {
30
+ if (isWithinNavigationVirtualCode(document, position)) {
31
+ return;
32
+ }
33
+ return worker(document, (stylesheet, cssLs) => {
34
+ return cssLs.findReferences(document, position, stylesheet);
35
+ });
36
+ },
29
37
  provideRenameRange(document, position) {
30
- do {
31
- const uri = vscode_uri_1.URI.parse(document.uri);
32
- const decoded = context.decodeEmbeddedDocumentUri(uri);
33
- const sourceScript = decoded && context.language.scripts.get(decoded[0]);
34
- const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
35
- if (!sourceScript?.generated || !virtualCode?.id.startsWith('style_')) {
36
- break;
37
- }
38
- const root = sourceScript.generated.root;
39
- if (!(root instanceof language_core_1.VueVirtualCode)) {
40
- break;
41
- }
42
- const block = root.sfc.styles.find(style => style.name === decoded[1]);
43
- if (!block) {
44
- break;
45
- }
46
- let script;
47
- for (const [key, value] of sourceScript.generated.embeddedCodes) {
48
- if (key.startsWith('script_')) {
49
- script = value;
50
- break;
51
- }
52
- }
53
- if (!script) {
54
- break;
55
- }
56
- const offset = document.offsetAt(position) + block.startTagEnd;
57
- for (const { sourceOffsets, lengths, data } of script.mappings) {
58
- if (!sourceOffsets.length
59
- || !data.navigation
60
- || typeof data.navigation === 'object' && !data.navigation.shouldRename) {
61
- continue;
62
- }
63
- const start = sourceOffsets[0];
64
- const end = sourceOffsets.at(-1) + lengths.at(-1);
65
- if (offset >= start && offset <= end) {
66
- return;
67
- }
68
- }
69
- } while (0);
38
+ if (isWithinNavigationVirtualCode(document, position)) {
39
+ return;
40
+ }
70
41
  return worker(document, (stylesheet, cssLs) => {
71
42
  return cssLs.prepareRename(document, position, stylesheet);
72
43
  });
73
44
  }
74
45
  };
46
+ function isWithinNavigationVirtualCode(document, position) {
47
+ const uri = vscode_uri_1.URI.parse(document.uri);
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 || !virtualCode?.id.startsWith('style_')) {
52
+ return false;
53
+ }
54
+ const root = sourceScript.generated.root;
55
+ if (!(root instanceof language_core_1.VueVirtualCode)) {
56
+ return false;
57
+ }
58
+ const block = root.sfc.styles.find(style => style.name === decoded[1]);
59
+ if (!block) {
60
+ return false;
61
+ }
62
+ let script;
63
+ for (const [key, value] of sourceScript.generated.embeddedCodes) {
64
+ if (key.startsWith('script_')) {
65
+ script = value;
66
+ break;
67
+ }
68
+ }
69
+ if (!script) {
70
+ return false;
71
+ }
72
+ const offset = document.offsetAt(position) + block.startTagEnd;
73
+ for (const { sourceOffsets, lengths, data } of script.mappings) {
74
+ if (!sourceOffsets.length
75
+ || !data.navigation
76
+ || typeof data.navigation === 'object' && !data.navigation.shouldRename) {
77
+ continue;
78
+ }
79
+ const start = sourceOffsets[0];
80
+ const end = sourceOffsets.at(-1) + lengths.at(-1);
81
+ if (offset >= start && offset <= end) {
82
+ return true;
83
+ }
84
+ }
85
+ return false;
86
+ }
75
87
  function worker(document, callback) {
76
88
  const cssLs = getCssLs(document);
77
89
  if (!cssLs) {
@@ -1,2 +1,2 @@
1
1
  import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
2
- export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
2
+ export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
@@ -1,2 +1,2 @@
1
- import { LanguageServicePlugin } from '../types';
1
+ import type { LanguageServicePlugin } from '../types';
2
2
  export declare function create(): LanguageServicePlugin;
@@ -1,2 +1,2 @@
1
- import { LanguageServiceContext, LanguageServicePlugin } from '../types';
2
- export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
1
+ import { type LanguageServiceContext, type LanguageServicePlugin } from '../types';
2
+ export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
@@ -16,52 +16,84 @@ function create() {
16
16
  const decoded = context.decodeEmbeddedDocumentUri(uri);
17
17
  const sourceScript = decoded && context.language.scripts.get(decoded[0]);
18
18
  const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
19
- if (!sourceScript?.generated || virtualCode?.id !== 'template') {
19
+ if (!sourceScript?.generated || (virtualCode?.id !== 'template' && virtualCode?.id !== "scriptsetup_raw")) {
20
20
  return;
21
21
  }
22
22
  const root = sourceScript.generated.root;
23
23
  if (!(root instanceof language_core_1.VueVirtualCode)) {
24
24
  return;
25
25
  }
26
- const result = [];
27
26
  const { sfc } = root;
28
27
  const codegen = language_core_1.tsCodegen.get(sfc);
29
- const scopedClasses = codegen?.getGeneratedTemplate()?.scopedClasses ?? [];
30
- const styleClasses = new Map();
31
- const option = root.vueCompilerOptions.experimentalResolveStyleCssClasses;
32
- for (let i = 0; i < sfc.styles.length; i++) {
33
- const style = sfc.styles[i];
34
- if (option === 'always' || (option === 'scoped' && style.scoped)) {
35
- for (const className of style.classNames) {
36
- if (!styleClasses.has(className.text.slice(1))) {
37
- styleClasses.set(className.text.slice(1), []);
28
+ const result = [];
29
+ if (virtualCode.id === 'template') {
30
+ const scopedClasses = codegen?.getGeneratedTemplate()?.scopedClasses ?? [];
31
+ const styleClasses = new Map();
32
+ const option = root.vueCompilerOptions.experimentalResolveStyleCssClasses;
33
+ for (let i = 0; i < sfc.styles.length; i++) {
34
+ const style = sfc.styles[i];
35
+ if (option === 'always' || (option === 'scoped' && style.scoped)) {
36
+ for (const className of style.classNames) {
37
+ if (!styleClasses.has(className.text.slice(1))) {
38
+ styleClasses.set(className.text.slice(1), []);
39
+ }
40
+ styleClasses.get(className.text.slice(1)).push({
41
+ index: i,
42
+ style,
43
+ classOffset: className.offset,
44
+ });
38
45
  }
39
- styleClasses.get(className.text.slice(1)).push({
40
- index: i,
41
- style,
42
- classOffset: className.offset,
43
- });
44
46
  }
45
47
  }
46
- }
47
- for (const { className, offset } of scopedClasses) {
48
- const styles = styleClasses.get(className);
49
- if (styles) {
50
- for (const style of styles) {
51
- const styleDocumentUri = context.encodeEmbeddedDocumentUri(decoded[0], 'style_' + style.index);
52
- const styleVirtualCode = sourceScript.generated.embeddedCodes.get('style_' + style.index);
53
- if (!styleVirtualCode) {
54
- continue;
48
+ for (const { className, offset } of scopedClasses) {
49
+ const styles = styleClasses.get(className);
50
+ if (styles) {
51
+ for (const style of styles) {
52
+ const styleDocumentUri = context.encodeEmbeddedDocumentUri(decoded[0], 'style_' + style.index);
53
+ const styleVirtualCode = sourceScript.generated.embeddedCodes.get('style_' + style.index);
54
+ if (!styleVirtualCode) {
55
+ continue;
56
+ }
57
+ const styleDocument = context.documents.get(styleDocumentUri, styleVirtualCode.languageId, styleVirtualCode.snapshot);
58
+ const start = styleDocument.positionAt(style.classOffset);
59
+ const end = styleDocument.positionAt(style.classOffset + className.length + 1);
60
+ result.push({
61
+ range: {
62
+ start: document.positionAt(offset),
63
+ end: document.positionAt(offset + className.length),
64
+ },
65
+ target: context.encodeEmbeddedDocumentUri(decoded[0], 'style_' + style.index) + `#L${start.line + 1},${start.character + 1}-L${end.line + 1},${end.character + 1}`,
66
+ });
55
67
  }
56
- const styleDocument = context.documents.get(styleDocumentUri, styleVirtualCode.languageId, styleVirtualCode.snapshot);
57
- const start = styleDocument.positionAt(style.classOffset);
58
- const end = styleDocument.positionAt(style.classOffset + className.length + 1);
68
+ }
69
+ }
70
+ }
71
+ else if (virtualCode.id === 'scriptsetup_raw') {
72
+ if (!sfc.scriptSetup) {
73
+ return;
74
+ }
75
+ const templateVirtualCode = sourceScript.generated.embeddedCodes.get('template');
76
+ if (!templateVirtualCode) {
77
+ return;
78
+ }
79
+ const templateDocumentUri = context.encodeEmbeddedDocumentUri(decoded[0], 'template');
80
+ const templateDocument = context.documents.get(templateDocumentUri, templateVirtualCode.languageId, templateVirtualCode.snapshot);
81
+ const templateRefs = codegen?.getGeneratedTemplate()?.templateRefs;
82
+ const useTemplateRefs = codegen?.getScriptSetupRanges()?.useTemplateRef ?? [];
83
+ for (const { arg } of useTemplateRefs) {
84
+ if (!arg) {
85
+ continue;
86
+ }
87
+ const name = sfc.scriptSetup.content.slice(arg.start + 1, arg.end - 1);
88
+ for (const { offset } of templateRefs?.get(name) ?? []) {
89
+ const start = templateDocument.positionAt(offset);
90
+ const end = templateDocument.positionAt(offset + name.length);
59
91
  result.push({
60
92
  range: {
61
- start: document.positionAt(offset),
62
- end: document.positionAt(offset + className.length),
93
+ start: document.positionAt(arg.start + 1),
94
+ end: document.positionAt(arg.end - 1),
63
95
  },
64
- target: context.encodeEmbeddedDocumentUri(decoded[0], 'style_' + style.index) + `#L${start.line + 1},${start.character + 1}-L${end.line + 1},${end.character + 1}`,
96
+ target: templateDocumentUri + `#L${start.line + 1},${start.character + 1}-L${end.line + 1},${end.character + 1}`,
65
97
  });
66
98
  }
67
99
  }
@@ -1,7 +1,7 @@
1
1
  import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
2
- import { Sfc } from '@vue/language-core';
2
+ import { type Sfc } from '@vue/language-core';
3
3
  import type * as ts from 'typescript';
4
- export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
4
+ export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
5
5
  export declare function getLastImportNode(ts: typeof import('typescript'), sourceFile: ts.SourceFile): ts.Node | undefined;
6
6
  export declare function createAddComponentToOptionEdit(ts: typeof import('typescript'), sfc: Sfc, ast: ts.SourceFile, componentName: string): {
7
7
  range: import("@vue/language-core").TextRange;
@@ -0,0 +1,2 @@
1
+ import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
2
+ export declare function create(getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.create = create;
4
+ const language_core_1 = require("@vue/language-core");
5
+ const vscode_uri_1 = require("vscode-uri");
6
+ function create(getTsPluginClient) {
7
+ return {
8
+ name: 'vue-file-references',
9
+ capabilities: {
10
+ codeLensProvider: {
11
+ resolveProvider: true,
12
+ },
13
+ },
14
+ create(context) {
15
+ const tsPluginClient = getTsPluginClient?.(context);
16
+ void tsPluginClient;
17
+ return {
18
+ provideReferencesCodeLensRanges(document) {
19
+ return worker(document, context, root => {
20
+ if (root.sfc.template) {
21
+ return [{
22
+ start: document.positionAt(root.sfc.template.start + 1),
23
+ end: document.positionAt(root.sfc.template.start + 1 + 'template'.length),
24
+ }];
25
+ }
26
+ });
27
+ },
28
+ provideReferences(document, position) {
29
+ return worker(document, context, async (root) => {
30
+ if (!root.sfc.template) {
31
+ return;
32
+ }
33
+ const offset = document.offsetAt(position);
34
+ const start = root.sfc.template.start + 1;
35
+ const end = start + 'template'.length;
36
+ if (offset < start || offset > end) {
37
+ return;
38
+ }
39
+ console.time('[VVVIP] getFileReferences');
40
+ const references = await tsPluginClient?.getFileReferences(root.fileName) ?? [];
41
+ console.timeEnd('[VVVIP] getFileReferences');
42
+ return references.map(({ fileName, range }) => ({
43
+ uri: vscode_uri_1.URI.file(fileName).toString(),
44
+ range,
45
+ }));
46
+ });
47
+ },
48
+ };
49
+ },
50
+ };
51
+ function worker(document, context, callback) {
52
+ if (document.languageId !== 'vue-root-tags') {
53
+ return;
54
+ }
55
+ const uri = vscode_uri_1.URI.parse(document.uri);
56
+ const decoded = context.decodeEmbeddedDocumentUri(uri);
57
+ const sourceScript = decoded && context.language.scripts.get(decoded[0]);
58
+ const root = sourceScript?.generated?.root;
59
+ if (root instanceof language_core_1.VueVirtualCode) {
60
+ return callback(root);
61
+ }
62
+ }
63
+ }
64
+ //# sourceMappingURL=vue-file-references.js.map
@@ -1,3 +1,3 @@
1
1
  import type { LanguageServiceContext } from '@volar/language-service';
2
- import { LanguageServicePlugin } from '../types';
2
+ import { type LanguageServicePlugin } from '../types';
3
3
  export declare function create(getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
@@ -23,7 +23,6 @@ function create(getTsPluginClient) {
23
23
  if (!context.project.vue) {
24
24
  return;
25
25
  }
26
- const vueCompilerOptions = context.project.vue.compilerOptions;
27
26
  const enabled = await context.env.getConfiguration?.('vue.inlayHints.missingProps') ?? false;
28
27
  if (!enabled) {
29
28
  return;
@@ -101,7 +100,7 @@ function create(getTsPluginClient) {
101
100
  attrText = attrText.slice('v-model:'.length);
102
101
  }
103
102
  else if (attrText === 'v-model') {
104
- attrText = vueCompilerOptions.target >= 3 ? 'modelValue' : 'value'; // TODO: support for experimentalModelPropName?
103
+ attrText = 'modelValue'; // TODO: support for experimentalModelPropName?
105
104
  }
106
105
  else if (attrText.startsWith('v-on:')) {
107
106
  attrText = 'on-' + (0, language_core_1.hyphenateAttr)(attrText.slice('v-on:'.length));
@@ -193,7 +193,9 @@ function create() {
193
193
  if (!result) {
194
194
  return;
195
195
  }
196
- result.items = result.items.filter(item => item.label !== '!DOCTYPE' && item.label !== 'Custom Blocks');
196
+ result.items = result.items.filter(item => item.label !== '!DOCTYPE' &&
197
+ item.label !== 'Custom Blocks' &&
198
+ item.label !== 'data-');
197
199
  const tags = sfcDataProvider?.provideTags();
198
200
  const scriptLangs = getLangs('script');
199
201
  const scriptItems = result.items.filter(item => item.label === 'script' || item.label === 'script setup');
@@ -0,0 +1,2 @@
1
+ import type { LanguageServicePlugin } from '../types';
2
+ export declare function create(): LanguageServicePlugin;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.create = create;
4
+ const language_core_1 = require("@vue/language-core");
5
+ const vscode_uri_1 = require("vscode-uri");
6
+ const utils_1 = require("./utils");
7
+ function create() {
8
+ return {
9
+ name: 'vue-document-drop',
10
+ capabilities: {
11
+ completionProvider: {},
12
+ },
13
+ create(context) {
14
+ return {
15
+ provideCompletionItems(document) {
16
+ if (!(0, utils_1.isTsDocument)(document)) {
17
+ return;
18
+ }
19
+ const uri = vscode_uri_1.URI.parse(document.uri);
20
+ const decoded = context.decodeEmbeddedDocumentUri(uri);
21
+ const sourceScript = decoded && context.language.scripts.get(decoded[0]);
22
+ const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
23
+ if (!sourceScript?.generated || !virtualCode) {
24
+ return;
25
+ }
26
+ const root = sourceScript.generated.root;
27
+ if (!(root instanceof language_core_1.VueVirtualCode)) {
28
+ return;
29
+ }
30
+ const { sfc } = root;
31
+ const codegen = language_core_1.tsCodegen.get(sfc);
32
+ const scriptSetupRanges = codegen.getScriptSetupRanges();
33
+ for (const {} of scriptSetupRanges?.useTemplateRef ?? []) {
34
+ return {
35
+ isIncomplete: false,
36
+ items: [],
37
+ };
38
+ }
39
+ }
40
+ };
41
+ },
42
+ };
43
+ }
44
+ //# sourceMappingURL=vue-template-refs.js.map
@@ -1,3 +1,3 @@
1
1
  import type { LanguageServiceContext } from '@volar/language-service';
2
- import { LanguageServicePlugin } from '../types';
3
- export declare function create(mode: 'html' | 'pug', ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
2
+ import { type LanguageServicePlugin } from '../types';
3
+ export declare function create(mode: 'html' | 'pug', getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
@@ -3,12 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.create = create;
4
4
  const language_core_1 = require("@vue/language-core");
5
5
  const shared_1 = require("@vue/shared");
6
- const common_1 = require("@vue/typescript-plugin/lib/common");
7
6
  const volar_service_html_1 = require("volar-service-html");
8
7
  const volar_service_pug_1 = require("volar-service-pug");
9
8
  const html = require("vscode-html-languageservice");
10
9
  const vscode_uri_1 = require("vscode-uri");
11
- const nameCasing_1 = require("../ideFeatures/nameCasing");
10
+ const nameCasing_1 = require("../nameCasing");
12
11
  const types_1 = require("../types");
13
12
  const data_1 = require("./data");
14
13
  const specialTags = new Set([
@@ -26,7 +25,7 @@ const specialProps = new Set([
26
25
  ]);
27
26
  let builtInData;
28
27
  let modelData;
29
- function create(mode, ts, getTsPluginClient) {
28
+ function create(mode, getTsPluginClient) {
30
29
  let customData = [];
31
30
  let extraCustomData = [];
32
31
  let lastCompletionComponentNames = new Set();
@@ -70,18 +69,7 @@ function create(mode, ts, getTsPluginClient) {
70
69
  '@', // vue event shorthand
71
70
  ],
72
71
  },
73
- inlayHintProvider: {},
74
72
  hoverProvider: true,
75
- diagnosticProvider: {
76
- interFileDependencies: false,
77
- workspaceDiagnostics: false,
78
- },
79
- semanticTokensProvider: {
80
- legend: {
81
- tokenTypes: ['class'],
82
- tokenModifiers: [],
83
- },
84
- }
85
73
  },
86
74
  create(context) {
87
75
  const tsPluginClient = getTsPluginClient?.(context);
@@ -159,122 +147,6 @@ function create(mode, ts, getTsPluginClient) {
159
147
  }
160
148
  return htmlComplete;
161
149
  },
162
- async provideInlayHints(document) {
163
- if (!isSupportedDocument(document)) {
164
- return;
165
- }
166
- if (!context.project.vue) {
167
- return;
168
- }
169
- const vueCompilerOptions = context.project.vue.compilerOptions;
170
- const enabled = await context.env.getConfiguration?.('vue.inlayHints.missingProps') ?? false;
171
- if (!enabled) {
172
- return;
173
- }
174
- const uri = vscode_uri_1.URI.parse(document.uri);
175
- const decoded = context.decodeEmbeddedDocumentUri(uri);
176
- const sourceScript = decoded && context.language.scripts.get(decoded[0]);
177
- const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
178
- if (!virtualCode) {
179
- return;
180
- }
181
- const root = sourceScript?.generated?.root;
182
- if (!(root instanceof language_core_1.VueVirtualCode)) {
183
- return;
184
- }
185
- const scanner = getScanner(baseServiceInstance, document);
186
- if (!scanner) {
187
- return;
188
- }
189
- const result = [];
190
- // visualize missing required props
191
- const casing = await (0, nameCasing_1.getNameCasing)(context, decoded[0]);
192
- const components = await tsPluginClient?.getComponentNames(root.fileName) ?? [];
193
- const componentProps = {};
194
- let token;
195
- let current;
196
- while ((token = scanner.scan()) !== html.TokenType.EOS) {
197
- if (token === html.TokenType.StartTag) {
198
- const tagName = scanner.getTokenText();
199
- const checkTag = tagName.includes('.')
200
- ? tagName
201
- : components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
202
- if (checkTag) {
203
- componentProps[checkTag] ??= (await tsPluginClient?.getComponentProps(root.fileName, checkTag) ?? [])
204
- .filter(prop => prop.required)
205
- .map(prop => prop.name);
206
- current = {
207
- unburnedRequiredProps: [...componentProps[checkTag]],
208
- labelOffset: scanner.getTokenOffset() + scanner.getTokenLength(),
209
- insertOffset: scanner.getTokenOffset() + scanner.getTokenLength(),
210
- };
211
- }
212
- }
213
- else if (token === html.TokenType.AttributeName) {
214
- if (current) {
215
- let attrText = scanner.getTokenText();
216
- if (attrText === 'v-bind') {
217
- current.unburnedRequiredProps = [];
218
- }
219
- else {
220
- // remove modifiers
221
- if (attrText.includes('.')) {
222
- attrText = attrText.split('.')[0];
223
- }
224
- // normalize
225
- if (attrText.startsWith('v-bind:')) {
226
- attrText = attrText.slice('v-bind:'.length);
227
- }
228
- else if (attrText.startsWith(':')) {
229
- attrText = attrText.slice(':'.length);
230
- }
231
- else if (attrText.startsWith('v-model:')) {
232
- attrText = attrText.slice('v-model:'.length);
233
- }
234
- else if (attrText === 'v-model') {
235
- attrText = vueCompilerOptions.target >= 3 ? 'modelValue' : 'value'; // TODO: support for experimentalModelPropName?
236
- }
237
- else if (attrText.startsWith('v-on:')) {
238
- attrText = 'on-' + (0, language_core_1.hyphenateAttr)(attrText.slice('v-on:'.length));
239
- }
240
- else if (attrText.startsWith('@')) {
241
- attrText = 'on-' + (0, language_core_1.hyphenateAttr)(attrText.slice('@'.length));
242
- }
243
- current.unburnedRequiredProps = current.unburnedRequiredProps.filter(propName => {
244
- return attrText !== propName
245
- && attrText !== (0, language_core_1.hyphenateAttr)(propName);
246
- });
247
- }
248
- }
249
- }
250
- else if (token === html.TokenType.StartTagSelfClose || token === html.TokenType.StartTagClose) {
251
- if (current) {
252
- for (const requiredProp of current.unburnedRequiredProps) {
253
- result.push({
254
- label: `${requiredProp}!`,
255
- paddingLeft: true,
256
- position: document.positionAt(current.labelOffset),
257
- kind: 2,
258
- textEdits: [{
259
- range: {
260
- start: document.positionAt(current.insertOffset),
261
- end: document.positionAt(current.insertOffset),
262
- },
263
- newText: ` :${casing.attr === types_1.AttrNameCasing.Kebab ? (0, language_core_1.hyphenateAttr)(requiredProp) : requiredProp}=`,
264
- }],
265
- });
266
- }
267
- current = undefined;
268
- }
269
- }
270
- if (token === html.TokenType.AttributeName || token === html.TokenType.AttributeValue) {
271
- if (current) {
272
- current.insertOffset = scanner.getTokenOffset() + scanner.getTokenLength();
273
- }
274
- }
275
- }
276
- return result;
277
- },
278
150
  provideHover(document, position, token) {
279
151
  if (!isSupportedDocument(document)) {
280
152
  return;
@@ -284,98 +156,6 @@ function create(mode, ts, getTsPluginClient) {
284
156
  }
285
157
  return baseServiceInstance.provideHover?.(document, position, token);
286
158
  },
287
- async provideDiagnostics(document, token) {
288
- if (!isSupportedDocument(document)) {
289
- return;
290
- }
291
- const uri = vscode_uri_1.URI.parse(document.uri);
292
- const decoded = context.decodeEmbeddedDocumentUri(uri);
293
- const sourceScript = decoded && context.language.scripts.get(decoded[0]);
294
- const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
295
- if (!virtualCode) {
296
- return;
297
- }
298
- const root = sourceScript?.generated?.root;
299
- if (!(root instanceof language_core_1.VueVirtualCode)) {
300
- return;
301
- }
302
- const originalResult = await baseServiceInstance.provideDiagnostics?.(document, token);
303
- const templateErrors = [];
304
- const { template } = root.sfc;
305
- if (template) {
306
- for (const error of template.errors) {
307
- onCompilerError(error, 1);
308
- }
309
- for (const warning of template.warnings) {
310
- onCompilerError(warning, 2);
311
- }
312
- function onCompilerError(error, severity) {
313
- const templateHtmlRange = {
314
- start: error.loc?.start.offset ?? 0,
315
- end: error.loc?.end.offset ?? 0,
316
- };
317
- let errorMessage = error.message;
318
- templateErrors.push({
319
- range: {
320
- start: document.positionAt(templateHtmlRange.start),
321
- end: document.positionAt(templateHtmlRange.end),
322
- },
323
- severity,
324
- code: error.code,
325
- source: 'vue',
326
- message: errorMessage,
327
- });
328
- }
329
- }
330
- return [
331
- ...originalResult ?? [],
332
- ...templateErrors,
333
- ];
334
- },
335
- provideDocumentSemanticTokens(document, range, legend) {
336
- if (!isSupportedDocument(document)) {
337
- return;
338
- }
339
- if (!context.project.vue) {
340
- return;
341
- }
342
- const vueCompilerOptions = context.project.vue.compilerOptions;
343
- const languageService = context.inject('typescript/languageService');
344
- if (!languageService) {
345
- return;
346
- }
347
- const uri = vscode_uri_1.URI.parse(document.uri);
348
- const decoded = context.decodeEmbeddedDocumentUri(uri);
349
- const sourceScript = decoded && context.language.scripts.get(decoded[0]);
350
- const root = sourceScript?.generated?.root;
351
- if (!(root instanceof language_core_1.VueVirtualCode)) {
352
- return;
353
- }
354
- const { template } = root.sfc;
355
- if (!template) {
356
- return;
357
- }
358
- const spans = common_1.getComponentSpans.call({
359
- files: context.language.scripts,
360
- languageService,
361
- typescript: ts,
362
- vueOptions: vueCompilerOptions,
363
- }, root, template, {
364
- start: document.offsetAt(range.start),
365
- length: document.offsetAt(range.end) - document.offsetAt(range.start),
366
- });
367
- const classTokenIndex = legend.tokenTypes.indexOf('class');
368
- return spans.map(span => {
369
- const start = document.positionAt(span.start);
370
- return [
371
- start.line,
372
- start.character,
373
- span.length,
374
- classTokenIndex,
375
- 0,
376
- ];
377
- });
378
- },
379
159
  };
380
160
  async function provideHtmlData(sourceDocumentUri, vueCode) {
381
161
  await (initializing ??= initialize());
@@ -467,14 +247,19 @@ function create(mode, ts, getTsPluginClient) {
467
247
  return [];
468
248
  }
469
249
  const { attrs, propInfos, events, directives } = tagInfo;
470
- const props = propInfos.map(prop => (0, language_core_1.hyphenateTag)(prop.name).startsWith('on-vnode-')
471
- ? 'onVue:' + prop.name.slice('onVnode'.length)
472
- : prop.name);
250
+ for (const prop of propInfos) {
251
+ if ((0, language_core_1.hyphenateTag)(prop.name).startsWith('on-vnode-')) {
252
+ prop.name = 'onVue:' + prop.name.slice('onVnode'.length);
253
+ }
254
+ }
473
255
  const attributes = [];
474
- const propsSet = new Set(props);
475
- for (const prop of [...props, ...attrs]) {
476
- const isGlobal = !propsSet.has(prop);
477
- const name = casing.attr === types_1.AttrNameCasing.Camel ? prop : (0, language_core_1.hyphenateAttr)(prop);
256
+ const propsSet = new Set(propInfos.map(prop => prop.name));
257
+ for (const prop of [
258
+ ...propInfos,
259
+ ...attrs.map(attr => ({ name: attr })),
260
+ ]) {
261
+ const isGlobal = prop.isAttribute || !propsSet.has(prop.name);
262
+ const name = casing.attr === types_1.AttrNameCasing.Camel ? prop.name : (0, language_core_1.hyphenateAttr)(prop.name);
478
263
  const isEvent = (0, language_core_1.hyphenateAttr)(name).startsWith('on-');
479
264
  if (isEvent) {
480
265
  const propNameBase = name.startsWith('on-')
@@ -502,6 +287,7 @@ function create(mode, ts, getTsPluginClient) {
502
287
  attributes.push({
503
288
  name: propName,
504
289
  description: propKey,
290
+ valueSet: prop.values?.some(value => typeof value === 'string') ? '__deferred__' : undefined,
505
291
  }, {
506
292
  name: ':' + propName,
507
293
  description: propKey,
@@ -529,10 +315,13 @@ function create(mode, ts, getTsPluginClient) {
529
315
  });
530
316
  }
531
317
  const models = [];
532
- for (const prop of [...props, ...attrs]) {
533
- if (prop.startsWith('onUpdate:')) {
534
- const isGlobal = !propsSet.has(prop);
535
- models.push([isGlobal, prop.slice('onUpdate:'.length)]);
318
+ for (const prop of [
319
+ ...propInfos,
320
+ ...attrs.map(attr => ({ name: attr })),
321
+ ]) {
322
+ if (prop.name.startsWith('onUpdate:')) {
323
+ const isGlobal = !propsSet.has(prop.name);
324
+ models.push([isGlobal, prop.name.slice('onUpdate:'.length)]);
536
325
  }
537
326
  }
538
327
  for (const event of events) {
@@ -806,17 +595,6 @@ function create(mode, ts, getTsPluginClient) {
806
595
  }
807
596
  },
808
597
  };
809
- function getScanner(service, document) {
810
- if (mode === 'html') {
811
- return service.provide['html/languageService']().createScanner(document.getText());
812
- }
813
- else {
814
- const pugDocument = service.provide['pug/pugDocument'](document);
815
- if (pugDocument) {
816
- return service.provide['pug/languageService']().createScanner(pugDocument);
817
- }
818
- }
819
- }
820
598
  function updateExtraCustomData(extraData) {
821
599
  extraCustomData = extraData;
822
600
  onDidChangeCustomDataListeners.forEach(l => l());
@@ -830,7 +608,6 @@ function create(mode, ts, getTsPluginClient) {
830
608
  }
831
609
  }
832
610
  }
833
- ;
834
611
  function parseLabel(label) {
835
612
  const leadingSlash = label.startsWith('/');
836
613
  const name = label.slice(leadingSlash ? 1 : 0);
@@ -1,2 +1,2 @@
1
1
  import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
2
- export declare function create(getTsPluginClient?: (context: LanguageServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
2
+ export declare function create(getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
@@ -38,7 +38,7 @@ function create(getTsPluginClient) {
38
38
  for (const [pointerPosition, hoverOffset] of hoverOffsets) {
39
39
  const map = context.language.maps.get(virtualCode, sourceScript);
40
40
  for (const [sourceOffset] of map.toSourceLocation(hoverOffset)) {
41
- const quickInfo = await tsPluginClient?.getQuickInfoAtPosition(root.fileName, sourceOffset);
41
+ const quickInfo = await tsPluginClient?.getQuickInfoAtPosition(root.fileName, document.positionAt(sourceOffset));
42
42
  if (quickInfo) {
43
43
  inlayHints.push({
44
44
  position: { line: pointerPosition.line, character: pointerPosition.character + 2 },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue/language-service",
3
- "version": "2.2.10",
3
+ "version": "3.0.0-alpha.10",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "data",
@@ -17,23 +17,23 @@
17
17
  "update-html-data": "node ./scripts/update-html-data.js"
18
18
  },
19
19
  "dependencies": {
20
- "@volar/language-core": "~2.4.11",
21
- "@volar/language-service": "~2.4.11",
22
- "@volar/typescript": "~2.4.11",
20
+ "@volar/language-core": "~2.4.13",
21
+ "@volar/language-service": "~2.4.13",
22
+ "@volar/typescript": "~2.4.13",
23
23
  "@vue/compiler-dom": "^3.5.0",
24
- "@vue/language-core": "2.2.10",
24
+ "@vue/language-core": "3.0.0-alpha.10",
25
25
  "@vue/shared": "^3.5.0",
26
- "@vue/typescript-plugin": "2.2.10",
27
- "alien-signals": "^1.0.3",
26
+ "@vue/typescript-plugin": "3.0.0-alpha.10",
27
+ "alien-signals": "^2.0.5",
28
28
  "path-browserify": "^1.0.1",
29
- "volar-service-css": "0.0.62",
30
- "volar-service-emmet": "0.0.62",
31
- "volar-service-html": "0.0.62",
32
- "volar-service-json": "0.0.62",
33
- "volar-service-pug": "0.0.62",
34
- "volar-service-pug-beautify": "0.0.62",
35
- "volar-service-typescript": "0.0.62",
36
- "volar-service-typescript-twoslash-queries": "0.0.62",
29
+ "volar-service-css": "0.0.64",
30
+ "volar-service-emmet": "0.0.64",
31
+ "volar-service-html": "0.0.64",
32
+ "volar-service-json": "0.0.64",
33
+ "volar-service-pug": "0.0.64",
34
+ "volar-service-pug-beautify": "0.0.64",
35
+ "volar-service-typescript": "0.0.64",
36
+ "volar-service-typescript-twoslash-queries": "0.0.64",
37
37
  "vscode-css-languageservice": "^6.3.1",
38
38
  "vscode-html-languageservice": "^5.2.0",
39
39
  "vscode-languageserver-textdocument": "^1.0.11",
@@ -42,8 +42,8 @@
42
42
  "devDependencies": {
43
43
  "@types/node": "^22.10.4",
44
44
  "@types/path-browserify": "^1.0.1",
45
- "@volar/kit": "~2.4.11",
45
+ "@volar/kit": "~2.4.13",
46
46
  "vscode-languageserver-protocol": "^3.17.5"
47
47
  },
48
- "gitHead": "0422c03ffa4958431c9cd3cd19ae51f726c30b07"
48
+ "gitHead": "28308b4f76cc80c7632f39ae7e0944f1889661a2"
49
49
  }
@@ -1,14 +0,0 @@
1
- import type { LanguageServiceContext } from '@volar/language-service';
2
- import type * as vscode from 'vscode-languageserver-protocol';
3
- import type { URI } from 'vscode-uri';
4
- import { AttrNameCasing, TagNameCasing } from '../types';
5
- export declare function convertTagName(context: LanguageServiceContext, uri: URI, casing: TagNameCasing, tsPluginClient: typeof import('@vue/typescript-plugin/lib/client') | undefined): Promise<vscode.TextEdit[] | undefined>;
6
- export declare function convertAttrName(context: LanguageServiceContext, uri: URI, casing: AttrNameCasing, tsPluginClient?: typeof import('@vue/typescript-plugin/lib/client')): Promise<vscode.TextEdit[] | undefined>;
7
- export declare function getNameCasing(context: LanguageServiceContext, uri: URI): Promise<{
8
- tag: TagNameCasing;
9
- attr: AttrNameCasing;
10
- }>;
11
- export declare function detect(context: LanguageServiceContext, uri: URI): Promise<{
12
- tag: TagNameCasing[];
13
- attr: AttrNameCasing[];
14
- }>;
@@ -1,202 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.convertTagName = convertTagName;
4
- exports.convertAttrName = convertAttrName;
5
- exports.getNameCasing = getNameCasing;
6
- exports.detect = detect;
7
- const vue = require("@vue/language-core");
8
- const language_core_1 = require("@vue/language-core");
9
- const alien_signals_1 = require("alien-signals");
10
- const types_1 = require("../types");
11
- async function convertTagName(context, uri, casing, tsPluginClient) {
12
- const sourceFile = context.language.scripts.get(uri);
13
- if (!sourceFile) {
14
- return;
15
- }
16
- const root = sourceFile?.generated?.root;
17
- if (!(root instanceof language_core_1.VueVirtualCode)) {
18
- return;
19
- }
20
- const { template } = root.sfc;
21
- if (!template) {
22
- return;
23
- }
24
- const document = context.documents.get(sourceFile.id, sourceFile.languageId, sourceFile.snapshot);
25
- const edits = [];
26
- const components = await tsPluginClient?.getComponentNames(root.fileName) ?? [];
27
- const tags = getTemplateTagsAndAttrs(root);
28
- for (const [tagName, { offsets }] of tags) {
29
- const componentName = components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
30
- if (componentName) {
31
- for (const offset of offsets) {
32
- const start = document.positionAt(template.startTagEnd + offset);
33
- const end = document.positionAt(template.startTagEnd + offset + tagName.length);
34
- const range = { start, end };
35
- if (casing === types_1.TagNameCasing.Kebab && tagName !== (0, language_core_1.hyphenateTag)(componentName)) {
36
- edits.push({ range, newText: (0, language_core_1.hyphenateTag)(componentName) });
37
- }
38
- if (casing === types_1.TagNameCasing.Pascal && tagName !== componentName) {
39
- edits.push({ range, newText: componentName });
40
- }
41
- }
42
- }
43
- }
44
- return edits;
45
- }
46
- async function convertAttrName(context, uri, casing, tsPluginClient) {
47
- const sourceFile = context.language.scripts.get(uri);
48
- if (!sourceFile) {
49
- return;
50
- }
51
- const root = sourceFile?.generated?.root;
52
- if (!(root instanceof language_core_1.VueVirtualCode)) {
53
- return;
54
- }
55
- const { template } = root.sfc;
56
- if (!template) {
57
- return;
58
- }
59
- const document = context.documents.get(uri, sourceFile.languageId, sourceFile.snapshot);
60
- const edits = [];
61
- const components = await tsPluginClient?.getComponentNames(root.fileName) ?? [];
62
- const tags = getTemplateTagsAndAttrs(root);
63
- for (const [tagName, { attrs }] of tags) {
64
- const componentName = components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
65
- if (componentName) {
66
- const props = (await tsPluginClient?.getComponentProps(root.fileName, componentName) ?? []).map(prop => prop.name);
67
- for (const [attrName, { offsets }] of attrs) {
68
- const propName = props.find(prop => prop === attrName || (0, language_core_1.hyphenateAttr)(prop) === attrName);
69
- if (propName) {
70
- for (const offset of offsets) {
71
- const start = document.positionAt(template.startTagEnd + offset);
72
- const end = document.positionAt(template.startTagEnd + offset + attrName.length);
73
- const range = { start, end };
74
- if (casing === types_1.AttrNameCasing.Kebab && attrName !== (0, language_core_1.hyphenateAttr)(propName)) {
75
- edits.push({ range, newText: (0, language_core_1.hyphenateAttr)(propName) });
76
- }
77
- if (casing === types_1.AttrNameCasing.Camel && attrName !== propName) {
78
- edits.push({ range, newText: propName });
79
- }
80
- }
81
- }
82
- }
83
- }
84
- }
85
- return edits;
86
- }
87
- async function getNameCasing(context, uri) {
88
- const detected = await detect(context, uri);
89
- const [attr, tag] = await Promise.all([
90
- context.env.getConfiguration?.('vue.complete.casing.props', uri.toString()),
91
- context.env.getConfiguration?.('vue.complete.casing.tags', uri.toString()),
92
- ]);
93
- const tagNameCasing = detected.tag.length === 1 && (tag === 'autoPascal' || tag === 'autoKebab') ? detected.tag[0] : (tag === 'autoKebab' || tag === 'kebab') ? types_1.TagNameCasing.Kebab : types_1.TagNameCasing.Pascal;
94
- const attrNameCasing = detected.attr.length === 1 && (attr === 'autoCamel' || attr === 'autoKebab') ? detected.attr[0] : (attr === 'autoCamel' || attr === 'camel') ? types_1.AttrNameCasing.Camel : types_1.AttrNameCasing.Kebab;
95
- return {
96
- tag: tagNameCasing,
97
- attr: attrNameCasing,
98
- };
99
- }
100
- async function detect(context, uri) {
101
- const rootFile = context.language.scripts.get(uri)?.generated?.root;
102
- if (!(rootFile instanceof language_core_1.VueVirtualCode)) {
103
- return {
104
- tag: [],
105
- attr: [],
106
- };
107
- }
108
- return {
109
- tag: await getTagNameCase(rootFile),
110
- attr: getAttrNameCase(rootFile),
111
- };
112
- function getAttrNameCase(file) {
113
- const tags = getTemplateTagsAndAttrs(file);
114
- const result = [];
115
- for (const [_, { attrs }] of tags) {
116
- for (const [tagName] of attrs) {
117
- // attrName
118
- if (tagName !== (0, language_core_1.hyphenateTag)(tagName)) {
119
- result.push(types_1.AttrNameCasing.Camel);
120
- break;
121
- }
122
- }
123
- for (const [tagName] of attrs) {
124
- // attr-name
125
- if (tagName.includes('-')) {
126
- result.push(types_1.AttrNameCasing.Kebab);
127
- break;
128
- }
129
- }
130
- }
131
- return result;
132
- }
133
- function getTagNameCase(file) {
134
- const result = new Set();
135
- if (file.sfc.template?.ast) {
136
- for (const element of vue.forEachElementNode(file.sfc.template.ast)) {
137
- if (element.tagType === 1) {
138
- if (element.tag !== (0, language_core_1.hyphenateTag)(element.tag)) {
139
- // TagName
140
- result.add(types_1.TagNameCasing.Pascal);
141
- }
142
- else {
143
- // Tagname -> tagname
144
- // TagName -> tag-name
145
- result.add(types_1.TagNameCasing.Kebab);
146
- }
147
- }
148
- }
149
- }
150
- return [...result];
151
- }
152
- }
153
- const map = new WeakMap();
154
- function getTemplateTagsAndAttrs(sourceFile) {
155
- if (!map.has(sourceFile)) {
156
- const getter = (0, alien_signals_1.computed)(() => {
157
- if (!(sourceFile instanceof vue.VueVirtualCode)) {
158
- return;
159
- }
160
- const ast = sourceFile.sfc.template?.ast;
161
- const tags = new Map();
162
- if (ast) {
163
- for (const node of vue.forEachElementNode(ast)) {
164
- if (!tags.has(node.tag)) {
165
- tags.set(node.tag, { offsets: [], attrs: new Map() });
166
- }
167
- const tag = tags.get(node.tag);
168
- const startTagHtmlOffset = node.loc.start.offset + node.loc.source.indexOf(node.tag);
169
- const endTagHtmlOffset = node.loc.start.offset + node.loc.source.lastIndexOf(node.tag);
170
- tag.offsets.push(startTagHtmlOffset);
171
- if (!node.isSelfClosing) {
172
- tag.offsets.push(endTagHtmlOffset);
173
- }
174
- for (const prop of node.props) {
175
- let name;
176
- let offset;
177
- if (prop.type === 7
178
- && prop.arg?.type === 4
179
- && prop.arg.isStatic) {
180
- name = prop.arg.content;
181
- offset = prop.arg.loc.start.offset;
182
- }
183
- else if (prop.type === 6) {
184
- name = prop.name;
185
- offset = prop.loc.start.offset;
186
- }
187
- if (name !== undefined && offset !== undefined) {
188
- if (!tag.attrs.has(name)) {
189
- tag.attrs.set(name, { offsets: [] });
190
- }
191
- tag.attrs.get(name).offsets.push(offset);
192
- }
193
- }
194
- }
195
- }
196
- return tags;
197
- });
198
- map.set(sourceFile, getter);
199
- }
200
- return map.get(sourceFile)() ?? new Map();
201
- }
202
- //# sourceMappingURL=nameCasing.js.map