@vue/language-service 2.2.8 → 3.0.0-alpha.2

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.
@@ -0,0 +1,160 @@
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 html = require("vscode-html-languageservice");
6
+ const vscode_uri_1 = require("vscode-uri");
7
+ const nameCasing_1 = require("../nameCasing");
8
+ const types_1 = require("../types");
9
+ function create(getTsPluginClient) {
10
+ return {
11
+ name: 'vue-missing-props-hints',
12
+ capabilities: {
13
+ inlayHintProvider: {},
14
+ },
15
+ create(context) {
16
+ const tsPluginClient = getTsPluginClient?.(context);
17
+ let intrinsicElementNames;
18
+ return {
19
+ async provideInlayHints(document, range, cancellationToken) {
20
+ if (!isSupportedDocument(document)) {
21
+ return;
22
+ }
23
+ if (!context.project.vue) {
24
+ return;
25
+ }
26
+ const vueCompilerOptions = context.project.vue.compilerOptions;
27
+ const enabled = await context.env.getConfiguration?.('vue.inlayHints.missingProps') ?? false;
28
+ if (!enabled) {
29
+ return;
30
+ }
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 (!virtualCode) {
36
+ return;
37
+ }
38
+ const root = sourceScript?.generated?.root;
39
+ if (!(root instanceof language_core_1.VueVirtualCode)) {
40
+ return;
41
+ }
42
+ const scanner = getScanner(context, document);
43
+ if (!scanner) {
44
+ return;
45
+ }
46
+ const result = [];
47
+ const casing = await (0, nameCasing_1.getNameCasing)(context, decoded[0]);
48
+ const components = await tsPluginClient?.getComponentNames(root.fileName) ?? [];
49
+ const componentProps = {};
50
+ intrinsicElementNames ??= new Set(await tsPluginClient?.getElementNames(root.fileName) ?? []);
51
+ let token;
52
+ let current;
53
+ while ((token = scanner.scan()) !== html.TokenType.EOS) {
54
+ if (token === html.TokenType.StartTag) {
55
+ const tagName = scanner.getTokenText();
56
+ const tagOffset = scanner.getTokenOffset();
57
+ const checkTag = tagName.includes('.')
58
+ ? tagName
59
+ : components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
60
+ if (intrinsicElementNames.has(tagName) || !checkTag) {
61
+ continue;
62
+ }
63
+ if (tagOffset < document.offsetAt(range.start)) {
64
+ continue;
65
+ }
66
+ if (tagOffset > document.offsetAt(range.end)) {
67
+ break;
68
+ }
69
+ if (!componentProps[checkTag]) {
70
+ if (cancellationToken.isCancellationRequested) {
71
+ break;
72
+ }
73
+ componentProps[checkTag] = (await tsPluginClient?.getComponentProps(root.fileName, checkTag) ?? [])
74
+ .filter(prop => prop.required)
75
+ .map(prop => prop.name);
76
+ }
77
+ current = {
78
+ unburnedRequiredProps: [...componentProps[checkTag]],
79
+ labelOffset: scanner.getTokenOffset() + scanner.getTokenLength(),
80
+ };
81
+ }
82
+ else if (token === html.TokenType.AttributeName) {
83
+ if (current) {
84
+ let attrText = scanner.getTokenText();
85
+ if (attrText === 'v-bind') {
86
+ current.unburnedRequiredProps = [];
87
+ }
88
+ else {
89
+ // remove modifiers
90
+ if (attrText.includes('.')) {
91
+ attrText = attrText.split('.')[0];
92
+ }
93
+ // normalize
94
+ if (attrText.startsWith('v-bind:')) {
95
+ attrText = attrText.slice('v-bind:'.length);
96
+ }
97
+ else if (attrText.startsWith(':')) {
98
+ attrText = attrText.slice(':'.length);
99
+ }
100
+ else if (attrText.startsWith('v-model:')) {
101
+ attrText = attrText.slice('v-model:'.length);
102
+ }
103
+ else if (attrText === 'v-model') {
104
+ attrText = vueCompilerOptions.target >= 3 ? 'modelValue' : 'value'; // TODO: support for experimentalModelPropName?
105
+ }
106
+ else if (attrText.startsWith('v-on:')) {
107
+ attrText = 'on-' + (0, language_core_1.hyphenateAttr)(attrText.slice('v-on:'.length));
108
+ }
109
+ else if (attrText.startsWith('@')) {
110
+ attrText = 'on-' + (0, language_core_1.hyphenateAttr)(attrText.slice('@'.length));
111
+ }
112
+ current.unburnedRequiredProps = current.unburnedRequiredProps.filter(propName => {
113
+ return attrText !== propName
114
+ && attrText !== (0, language_core_1.hyphenateAttr)(propName);
115
+ });
116
+ }
117
+ }
118
+ }
119
+ else if (token === html.TokenType.StartTagSelfClose || token === html.TokenType.StartTagClose) {
120
+ if (current) {
121
+ for (const requiredProp of current.unburnedRequiredProps) {
122
+ result.push({
123
+ label: `${requiredProp}!`,
124
+ paddingLeft: true,
125
+ position: document.positionAt(current.labelOffset),
126
+ kind: 2,
127
+ textEdits: [{
128
+ range: {
129
+ start: document.positionAt(current.labelOffset),
130
+ end: document.positionAt(current.labelOffset),
131
+ },
132
+ newText: ` :${casing.attr === types_1.AttrNameCasing.Kebab ? (0, language_core_1.hyphenateAttr)(requiredProp) : requiredProp}=`,
133
+ }],
134
+ });
135
+ }
136
+ current = undefined;
137
+ }
138
+ }
139
+ }
140
+ return result;
141
+ },
142
+ };
143
+ },
144
+ };
145
+ function getScanner(context, document) {
146
+ if (document.languageId === 'html') {
147
+ return context.inject('html/languageService').createScanner(document.getText());
148
+ }
149
+ else {
150
+ const pugDocument = context.inject('pug/pugDocument', document);
151
+ if (pugDocument) {
152
+ return context.inject('pug/languageService').createScanner(pugDocument);
153
+ }
154
+ }
155
+ }
156
+ function isSupportedDocument(document) {
157
+ return document.languageId === 'jade' || document.languageId === 'html';
158
+ }
159
+ }
160
+ //# sourceMappingURL=vue-missing-props-hints.js.map
@@ -1,3 +1,3 @@
1
1
  import type { LanguageServiceContext } from '@volar/language-service';
2
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;
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());
@@ -806,17 +586,6 @@ function create(mode, ts, getTsPluginClient) {
806
586
  }
807
587
  },
808
588
  };
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
589
  function updateExtraCustomData(extraData) {
821
590
  extraCustomData = extraData;
822
591
  onDidChangeCustomDataListeners.forEach(l => l());
@@ -830,7 +599,6 @@ function create(mode, ts, getTsPluginClient) {
830
599
  }
831
600
  }
832
601
  }
833
- ;
834
602
  function parseLabel(label) {
835
603
  const leadingSlash = label.startsWith('/');
836
604
  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.8",
3
+ "version": "3.0.0-alpha.2",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "data",
@@ -21,9 +21,9 @@
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.8",
24
+ "@vue/language-core": "3.0.0-alpha.2",
25
25
  "@vue/shared": "^3.5.0",
26
- "@vue/typescript-plugin": "2.2.8",
26
+ "@vue/typescript-plugin": "3.0.0-alpha.2",
27
27
  "alien-signals": "^1.0.3",
28
28
  "path-browserify": "^1.0.1",
29
29
  "volar-service-css": "0.0.62",
@@ -45,5 +45,5 @@
45
45
  "@volar/kit": "~2.4.11",
46
46
  "vscode-languageserver-protocol": "^3.17.5"
47
47
  },
48
- "gitHead": "cdf00e6f19971260607ea2347924b94126a254fc"
48
+ "gitHead": "79247b7c24b7202ec676723440fdb36c38e6d450"
49
49
  }
@@ -1,6 +0,0 @@
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>;
@@ -1,39 +0,0 @@
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
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=autoinsert-selfClosingTags.js.map
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=autoinsert-selfclosing-tags.js.map