@vue/language-service 1.9.0-alpha.3 → 2.0.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/data/template/en.json +2 -2
- package/data/template/fr.json +1 -1
- package/data/template/ja.json +2 -2
- package/data/template/ko.json +13 -13
- package/data/template/pt.json +18 -18
- package/data/template/zh-cn.json +2 -2
- package/index.d.ts +7 -0
- package/index.js +64 -0
- package/lib/ideFeatures/nameCasing.d.ts +13 -0
- package/{out → lib}/ideFeatures/nameCasing.js +82 -29
- package/lib/plugins/css.d.ts +2 -0
- package/lib/plugins/css.js +27 -0
- package/{out → lib}/plugins/data.d.ts +1 -2
- package/lib/plugins/vue-autoinsert-dotvalue.d.ts +10 -0
- package/{out → lib}/plugins/vue-autoinsert-dotvalue.js +70 -54
- package/lib/plugins/vue-autoinsert-parentheses.d.ts +2 -0
- package/lib/plugins/vue-autoinsert-parentheses.js +60 -0
- package/lib/plugins/vue-autoinsert-space.d.ts +2 -0
- package/lib/plugins/vue-autoinsert-space.js +34 -0
- package/lib/plugins/vue-codelens-references.d.ts +2 -0
- package/lib/plugins/vue-codelens-references.js +38 -0
- package/lib/plugins/vue-directive-comments.d.ts +2 -0
- package/lib/plugins/vue-directive-comments.js +61 -0
- package/lib/plugins/vue-document-drop.d.ts +2 -0
- package/lib/plugins/vue-document-drop.js +81 -0
- package/lib/plugins/vue-extract-file.d.ts +8 -0
- package/lib/plugins/vue-extract-file.js +258 -0
- package/lib/plugins/vue-sfc.d.ts +7 -0
- package/lib/plugins/vue-sfc.js +163 -0
- package/lib/plugins/vue-template.d.ts +3 -0
- package/lib/plugins/vue-template.js +594 -0
- package/lib/plugins/vue-toggle-v-bind-codeaction.d.ts +2 -0
- package/lib/plugins/vue-toggle-v-bind-codeaction.js +126 -0
- package/lib/plugins/vue-twoslash-queries.d.ts +2 -0
- package/lib/plugins/vue-twoslash-queries.js +50 -0
- package/lib/plugins/vue-visualize-hidden-callback-param.d.ts +2 -0
- package/lib/plugins/vue-visualize-hidden-callback-param.js +45 -0
- package/{out → lib}/types.d.ts +1 -2
- package/{out → lib}/types.js +1 -1
- package/package.json +20 -20
- package/scripts/update-html-data.js +426 -0
- package/out/helpers.d.ts +0 -17
- package/out/helpers.js +0 -235
- package/out/ideFeatures/dragImport.d.ts +0 -9
- package/out/ideFeatures/dragImport.js +0 -50
- package/out/ideFeatures/nameCasing.d.ts +0 -16
- package/out/index.d.ts +0 -8
- package/out/index.js +0 -26
- package/out/languageService.d.ts +0 -9
- package/out/languageService.js +0 -239
- package/out/plugins/vue-autoinsert-dotvalue.d.ts +0 -7
- package/out/plugins/vue-autoinsert-parentheses.d.ts +0 -3
- package/out/plugins/vue-autoinsert-parentheses.js +0 -61
- package/out/plugins/vue-autoinsert-space.d.ts +0 -3
- package/out/plugins/vue-autoinsert-space.js +0 -32
- package/out/plugins/vue-codelens-references.d.ts +0 -3
- package/out/plugins/vue-codelens-references.js +0 -54
- package/out/plugins/vue-directive-comments.d.ts +0 -3
- package/out/plugins/vue-directive-comments.js +0 -57
- package/out/plugins/vue-extract-file.d.ts +0 -9
- package/out/plugins/vue-extract-file.js +0 -293
- package/out/plugins/vue-template.d.ts +0 -12
- package/out/plugins/vue-template.js +0 -548
- package/out/plugins/vue-toggle-v-bind-codeaction.d.ts +0 -3
- package/out/plugins/vue-toggle-v-bind-codeaction.js +0 -126
- package/out/plugins/vue-twoslash-queries.d.ts +0 -3
- package/out/plugins/vue-twoslash-queries.js +0 -60
- package/out/plugins/vue-visualize-hidden-callback-param.d.ts +0 -3
- package/out/plugins/vue-visualize-hidden-callback-param.js +0 -43
- package/out/plugins/vue.d.ts +0 -8
- package/out/plugins/vue.js +0 -169
- /package/{out → lib}/plugins/data.js +0 -0
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createAddComponentToOptionEdit = exports.getLastImportNode = exports.create = void 0;
|
|
4
|
-
const language_core_1 = require("@vue/language-core");
|
|
5
|
-
const unicodeReg = /\\u/g;
|
|
6
|
-
const create = function () {
|
|
7
|
-
return (ctx, modules) => {
|
|
8
|
-
if (!modules?.typescript)
|
|
9
|
-
return {};
|
|
10
|
-
const ts = modules.typescript;
|
|
11
|
-
return {
|
|
12
|
-
async provideCodeActions(document, range, _context) {
|
|
13
|
-
const startOffset = document.offsetAt(range.start);
|
|
14
|
-
const endOffset = document.offsetAt(range.end);
|
|
15
|
-
if (startOffset === endOffset) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
const [vueFile] = ctx.documents.getVirtualFileByUri(document.uri);
|
|
19
|
-
if (!vueFile || !(vueFile instanceof language_core_1.VueFile))
|
|
20
|
-
return;
|
|
21
|
-
const { sfc } = vueFile;
|
|
22
|
-
const script = sfc.scriptSetup ?? sfc.script;
|
|
23
|
-
if (!sfc.template || !script)
|
|
24
|
-
return;
|
|
25
|
-
const templateCodeRange = selectTemplateCode(startOffset, endOffset, sfc.template);
|
|
26
|
-
if (!templateCodeRange)
|
|
27
|
-
return;
|
|
28
|
-
return [
|
|
29
|
-
{
|
|
30
|
-
title: 'Extract into new dumb component',
|
|
31
|
-
kind: 'refactor.move.newFile.dumb',
|
|
32
|
-
data: {
|
|
33
|
-
uri: document.uri,
|
|
34
|
-
range: [startOffset, endOffset],
|
|
35
|
-
newName: 'NewComponent',
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
];
|
|
39
|
-
},
|
|
40
|
-
async resolveCodeAction(codeAction) {
|
|
41
|
-
const { uri, range, newName } = codeAction.data;
|
|
42
|
-
const document = ctx.getTextDocument(uri);
|
|
43
|
-
const [startOffset, endOffset] = range;
|
|
44
|
-
const [vueFile] = ctx.documents.getVirtualFileByUri(document.uri);
|
|
45
|
-
const { sfc } = vueFile;
|
|
46
|
-
const script = sfc.scriptSetup ?? sfc.script;
|
|
47
|
-
if (!sfc.template || !script)
|
|
48
|
-
return codeAction;
|
|
49
|
-
const templateCodeRange = selectTemplateCode(startOffset, endOffset, sfc.template);
|
|
50
|
-
if (!templateCodeRange)
|
|
51
|
-
return codeAction;
|
|
52
|
-
const languageService = ctx.inject('typescript/languageService');
|
|
53
|
-
const languageServiceHost = ctx.inject('typescript/languageServiceHost');
|
|
54
|
-
const sourceFile = languageService.getProgram().getSourceFile(vueFile.mainScriptName);
|
|
55
|
-
const sourceFileKind = languageServiceHost.getScriptKind?.(vueFile.mainScriptName);
|
|
56
|
-
const toExtract = collectExtractProps();
|
|
57
|
-
const initialIndentSetting = await ctx.env.getConfiguration('volar.format.initialIndent');
|
|
58
|
-
const newUri = document.uri.substring(0, document.uri.lastIndexOf('/') + 1) + `${newName}.vue`;
|
|
59
|
-
const lastImportNode = getLastImportNode(ts, script.ast);
|
|
60
|
-
let newFileTags = [];
|
|
61
|
-
newFileTags.push(constructTag('template', [], initialIndentSetting.html, sfc.template.content.substring(templateCodeRange[0], templateCodeRange[1])));
|
|
62
|
-
if (toExtract.length) {
|
|
63
|
-
newFileTags.push(constructTag('script', ['setup', 'lang="ts"'], isInitialIndentNeeded(ts, sourceFileKind, initialIndentSetting), generateNewScriptContents()));
|
|
64
|
-
}
|
|
65
|
-
if (sfc.template.startTagEnd > script.startTagEnd) {
|
|
66
|
-
newFileTags = newFileTags.reverse();
|
|
67
|
-
}
|
|
68
|
-
const currentFileEdits = [
|
|
69
|
-
{
|
|
70
|
-
range: {
|
|
71
|
-
start: document.positionAt(sfc.template.startTagEnd + templateCodeRange[0]),
|
|
72
|
-
end: document.positionAt(sfc.template.startTagEnd + templateCodeRange[1]),
|
|
73
|
-
},
|
|
74
|
-
newText: generateReplaceTemplate(),
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
range: lastImportNode ? {
|
|
78
|
-
start: document.positionAt(script.startTagEnd + lastImportNode.end),
|
|
79
|
-
end: document.positionAt(script.startTagEnd + lastImportNode.end),
|
|
80
|
-
} : {
|
|
81
|
-
start: document.positionAt(script.startTagEnd),
|
|
82
|
-
end: document.positionAt(script.startTagEnd),
|
|
83
|
-
},
|
|
84
|
-
newText: `\nimport ${newName} from './${newName}.vue'`,
|
|
85
|
-
},
|
|
86
|
-
];
|
|
87
|
-
if (sfc.script) {
|
|
88
|
-
const edit = createAddComponentToOptionEdit(ts, sfc.script.ast, newName);
|
|
89
|
-
if (edit) {
|
|
90
|
-
currentFileEdits.push({
|
|
91
|
-
range: {
|
|
92
|
-
start: document.positionAt(sfc.script.startTagEnd + edit.range.start),
|
|
93
|
-
end: document.positionAt(sfc.script.startTagEnd + edit.range.end),
|
|
94
|
-
},
|
|
95
|
-
newText: edit.newText,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
...codeAction,
|
|
101
|
-
edit: {
|
|
102
|
-
documentChanges: [
|
|
103
|
-
// editing current file
|
|
104
|
-
{
|
|
105
|
-
textDocument: {
|
|
106
|
-
uri: document.uri,
|
|
107
|
-
version: null,
|
|
108
|
-
},
|
|
109
|
-
edits: currentFileEdits,
|
|
110
|
-
},
|
|
111
|
-
// creating new file with content
|
|
112
|
-
{
|
|
113
|
-
uri: newUri,
|
|
114
|
-
kind: 'create',
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
textDocument: {
|
|
118
|
-
uri: newUri,
|
|
119
|
-
version: null,
|
|
120
|
-
},
|
|
121
|
-
edits: [
|
|
122
|
-
{
|
|
123
|
-
range: {
|
|
124
|
-
start: { line: 0, character: 0 },
|
|
125
|
-
end: { line: 0, character: 0 },
|
|
126
|
-
},
|
|
127
|
-
newText: newFileTags.join('\n'),
|
|
128
|
-
},
|
|
129
|
-
],
|
|
130
|
-
},
|
|
131
|
-
],
|
|
132
|
-
},
|
|
133
|
-
};
|
|
134
|
-
function collectExtractProps() {
|
|
135
|
-
const result = new Map();
|
|
136
|
-
const checker = languageService.getProgram().getTypeChecker();
|
|
137
|
-
const maps = [...ctx.documents.getMapsByVirtualFileName(vueFile.mainScriptName)];
|
|
138
|
-
sourceFile.forEachChild(function visit(node) {
|
|
139
|
-
if (ts.isPropertyAccessExpression(node)
|
|
140
|
-
&& ts.isIdentifier(node.expression)
|
|
141
|
-
&& node.expression.text === '__VLS_ctx'
|
|
142
|
-
&& ts.isIdentifier(node.name)) {
|
|
143
|
-
const { name } = node;
|
|
144
|
-
for (const [_, map] of maps) {
|
|
145
|
-
const source = map.map.toSourceOffset(name.getEnd());
|
|
146
|
-
if (source && source[0] >= sfc.template.startTagEnd + templateCodeRange[0] && source[0] <= sfc.template.startTagEnd + templateCodeRange[1] && source[1].data.semanticTokens) {
|
|
147
|
-
if (!result.has(name.text)) {
|
|
148
|
-
const type = checker.getTypeAtLocation(node);
|
|
149
|
-
const typeString = checker.typeToString(type, node, ts.TypeFormatFlags.NoTruncation);
|
|
150
|
-
result.set(name.text, {
|
|
151
|
-
name: name.text,
|
|
152
|
-
type: typeString.includes('__VLS_') ? 'any' : typeString,
|
|
153
|
-
model: false,
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
const isModel = ts.isPostfixUnaryExpression(node.parent) || ts.isBinaryExpression(node.parent);
|
|
157
|
-
if (isModel) {
|
|
158
|
-
result.get(name.text).model = true;
|
|
159
|
-
}
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
node.forEachChild(visit);
|
|
165
|
-
});
|
|
166
|
-
return [...result.values()];
|
|
167
|
-
}
|
|
168
|
-
function generateNewScriptContents() {
|
|
169
|
-
const lines = [];
|
|
170
|
-
const props = [...toExtract.values()].filter(p => !p.model);
|
|
171
|
-
const models = [...toExtract.values()].filter(p => p.model);
|
|
172
|
-
if (props.length) {
|
|
173
|
-
lines.push(`defineProps<{ \n\t${props.map(p => `${p.name}: ${p.type};`).join('\n\t')}\n}>()`);
|
|
174
|
-
}
|
|
175
|
-
for (const model of models) {
|
|
176
|
-
lines.push(`const ${model.name} = defineModel<${model.type}>('${model.name}', { required: true })`);
|
|
177
|
-
}
|
|
178
|
-
return lines.join('\n');
|
|
179
|
-
}
|
|
180
|
-
function generateReplaceTemplate() {
|
|
181
|
-
const props = [...toExtract.values()].filter(p => !p.model);
|
|
182
|
-
const models = [...toExtract.values()].filter(p => p.model);
|
|
183
|
-
return [
|
|
184
|
-
`<${newName}`,
|
|
185
|
-
...props.map(p => `:${p.name}="${p.name}"`),
|
|
186
|
-
...models.map(p => `v-model:${p.name}="${p.name}"`),
|
|
187
|
-
`/>`,
|
|
188
|
-
].join(' ');
|
|
189
|
-
}
|
|
190
|
-
},
|
|
191
|
-
transformCodeAction(item) {
|
|
192
|
-
return item; // ignore mapping
|
|
193
|
-
},
|
|
194
|
-
};
|
|
195
|
-
};
|
|
196
|
-
};
|
|
197
|
-
exports.create = create;
|
|
198
|
-
function selectTemplateCode(startOffset, endOffset, templateBlock) {
|
|
199
|
-
if (startOffset < templateBlock.startTagEnd || endOffset > templateBlock.endTagStart)
|
|
200
|
-
return;
|
|
201
|
-
const insideNodes = [];
|
|
202
|
-
templateBlock.ast?.children.forEach(function visit(node) {
|
|
203
|
-
if (node.loc.start.offset + templateBlock.startTagEnd >= startOffset
|
|
204
|
-
&& node.loc.end.offset + templateBlock.startTagEnd <= endOffset) {
|
|
205
|
-
insideNodes.push(node);
|
|
206
|
-
}
|
|
207
|
-
if ('children' in node) {
|
|
208
|
-
node.children.forEach(node => {
|
|
209
|
-
if (typeof node === 'object') {
|
|
210
|
-
visit(node);
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
else if ('branches' in node) {
|
|
215
|
-
node.branches.forEach(visit);
|
|
216
|
-
}
|
|
217
|
-
else if ('content' in node) {
|
|
218
|
-
if (typeof node.content === 'object') {
|
|
219
|
-
visit(node.content);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
if (insideNodes.length) {
|
|
224
|
-
const first = insideNodes.sort((a, b) => a.loc.start.offset - b.loc.start.offset)[0];
|
|
225
|
-
const last = insideNodes.sort((a, b) => b.loc.end.offset - a.loc.end.offset)[0];
|
|
226
|
-
return [first.loc.start.offset, last.loc.end.offset];
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
function constructTag(name, attributes, initialIndent, content) {
|
|
230
|
-
if (initialIndent)
|
|
231
|
-
content = content.split('\n').map(line => `\t${line}`).join('\n');
|
|
232
|
-
const attributesString = attributes.length ? ` ${attributes.join(' ')}` : '';
|
|
233
|
-
return `<${name}${attributesString}>\n${content}\n</${name}>\n`;
|
|
234
|
-
}
|
|
235
|
-
function isInitialIndentNeeded(ts, languageKind, initialIndentSetting) {
|
|
236
|
-
const languageKindIdMap = {
|
|
237
|
-
[ts.ScriptKind.JS]: 'javascript',
|
|
238
|
-
[ts.ScriptKind.TS]: 'typescript',
|
|
239
|
-
[ts.ScriptKind.JSX]: 'javascriptreact',
|
|
240
|
-
[ts.ScriptKind.TSX]: 'typescriptreact',
|
|
241
|
-
};
|
|
242
|
-
return initialIndentSetting[languageKindIdMap[languageKind]] ?? false;
|
|
243
|
-
}
|
|
244
|
-
function getLastImportNode(ts, sourceFile) {
|
|
245
|
-
let lastImportNode;
|
|
246
|
-
for (const statement of sourceFile.statements) {
|
|
247
|
-
if (ts.isImportDeclaration(statement)) {
|
|
248
|
-
lastImportNode = statement;
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
break;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
return lastImportNode;
|
|
255
|
-
}
|
|
256
|
-
exports.getLastImportNode = getLastImportNode;
|
|
257
|
-
function createAddComponentToOptionEdit(ts, ast, componentName) {
|
|
258
|
-
const exportDefault = language_core_1.scriptRanges.parseScriptRanges(ts, ast, false, true).exportDefault;
|
|
259
|
-
if (!exportDefault)
|
|
260
|
-
return;
|
|
261
|
-
// https://github.com/microsoft/TypeScript/issues/36174
|
|
262
|
-
const printer = ts.createPrinter();
|
|
263
|
-
if (exportDefault.componentsOption && exportDefault.componentsOptionNode) {
|
|
264
|
-
const newNode = {
|
|
265
|
-
...exportDefault.componentsOptionNode,
|
|
266
|
-
properties: [
|
|
267
|
-
...exportDefault.componentsOptionNode.properties,
|
|
268
|
-
ts.factory.createShorthandPropertyAssignment(componentName),
|
|
269
|
-
],
|
|
270
|
-
};
|
|
271
|
-
const printText = printer.printNode(ts.EmitHint.Expression, newNode, ast);
|
|
272
|
-
return {
|
|
273
|
-
range: exportDefault.componentsOption,
|
|
274
|
-
newText: unescape(printText.replace(unicodeReg, '%u')),
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
else if (exportDefault.args && exportDefault.argsNode) {
|
|
278
|
-
const newNode = {
|
|
279
|
-
...exportDefault.argsNode,
|
|
280
|
-
properties: [
|
|
281
|
-
...exportDefault.argsNode.properties,
|
|
282
|
-
ts.factory.createShorthandPropertyAssignment(`components: { ${componentName} }`),
|
|
283
|
-
],
|
|
284
|
-
};
|
|
285
|
-
const printText = printer.printNode(ts.EmitHint.Expression, newNode, ast);
|
|
286
|
-
return {
|
|
287
|
-
range: exportDefault.args,
|
|
288
|
-
newText: unescape(printText.replace(unicodeReg, '%u')),
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
exports.createAddComponentToOptionEdit = createAddComponentToOptionEdit;
|
|
293
|
-
//# sourceMappingURL=vue-extract-file.js.map
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Service } from '@volar/language-service';
|
|
2
|
-
import * as html from 'vscode-html-languageservice';
|
|
3
|
-
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
4
|
-
import { VueCompilerOptions } from '../types';
|
|
5
|
-
export declare const create: <S extends Service>(options: {
|
|
6
|
-
getScanner(service: ReturnType<S>, document: TextDocument): html.Scanner | undefined;
|
|
7
|
-
updateCustomData(service: ReturnType<S>, extraData: html.IHTMLDataProvider[]): void;
|
|
8
|
-
baseService: S;
|
|
9
|
-
isSupportedDocument: (document: TextDocument) => boolean;
|
|
10
|
-
vueCompilerOptions: VueCompilerOptions;
|
|
11
|
-
}) => Service;
|
|
12
|
-
//# sourceMappingURL=vue-template.d.ts.map
|