@vue/language-service 3.0.0-alpha.6 → 3.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +4 -7
- package/index.js +4 -181
- package/lib/nameCasing.d.ts +9 -9
- package/lib/nameCasing.js +100 -174
- package/lib/plugins/css.js +54 -42
- package/lib/plugins/utils.d.ts +1 -1
- package/lib/plugins/vue-compiler-dom-errors.d.ts +1 -1
- package/lib/plugins/vue-document-drop.d.ts +1 -1
- package/lib/plugins/vue-document-drop.js +3 -3
- package/lib/plugins/vue-document-links.js +63 -31
- package/lib/plugins/vue-inlayhints.d.ts +1 -1
- package/lib/plugins/vue-inlayhints.js +2 -3
- package/lib/plugins/vue-missing-props-hints.d.ts +1 -2
- package/lib/plugins/vue-missing-props-hints.js +3 -5
- package/lib/plugins/vue-template.d.ts +1 -2
- package/lib/plugins/vue-template.js +66 -82
- package/package.json +9 -13
- package/lib/ideFeatures/nameCasing.d.ts +0 -14
- package/lib/ideFeatures/nameCasing.js +0 -202
- package/lib/types.d.ts +0 -18
- package/lib/types.js +0 -39
package/lib/plugins/css.js
CHANGED
|
@@ -23,55 +23,67 @@ function create() {
|
|
|
23
23
|
return diagnostics;
|
|
24
24
|
},
|
|
25
25
|
/**
|
|
26
|
-
* If the
|
|
27
|
-
* skip the CSS
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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) {
|
package/lib/plugins/utils.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { LanguageServicePlugin } from '
|
|
1
|
+
import type { LanguageServicePlugin } from '@volar/language-service';
|
|
2
2
|
export declare function create(): LanguageServicePlugin;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
|
|
2
2
|
export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
|
|
@@ -6,8 +6,8 @@ const shared_1 = require("@vue/shared");
|
|
|
6
6
|
const path_browserify_1 = require("path-browserify");
|
|
7
7
|
const getUserPreferences_1 = require("volar-service-typescript/lib/configs/getUserPreferences");
|
|
8
8
|
const vscode_uri_1 = require("vscode-uri");
|
|
9
|
+
const nameCasing_1 = require("../nameCasing");
|
|
9
10
|
const vue_extract_file_1 = require("../plugins/vue-extract-file");
|
|
10
|
-
const types_1 = require("../types");
|
|
11
11
|
function create(ts, getTsPluginClient) {
|
|
12
12
|
return {
|
|
13
13
|
name: 'vue-document-drop',
|
|
@@ -18,7 +18,7 @@ function create(ts, getTsPluginClient) {
|
|
|
18
18
|
if (!context.project.vue) {
|
|
19
19
|
return {};
|
|
20
20
|
}
|
|
21
|
-
let casing =
|
|
21
|
+
let casing = nameCasing_1.TagNameCasing.Pascal; // TODO
|
|
22
22
|
const tsPluginClient = getTsPluginClient?.(context);
|
|
23
23
|
const vueCompilerOptions = context.project.vue.compilerOptions;
|
|
24
24
|
return {
|
|
@@ -103,7 +103,7 @@ function create(ts, getTsPluginClient) {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
return {
|
|
106
|
-
insertText: `<${casing ===
|
|
106
|
+
insertText: `<${casing === nameCasing_1.TagNameCasing.Kebab ? (0, shared_1.hyphenate)(newName) : newName}$0 />`,
|
|
107
107
|
insertTextFormat: 2,
|
|
108
108
|
additionalEdit,
|
|
109
109
|
};
|
|
@@ -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
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
const result = [];
|
|
29
|
+
if (virtualCode.id === 'template') {
|
|
30
|
+
const scopedClasses = codegen?.getGeneratedTemplate()?.scopedClasses ?? [];
|
|
31
|
+
const styleClasses = new Map();
|
|
32
|
+
const option = root.vueCompilerOptions.resolveStyleClassNames;
|
|
33
|
+
for (let i = 0; i < sfc.styles.length; i++) {
|
|
34
|
+
const style = sfc.styles[i];
|
|
35
|
+
if (option === true || (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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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(
|
|
62
|
-
end: document.positionAt(
|
|
93
|
+
start: document.positionAt(arg.start + 1),
|
|
94
|
+
end: document.positionAt(arg.end - 1),
|
|
63
95
|
},
|
|
64
|
-
target:
|
|
96
|
+
target: templateDocumentUri + `#L${start.line + 1},${start.character + 1}-L${end.line + 1},${end.character + 1}`,
|
|
65
97
|
});
|
|
66
98
|
}
|
|
67
99
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { LanguageServicePlugin } from '@volar/language-service';
|
|
1
2
|
import type * as ts from 'typescript';
|
|
2
|
-
import type { LanguageServicePlugin } from '../types';
|
|
3
3
|
export declare function create(ts: typeof import('typescript')): LanguageServicePlugin;
|
|
4
4
|
/**
|
|
5
5
|
* Refactored from https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/script/definePropsDestructure.ts
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.create = create;
|
|
4
4
|
exports.findDestructuredProps = findDestructuredProps;
|
|
5
5
|
const language_core_1 = require("@vue/language-core");
|
|
6
|
-
const index_1 = require("@vue/language-core/lib/codegen/utils/index");
|
|
7
6
|
const vscode_uri_1 = require("vscode-uri");
|
|
8
7
|
function create(ts) {
|
|
9
8
|
return {
|
|
@@ -148,7 +147,7 @@ function findDestructuredProps(ts, ast, props) {
|
|
|
148
147
|
&& initializer
|
|
149
148
|
&& ts.isCallExpression(initializer)
|
|
150
149
|
&& initializer.expression.getText(ast) === 'defineProps';
|
|
151
|
-
for (const { id } of (0,
|
|
150
|
+
for (const { id } of (0, language_core_1.collectIdentifiers)(ts, name)) {
|
|
152
151
|
if (isDefineProps) {
|
|
153
152
|
excludedIds.add(id);
|
|
154
153
|
}
|
|
@@ -163,7 +162,7 @@ function findDestructuredProps(ts, ast, props) {
|
|
|
163
162
|
registerLocalBinding(name);
|
|
164
163
|
}
|
|
165
164
|
for (const p of parameters) {
|
|
166
|
-
for (const { id } of (0,
|
|
165
|
+
for (const { id } of (0, language_core_1.collectIdentifiers)(ts, p)) {
|
|
167
166
|
registerLocalBinding(id);
|
|
168
167
|
}
|
|
169
168
|
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import type { LanguageServiceContext } from '@volar/language-service';
|
|
2
|
-
import { type LanguageServicePlugin } from '../types';
|
|
1
|
+
import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
|
|
3
2
|
export declare function create(getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
|
|
@@ -5,7 +5,6 @@ const language_core_1 = require("@vue/language-core");
|
|
|
5
5
|
const html = require("vscode-html-languageservice");
|
|
6
6
|
const vscode_uri_1 = require("vscode-uri");
|
|
7
7
|
const nameCasing_1 = require("../nameCasing");
|
|
8
|
-
const types_1 = require("../types");
|
|
9
8
|
function create(getTsPluginClient) {
|
|
10
9
|
return {
|
|
11
10
|
name: 'vue-missing-props-hints',
|
|
@@ -23,7 +22,6 @@ function create(getTsPluginClient) {
|
|
|
23
22
|
if (!context.project.vue) {
|
|
24
23
|
return;
|
|
25
24
|
}
|
|
26
|
-
const vueCompilerOptions = context.project.vue.compilerOptions;
|
|
27
25
|
const enabled = await context.env.getConfiguration?.('vue.inlayHints.missingProps') ?? false;
|
|
28
26
|
if (!enabled) {
|
|
29
27
|
return;
|
|
@@ -44,7 +42,7 @@ function create(getTsPluginClient) {
|
|
|
44
42
|
return;
|
|
45
43
|
}
|
|
46
44
|
const result = [];
|
|
47
|
-
const casing = await (0, nameCasing_1.
|
|
45
|
+
const casing = await (0, nameCasing_1.checkCasing)(context, decoded[0]);
|
|
48
46
|
const components = await tsPluginClient?.getComponentNames(root.fileName) ?? [];
|
|
49
47
|
const componentProps = {};
|
|
50
48
|
intrinsicElementNames ??= new Set(await tsPluginClient?.getElementNames(root.fileName) ?? []);
|
|
@@ -101,7 +99,7 @@ function create(getTsPluginClient) {
|
|
|
101
99
|
attrText = attrText.slice('v-model:'.length);
|
|
102
100
|
}
|
|
103
101
|
else if (attrText === 'v-model') {
|
|
104
|
-
attrText =
|
|
102
|
+
attrText = 'modelValue'; // TODO: support for experimentalModelPropName?
|
|
105
103
|
}
|
|
106
104
|
else if (attrText.startsWith('v-on:')) {
|
|
107
105
|
attrText = 'on-' + (0, language_core_1.hyphenateAttr)(attrText.slice('v-on:'.length));
|
|
@@ -129,7 +127,7 @@ function create(getTsPluginClient) {
|
|
|
129
127
|
start: document.positionAt(current.labelOffset),
|
|
130
128
|
end: document.positionAt(current.labelOffset),
|
|
131
129
|
},
|
|
132
|
-
newText: ` :${casing.attr ===
|
|
130
|
+
newText: ` :${casing.attr === nameCasing_1.AttrNameCasing.Kebab ? (0, language_core_1.hyphenateAttr)(requiredProp) : requiredProp}=`,
|
|
133
131
|
}],
|
|
134
132
|
});
|
|
135
133
|
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import type { LanguageServiceContext } from '@volar/language-service';
|
|
2
|
-
import { type LanguageServicePlugin } from '../types';
|
|
1
|
+
import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
|
|
3
2
|
export declare function create(mode: 'html' | 'pug', getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
|