@volar/typescript 2.2.0-alpha.0 → 2.2.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/documentRegistry.d.ts +2 -0
- package/lib/documentRegistry.js +14 -0
- package/lib/node/decorateLanguageService.js +181 -122
- package/lib/node/decorateLanguageServiceHost.d.ts +2 -2
- package/lib/node/decorateLanguageServiceHost.js +21 -22
- package/lib/node/proxyCreateProgram.d.ts +1 -1
- package/lib/node/proxyCreateProgram.js +8 -4
- package/lib/node/transform.d.ts +11 -6
- package/lib/node/transform.js +76 -42
- package/lib/quickstart/createAsyncLanguageServicePlugin.d.ts +1 -1
- package/lib/quickstart/createAsyncLanguageServicePlugin.js +3 -3
- package/lib/quickstart/createLanguageServicePlugin.d.ts +1 -1
- package/lib/quickstart/createLanguageServicePlugin.js +3 -3
- package/lib/quickstart/runTsc.d.ts +2 -1
- package/lib/quickstart/runTsc.js +11 -6
- package/package.json +4 -4
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDocumentRegistry = void 0;
|
|
4
|
+
const documentRegistries = [];
|
|
5
|
+
function getDocumentRegistry(ts, useCaseSensitiveFileNames, currentDirectory) {
|
|
6
|
+
let documentRegistry = documentRegistries.find(item => item[0] === useCaseSensitiveFileNames && item[1] === currentDirectory)?.[2];
|
|
7
|
+
if (!documentRegistry) {
|
|
8
|
+
documentRegistry = ts.createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory);
|
|
9
|
+
documentRegistries.push([useCaseSensitiveFileNames, currentDirectory, documentRegistry]);
|
|
10
|
+
}
|
|
11
|
+
return documentRegistry;
|
|
12
|
+
}
|
|
13
|
+
exports.getDocumentRegistry = getDocumentRegistry;
|
|
14
|
+
//# sourceMappingURL=documentRegistry.js.map
|
|
@@ -29,19 +29,92 @@ function decorateLanguageService(language, languageService) {
|
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
31
|
// methods
|
|
32
|
-
const { findReferences, findRenameLocations, getCompletionEntryDetails, getCompletionsAtPosition, getDefinitionAndBoundSpan, getDefinitionAtPosition, getFileReferences, getImplementationAtPosition, getQuickInfoAtPosition, getReferencesAtPosition, getSemanticDiagnostics, getSyntacticDiagnostics, getSuggestionDiagnostics, getTypeDefinitionAtPosition, getEncodedSemanticClassifications, getDocumentHighlights, getApplicableRefactors, getEditsForRefactor, getRenameInfo, getCodeFixesAtPosition, prepareCallHierarchy, provideCallHierarchyIncomingCalls, provideCallHierarchyOutgoingCalls, provideInlayHints, organizeImports, } = languageService;
|
|
32
|
+
const { findReferences, findRenameLocations, getCompletionEntryDetails, getCompletionsAtPosition, getDefinitionAndBoundSpan, getDefinitionAtPosition, getFileReferences, getFormattingEditsForDocument, getFormattingEditsForRange, getFormattingEditsAfterKeystroke, getImplementationAtPosition, getLinkedEditingRangeAtPosition, getQuickInfoAtPosition, getReferencesAtPosition, getSemanticDiagnostics, getSyntacticDiagnostics, getSuggestionDiagnostics, getTypeDefinitionAtPosition, getEncodedSemanticClassifications, getDocumentHighlights, getApplicableRefactors, getEditsForFileRename, getEditsForRefactor, getRenameInfo, getCodeFixesAtPosition, prepareCallHierarchy, provideCallHierarchyIncomingCalls, provideCallHierarchyOutgoingCalls, provideInlayHints, organizeImports, } = languageService;
|
|
33
|
+
languageService.getFormattingEditsForDocument = (fileName, options) => {
|
|
34
|
+
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
35
|
+
if (serviceScript) {
|
|
36
|
+
if (!map.mappings.some(mapping => (0, language_core_1.isFormattingEnabled)(mapping.data))) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
const edits = getFormattingEditsForDocument(fileName, options);
|
|
40
|
+
return edits
|
|
41
|
+
.map(edit => (0, transform_1.transformTextChange)(sourceScript, map, edit, language_core_1.isFormattingEnabled))
|
|
42
|
+
.filter(utils_1.notEmpty);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return getFormattingEditsForDocument(fileName, options);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
languageService.getFormattingEditsForRange = (fileName, start, end, options) => {
|
|
49
|
+
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
50
|
+
if (serviceScript) {
|
|
51
|
+
const generateStart = (0, transform_1.toGeneratedOffset)(sourceScript, map, start, language_core_1.isFormattingEnabled);
|
|
52
|
+
const generateEnd = (0, transform_1.toGeneratedOffset)(sourceScript, map, end, language_core_1.isFormattingEnabled);
|
|
53
|
+
if (generateStart !== undefined && generateEnd !== undefined) {
|
|
54
|
+
const edits = getFormattingEditsForRange(fileName, generateStart, generateEnd, options);
|
|
55
|
+
return edits
|
|
56
|
+
.map(edit => (0, transform_1.transformTextChange)(sourceScript, map, edit, language_core_1.isFormattingEnabled))
|
|
57
|
+
.filter(utils_1.notEmpty);
|
|
58
|
+
}
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
return getFormattingEditsForRange(fileName, start, end, options);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
languageService.getFormattingEditsAfterKeystroke = (fileName, position, key, options) => {
|
|
66
|
+
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
67
|
+
if (serviceScript) {
|
|
68
|
+
const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isFormattingEnabled);
|
|
69
|
+
if (generatePosition !== undefined) {
|
|
70
|
+
const edits = getFormattingEditsAfterKeystroke(fileName, generatePosition, key, options);
|
|
71
|
+
return edits
|
|
72
|
+
.map(edit => (0, transform_1.transformTextChange)(sourceScript, map, edit, language_core_1.isFormattingEnabled))
|
|
73
|
+
.filter(utils_1.notEmpty);
|
|
74
|
+
}
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return getFormattingEditsAfterKeystroke(fileName, position, key, options);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
languageService.getEditsForFileRename = (oldFilePath, newFilePath, formatOptions, preferences) => {
|
|
82
|
+
const edits = getEditsForFileRename(oldFilePath, newFilePath, formatOptions, preferences);
|
|
83
|
+
return edits
|
|
84
|
+
.map(edit => (0, transform_1.transformFileTextChanges)(language, edit, language_core_1.isRenameEnabled))
|
|
85
|
+
.filter(utils_1.notEmpty);
|
|
86
|
+
};
|
|
87
|
+
languageService.getLinkedEditingRangeAtPosition = (fileName, position) => {
|
|
88
|
+
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
89
|
+
if (serviceScript) {
|
|
90
|
+
const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isLinkedEditingEnabled);
|
|
91
|
+
if (generatePosition !== undefined) {
|
|
92
|
+
const info = getLinkedEditingRangeAtPosition(fileName, generatePosition);
|
|
93
|
+
if (info) {
|
|
94
|
+
return {
|
|
95
|
+
ranges: info.ranges
|
|
96
|
+
.map(span => (0, transform_1.transformTextSpan)(sourceScript, map, span, language_core_1.isLinkedEditingEnabled))
|
|
97
|
+
.filter(utils_1.notEmpty),
|
|
98
|
+
wordPattern: info.wordPattern,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
return getLinkedEditingRangeAtPosition(fileName, position);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
33
107
|
languageService.prepareCallHierarchy = (fileName, position) => {
|
|
34
108
|
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
35
109
|
if (serviceScript) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
110
|
+
const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isCallHierarchyEnabled);
|
|
111
|
+
if (generatePosition !== undefined) {
|
|
112
|
+
const item = prepareCallHierarchy(fileName, generatePosition);
|
|
113
|
+
if (Array.isArray(item)) {
|
|
114
|
+
return item.map(item => (0, transform_1.transformCallHierarchyItem)(language, item, language_core_1.isCallHierarchyEnabled));
|
|
115
|
+
}
|
|
116
|
+
else if (item) {
|
|
117
|
+
return (0, transform_1.transformCallHierarchyItem)(language, item, language_core_1.isCallHierarchyEnabled);
|
|
45
118
|
}
|
|
46
119
|
}
|
|
47
120
|
}
|
|
@@ -53,10 +126,9 @@ function decorateLanguageService(language, languageService) {
|
|
|
53
126
|
let calls = [];
|
|
54
127
|
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
55
128
|
if (serviceScript) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
129
|
+
const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isCallHierarchyEnabled);
|
|
130
|
+
if (generatePosition !== undefined) {
|
|
131
|
+
calls = provideCallHierarchyIncomingCalls(fileName, generatePosition);
|
|
60
132
|
}
|
|
61
133
|
}
|
|
62
134
|
else {
|
|
@@ -78,10 +150,9 @@ function decorateLanguageService(language, languageService) {
|
|
|
78
150
|
let calls = [];
|
|
79
151
|
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
80
152
|
if (serviceScript) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
153
|
+
const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isCallHierarchyEnabled);
|
|
154
|
+
if (generatePosition !== undefined) {
|
|
155
|
+
calls = provideCallHierarchyOutgoingCalls(fileName, generatePosition);
|
|
85
156
|
}
|
|
86
157
|
}
|
|
87
158
|
else {
|
|
@@ -91,7 +162,9 @@ function decorateLanguageService(language, languageService) {
|
|
|
91
162
|
.map(call => {
|
|
92
163
|
const to = (0, transform_1.transformCallHierarchyItem)(language, call.to, language_core_1.isCallHierarchyEnabled);
|
|
93
164
|
const fromSpans = call.fromSpans
|
|
94
|
-
.map(span =>
|
|
165
|
+
.map(span => sourceScript
|
|
166
|
+
? (0, transform_1.transformTextSpan)(sourceScript, map, span, language_core_1.isCallHierarchyEnabled)
|
|
167
|
+
: span)
|
|
95
168
|
.filter(utils_1.notEmpty);
|
|
96
169
|
return {
|
|
97
170
|
to,
|
|
@@ -109,17 +182,16 @@ function decorateLanguageService(language, languageService) {
|
|
|
109
182
|
languageService.getQuickInfoAtPosition = (fileName, position) => {
|
|
110
183
|
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
111
184
|
if (serviceScript) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
185
|
+
const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isHoverEnabled);
|
|
186
|
+
if (generatePosition !== undefined) {
|
|
187
|
+
const result = getQuickInfoAtPosition(fileName, generatePosition);
|
|
188
|
+
if (result) {
|
|
189
|
+
const textSpan = (0, transform_1.transformTextSpan)(sourceScript, map, result.textSpan, language_core_1.isHoverEnabled);
|
|
190
|
+
if (textSpan) {
|
|
191
|
+
return {
|
|
192
|
+
...result,
|
|
193
|
+
textSpan,
|
|
194
|
+
};
|
|
123
195
|
}
|
|
124
196
|
}
|
|
125
197
|
}
|
|
@@ -160,16 +232,15 @@ function decorateLanguageService(language, languageService) {
|
|
|
160
232
|
languageService.getApplicableRefactors = (fileName, positionOrRange, preferences, triggerReason, kind, includeInteractiveActions) => {
|
|
161
233
|
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
162
234
|
if (serviceScript) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
235
|
+
const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos, language_core_1.isCodeActionsEnabled);
|
|
236
|
+
if (generatePosition !== undefined) {
|
|
237
|
+
const por = typeof positionOrRange === 'number'
|
|
238
|
+
? generatePosition
|
|
239
|
+
: {
|
|
240
|
+
pos: generatePosition,
|
|
241
|
+
end: generatePosition + positionOrRange.end - positionOrRange.pos,
|
|
242
|
+
};
|
|
243
|
+
return getApplicableRefactors(fileName, por, preferences, triggerReason, kind, includeInteractiveActions);
|
|
173
244
|
}
|
|
174
245
|
return [];
|
|
175
246
|
}
|
|
@@ -181,16 +252,17 @@ function decorateLanguageService(language, languageService) {
|
|
|
181
252
|
let edits;
|
|
182
253
|
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
183
254
|
if (serviceScript) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
255
|
+
const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, typeof positionOrRange === 'number'
|
|
256
|
+
? positionOrRange
|
|
257
|
+
: positionOrRange.pos, language_core_1.isCodeActionsEnabled);
|
|
258
|
+
if (generatePosition !== undefined) {
|
|
259
|
+
const por = typeof positionOrRange === 'number'
|
|
260
|
+
? generatePosition
|
|
261
|
+
: {
|
|
262
|
+
pos: generatePosition,
|
|
263
|
+
end: generatePosition + positionOrRange.end - positionOrRange.pos,
|
|
264
|
+
};
|
|
265
|
+
edits = getEditsForRefactor(fileName, formatOptions, por, refactorName, actionName, preferences);
|
|
194
266
|
}
|
|
195
267
|
}
|
|
196
268
|
else {
|
|
@@ -206,20 +278,19 @@ function decorateLanguageService(language, languageService) {
|
|
|
206
278
|
languageService.getRenameInfo = (fileName, position, options) => {
|
|
207
279
|
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
208
280
|
if (serviceScript) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return info;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
281
|
+
const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isRenameEnabled);
|
|
282
|
+
if (generatePosition !== undefined) {
|
|
283
|
+
const info = getRenameInfo(fileName, generatePosition, options);
|
|
284
|
+
if (info.canRename) {
|
|
285
|
+
const span = (0, transform_1.transformTextSpan)(sourceScript, map, info.triggerSpan, language_core_1.isRenameEnabled);
|
|
286
|
+
if (span) {
|
|
287
|
+
info.triggerSpan = span;
|
|
220
288
|
return info;
|
|
221
289
|
}
|
|
222
290
|
}
|
|
291
|
+
else {
|
|
292
|
+
return info;
|
|
293
|
+
}
|
|
223
294
|
}
|
|
224
295
|
return {
|
|
225
296
|
canRename: false,
|
|
@@ -234,16 +305,10 @@ function decorateLanguageService(language, languageService) {
|
|
|
234
305
|
let fixes = [];
|
|
235
306
|
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
236
307
|
if (serviceScript) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
fixes = getCodeFixesAtPosition(fileName, generateStart + sourceScript.snapshot.getLength(), generateEnd + sourceScript.snapshot.getLength(), errorCodes, formatOptions, preferences);
|
|
242
|
-
break;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
break;
|
|
246
|
-
}
|
|
308
|
+
const generateStart = (0, transform_1.toGeneratedOffset)(sourceScript, map, start, language_core_1.isCodeActionsEnabled);
|
|
309
|
+
const generateEnd = (0, transform_1.toGeneratedOffset)(sourceScript, map, end, language_core_1.isCodeActionsEnabled);
|
|
310
|
+
if (generateStart !== undefined && generateEnd !== undefined) {
|
|
311
|
+
fixes = getCodeFixesAtPosition(fileName, generateStart, generateEnd, errorCodes, formatOptions, preferences);
|
|
247
312
|
}
|
|
248
313
|
}
|
|
249
314
|
else {
|
|
@@ -261,32 +326,25 @@ function decorateLanguageService(language, languageService) {
|
|
|
261
326
|
let start;
|
|
262
327
|
let end;
|
|
263
328
|
for (const mapping of map.mappings) {
|
|
329
|
+
// TODO reuse the logic from language service
|
|
264
330
|
if ((0, language_core_1.isSemanticTokensEnabled)(mapping.data) && mapping.sourceOffsets[0] >= span.start && mapping.sourceOffsets[0] <= span.start + span.length) {
|
|
265
331
|
start ??= mapping.generatedOffsets[0];
|
|
266
|
-
end ??= mapping.generatedOffsets[mapping.generatedOffsets.length - 1];
|
|
332
|
+
end ??= mapping.generatedOffsets[mapping.generatedOffsets.length - 1] + mapping.lengths[mapping.lengths.length - 1];
|
|
267
333
|
start = Math.min(start, mapping.generatedOffsets[0]);
|
|
268
|
-
end = Math.max(end, mapping.generatedOffsets[mapping.generatedOffsets.length - 1]);
|
|
334
|
+
end = Math.max(end, mapping.generatedOffsets[mapping.generatedOffsets.length - 1] + mapping.lengths[mapping.lengths.length - 1]);
|
|
269
335
|
}
|
|
270
336
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
end = 0;
|
|
274
|
-
}
|
|
337
|
+
start ??= 0;
|
|
338
|
+
end ??= sourceScript.snapshot.getLength();
|
|
275
339
|
start += sourceScript.snapshot.getLength();
|
|
276
340
|
end += sourceScript.snapshot.getLength();
|
|
277
341
|
const result = getEncodedSemanticClassifications(fileName, { start, length: end - start }, format);
|
|
278
342
|
const spans = [];
|
|
279
343
|
for (let i = 0; i < result.spans.length; i += 3) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
spans.push(sourceStart, sourceEnd - sourceStart, result.spans[i + 2]);
|
|
285
|
-
break;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
break;
|
|
289
|
-
}
|
|
344
|
+
const sourceStart = (0, transform_1.toSourceOffset)(sourceScript, map, result.spans[i], language_core_1.isSemanticTokensEnabled);
|
|
345
|
+
const sourceEnd = (0, transform_1.toSourceOffset)(sourceScript, map, result.spans[i] + result.spans[i + 1], language_core_1.isSemanticTokensEnabled);
|
|
346
|
+
if (sourceStart !== undefined && sourceEnd !== undefined) {
|
|
347
|
+
spans.push(sourceStart, sourceEnd - sourceStart, result.spans[i + 2]);
|
|
290
348
|
}
|
|
291
349
|
}
|
|
292
350
|
result.spans = spans;
|
|
@@ -423,24 +481,29 @@ function decorateLanguageService(language, languageService) {
|
|
|
423
481
|
if (serviceScript) {
|
|
424
482
|
let mainResult;
|
|
425
483
|
let additionalResults = [];
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
484
|
+
let isAdditional;
|
|
485
|
+
const generatedOffset = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, data => {
|
|
486
|
+
if (!(0, language_core_1.isCompletionEnabled)(data)) {
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
isAdditional = typeof data.completion === 'object' && data.completion.isAdditional;
|
|
490
|
+
if (!isAdditional && mainResult) {
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
return true;
|
|
494
|
+
});
|
|
495
|
+
if (generatedOffset !== undefined) {
|
|
496
|
+
const result = getCompletionsAtPosition(fileName, generatedOffset, options, formattingSettings);
|
|
497
|
+
if (result) {
|
|
498
|
+
for (const entry of result.entries) {
|
|
499
|
+
entry.replacementSpan = entry.replacementSpan && (0, transform_1.transformTextSpan)(sourceScript, map, entry.replacementSpan, language_core_1.isCompletionEnabled);
|
|
431
500
|
}
|
|
432
|
-
|
|
433
|
-
if (
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
if (isAdditional) {
|
|
439
|
-
additionalResults.push(result);
|
|
440
|
-
}
|
|
441
|
-
else {
|
|
442
|
-
mainResult = result;
|
|
443
|
-
}
|
|
501
|
+
result.optionalReplacementSpan = result.optionalReplacementSpan && (0, transform_1.transformTextSpan)(sourceScript, map, result.optionalReplacementSpan, language_core_1.isCompletionEnabled);
|
|
502
|
+
if (isAdditional) {
|
|
503
|
+
additionalResults.push(result);
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
mainResult = result;
|
|
444
507
|
}
|
|
445
508
|
}
|
|
446
509
|
}
|
|
@@ -465,11 +528,9 @@ function decorateLanguageService(language, languageService) {
|
|
|
465
528
|
let details;
|
|
466
529
|
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
467
530
|
if (serviceScript) {
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
break;
|
|
472
|
-
}
|
|
531
|
+
const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isCompletionEnabled);
|
|
532
|
+
if (generatePosition !== undefined) {
|
|
533
|
+
details = getCompletionEntryDetails(fileName, generatePosition, entryName, formatOptions, source, preferences, data);
|
|
473
534
|
}
|
|
474
535
|
}
|
|
475
536
|
else {
|
|
@@ -504,14 +565,12 @@ function decorateLanguageService(language, languageService) {
|
|
|
504
565
|
const result = provideInlayHints(fileName, { start, length: end - start }, preferences);
|
|
505
566
|
const hints = [];
|
|
506
567
|
for (const hint of result) {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
break;
|
|
514
|
-
}
|
|
568
|
+
const sourcePosition = (0, transform_1.toSourceOffset)(sourceScript, map, hint.position, language_core_1.isInlayHintsEnabled);
|
|
569
|
+
if (sourcePosition !== undefined) {
|
|
570
|
+
hints.push({
|
|
571
|
+
...hint,
|
|
572
|
+
position: sourcePosition,
|
|
573
|
+
});
|
|
515
574
|
}
|
|
516
575
|
}
|
|
517
576
|
return hints;
|
|
@@ -532,9 +591,9 @@ function decorateLanguageService(language, languageService) {
|
|
|
532
591
|
const processedFilePositions = new Set();
|
|
533
592
|
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
534
593
|
if (serviceScript) {
|
|
535
|
-
for (const [
|
|
594
|
+
for (const [generatedOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
536
595
|
if (filter(mapping.data)) {
|
|
537
|
-
process(fileName,
|
|
596
|
+
process(fileName, generatedOffset + sourceScript.snapshot.getLength());
|
|
538
597
|
}
|
|
539
598
|
}
|
|
540
599
|
}
|
|
@@ -554,11 +613,11 @@ function decorateLanguageService(language, languageService) {
|
|
|
554
613
|
results = results.concat(result);
|
|
555
614
|
for (const ref of getLinkedCodes(result)) {
|
|
556
615
|
processedFilePositions.add(ref[0] + ':' + ref[1]);
|
|
557
|
-
const [
|
|
558
|
-
if (!
|
|
616
|
+
const [virtualFile, sourceScript] = (0, utils_1.getServiceScript)(language, ref[0]);
|
|
617
|
+
if (!virtualFile) {
|
|
559
618
|
continue;
|
|
560
619
|
}
|
|
561
|
-
const linkedCodeMap = language.linkedCodeMaps.get(
|
|
620
|
+
const linkedCodeMap = language.linkedCodeMaps.get(virtualFile.code);
|
|
562
621
|
if (!linkedCodeMap) {
|
|
563
622
|
continue;
|
|
564
623
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Language } from '@volar/language-core';
|
|
2
2
|
import type * as ts from 'typescript';
|
|
3
|
-
export declare function decorateLanguageServiceHost(language: Language, languageServiceHost: ts.LanguageServiceHost,
|
|
3
|
+
export declare function decorateLanguageServiceHost(ts: typeof import('typescript'), language: Language, languageServiceHost: ts.LanguageServiceHost, getLanguageId: (fileName: string) => string): void;
|
|
4
4
|
export declare function searchExternalFiles(ts: typeof import('typescript'), project: ts.server.Project, exts: string[]): string[];
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.searchExternalFiles = exports.decorateLanguageServiceHost = void 0;
|
|
4
|
-
const language_core_1 = require("@volar/language-core");
|
|
5
4
|
const resolveModuleName_1 = require("../resolveModuleName");
|
|
6
|
-
function decorateLanguageServiceHost(language, languageServiceHost,
|
|
5
|
+
function decorateLanguageServiceHost(ts, language, languageServiceHost, getLanguageId) {
|
|
7
6
|
let extraProjectVersion = 0;
|
|
8
7
|
const exts = language.plugins
|
|
9
8
|
.map(plugin => plugin.typescript?.extraFileExtensions.map(ext => '.' + ext.extension) ?? [])
|
|
@@ -57,35 +56,31 @@ function decorateLanguageServiceHost(language, languageServiceHost, ts) {
|
|
|
57
56
|
};
|
|
58
57
|
}
|
|
59
58
|
languageServiceHost.getScriptSnapshot = fileName => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return
|
|
59
|
+
const virtualScript = updateVirtualScript(fileName);
|
|
60
|
+
if (virtualScript) {
|
|
61
|
+
return virtualScript.snapshot;
|
|
63
62
|
}
|
|
64
63
|
return getScriptSnapshot(fileName);
|
|
65
64
|
};
|
|
66
65
|
if (getScriptKind) {
|
|
67
66
|
languageServiceHost.getScriptKind = fileName => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (script) {
|
|
72
|
-
return script.kind;
|
|
73
|
-
}
|
|
74
|
-
return ts.ScriptKind.Deferred;
|
|
67
|
+
const virtualScript = updateVirtualScript(fileName);
|
|
68
|
+
if (virtualScript) {
|
|
69
|
+
return virtualScript.kind;
|
|
75
70
|
}
|
|
76
71
|
return getScriptKind(fileName);
|
|
77
72
|
};
|
|
78
73
|
}
|
|
79
|
-
function
|
|
74
|
+
function updateVirtualScript(fileName) {
|
|
80
75
|
const version = languageServiceHost.getScriptVersion(fileName);
|
|
81
|
-
if (version !== scripts.get(fileName)?.
|
|
76
|
+
if (version !== scripts.get(fileName)?.[0]) {
|
|
82
77
|
let extension = '.ts';
|
|
83
78
|
let snapshotSnapshot;
|
|
84
79
|
let scriptKind = ts.ScriptKind.TS;
|
|
85
80
|
const snapshot = getScriptSnapshot(fileName);
|
|
86
81
|
if (snapshot) {
|
|
87
82
|
extraProjectVersion++;
|
|
88
|
-
const sourceScript = language.scripts.set(fileName, (
|
|
83
|
+
const sourceScript = language.scripts.set(fileName, getLanguageId(fileName), snapshot);
|
|
89
84
|
if (sourceScript.generated) {
|
|
90
85
|
const text = snapshot.getText(0, snapshot.getLength());
|
|
91
86
|
let patchedText = text.split('\n').map(line => ' '.repeat(line.length)).join('\n');
|
|
@@ -105,14 +100,18 @@ function decorateLanguageServiceHost(language, languageServiceHost, ts) {
|
|
|
105
100
|
extraProjectVersion++;
|
|
106
101
|
language.scripts.delete(fileName);
|
|
107
102
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
103
|
+
if (snapshotSnapshot) {
|
|
104
|
+
scripts.set(fileName, [
|
|
105
|
+
version,
|
|
106
|
+
{
|
|
107
|
+
extension,
|
|
108
|
+
snapshot: snapshotSnapshot,
|
|
109
|
+
kind: scriptKind,
|
|
110
|
+
}
|
|
111
|
+
]);
|
|
112
|
+
}
|
|
114
113
|
}
|
|
115
|
-
return scripts.get(fileName);
|
|
114
|
+
return scripts.get(fileName)?.[1];
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
exports.decorateLanguageServiceHost = decorateLanguageServiceHost;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type * as ts from 'typescript';
|
|
2
2
|
import { LanguagePlugin } from '@volar/language-core';
|
|
3
|
-
export declare function proxyCreateProgram(ts: typeof import('typescript'), original: typeof ts['createProgram'],
|
|
3
|
+
export declare function proxyCreateProgram(ts: typeof import('typescript'), original: typeof ts['createProgram'], getLanguagePlugins: (ts: typeof import('typescript'), options: ts.CreateProgramOptions) => LanguagePlugin[], getLanguageId: (fileName: string) => string): typeof import("typescript").createProgram;
|
|
@@ -3,13 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.proxyCreateProgram = void 0;
|
|
4
4
|
const decorateProgram_1 = require("./decorateProgram");
|
|
5
5
|
const language_core_1 = require("@volar/language-core");
|
|
6
|
-
function proxyCreateProgram(ts, original,
|
|
6
|
+
function proxyCreateProgram(ts, original, getLanguagePlugins, getLanguageId) {
|
|
7
7
|
return new Proxy(original, {
|
|
8
8
|
apply: (target, thisArg, args) => {
|
|
9
9
|
const options = args[0];
|
|
10
10
|
assert(!!options.host, '!!options.host');
|
|
11
|
+
const languagePlugins = getLanguagePlugins(ts, options);
|
|
12
|
+
const extensions = languagePlugins
|
|
13
|
+
.map(plugin => plugin.typescript?.extraFileExtensions.map(({ extension }) => `.${extension}`) ?? [])
|
|
14
|
+
.flat();
|
|
11
15
|
const sourceFileToSnapshotMap = new WeakMap();
|
|
12
|
-
const language = (0, language_core_1.createLanguage)(
|
|
16
|
+
const language = (0, language_core_1.createLanguage)(languagePlugins, ts.sys.useCaseSensitiveFileNames, fileName => {
|
|
13
17
|
let snapshot;
|
|
14
18
|
assert(originalSourceFiles.has(fileName), `originalSourceFiles.has(${fileName})`);
|
|
15
19
|
const sourceFile = originalSourceFiles.get(fileName);
|
|
@@ -31,7 +35,7 @@ function proxyCreateProgram(ts, original, extensions, getLanguagePlugins) {
|
|
|
31
35
|
}
|
|
32
36
|
}
|
|
33
37
|
if (snapshot) {
|
|
34
|
-
language.scripts.set(fileName, (
|
|
38
|
+
language.scripts.set(fileName, getLanguageId(fileName), snapshot);
|
|
35
39
|
}
|
|
36
40
|
else {
|
|
37
41
|
language.scripts.delete(fileName);
|
|
@@ -97,7 +101,7 @@ function proxyCreateProgram(ts, original, extensions, getLanguagePlugins) {
|
|
|
97
101
|
const program = Reflect.apply(target, thisArg, [options]);
|
|
98
102
|
(0, decorateProgram_1.decorateProgram)(language, program);
|
|
99
103
|
// TODO: #128
|
|
100
|
-
program.__volar__ = {
|
|
104
|
+
program.__volar__ = { language };
|
|
101
105
|
return program;
|
|
102
106
|
function resolveModuleName(name, containingFile, options, redirectedReference) {
|
|
103
107
|
const resolved = ts.resolveModuleName(name, containingFile, options, moduleResolutionHost, originalHost.getModuleResolutionCache?.(), redirectedReference);
|
package/lib/node/transform.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { Language, CodeInformation } from '@volar/language-core';
|
|
1
|
+
import { Language, CodeInformation, SourceMap, SourceScript } from '@volar/language-core';
|
|
2
2
|
import type * as ts from 'typescript';
|
|
3
|
-
export declare function transformCallHierarchyItem(
|
|
4
|
-
export declare function transformDiagnostic<T extends ts.Diagnostic>(
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
3
|
+
export declare function transformCallHierarchyItem(language: Language, item: ts.CallHierarchyItem, filter: (data: CodeInformation) => boolean): ts.CallHierarchyItem;
|
|
4
|
+
export declare function transformDiagnostic<T extends ts.Diagnostic>(language: Language, diagnostic: T): T | undefined;
|
|
5
|
+
export declare function transformSourceFile(sourceFile: ts.SourceFile, sourceText: string): ts.SourceFile;
|
|
6
|
+
export declare function transformFileTextChanges(language: Language, changes: ts.FileTextChanges, filter: (data: CodeInformation) => boolean): ts.FileTextChanges | undefined;
|
|
7
|
+
export declare function transformDocumentSpan<T extends ts.DocumentSpan>(language: Language, documentSpan: T, filter: (data: CodeInformation) => boolean, shouldFallback?: boolean): T | undefined;
|
|
8
|
+
export declare function transformSpan(language: Language, fileName: string | undefined, textSpan: ts.TextSpan | undefined, filter: (data: CodeInformation) => boolean): {
|
|
8
9
|
fileName: string;
|
|
9
10
|
textSpan: ts.TextSpan;
|
|
10
11
|
} | undefined;
|
|
12
|
+
export declare function transformTextChange(sourceScript: SourceScript, map: SourceMap<CodeInformation>, textChange: ts.TextChange, filter: (data: CodeInformation) => boolean): ts.TextChange | undefined;
|
|
13
|
+
export declare function transformTextSpan(sourceScript: SourceScript, map: SourceMap<CodeInformation>, textSpan: ts.TextSpan, filter: (data: CodeInformation) => boolean): ts.TextSpan | undefined;
|
|
14
|
+
export declare function toSourceOffset(sourceScript: SourceScript, map: SourceMap, position: number, filter: (data: CodeInformation) => boolean): number | undefined;
|
|
15
|
+
export declare function toGeneratedOffset(sourceScript: SourceScript, map: SourceMap, position: number, filter: (data: CodeInformation) => boolean): number | undefined;
|
package/lib/node/transform.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.transformSpan = exports.transformDocumentSpan = exports.transformFileTextChanges = exports.transformDiagnostic = exports.transformCallHierarchyItem = void 0;
|
|
3
|
+
exports.toGeneratedOffset = exports.toSourceOffset = exports.transformTextSpan = exports.transformTextChange = exports.transformSpan = exports.transformDocumentSpan = exports.transformFileTextChanges = exports.transformSourceFile = exports.transformDiagnostic = exports.transformCallHierarchyItem = void 0;
|
|
4
4
|
const language_core_1 = require("@volar/language-core");
|
|
5
5
|
const utils_1 = require("./utils");
|
|
6
6
|
const transformedDiagnostics = new WeakMap();
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
7
|
+
const transformedSourceFiles = new WeakMap();
|
|
8
|
+
function transformCallHierarchyItem(language, item, filter) {
|
|
9
|
+
const span = transformSpan(language, item.file, item.span, filter);
|
|
10
|
+
const selectionSpan = transformSpan(language, item.file, item.selectionSpan, filter);
|
|
10
11
|
return {
|
|
11
12
|
...item,
|
|
12
13
|
span: span?.textSpan ?? { start: 0, length: 0 },
|
|
@@ -14,26 +15,27 @@ function transformCallHierarchyItem(files, item, filter) {
|
|
|
14
15
|
};
|
|
15
16
|
}
|
|
16
17
|
exports.transformCallHierarchyItem = transformCallHierarchyItem;
|
|
17
|
-
function transformDiagnostic(
|
|
18
|
+
function transformDiagnostic(language, diagnostic) {
|
|
18
19
|
if (!transformedDiagnostics.has(diagnostic)) {
|
|
19
20
|
transformedDiagnostics.set(diagnostic, undefined);
|
|
20
21
|
const { relatedInformation } = diagnostic;
|
|
21
22
|
if (relatedInformation) {
|
|
22
23
|
diagnostic.relatedInformation = relatedInformation
|
|
23
|
-
.map(d => transformDiagnostic(
|
|
24
|
+
.map(d => transformDiagnostic(language, d))
|
|
24
25
|
.filter(utils_1.notEmpty);
|
|
25
26
|
}
|
|
26
27
|
if (diagnostic.file !== undefined
|
|
27
28
|
&& diagnostic.start !== undefined
|
|
28
29
|
&& diagnostic.length !== undefined) {
|
|
29
|
-
const [
|
|
30
|
-
if (
|
|
31
|
-
const
|
|
32
|
-
if (
|
|
30
|
+
const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, diagnostic.file.fileName);
|
|
31
|
+
if (serviceScript) {
|
|
32
|
+
const sourceSpan = transformTextSpan(sourceScript, map, { start: diagnostic.start, length: diagnostic.length }, language_core_1.shouldReportDiagnostics);
|
|
33
|
+
if (sourceSpan) {
|
|
33
34
|
transformedDiagnostics.set(diagnostic, {
|
|
34
35
|
...diagnostic,
|
|
35
|
-
start:
|
|
36
|
-
length:
|
|
36
|
+
start: sourceSpan.start,
|
|
37
|
+
length: sourceSpan.length,
|
|
38
|
+
file: transformSourceFile(diagnostic.file, sourceScript.snapshot.getText(0, sourceScript.snapshot.getLength())),
|
|
37
39
|
});
|
|
38
40
|
}
|
|
39
41
|
}
|
|
@@ -48,13 +50,23 @@ function transformDiagnostic(files, diagnostic) {
|
|
|
48
50
|
return transformedDiagnostics.get(diagnostic);
|
|
49
51
|
}
|
|
50
52
|
exports.transformDiagnostic = transformDiagnostic;
|
|
51
|
-
function
|
|
52
|
-
|
|
53
|
+
function transformSourceFile(sourceFile, sourceText) {
|
|
54
|
+
if (!transformedSourceFiles.has(sourceFile)) {
|
|
55
|
+
transformedSourceFiles.set(sourceFile, {
|
|
56
|
+
...sourceFile,
|
|
57
|
+
text: sourceText,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return transformedSourceFiles.get(sourceFile);
|
|
61
|
+
}
|
|
62
|
+
exports.transformSourceFile = transformSourceFile;
|
|
63
|
+
function transformFileTextChanges(language, changes, filter) {
|
|
64
|
+
const [_, source] = (0, utils_1.getServiceScript)(language, changes.fileName);
|
|
53
65
|
if (source) {
|
|
54
66
|
return {
|
|
55
67
|
...changes,
|
|
56
68
|
textChanges: changes.textChanges.map(c => {
|
|
57
|
-
const span = transformSpan(
|
|
69
|
+
const span = transformSpan(language, changes.fileName, c.span, filter);
|
|
58
70
|
if (span) {
|
|
59
71
|
return {
|
|
60
72
|
...c,
|
|
@@ -69,11 +81,11 @@ function transformFileTextChanges(files, changes, filter) {
|
|
|
69
81
|
}
|
|
70
82
|
}
|
|
71
83
|
exports.transformFileTextChanges = transformFileTextChanges;
|
|
72
|
-
function transformDocumentSpan(
|
|
73
|
-
let textSpan = transformSpan(
|
|
84
|
+
function transformDocumentSpan(language, documentSpan, filter, shouldFallback) {
|
|
85
|
+
let textSpan = transformSpan(language, documentSpan.fileName, documentSpan.textSpan, filter);
|
|
74
86
|
if (!textSpan && shouldFallback) {
|
|
75
|
-
const [
|
|
76
|
-
if (
|
|
87
|
+
const [serviceScript] = (0, utils_1.getServiceScript)(language, documentSpan.fileName);
|
|
88
|
+
if (serviceScript) {
|
|
77
89
|
textSpan = {
|
|
78
90
|
fileName: documentSpan.fileName,
|
|
79
91
|
textSpan: { start: 0, length: 0 },
|
|
@@ -83,9 +95,9 @@ function transformDocumentSpan(files, documentSpan, filter, shouldFallback) {
|
|
|
83
95
|
if (!textSpan) {
|
|
84
96
|
return;
|
|
85
97
|
}
|
|
86
|
-
const contextSpan = transformSpan(
|
|
87
|
-
const originalTextSpan = transformSpan(
|
|
88
|
-
const originalContextSpan = transformSpan(
|
|
98
|
+
const contextSpan = transformSpan(language, documentSpan.fileName, documentSpan.contextSpan, filter);
|
|
99
|
+
const originalTextSpan = transformSpan(language, documentSpan.originalFileName, documentSpan.originalTextSpan, filter);
|
|
100
|
+
const originalContextSpan = transformSpan(language, documentSpan.originalFileName, documentSpan.originalContextSpan, filter);
|
|
89
101
|
return {
|
|
90
102
|
...documentSpan,
|
|
91
103
|
fileName: textSpan.fileName,
|
|
@@ -97,23 +109,17 @@ function transformDocumentSpan(files, documentSpan, filter, shouldFallback) {
|
|
|
97
109
|
};
|
|
98
110
|
}
|
|
99
111
|
exports.transformDocumentSpan = transformDocumentSpan;
|
|
100
|
-
function transformSpan(
|
|
101
|
-
if (!fileName) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
if (!textSpan) {
|
|
112
|
+
function transformSpan(language, fileName, textSpan, filter) {
|
|
113
|
+
if (!fileName || !textSpan) {
|
|
105
114
|
return;
|
|
106
115
|
}
|
|
107
|
-
const [virtualFile, sourceScript, map] = (0, utils_1.getServiceScript)(
|
|
116
|
+
const [virtualFile, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
|
|
108
117
|
if (virtualFile) {
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
118
|
+
const sourceSpan = transformTextSpan(sourceScript, map, textSpan, filter);
|
|
119
|
+
if (sourceSpan) {
|
|
111
120
|
return {
|
|
112
121
|
fileName,
|
|
113
|
-
textSpan:
|
|
114
|
-
start: sourceRange[0],
|
|
115
|
-
length: sourceRange[1] - sourceRange[0],
|
|
116
|
-
},
|
|
122
|
+
textSpan: sourceSpan,
|
|
117
123
|
};
|
|
118
124
|
}
|
|
119
125
|
}
|
|
@@ -125,15 +131,43 @@ function transformSpan(files, fileName, textSpan, filter) {
|
|
|
125
131
|
}
|
|
126
132
|
}
|
|
127
133
|
exports.transformSpan = transformSpan;
|
|
128
|
-
function
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
function transformTextChange(sourceScript, map, textChange, filter) {
|
|
135
|
+
const sourceSpan = transformTextSpan(sourceScript, map, textChange.span, filter);
|
|
136
|
+
if (sourceSpan) {
|
|
137
|
+
return {
|
|
138
|
+
newText: textChange.newText,
|
|
139
|
+
span: sourceSpan,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.transformTextChange = transformTextChange;
|
|
144
|
+
function transformTextSpan(sourceScript, map, textSpan, filter) {
|
|
145
|
+
const start = textSpan.start;
|
|
146
|
+
const end = textSpan.start + textSpan.length;
|
|
147
|
+
const sourceStart = toSourceOffset(sourceScript, map, start, filter);
|
|
148
|
+
const sourceEnd = toSourceOffset(sourceScript, map, end, filter);
|
|
149
|
+
if (sourceStart !== undefined && sourceEnd !== undefined && sourceEnd >= sourceStart) {
|
|
150
|
+
return {
|
|
151
|
+
start: sourceStart,
|
|
152
|
+
length: sourceEnd - sourceStart,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.transformTextSpan = transformTextSpan;
|
|
157
|
+
function toSourceOffset(sourceScript, map, position, filter) {
|
|
158
|
+
for (const [sourceOffset, mapping] of map.getSourceOffsets(position - sourceScript.snapshot.getLength())) {
|
|
159
|
+
if (filter(mapping.data)) {
|
|
160
|
+
return sourceOffset;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.toSourceOffset = toSourceOffset;
|
|
165
|
+
function toGeneratedOffset(sourceScript, map, position, filter) {
|
|
166
|
+
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
167
|
+
if (filter(mapping.data)) {
|
|
168
|
+
return generateOffset + sourceScript.snapshot.getLength();
|
|
136
169
|
}
|
|
137
170
|
}
|
|
138
171
|
}
|
|
172
|
+
exports.toGeneratedOffset = toGeneratedOffset;
|
|
139
173
|
//# sourceMappingURL=transform.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type * as ts from 'typescript';
|
|
2
2
|
import { LanguagePlugin } from '@volar/language-core';
|
|
3
|
-
export declare function createAsyncLanguageServicePlugin(extensions: string[], scriptKind: ts.ScriptKind, loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => Promise<LanguagePlugin[]
|
|
3
|
+
export declare function createAsyncLanguageServicePlugin(extensions: string[], scriptKind: ts.ScriptKind, loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => Promise<LanguagePlugin[]>, getLanguageId: (fileName: string) => string): ts.server.PluginModuleFactory;
|
|
@@ -8,7 +8,7 @@ const createLanguageServicePlugin_1 = require("./createLanguageServicePlugin");
|
|
|
8
8
|
const externalFiles = new WeakMap();
|
|
9
9
|
const decoratedLanguageServices = new WeakSet();
|
|
10
10
|
const decoratedLanguageServiceHosts = new WeakSet();
|
|
11
|
-
function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePlugins) {
|
|
11
|
+
function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePlugins, getLanguageId) {
|
|
12
12
|
return modules => {
|
|
13
13
|
const { typescript: ts } = modules;
|
|
14
14
|
const pluginModule = {
|
|
@@ -55,14 +55,14 @@ function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePl
|
|
|
55
55
|
const language = (0, language_core_1.createLanguage)(languagePlugins, ts.sys.useCaseSensitiveFileNames, fileName => {
|
|
56
56
|
const snapshot = getScriptSnapshot(fileName);
|
|
57
57
|
if (snapshot) {
|
|
58
|
-
language.scripts.set(fileName, (
|
|
58
|
+
language.scripts.set(fileName, getLanguageId(fileName), snapshot);
|
|
59
59
|
}
|
|
60
60
|
else {
|
|
61
61
|
language.scripts.delete(fileName);
|
|
62
62
|
}
|
|
63
63
|
});
|
|
64
64
|
(0, decorateLanguageService_1.decorateLanguageService)(language, info.languageService);
|
|
65
|
-
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(language, info.languageServiceHost,
|
|
65
|
+
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(ts, language, info.languageServiceHost, getLanguageId);
|
|
66
66
|
info.project.markAsDirty();
|
|
67
67
|
initialized = true;
|
|
68
68
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type * as ts from 'typescript';
|
|
2
2
|
import { LanguagePlugin } from '@volar/language-core';
|
|
3
|
-
export declare function createLanguageServicePlugin(loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => LanguagePlugin[]): ts.server.PluginModuleFactory;
|
|
3
|
+
export declare function createLanguageServicePlugin(loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => LanguagePlugin[], getLanguageId: (fileName: string) => string): ts.server.PluginModuleFactory;
|
|
4
4
|
export declare function arrayItemsEqual(a: string[], b: string[]): boolean;
|
|
@@ -8,7 +8,7 @@ const externalFiles = new WeakMap();
|
|
|
8
8
|
const projectExternalFileExtensions = new WeakMap();
|
|
9
9
|
const decoratedLanguageServices = new WeakSet();
|
|
10
10
|
const decoratedLanguageServiceHosts = new WeakSet();
|
|
11
|
-
function createLanguageServicePlugin(loadLanguagePlugins) {
|
|
11
|
+
function createLanguageServicePlugin(loadLanguagePlugins, getLanguageId) {
|
|
12
12
|
return modules => {
|
|
13
13
|
const { typescript: ts } = modules;
|
|
14
14
|
const pluginModule = {
|
|
@@ -26,14 +26,14 @@ function createLanguageServicePlugin(loadLanguagePlugins) {
|
|
|
26
26
|
const language = (0, language_core_1.createLanguage)(languagePlugins, ts.sys.useCaseSensitiveFileNames, fileName => {
|
|
27
27
|
const snapshot = getScriptSnapshot(fileName);
|
|
28
28
|
if (snapshot) {
|
|
29
|
-
language.scripts.set(fileName, (
|
|
29
|
+
language.scripts.set(fileName, getLanguageId(fileName), snapshot);
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
32
|
language.scripts.delete(fileName);
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
35
|
(0, decorateLanguageService_1.decorateLanguageService)(language, info.languageService);
|
|
36
|
-
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(language, info.languageServiceHost,
|
|
36
|
+
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(ts, language, info.languageServiceHost, getLanguageId);
|
|
37
37
|
}
|
|
38
38
|
return info.languageService;
|
|
39
39
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type * as ts from 'typescript';
|
|
2
2
|
import type { LanguagePlugin } from '@volar/language-core';
|
|
3
3
|
export declare let getLanguagePlugins: (ts: typeof import('typescript'), options: ts.CreateProgramOptions) => LanguagePlugin[];
|
|
4
|
-
export declare
|
|
4
|
+
export declare let getLanguageId: (fileName: string) => string;
|
|
5
|
+
export declare function runTsc(tscPath: string, extensions: string[], _getLanguagePlugins: typeof getLanguagePlugins, _getLanguageId: typeof getLanguageId): void;
|
package/lib/quickstart/runTsc.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.runTsc = exports.getLanguagePlugins = void 0;
|
|
3
|
+
exports.runTsc = exports.getLanguageId = exports.getLanguagePlugins = void 0;
|
|
4
4
|
const fs = require("fs");
|
|
5
5
|
let getLanguagePlugins = () => [];
|
|
6
6
|
exports.getLanguagePlugins = getLanguagePlugins;
|
|
7
|
-
|
|
7
|
+
let getLanguageId = () => 'ts';
|
|
8
|
+
exports.getLanguageId = getLanguageId;
|
|
9
|
+
function runTsc(tscPath, extensions, _getLanguagePlugins, _getLanguageId) {
|
|
8
10
|
exports.getLanguagePlugins = _getLanguagePlugins;
|
|
11
|
+
exports.getLanguageId = _getLanguageId;
|
|
9
12
|
const proxyApiPath = require.resolve('../node/proxyCreateProgram');
|
|
10
13
|
const readFileSync = fs.readFileSync;
|
|
11
14
|
fs.readFileSync = (...args) => {
|
|
@@ -18,10 +21,12 @@ function runTsc(tscPath, extensions, _getLanguagePlugins) {
|
|
|
18
21
|
tsc = replace(tsc, /allSupportedExtensions = .*(?=;)/, s => s + `.concat([[${extsText}]])`);
|
|
19
22
|
// proxy createProgram
|
|
20
23
|
tsc = replace(tsc, /function createProgram\(.+\) {/, s => `var createProgram = require(${JSON.stringify(proxyApiPath)}).proxyCreateProgram(`
|
|
21
|
-
+
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
+ [
|
|
25
|
+
`new Proxy({}, { get(_target, p, _receiver) { return eval(p); } } )`,
|
|
26
|
+
`_createProgram`,
|
|
27
|
+
`require(${JSON.stringify(__filename)}).getLanguagePlugins`,
|
|
28
|
+
`require(${JSON.stringify(__filename)}).getLanguageId`,
|
|
29
|
+
].join(', ')
|
|
25
30
|
+ `);\n`
|
|
26
31
|
+ s.replace('createProgram', '_createProgram'));
|
|
27
32
|
return tsc;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volar/typescript",
|
|
3
|
-
"version": "2.2.0-alpha.
|
|
3
|
+
"version": "2.2.0-alpha.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.js",
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
"directory": "packages/typescript"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@volar/language-core": "2.2.0-alpha.
|
|
15
|
+
"@volar/language-core": "2.2.0-alpha.2",
|
|
16
16
|
"path-browserify": "^1.0.1"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/node": "latest",
|
|
20
20
|
"@types/path-browserify": "latest",
|
|
21
|
-
"@volar/language-service": "2.2.0-alpha.
|
|
21
|
+
"@volar/language-service": "2.2.0-alpha.2"
|
|
22
22
|
},
|
|
23
|
-
"gitHead": "
|
|
23
|
+
"gitHead": "c6a538c915cc8b32ad9a7ca1092a29a326d49161"
|
|
24
24
|
}
|