@vue/language-service 2.2.8 → 3.0.0-alpha.0
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/data/language-blocks/ko.json +6 -6
- package/data/template/ko.json +26 -26
- package/index.d.ts +3 -5
- package/index.js +16 -7
- package/lib/{ideFeatures/nameCasing.d.ts → nameCasing.d.ts} +3 -3
- package/lib/{ideFeatures/nameCasing.js → nameCasing.js} +4 -5
- package/lib/plugins/vue-autoinsert-dotvalue.d.ts +1 -1
- package/lib/plugins/vue-compiler-dom-errors.d.ts +2 -0
- package/lib/plugins/vue-compiler-dom-errors.js +68 -0
- package/lib/plugins/vue-document-drop.d.ts +1 -1
- package/lib/plugins/vue-extract-file.d.ts +1 -1
- package/lib/plugins/vue-missing-props-hints.d.ts +3 -0
- package/lib/plugins/vue-missing-props-hints.js +160 -0
- package/lib/plugins/vue-template.d.ts +1 -1
- package/lib/plugins/vue-template.js +2 -234
- package/lib/plugins/vue-twoslash-queries.d.ts +1 -1
- package/package.json +4 -4
- package/lib/plugins/vue-autoinsert-self-closing.d.ts +0 -2
- package/lib/plugins/vue-autoinsert-self-closing.js +0 -33
- package/lib/plugins/vue-template/autoinsert-self-closing-tags.d.ts +0 -6
- package/lib/plugins/vue-template/autoinsert-self-closing-tags.js +0 -39
- package/lib/plugins/vue-template/autoinsert-selfClosingTags.d.ts +0 -1
- package/lib/plugins/vue-template/autoinsert-selfClosingTags.js +0 -3
- package/lib/plugins/vue-template/autoinsert-selfclosing-tags.d.ts +0 -1
- package/lib/plugins/vue-template/autoinsert-selfclosing-tags.js +0 -3
|
@@ -4,10 +4,9 @@ exports.convertTagName = convertTagName;
|
|
|
4
4
|
exports.convertAttrName = convertAttrName;
|
|
5
5
|
exports.getNameCasing = getNameCasing;
|
|
6
6
|
exports.detect = detect;
|
|
7
|
-
const vue = require("@vue/language-core");
|
|
8
7
|
const language_core_1 = require("@vue/language-core");
|
|
9
8
|
const alien_signals_1 = require("alien-signals");
|
|
10
|
-
const types_1 = require("
|
|
9
|
+
const types_1 = require("./types");
|
|
11
10
|
async function convertTagName(context, uri, casing, tsPluginClient) {
|
|
12
11
|
const sourceFile = context.language.scripts.get(uri);
|
|
13
12
|
if (!sourceFile) {
|
|
@@ -133,7 +132,7 @@ async function detect(context, uri) {
|
|
|
133
132
|
function getTagNameCase(file) {
|
|
134
133
|
const result = new Set();
|
|
135
134
|
if (file.sfc.template?.ast) {
|
|
136
|
-
for (const element of
|
|
135
|
+
for (const element of (0, language_core_1.forEachElementNode)(file.sfc.template.ast)) {
|
|
137
136
|
if (element.tagType === 1) {
|
|
138
137
|
if (element.tag !== (0, language_core_1.hyphenateTag)(element.tag)) {
|
|
139
138
|
// TagName
|
|
@@ -154,13 +153,13 @@ const map = new WeakMap();
|
|
|
154
153
|
function getTemplateTagsAndAttrs(sourceFile) {
|
|
155
154
|
if (!map.has(sourceFile)) {
|
|
156
155
|
const getter = (0, alien_signals_1.computed)(() => {
|
|
157
|
-
if (!(sourceFile instanceof
|
|
156
|
+
if (!(sourceFile instanceof language_core_1.VueVirtualCode)) {
|
|
158
157
|
return;
|
|
159
158
|
}
|
|
160
159
|
const ast = sourceFile.sfc.template?.ast;
|
|
161
160
|
const tags = new Map();
|
|
162
161
|
if (ast) {
|
|
163
|
-
for (const node of
|
|
162
|
+
for (const node of (0, language_core_1.forEachElementNode)(ast)) {
|
|
164
163
|
if (!tags.has(node.tag)) {
|
|
165
164
|
tags.set(node.tag, { offsets: [], attrs: new Map() });
|
|
166
165
|
}
|
|
@@ -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) =>
|
|
2
|
+
export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
|
|
@@ -0,0 +1,68 @@
|
|
|
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() {
|
|
7
|
+
return {
|
|
8
|
+
name: 'vue-compiler-dom-errors',
|
|
9
|
+
capabilities: {
|
|
10
|
+
diagnosticProvider: {
|
|
11
|
+
interFileDependencies: false,
|
|
12
|
+
workspaceDiagnostics: false,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
create(context) {
|
|
16
|
+
return {
|
|
17
|
+
provideDiagnostics(document) {
|
|
18
|
+
if (!isSupportedDocument(document)) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const uri = vscode_uri_1.URI.parse(document.uri);
|
|
22
|
+
const decoded = context.decodeEmbeddedDocumentUri(uri);
|
|
23
|
+
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
24
|
+
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
|
25
|
+
if (!virtualCode) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const root = sourceScript?.generated?.root;
|
|
29
|
+
if (!(root instanceof language_core_1.VueVirtualCode)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const templateErrors = [];
|
|
33
|
+
const { template } = root.sfc;
|
|
34
|
+
if (template) {
|
|
35
|
+
for (const error of template.errors) {
|
|
36
|
+
onCompilerError(error, 1);
|
|
37
|
+
}
|
|
38
|
+
for (const warning of template.warnings) {
|
|
39
|
+
onCompilerError(warning, 2);
|
|
40
|
+
}
|
|
41
|
+
function onCompilerError(error, severity) {
|
|
42
|
+
const templateHtmlRange = {
|
|
43
|
+
start: error.loc?.start.offset ?? 0,
|
|
44
|
+
end: error.loc?.end.offset ?? 0,
|
|
45
|
+
};
|
|
46
|
+
let errorMessage = error.message;
|
|
47
|
+
templateErrors.push({
|
|
48
|
+
range: {
|
|
49
|
+
start: document.positionAt(templateHtmlRange.start),
|
|
50
|
+
end: document.positionAt(templateHtmlRange.end),
|
|
51
|
+
},
|
|
52
|
+
severity,
|
|
53
|
+
code: error.code,
|
|
54
|
+
source: 'vue',
|
|
55
|
+
message: errorMessage,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return templateErrors;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
function isSupportedDocument(document) {
|
|
65
|
+
return document.languageId === 'jade' || document.languageId === 'html';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=vue-compiler-dom-errors.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { LanguageServiceContext, LanguageServicePlugin } from '../types';
|
|
2
|
-
export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) =>
|
|
2
|
+
export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
|
|
2
2
|
import { 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) =>
|
|
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,3 @@
|
|
|
1
|
+
import type { LanguageServiceContext } from '@volar/language-service';
|
|
2
|
+
import { LanguageServicePlugin } from '../types';
|
|
3
|
+
export declare function create(getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
|
|
@@ -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',
|
|
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("../
|
|
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,
|
|
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) =>
|
|
2
|
+
export declare function create(getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue/language-service",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.0",
|
|
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": "
|
|
24
|
+
"@vue/language-core": "3.0.0-alpha.0",
|
|
25
25
|
"@vue/shared": "^3.5.0",
|
|
26
|
-
"@vue/typescript-plugin": "
|
|
26
|
+
"@vue/typescript-plugin": "3.0.0-alpha.0",
|
|
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": "
|
|
48
|
+
"gitHead": "4b49cbe09097e482def4603b90f6c3b93bb2e913"
|
|
49
49
|
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.create = create;
|
|
4
|
-
function create() {
|
|
5
|
-
return {
|
|
6
|
-
name: 'vue-autoinsert-selfClosing',
|
|
7
|
-
capabilities: {
|
|
8
|
-
autoInsertionProvider: {
|
|
9
|
-
triggerCharacters: ['/'],
|
|
10
|
-
configurationSections: ['vue.autoInsert.selfClosing'],
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
create(context) {
|
|
14
|
-
return {
|
|
15
|
-
async provideAutoInsertSnippet(document, selection, change) {
|
|
16
|
-
if (document.languageId !== 'html') {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
const enabled = await context.env.getConfiguration?.('vue.autoInsert.selfClosing') ?? true;
|
|
20
|
-
if (!enabled) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
if (change.text === '{}'
|
|
24
|
-
&& document.getText().slice(change.rangeOffset - 1, change.rangeOffset + 3) === '{{}}'
|
|
25
|
-
&& document.offsetAt(selection) === change.rangeOffset + 1) {
|
|
26
|
-
return ` $0 `;
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=vue-autoinsert-self-closing.js.map
|