@vue/language-service 1.7.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/LICENSE +21 -0
- package/data/language-blocks/en.json +626 -0
- package/data/language-blocks/fr.json +626 -0
- package/data/language-blocks/ja.json +626 -0
- package/data/language-blocks/ko.json +626 -0
- package/data/language-blocks/zh-cn.json +626 -0
- package/data/language-blocks/zh-tw.json +626 -0
- package/data/model-modifiers/en.json +104 -0
- package/data/model-modifiers/fr.json +104 -0
- package/data/model-modifiers/ja.json +104 -0
- package/data/model-modifiers/ko.json +104 -0
- package/data/model-modifiers/zh-cn.json +104 -0
- package/data/model-modifiers/zh-tw.json +104 -0
- package/data/template/en.json +866 -0
- package/data/template/fr.json +866 -0
- package/data/template/ja.json +866 -0
- package/data/template/ko.json +866 -0
- package/data/template/zh-cn.json +866 -0
- package/data/template/zh-tw.json +866 -0
- package/out/helpers.d.ts +15 -0
- package/out/helpers.js +246 -0
- package/out/ideFeatures/nameCasing.d.ts +13 -0
- package/out/ideFeatures/nameCasing.js +173 -0
- package/out/index.d.ts +5 -0
- package/out/index.js +24 -0
- package/out/languageService.d.ts +9 -0
- package/out/languageService.js +243 -0
- package/out/plugins/data.d.ts +4 -0
- package/out/plugins/data.js +90 -0
- package/out/plugins/vue-autoinsert-dotvalue.d.ts +7 -0
- package/out/plugins/vue-autoinsert-dotvalue.js +157 -0
- package/out/plugins/vue-autoinsert-parentheses.d.ts +3 -0
- package/out/plugins/vue-autoinsert-parentheses.js +67 -0
- package/out/plugins/vue-autoinsert-space.d.ts +3 -0
- package/out/plugins/vue-autoinsert-space.js +30 -0
- package/out/plugins/vue-codelens-references.d.ts +2 -0
- package/out/plugins/vue-codelens-references.js +53 -0
- package/out/plugins/vue-template.d.ts +10 -0
- package/out/plugins/vue-template.js +538 -0
- package/out/plugins/vue-twoslash-queries.d.ts +3 -0
- package/out/plugins/vue-twoslash-queries.js +59 -0
- package/out/plugins/vue-visualize-hidden-callback-param.d.ts +3 -0
- package/out/plugins/vue-visualize-hidden-callback-param.js +42 -0
- package/out/plugins/vue.d.ts +8 -0
- package/out/plugins/vue.js +137 -0
- package/out/types.d.ts +10 -0
- package/out/types.js +31 -0
- package/package.json +44 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveConfig = void 0;
|
|
4
|
+
const volar_service_css_1 = require("volar-service-css");
|
|
5
|
+
const volar_service_emmet_1 = require("volar-service-emmet");
|
|
6
|
+
const volar_service_html_1 = require("volar-service-html");
|
|
7
|
+
const volar_service_json_1 = require("volar-service-json");
|
|
8
|
+
const volar_service_pug_1 = require("volar-service-pug");
|
|
9
|
+
const volar_service_typescript_1 = require("volar-service-typescript");
|
|
10
|
+
const volar_service_typescript_twoslash_queries_1 = require("volar-service-typescript-twoslash-queries");
|
|
11
|
+
const vue = require("@vue/language-core");
|
|
12
|
+
const vscode = require("vscode-languageserver-protocol");
|
|
13
|
+
const vue_1 = require("./plugins/vue");
|
|
14
|
+
const vue_autoinsert_dotvalue_1 = require("./plugins/vue-autoinsert-dotvalue");
|
|
15
|
+
const vue_codelens_references_1 = require("./plugins/vue-codelens-references");
|
|
16
|
+
const vue_twoslash_queries_1 = require("./plugins/vue-twoslash-queries");
|
|
17
|
+
const vue_template_1 = require("./plugins/vue-template");
|
|
18
|
+
const vue_visualize_hidden_callback_param_1 = require("./plugins/vue-visualize-hidden-callback-param");
|
|
19
|
+
const shared_1 = require("@vue/shared");
|
|
20
|
+
const volar_service_pug_beautify_1 = require("volar-service-pug-beautify");
|
|
21
|
+
const vue_autoinsert_parentheses_1 = require("./plugins/vue-autoinsert-parentheses");
|
|
22
|
+
const vue_autoinsert_space_1 = require("./plugins/vue-autoinsert-space");
|
|
23
|
+
const types_1 = require("./types");
|
|
24
|
+
const nameCasing_1 = require("./ideFeatures/nameCasing");
|
|
25
|
+
function resolveConfig(config, // volar.config.js
|
|
26
|
+
compilerOptions = {}, vueCompilerOptions = vue.resolveVueCompilerOptions({}), settings, ts = require('typescript')) {
|
|
27
|
+
const vueLanguageModules = vue.createLanguages(compilerOptions, vueCompilerOptions, ts);
|
|
28
|
+
config.languages = Object.assign({}, vueLanguageModules, config.languages);
|
|
29
|
+
config.services = resolvePlugins(config.services, vueCompilerOptions, settings);
|
|
30
|
+
return config;
|
|
31
|
+
}
|
|
32
|
+
exports.resolveConfig = resolveConfig;
|
|
33
|
+
function resolvePlugins(services, vueCompilerOptions, settings) {
|
|
34
|
+
const originalTsPlugin = services?.typescript ?? (0, volar_service_typescript_1.default)();
|
|
35
|
+
services ??= {};
|
|
36
|
+
services.typescript = (_context, modules) => {
|
|
37
|
+
const base = typeof originalTsPlugin === 'function' ? originalTsPlugin(_context, modules) : originalTsPlugin;
|
|
38
|
+
if (!_context || !modules?.typescript)
|
|
39
|
+
return base;
|
|
40
|
+
const ts = modules.typescript;
|
|
41
|
+
const autoImportPositions = new WeakSet();
|
|
42
|
+
return {
|
|
43
|
+
...base,
|
|
44
|
+
resolveEmbeddedRange(range) {
|
|
45
|
+
if (autoImportPositions.has(range.start) && autoImportPositions.has(range.end))
|
|
46
|
+
return range;
|
|
47
|
+
},
|
|
48
|
+
async provideCompletionItems(document, position, context, item) {
|
|
49
|
+
const result = await base.provideCompletionItems?.(document, position, context, item);
|
|
50
|
+
if (result) {
|
|
51
|
+
// filter __VLS_
|
|
52
|
+
result.items = result.items.filter(item => item.label.indexOf('__VLS_') === -1
|
|
53
|
+
&& (!item.labelDetails?.description || item.labelDetails.description.indexOf('__VLS_') === -1));
|
|
54
|
+
// handle component auto-import patch
|
|
55
|
+
for (const [_, map] of _context.documents.getMapsByVirtualFileUri(document.uri)) {
|
|
56
|
+
const virtualFile = _context.documents.getSourceByUri(map.sourceFileDocument.uri)?.root;
|
|
57
|
+
if (virtualFile instanceof vue.VueFile) {
|
|
58
|
+
const isAutoImport = !!map.toSourcePosition(position, data => typeof data.completion === 'object' && !!data.completion.autoImportOnly);
|
|
59
|
+
if (isAutoImport) {
|
|
60
|
+
result.items.forEach(item => {
|
|
61
|
+
item.data.__isComponentAutoImport = true;
|
|
62
|
+
});
|
|
63
|
+
// fix #2458
|
|
64
|
+
const source = _context.documents.getVirtualFileByUri(document.uri)[1];
|
|
65
|
+
if (source && _context.typescript) {
|
|
66
|
+
const casing = await (0, nameCasing_1.getNameCasing)(ts, _context, _context.env.fileNameToUri(source.fileName));
|
|
67
|
+
if (casing.tag === types_1.TagNameCasing.Kebab) {
|
|
68
|
+
result.items.forEach(item => {
|
|
69
|
+
item.filterText = (0, shared_1.hyphenate)(item.filterText ?? item.label);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
},
|
|
79
|
+
async resolveCompletionItem(item, token) {
|
|
80
|
+
item = await base.resolveCompletionItem?.(item, token) ?? item;
|
|
81
|
+
const itemData = item.data;
|
|
82
|
+
let newName;
|
|
83
|
+
if (itemData?.uri && item.additionalTextEdits) {
|
|
84
|
+
patchAdditionalTextEdits(itemData.uri, item.additionalTextEdits);
|
|
85
|
+
}
|
|
86
|
+
for (const ext of vueCompilerOptions.extensions) {
|
|
87
|
+
const suffix = (0, shared_1.capitalize)(ext.substring('.'.length)); // .vue -> Vue
|
|
88
|
+
if (itemData?.uri
|
|
89
|
+
&& _context.typescript
|
|
90
|
+
&& item.textEdit?.newText.endsWith(suffix)
|
|
91
|
+
&& item.additionalTextEdits?.length === 1 && item.additionalTextEdits[0].newText.indexOf('import ' + item.textEdit.newText + ' from ') >= 0
|
|
92
|
+
&& (await _context.env.getConfiguration?.('vue.complete.normalizeComponentImportName') ?? true)) {
|
|
93
|
+
newName = item.textEdit.newText.slice(0, -suffix.length);
|
|
94
|
+
newName = newName[0].toUpperCase() + newName.substring(1);
|
|
95
|
+
if (newName === 'Index') {
|
|
96
|
+
const tsItem = item.data.originalItem;
|
|
97
|
+
if (tsItem.source) {
|
|
98
|
+
const dirs = tsItem.source.split('/');
|
|
99
|
+
if (dirs.length >= 3) {
|
|
100
|
+
newName = dirs[dirs.length - 2];
|
|
101
|
+
newName = newName[0].toUpperCase() + newName.substring(1);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
item.additionalTextEdits[0].newText = item.additionalTextEdits[0].newText.replace('import ' + item.textEdit.newText + ' from ', 'import ' + newName + ' from ');
|
|
106
|
+
item.textEdit.newText = newName;
|
|
107
|
+
const source = _context.documents.getVirtualFileByUri(itemData.uri)[1];
|
|
108
|
+
if (source) {
|
|
109
|
+
const casing = await (0, nameCasing_1.getNameCasing)(ts, _context, _context.env.fileNameToUri(source.fileName));
|
|
110
|
+
if (casing.tag === types_1.TagNameCasing.Kebab) {
|
|
111
|
+
item.textEdit.newText = (0, shared_1.hyphenate)(item.textEdit.newText);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else if (item.textEdit?.newText && new RegExp(`import \\w*${suffix}\\$1 from [\\S\\s]*`).test(item.textEdit.newText)) {
|
|
116
|
+
// https://github.com/vuejs/language-tools/issues/2286
|
|
117
|
+
item.textEdit.newText = item.textEdit.newText.replace(`${suffix}$1`, '$1');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const data = item.data;
|
|
121
|
+
if (item.data?.__isComponentAutoImport && data && item.additionalTextEdits?.length && item.textEdit) {
|
|
122
|
+
for (const [_, map] of _context.documents.getMapsByVirtualFileUri(data.uri)) {
|
|
123
|
+
const virtualFile = _context.documents.getSourceByUri(map.sourceFileDocument.uri)?.root;
|
|
124
|
+
if (virtualFile instanceof vue.VueFile) {
|
|
125
|
+
const sfc = virtualFile.sfc;
|
|
126
|
+
const componentName = newName ?? item.textEdit.newText;
|
|
127
|
+
const textDoc = _context.documents.getDocumentByFileName(virtualFile.snapshot, virtualFile.fileName);
|
|
128
|
+
if (sfc.scriptAst && sfc.script) {
|
|
129
|
+
const _scriptRanges = vue.scriptRanges.parseScriptRanges(ts, sfc.scriptAst, !!sfc.scriptSetup, true);
|
|
130
|
+
const exportDefault = _scriptRanges.exportDefault;
|
|
131
|
+
if (exportDefault) {
|
|
132
|
+
// https://github.com/microsoft/TypeScript/issues/36174
|
|
133
|
+
const printer = ts.createPrinter();
|
|
134
|
+
if (exportDefault.componentsOption && exportDefault.componentsOptionNode) {
|
|
135
|
+
const newNode = {
|
|
136
|
+
...exportDefault.componentsOptionNode,
|
|
137
|
+
properties: [
|
|
138
|
+
...exportDefault.componentsOptionNode.properties,
|
|
139
|
+
ts.factory.createShorthandPropertyAssignment(componentName),
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
const printText = printer.printNode(ts.EmitHint.Expression, newNode, sfc.scriptAst);
|
|
143
|
+
const editRange = vscode.Range.create(textDoc.positionAt(sfc.script.startTagEnd + exportDefault.componentsOption.start), textDoc.positionAt(sfc.script.startTagEnd + exportDefault.componentsOption.end));
|
|
144
|
+
autoImportPositions.add(editRange.start);
|
|
145
|
+
autoImportPositions.add(editRange.end);
|
|
146
|
+
item.additionalTextEdits.push(vscode.TextEdit.replace(editRange, unescape(printText.replace(/\\u/g, '%u'))));
|
|
147
|
+
}
|
|
148
|
+
else if (exportDefault.args && exportDefault.argsNode) {
|
|
149
|
+
const newNode = {
|
|
150
|
+
...exportDefault.argsNode,
|
|
151
|
+
properties: [
|
|
152
|
+
...exportDefault.argsNode.properties,
|
|
153
|
+
ts.factory.createShorthandPropertyAssignment(`components: { ${componentName} }`),
|
|
154
|
+
],
|
|
155
|
+
};
|
|
156
|
+
const printText = printer.printNode(ts.EmitHint.Expression, newNode, sfc.scriptAst);
|
|
157
|
+
const editRange = vscode.Range.create(textDoc.positionAt(sfc.script.startTagEnd + exportDefault.args.start), textDoc.positionAt(sfc.script.startTagEnd + exportDefault.args.end));
|
|
158
|
+
autoImportPositions.add(editRange.start);
|
|
159
|
+
autoImportPositions.add(editRange.end);
|
|
160
|
+
item.additionalTextEdits.push(vscode.TextEdit.replace(editRange, unescape(printText.replace(/\\u/g, '%u'))));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return item;
|
|
168
|
+
},
|
|
169
|
+
async provideCodeActions(document, range, context, token) {
|
|
170
|
+
const result = await base.provideCodeActions?.(document, range, context, token);
|
|
171
|
+
return result?.filter(codeAction => codeAction.title.indexOf('__VLS_') === -1);
|
|
172
|
+
},
|
|
173
|
+
async resolveCodeAction(item, token) {
|
|
174
|
+
const result = await base.resolveCodeAction?.(item, token) ?? item;
|
|
175
|
+
if (result?.edit?.changes) {
|
|
176
|
+
for (const uri in result.edit.changes) {
|
|
177
|
+
const edits = result.edit.changes[uri];
|
|
178
|
+
if (edits) {
|
|
179
|
+
patchAdditionalTextEdits(uri, edits);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (result?.edit?.documentChanges) {
|
|
184
|
+
for (const documentChange of result.edit.documentChanges) {
|
|
185
|
+
if (vscode.TextDocumentEdit.is(documentChange)) {
|
|
186
|
+
patchAdditionalTextEdits(documentChange.textDocument.uri, documentChange.edits);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return result;
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
services.html ??= (0, vue_template_1.default)({
|
|
195
|
+
templateLanguagePlugin: (0, volar_service_html_1.default)(),
|
|
196
|
+
getScanner: (document, htmlPlugin) => {
|
|
197
|
+
return htmlPlugin.getHtmlLs().createScanner(document.getText());
|
|
198
|
+
},
|
|
199
|
+
isSupportedDocument: (document) => document.languageId === 'html',
|
|
200
|
+
vueCompilerOptions,
|
|
201
|
+
});
|
|
202
|
+
services.pug ??= (0, vue_template_1.default)({
|
|
203
|
+
templateLanguagePlugin: (0, volar_service_pug_1.default)(),
|
|
204
|
+
getScanner: (document, pugPlugin) => {
|
|
205
|
+
const pugDocument = pugPlugin.getPugDocument(document);
|
|
206
|
+
if (pugDocument) {
|
|
207
|
+
return pugPlugin.getPugLs().createScanner(pugDocument);
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
isSupportedDocument: (document) => document.languageId === 'jade',
|
|
211
|
+
vueCompilerOptions,
|
|
212
|
+
});
|
|
213
|
+
services.vue ??= (0, vue_1.default)();
|
|
214
|
+
services.css ??= (0, volar_service_css_1.default)();
|
|
215
|
+
services['pug-beautify'] ??= (0, volar_service_pug_beautify_1.default)();
|
|
216
|
+
services.json ??= (0, volar_service_json_1.default)(settings?.json);
|
|
217
|
+
services['typescript/twoslash-queries'] ??= (0, volar_service_typescript_twoslash_queries_1.default)();
|
|
218
|
+
services['vue/referencesCodeLens'] ??= (0, vue_codelens_references_1.default)();
|
|
219
|
+
services['vue/autoInsertDotValue'] ??= (0, vue_autoinsert_dotvalue_1.default)();
|
|
220
|
+
services['vue/twoslash-queries'] ??= (0, vue_twoslash_queries_1.default)();
|
|
221
|
+
services['vue/autoInsertParentheses'] ??= (0, vue_autoinsert_parentheses_1.default)();
|
|
222
|
+
services['vue/autoInsertSpaces'] ??= (0, vue_autoinsert_space_1.default)();
|
|
223
|
+
services['vue/visualizeHiddenCallbackParam'] ??= (0, vue_visualize_hidden_callback_param_1.default)();
|
|
224
|
+
services.emmet ??= (0, volar_service_emmet_1.default)();
|
|
225
|
+
return services;
|
|
226
|
+
}
|
|
227
|
+
// fix https://github.com/vuejs/language-tools/issues/916
|
|
228
|
+
function patchAdditionalTextEdits(uri, edits) {
|
|
229
|
+
if (uri.endsWith('.vue.js')
|
|
230
|
+
|| uri.endsWith('.vue.ts')
|
|
231
|
+
|| uri.endsWith('.vue.jsx')
|
|
232
|
+
|| uri.endsWith('.vue.tsx')) {
|
|
233
|
+
for (const edit of edits) {
|
|
234
|
+
if (edit.range.start.line === 0
|
|
235
|
+
&& edit.range.start.character === 0
|
|
236
|
+
&& edit.range.end.line === 0
|
|
237
|
+
&& edit.range.end.character === 0) {
|
|
238
|
+
edit.newText = '\n' + edit.newText;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=languageService.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import * as html from 'vscode-html-languageservice';
|
|
2
|
+
export declare function loadTemplateData(lang: string): html.HTMLDataV1;
|
|
3
|
+
export declare function loadLanguageBlocks(lang: string): html.HTMLDataV1;
|
|
4
|
+
export declare function loadModelModifiersData(lang: string): html.HTMLDataV1;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadModelModifiersData = exports.loadLanguageBlocks = exports.loadTemplateData = void 0;
|
|
4
|
+
function loadTemplateData(lang) {
|
|
5
|
+
lang = lang.toLowerCase();
|
|
6
|
+
let data;
|
|
7
|
+
if (lang === 'ja') {
|
|
8
|
+
data = require('../../data/template/ja.json');
|
|
9
|
+
}
|
|
10
|
+
else if (lang === 'fr') {
|
|
11
|
+
data = require('../../data/template/fr.json');
|
|
12
|
+
}
|
|
13
|
+
else if (lang === 'ko') {
|
|
14
|
+
data = require('../../data/template/ko.json');
|
|
15
|
+
}
|
|
16
|
+
else if (lang === 'zh-cn') {
|
|
17
|
+
data = require('../../data/template/zh-cn.json');
|
|
18
|
+
}
|
|
19
|
+
else if (lang === 'zh-tw') {
|
|
20
|
+
data = require('../../data/template/zh-tw.json');
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
data = require('../../data/template/en.json');
|
|
24
|
+
}
|
|
25
|
+
for (const attr of [...data.globalAttributes ?? []]) {
|
|
26
|
+
if (!attr.name.startsWith('v-')) {
|
|
27
|
+
data.globalAttributes?.push({ ...attr, name: `:${attr.name}` });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const vOn = data.globalAttributes?.find(d => d.name === 'v-on');
|
|
31
|
+
const vSlot = data.globalAttributes?.find(d => d.name === 'v-slot');
|
|
32
|
+
const vBind = data.globalAttributes?.find(d => d.name === 'v-bind');
|
|
33
|
+
if (vOn)
|
|
34
|
+
data.globalAttributes?.push({ ...vOn, name: '@' });
|
|
35
|
+
if (vSlot)
|
|
36
|
+
data.globalAttributes?.push({ ...vSlot, name: '#' });
|
|
37
|
+
if (vBind)
|
|
38
|
+
data.globalAttributes?.push({ ...vBind, name: ':' });
|
|
39
|
+
return data;
|
|
40
|
+
}
|
|
41
|
+
exports.loadTemplateData = loadTemplateData;
|
|
42
|
+
function loadLanguageBlocks(lang) {
|
|
43
|
+
lang = lang.toLowerCase();
|
|
44
|
+
let data;
|
|
45
|
+
if (lang === 'ja') {
|
|
46
|
+
data = require('../../data/language-blocks/ja.json');
|
|
47
|
+
}
|
|
48
|
+
else if (lang === 'fr') {
|
|
49
|
+
data = require('../../data/language-blocks/fr.json');
|
|
50
|
+
}
|
|
51
|
+
else if (lang === 'ko') {
|
|
52
|
+
data = require('../../data/language-blocks/ko.json');
|
|
53
|
+
}
|
|
54
|
+
else if (lang === 'zh-cn') {
|
|
55
|
+
data = require('../../data/language-blocks/zh-cn.json');
|
|
56
|
+
}
|
|
57
|
+
else if (lang === 'zh-tw') {
|
|
58
|
+
data = require('../../data/language-blocks/zh-tw.json');
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
data = require('../../data/language-blocks/en.json');
|
|
62
|
+
}
|
|
63
|
+
return data;
|
|
64
|
+
}
|
|
65
|
+
exports.loadLanguageBlocks = loadLanguageBlocks;
|
|
66
|
+
function loadModelModifiersData(lang) {
|
|
67
|
+
lang = lang.toLowerCase();
|
|
68
|
+
let data;
|
|
69
|
+
if (lang === 'ja') {
|
|
70
|
+
data = require('../../data/model-modifiers/ja.json');
|
|
71
|
+
}
|
|
72
|
+
else if (lang === 'fr') {
|
|
73
|
+
data = require('../../data/model-modifiers/fr.json');
|
|
74
|
+
}
|
|
75
|
+
else if (lang === 'ko') {
|
|
76
|
+
data = require('../../data/model-modifiers/ko.json');
|
|
77
|
+
}
|
|
78
|
+
else if (lang === 'zh-cn') {
|
|
79
|
+
data = require('../../data/model-modifiers/zh-cn.json');
|
|
80
|
+
}
|
|
81
|
+
else if (lang === 'zh-tw') {
|
|
82
|
+
data = require('../../data/model-modifiers/zh-tw.json');
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
data = require('../../data/model-modifiers/en.json');
|
|
86
|
+
}
|
|
87
|
+
return data;
|
|
88
|
+
}
|
|
89
|
+
exports.loadModelModifiersData = loadModelModifiersData;
|
|
90
|
+
//# sourceMappingURL=data.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AutoInsertionContext, Service } from '@volar/language-service';
|
|
2
|
+
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
3
|
+
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
4
|
+
declare const _default: () => Service;
|
|
5
|
+
export default _default;
|
|
6
|
+
export declare function isCharacterTyping(document: TextDocument, options: AutoInsertionContext): boolean;
|
|
7
|
+
export declare function isBlacklistNode(ts: typeof import('typescript/lib/tsserverlibrary'), node: ts.Node, pos: number, allowAccessDotValue: boolean): boolean;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isBlacklistNode = exports.isCharacterTyping = void 0;
|
|
4
|
+
const shared_1 = require("@vue/shared");
|
|
5
|
+
const vscode = require("vscode-languageserver-protocol");
|
|
6
|
+
const plugin = (context, modules) => {
|
|
7
|
+
if (!modules?.typescript)
|
|
8
|
+
return {};
|
|
9
|
+
if (!context?.typescript)
|
|
10
|
+
return {};
|
|
11
|
+
const ts = modules.typescript;
|
|
12
|
+
const _ts = context.typescript;
|
|
13
|
+
return {
|
|
14
|
+
async provideAutoInsertionEdit(document, position, insertContext) {
|
|
15
|
+
if (!isTsDocument(document))
|
|
16
|
+
return;
|
|
17
|
+
if (!isCharacterTyping(document, insertContext))
|
|
18
|
+
return;
|
|
19
|
+
const enabled = await context.env.getConfiguration?.('vue.autoInsert.dotValue') ?? true;
|
|
20
|
+
if (!enabled)
|
|
21
|
+
return;
|
|
22
|
+
const program = _ts.languageService.getProgram();
|
|
23
|
+
if (!program)
|
|
24
|
+
return;
|
|
25
|
+
const sourceFile = program.getSourceFile(context.env.uriToFileName(document.uri));
|
|
26
|
+
if (!sourceFile)
|
|
27
|
+
return;
|
|
28
|
+
if (isBlacklistNode(ts, sourceFile, document.offsetAt(position), false))
|
|
29
|
+
return;
|
|
30
|
+
const node = findPositionIdentifier(sourceFile, sourceFile, document.offsetAt(position));
|
|
31
|
+
if (!node)
|
|
32
|
+
return;
|
|
33
|
+
const token = _ts.languageServiceHost.getCancellationToken?.();
|
|
34
|
+
if (token) {
|
|
35
|
+
_ts.languageService.getQuickInfoAtPosition(context.env.uriToFileName(document.uri), node.end);
|
|
36
|
+
if (token?.isCancellationRequested()) {
|
|
37
|
+
return; // check cancel here because type checker do not use cancel token
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const checker = program.getTypeChecker();
|
|
41
|
+
const type = checker.getTypeAtLocation(node);
|
|
42
|
+
const props = type.getProperties();
|
|
43
|
+
if (props.some(prop => prop.name === 'value')) {
|
|
44
|
+
return '${1:.value}';
|
|
45
|
+
}
|
|
46
|
+
function findPositionIdentifier(sourceFile, node, offset) {
|
|
47
|
+
let result;
|
|
48
|
+
node.forEachChild(child => {
|
|
49
|
+
if (!result) {
|
|
50
|
+
if (child.end === offset && ts.isIdentifier(child)) {
|
|
51
|
+
result = child;
|
|
52
|
+
}
|
|
53
|
+
else if (child.end >= offset && child.getStart(sourceFile) < offset) {
|
|
54
|
+
result = findPositionIdentifier(sourceFile, child, offset);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
exports.default = () => plugin;
|
|
64
|
+
function isTsDocument(document) {
|
|
65
|
+
return document.languageId === 'javascript' ||
|
|
66
|
+
document.languageId === 'typescript' ||
|
|
67
|
+
document.languageId === 'javascriptreact' ||
|
|
68
|
+
document.languageId === 'typescriptreact';
|
|
69
|
+
}
|
|
70
|
+
function isCharacterTyping(document, options) {
|
|
71
|
+
const lastCharacter = options.lastChange.text[options.lastChange.text.length - 1];
|
|
72
|
+
const rangeStart = options.lastChange.range.start;
|
|
73
|
+
const position = vscode.Position.create(rangeStart.line, rangeStart.character + options.lastChange.text.length);
|
|
74
|
+
const nextCharacter = document.getText(vscode.Range.create(position, document.positionAt(document.offsetAt(position) + 1)));
|
|
75
|
+
if (lastCharacter === undefined) { // delete text
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
if (options.lastChange.text.indexOf('\n') >= 0) { // multi-line change
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return /\w/.test(lastCharacter) && !/\w/.test(nextCharacter);
|
|
82
|
+
}
|
|
83
|
+
exports.isCharacterTyping = isCharacterTyping;
|
|
84
|
+
function isBlacklistNode(ts, node, pos, allowAccessDotValue) {
|
|
85
|
+
if (ts.isVariableDeclaration(node) && pos >= node.name.getFullStart() && pos <= node.name.getEnd()) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
else if (ts.isFunctionDeclaration(node) && node.name && pos >= node.name.getFullStart() && pos <= node.name.getEnd()) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
else if (ts.isParameter(node) && pos >= node.name.getFullStart() && pos <= node.name.getEnd()) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
else if (ts.isPropertyAssignment(node) && pos >= node.name.getFullStart() && pos <= node.name.getEnd()) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
else if (ts.isShorthandPropertyAssignment(node)) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
else if (ts.isImportDeclaration(node)) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
else if (ts.isLiteralTypeNode(node)) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
else if (ts.isTypeReferenceNode(node)) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
else if (!allowAccessDotValue && ts.isPropertyAccessExpression(node) && node.expression.end === pos && node.name.text === 'value') {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
else if (ts.isCallExpression(node)
|
|
113
|
+
&& ts.isIdentifier(node.expression)
|
|
114
|
+
&& isWatchOrUseFunction(node.expression.text)
|
|
115
|
+
&& isTopLevelArgOrArrayTopLevelItemItem(node)) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
let _isBlacklistNode = false;
|
|
120
|
+
node.forEachChild(node => {
|
|
121
|
+
if (_isBlacklistNode)
|
|
122
|
+
return;
|
|
123
|
+
if (pos >= node.getFullStart() && pos <= node.getEnd()) {
|
|
124
|
+
if (isBlacklistNode(ts, node, pos, allowAccessDotValue)) {
|
|
125
|
+
_isBlacklistNode = true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return _isBlacklistNode;
|
|
130
|
+
}
|
|
131
|
+
function isWatchOrUseFunction(fnName) {
|
|
132
|
+
return fnName === 'watch'
|
|
133
|
+
|| fnName === 'unref'
|
|
134
|
+
|| fnName === 'triggerRef'
|
|
135
|
+
|| fnName === 'isRef'
|
|
136
|
+
|| (0, shared_1.hyphenate)(fnName).startsWith('use-');
|
|
137
|
+
}
|
|
138
|
+
function isTopLevelArgOrArrayTopLevelItemItem(node) {
|
|
139
|
+
for (const arg of node.arguments) {
|
|
140
|
+
if (pos >= arg.getFullStart() && pos <= arg.getEnd()) {
|
|
141
|
+
if (ts.isIdentifier(arg)) {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
if (ts.isArrayLiteralExpression(arg)) {
|
|
145
|
+
for (const el of arg.elements) {
|
|
146
|
+
if (pos >= el.getFullStart() && pos <= el.getEnd()) {
|
|
147
|
+
return ts.isIdentifier(el);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.isBlacklistNode = isBlacklistNode;
|
|
157
|
+
//# sourceMappingURL=vue-autoinsert-dotvalue.js.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const embedded = require("@volar/language-core");
|
|
4
|
+
const language_core_1 = require("@vue/language-core");
|
|
5
|
+
const vscode = require("vscode-languageserver-protocol");
|
|
6
|
+
const vue_autoinsert_dotvalue_1 = require("./vue-autoinsert-dotvalue");
|
|
7
|
+
const plugin = (context, modules) => {
|
|
8
|
+
if (!context) {
|
|
9
|
+
return {};
|
|
10
|
+
}
|
|
11
|
+
if (!modules?.typescript) {
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
const ts = modules.typescript;
|
|
15
|
+
return {
|
|
16
|
+
async provideAutoInsertionEdit(document, position, options_2) {
|
|
17
|
+
const enabled = await context.env.getConfiguration?.('vue.autoInsert.parentheses') ?? false;
|
|
18
|
+
if (!enabled)
|
|
19
|
+
return;
|
|
20
|
+
if (!(0, vue_autoinsert_dotvalue_1.isCharacterTyping)(document, options_2))
|
|
21
|
+
return;
|
|
22
|
+
const [vueFile] = context.documents.getVirtualFileByUri(document.uri);
|
|
23
|
+
if (!(vueFile instanceof language_core_1.VueFile))
|
|
24
|
+
return;
|
|
25
|
+
let templateFormatScript;
|
|
26
|
+
embedded.forEachEmbeddedFile(vueFile, embedded => {
|
|
27
|
+
if (embedded.fileName.endsWith('.template_format.ts')) {
|
|
28
|
+
templateFormatScript = embedded;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
if (!templateFormatScript)
|
|
32
|
+
return;
|
|
33
|
+
const offset = document.offsetAt(position);
|
|
34
|
+
for (const mappedRange of templateFormatScript.mappings) {
|
|
35
|
+
if (mappedRange.sourceRange[1] === offset) {
|
|
36
|
+
const text = document.getText().substring(mappedRange.sourceRange[0], mappedRange.sourceRange[1]);
|
|
37
|
+
const ast = ts.createSourceFile(templateFormatScript.fileName, text, ts.ScriptTarget.Latest);
|
|
38
|
+
if (ast.statements.length === 1) {
|
|
39
|
+
const statement = ast.statements[0];
|
|
40
|
+
if (ts.isExpressionStatement(statement)
|
|
41
|
+
&& ((ts.isAsExpression(statement.expression)
|
|
42
|
+
&& ts.isTypeReferenceNode(statement.expression.type)
|
|
43
|
+
&& ts.isIdentifier(statement.expression.type.typeName)
|
|
44
|
+
&& statement.expression.type.typeName.text)
|
|
45
|
+
|| (ts.isBinaryExpression(statement.expression)
|
|
46
|
+
&& statement.expression.right.getText(ast)
|
|
47
|
+
&& statement.expression.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword)
|
|
48
|
+
|| (ts.isTypeOfExpression(statement.expression)
|
|
49
|
+
&& statement.expression.expression.getText(ast)))) {
|
|
50
|
+
// https://code.visualstudio.com/docs/editor/userdefinedsnippets#_grammar
|
|
51
|
+
const escapedText = text
|
|
52
|
+
.replaceAll('\\', '\\\\')
|
|
53
|
+
.replaceAll('$', '\\$')
|
|
54
|
+
.replaceAll('}', '\\}');
|
|
55
|
+
return vscode.TextEdit.replace({
|
|
56
|
+
start: document.positionAt(mappedRange.sourceRange[0]),
|
|
57
|
+
end: document.positionAt(mappedRange.sourceRange[1]),
|
|
58
|
+
}, '(' + escapedText + '$0' + ')');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
exports.default = () => plugin;
|
|
67
|
+
//# sourceMappingURL=vue-autoinsert-parentheses.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const plugin = (context) => {
|
|
4
|
+
if (!context)
|
|
5
|
+
return {};
|
|
6
|
+
return {
|
|
7
|
+
async provideAutoInsertionEdit(document, _, { lastChange }) {
|
|
8
|
+
if (document.languageId === 'html' || document.languageId === 'jade') {
|
|
9
|
+
const enabled = await context.env.getConfiguration?.('vue.autoInsert.bracketSpacing') ?? true;
|
|
10
|
+
if (!enabled)
|
|
11
|
+
return;
|
|
12
|
+
if (lastChange.text === '{}'
|
|
13
|
+
&& document.getText({
|
|
14
|
+
start: { line: lastChange.range.start.line, character: lastChange.range.start.character - 1 },
|
|
15
|
+
end: { line: lastChange.range.start.line, character: lastChange.range.start.character + 3 }
|
|
16
|
+
}) === '{{}}') {
|
|
17
|
+
return {
|
|
18
|
+
newText: ` $0 `,
|
|
19
|
+
range: {
|
|
20
|
+
start: { line: lastChange.range.start.line, character: lastChange.range.start.character + 1 },
|
|
21
|
+
end: { line: lastChange.range.start.line, character: lastChange.range.start.character + 1 }
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
exports.default = () => plugin;
|
|
30
|
+
//# sourceMappingURL=vue-autoinsert-space.js.map
|