@volar/typescript 2.0.0-alpha.3 → 2.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +2 -1
- package/index.js +2 -1
- package/lib/node/decorateLanguageService.d.ts +1 -1
- package/lib/node/decorateLanguageService.js +90 -242
- package/lib/node/decorateProgram.d.ts +3 -0
- package/lib/node/decorateProgram.js +48 -0
- package/lib/node/proxyCreateProgram.d.ts +3 -0
- package/lib/node/proxyCreateProgram.js +122 -0
- package/lib/node/transform.d.ts +10 -0
- package/lib/node/transform.js +137 -0
- package/lib/node/utils.d.ts +3 -0
- package/lib/node/utils.js +26 -0
- package/lib/starters/createAsyncTSServerPlugin.d.ts +3 -0
- package/lib/starters/createAsyncTSServerPlugin.js +82 -0
- package/lib/starters/createTSServerPlugin.d.ts +7 -0
- package/lib/starters/createTSServerPlugin.js +60 -0
- package/lib/starters/runTsc.d.ts +4 -0
- package/lib/starters/runTsc.js +44 -0
- package/package.json +5 -4
package/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './lib/documentRegistry';
|
|
2
2
|
export * from './lib/node/decorateLanguageService';
|
|
3
3
|
export * from './lib/node/decorateLanguageServiceHost';
|
|
4
|
+
export * from './lib/node/decorateProgram';
|
|
5
|
+
export * from './lib/node/proxyCreateProgram';
|
|
4
6
|
export * from './lib/protocol/createProject';
|
|
5
7
|
export * from './lib/protocol/createSys';
|
|
6
|
-
export * from './lib/protocol/getProgram';
|
package/index.js
CHANGED
|
@@ -17,7 +17,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./lib/documentRegistry"), exports);
|
|
18
18
|
__exportStar(require("./lib/node/decorateLanguageService"), exports);
|
|
19
19
|
__exportStar(require("./lib/node/decorateLanguageServiceHost"), exports);
|
|
20
|
+
__exportStar(require("./lib/node/decorateProgram"), exports);
|
|
21
|
+
__exportStar(require("./lib/node/proxyCreateProgram"), exports);
|
|
20
22
|
__exportStar(require("./lib/protocol/createProject"), exports);
|
|
21
23
|
__exportStar(require("./lib/protocol/createSys"), exports);
|
|
22
|
-
__exportStar(require("./lib/protocol/getProgram"), exports);
|
|
23
24
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { FileProvider } from '@volar/language-core';
|
|
2
2
|
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
3
|
-
export declare function decorateLanguageService(
|
|
3
|
+
export declare function decorateLanguageService(files: FileProvider, languageService: ts.LanguageService): void;
|
|
@@ -3,12 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.decorateLanguageService = void 0;
|
|
4
4
|
const language_core_1 = require("@volar/language-core");
|
|
5
5
|
const dedupe_1 = require("./dedupe");
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
const transform_1 = require("./transform");
|
|
8
|
+
function decorateLanguageService(files, languageService) {
|
|
8
9
|
// ignored methods
|
|
9
10
|
const { getNavigationTree, getOutliningSpans, } = languageService;
|
|
10
11
|
languageService.getNavigationTree = (fileName) => {
|
|
11
|
-
const [virtualFile] = getVirtualFileAndMap(fileName);
|
|
12
|
+
const [virtualFile] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
12
13
|
if (virtualFile) {
|
|
13
14
|
const tree = getNavigationTree(fileName);
|
|
14
15
|
tree.childItems = undefined;
|
|
@@ -19,7 +20,7 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
19
20
|
}
|
|
20
21
|
};
|
|
21
22
|
languageService.getOutliningSpans = (fileName) => {
|
|
22
|
-
const [virtualFile] = getVirtualFileAndMap(fileName);
|
|
23
|
+
const [virtualFile] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
23
24
|
if (virtualFile) {
|
|
24
25
|
return [];
|
|
25
26
|
}
|
|
@@ -30,16 +31,16 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
30
31
|
// methods
|
|
31
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
33
|
languageService.prepareCallHierarchy = (fileName, position) => {
|
|
33
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
34
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
34
35
|
if (virtualFile) {
|
|
35
36
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
36
37
|
if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
|
|
37
|
-
const item = prepareCallHierarchy(fileName, generateOffset +
|
|
38
|
+
const item = prepareCallHierarchy(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
38
39
|
if (Array.isArray(item)) {
|
|
39
|
-
return item.map(item => transformCallHierarchyItem(item, language_core_1.isCallHierarchyEnabled));
|
|
40
|
+
return item.map(item => (0, transform_1.transformCallHierarchyItem)(files, item, language_core_1.isCallHierarchyEnabled));
|
|
40
41
|
}
|
|
41
42
|
else if (item) {
|
|
42
|
-
return transformCallHierarchyItem(item, language_core_1.isCallHierarchyEnabled);
|
|
43
|
+
return (0, transform_1.transformCallHierarchyItem)(files, item, language_core_1.isCallHierarchyEnabled);
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
}
|
|
@@ -50,11 +51,11 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
50
51
|
};
|
|
51
52
|
languageService.provideCallHierarchyIncomingCalls = (fileName, position) => {
|
|
52
53
|
let calls = [];
|
|
53
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
54
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
54
55
|
if (virtualFile) {
|
|
55
56
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
56
57
|
if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
|
|
57
|
-
calls = provideCallHierarchyIncomingCalls(fileName, generateOffset +
|
|
58
|
+
calls = provideCallHierarchyIncomingCalls(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
}
|
|
@@ -63,10 +64,10 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
63
64
|
}
|
|
64
65
|
return calls
|
|
65
66
|
.map(call => {
|
|
66
|
-
const from = transformCallHierarchyItem(call.from, language_core_1.isCallHierarchyEnabled);
|
|
67
|
+
const from = (0, transform_1.transformCallHierarchyItem)(files, call.from, language_core_1.isCallHierarchyEnabled);
|
|
67
68
|
const fromSpans = call.fromSpans
|
|
68
|
-
.map(span => transformSpan(call.from.file, span, language_core_1.isCallHierarchyEnabled)?.textSpan)
|
|
69
|
-
.filter(notEmpty);
|
|
69
|
+
.map(span => (0, transform_1.transformSpan)(files, call.from.file, span, language_core_1.isCallHierarchyEnabled)?.textSpan)
|
|
70
|
+
.filter(utils_1.notEmpty);
|
|
70
71
|
return {
|
|
71
72
|
from,
|
|
72
73
|
fromSpans,
|
|
@@ -75,11 +76,11 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
75
76
|
};
|
|
76
77
|
languageService.provideCallHierarchyOutgoingCalls = (fileName, position) => {
|
|
77
78
|
let calls = [];
|
|
78
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
79
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
79
80
|
if (virtualFile) {
|
|
80
81
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
81
82
|
if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
|
|
82
|
-
calls = provideCallHierarchyOutgoingCalls(fileName, generateOffset +
|
|
83
|
+
calls = provideCallHierarchyOutgoingCalls(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
}
|
|
@@ -88,10 +89,10 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
88
89
|
}
|
|
89
90
|
return calls
|
|
90
91
|
.map(call => {
|
|
91
|
-
const to = transformCallHierarchyItem(call.to, language_core_1.isCallHierarchyEnabled);
|
|
92
|
+
const to = (0, transform_1.transformCallHierarchyItem)(files, call.to, language_core_1.isCallHierarchyEnabled);
|
|
92
93
|
const fromSpans = call.fromSpans
|
|
93
|
-
.map(span => transformSpan(fileName, span, language_core_1.isCallHierarchyEnabled)?.textSpan)
|
|
94
|
-
.filter(notEmpty);
|
|
94
|
+
.map(span => (0, transform_1.transformSpan)(files, fileName, span, language_core_1.isCallHierarchyEnabled)?.textSpan)
|
|
95
|
+
.filter(utils_1.notEmpty);
|
|
95
96
|
return {
|
|
96
97
|
to,
|
|
97
98
|
fromSpans,
|
|
@@ -101,18 +102,18 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
101
102
|
languageService.organizeImports = (args, formatOptions, preferences) => {
|
|
102
103
|
const unresolved = organizeImports(args, formatOptions, preferences);
|
|
103
104
|
const resolved = unresolved
|
|
104
|
-
.map(changes => transformFileTextChanges(changes, language_core_1.isCodeActionsEnabled))
|
|
105
|
-
.filter(notEmpty);
|
|
105
|
+
.map(changes => (0, transform_1.transformFileTextChanges)(files, changes, language_core_1.isCodeActionsEnabled))
|
|
106
|
+
.filter(utils_1.notEmpty);
|
|
106
107
|
return resolved;
|
|
107
108
|
};
|
|
108
109
|
languageService.getQuickInfoAtPosition = (fileName, position) => {
|
|
109
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
110
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
110
111
|
if (virtualFile) {
|
|
111
112
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
112
113
|
if ((0, language_core_1.isHoverEnabled)(mapping.data)) {
|
|
113
|
-
const result = getQuickInfoAtPosition(fileName, generateOffset +
|
|
114
|
+
const result = getQuickInfoAtPosition(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
114
115
|
if (result) {
|
|
115
|
-
const textSpan = transformSpan(fileName, result.textSpan, language_core_1.isHoverEnabled)?.textSpan;
|
|
116
|
+
const textSpan = (0, transform_1.transformSpan)(files, fileName, result.textSpan, language_core_1.isHoverEnabled)?.textSpan;
|
|
116
117
|
if (textSpan) {
|
|
117
118
|
return {
|
|
118
119
|
...result,
|
|
@@ -142,30 +143,30 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
142
143
|
...highlights,
|
|
143
144
|
highlightSpans: highlights.highlightSpans
|
|
144
145
|
.map(span => {
|
|
145
|
-
const textSpan = transformSpan(span.fileName ?? highlights.fileName, span.textSpan, language_core_1.isHighlightEnabled)?.textSpan;
|
|
146
|
+
const textSpan = (0, transform_1.transformSpan)(files, span.fileName ?? highlights.fileName, span.textSpan, language_core_1.isHighlightEnabled)?.textSpan;
|
|
146
147
|
if (textSpan) {
|
|
147
148
|
return {
|
|
148
149
|
...span,
|
|
149
|
-
contextSpan: transformSpan(span.fileName ?? highlights.fileName, span.contextSpan, language_core_1.isHighlightEnabled)?.textSpan,
|
|
150
|
+
contextSpan: (0, transform_1.transformSpan)(files, span.fileName ?? highlights.fileName, span.contextSpan, language_core_1.isHighlightEnabled)?.textSpan,
|
|
150
151
|
textSpan,
|
|
151
152
|
};
|
|
152
153
|
}
|
|
153
154
|
})
|
|
154
|
-
.filter(notEmpty),
|
|
155
|
+
.filter(utils_1.notEmpty),
|
|
155
156
|
};
|
|
156
157
|
});
|
|
157
158
|
return resolved;
|
|
158
159
|
};
|
|
159
160
|
languageService.getApplicableRefactors = (fileName, positionOrRange, preferences, triggerReason, kind, includeInteractiveActions) => {
|
|
160
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
161
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
161
162
|
if (virtualFile) {
|
|
162
163
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos)) {
|
|
163
164
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
164
165
|
const por = typeof positionOrRange === 'number'
|
|
165
|
-
? generateOffset +
|
|
166
|
+
? generateOffset + sourceFile.snapshot.getLength()
|
|
166
167
|
: {
|
|
167
|
-
pos: generateOffset +
|
|
168
|
-
end: generateOffset + positionOrRange.end - positionOrRange.pos +
|
|
168
|
+
pos: generateOffset + sourceFile.snapshot.getLength(),
|
|
169
|
+
end: generateOffset + positionOrRange.end - positionOrRange.pos + sourceFile.snapshot.getLength(),
|
|
169
170
|
};
|
|
170
171
|
return getApplicableRefactors(fileName, por, preferences, triggerReason, kind, includeInteractiveActions);
|
|
171
172
|
}
|
|
@@ -178,15 +179,15 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
178
179
|
};
|
|
179
180
|
languageService.getEditsForRefactor = (fileName, formatOptions, positionOrRange, refactorName, actionName, preferences) => {
|
|
180
181
|
let edits;
|
|
181
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
182
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
182
183
|
if (virtualFile) {
|
|
183
184
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos)) {
|
|
184
185
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
185
186
|
const por = typeof positionOrRange === 'number'
|
|
186
|
-
? generateOffset +
|
|
187
|
+
? generateOffset + sourceFile.snapshot.getLength()
|
|
187
188
|
: {
|
|
188
|
-
pos: generateOffset +
|
|
189
|
-
end: generateOffset + positionOrRange.end - positionOrRange.pos +
|
|
189
|
+
pos: generateOffset + sourceFile.snapshot.getLength(),
|
|
190
|
+
end: generateOffset + positionOrRange.end - positionOrRange.pos + sourceFile.snapshot.getLength(),
|
|
190
191
|
};
|
|
191
192
|
edits = getEditsForRefactor(fileName, formatOptions, por, refactorName, actionName, preferences);
|
|
192
193
|
}
|
|
@@ -197,19 +198,19 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
197
198
|
}
|
|
198
199
|
if (edits) {
|
|
199
200
|
edits.edits = edits.edits
|
|
200
|
-
.map(edit => transformFileTextChanges(edit, language_core_1.isCodeActionsEnabled))
|
|
201
|
-
.filter(notEmpty);
|
|
201
|
+
.map(edit => (0, transform_1.transformFileTextChanges)(files, edit, language_core_1.isCodeActionsEnabled))
|
|
202
|
+
.filter(utils_1.notEmpty);
|
|
202
203
|
return edits;
|
|
203
204
|
}
|
|
204
205
|
};
|
|
205
206
|
languageService.getRenameInfo = (fileName, position, options) => {
|
|
206
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
207
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
207
208
|
if (virtualFile) {
|
|
208
209
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
209
210
|
if ((0, language_core_1.isRenameEnabled)(mapping.data)) {
|
|
210
|
-
const info = getRenameInfo(fileName, generateOffset +
|
|
211
|
+
const info = getRenameInfo(fileName, generateOffset + sourceFile.snapshot.getLength(), options);
|
|
211
212
|
if (info.canRename) {
|
|
212
|
-
const span = transformSpan(fileName, info.triggerSpan, language_core_1.isRenameEnabled);
|
|
213
|
+
const span = (0, transform_1.transformSpan)(files, fileName, info.triggerSpan, language_core_1.isRenameEnabled);
|
|
213
214
|
if (span) {
|
|
214
215
|
info.triggerSpan = span.textSpan;
|
|
215
216
|
return info;
|
|
@@ -231,13 +232,13 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
231
232
|
};
|
|
232
233
|
languageService.getCodeFixesAtPosition = (fileName, start, end, errorCodes, formatOptions, preferences) => {
|
|
233
234
|
let fixes = [];
|
|
234
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
235
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
235
236
|
if (virtualFile) {
|
|
236
237
|
for (const [generateStart, mapping] of map.getGeneratedOffsets(start)) {
|
|
237
238
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
238
239
|
for (const [generateEnd, mapping] of map.getGeneratedOffsets(end)) {
|
|
239
240
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
240
|
-
fixes = getCodeFixesAtPosition(fileName, generateStart +
|
|
241
|
+
fixes = getCodeFixesAtPosition(fileName, generateStart + sourceFile.snapshot.getLength(), generateEnd + sourceFile.snapshot.getLength(), errorCodes, formatOptions, preferences);
|
|
241
242
|
break;
|
|
242
243
|
}
|
|
243
244
|
}
|
|
@@ -249,13 +250,13 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
249
250
|
fixes = getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences);
|
|
250
251
|
}
|
|
251
252
|
fixes = fixes.map(fix => {
|
|
252
|
-
fix.changes = fix.changes.map(edit => transformFileTextChanges(edit, language_core_1.isCodeActionsEnabled)).filter(notEmpty);
|
|
253
|
+
fix.changes = fix.changes.map(edit => (0, transform_1.transformFileTextChanges)(files, edit, language_core_1.isCodeActionsEnabled)).filter(utils_1.notEmpty);
|
|
253
254
|
return fix;
|
|
254
255
|
});
|
|
255
256
|
return fixes;
|
|
256
257
|
};
|
|
257
258
|
languageService.getEncodedSemanticClassifications = (fileName, span, format) => {
|
|
258
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
259
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
259
260
|
if (virtualFile) {
|
|
260
261
|
let start;
|
|
261
262
|
let end;
|
|
@@ -271,16 +272,14 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
271
272
|
start = 0;
|
|
272
273
|
end = 0;
|
|
273
274
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
end += sourceFile.snapshot.getLength();
|
|
277
|
-
}
|
|
275
|
+
start += sourceFile.snapshot.getLength();
|
|
276
|
+
end += sourceFile.snapshot.getLength();
|
|
278
277
|
const result = getEncodedSemanticClassifications(fileName, { start, length: end - start }, format);
|
|
279
278
|
const spans = [];
|
|
280
279
|
for (let i = 0; i < result.spans.length; i += 3) {
|
|
281
|
-
for (const [sourceStart, mapping] of map.getSourceOffsets(result.spans[i] -
|
|
280
|
+
for (const [sourceStart, mapping] of map.getSourceOffsets(result.spans[i] - sourceFile.snapshot.getLength())) {
|
|
282
281
|
if ((0, language_core_1.isSemanticTokensEnabled)(mapping.data)) {
|
|
283
|
-
for (const [sourceEnd, mapping] of map.getSourceOffsets(result.spans[i] + result.spans[i + 1] -
|
|
282
|
+
for (const [sourceEnd, mapping] of map.getSourceOffsets(result.spans[i] + result.spans[i + 1] - sourceFile.snapshot.getLength())) {
|
|
284
283
|
if ((0, language_core_1.isSemanticTokensEnabled)(mapping.data)) {
|
|
285
284
|
spans.push(sourceStart, sourceEnd - sourceStart, result.spans[i + 2]);
|
|
286
285
|
break;
|
|
@@ -299,18 +298,18 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
299
298
|
};
|
|
300
299
|
languageService.getSyntacticDiagnostics = (fileName) => {
|
|
301
300
|
return getSyntacticDiagnostics(fileName)
|
|
302
|
-
.map(
|
|
303
|
-
.filter(notEmpty);
|
|
301
|
+
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
302
|
+
.filter(utils_1.notEmpty);
|
|
304
303
|
};
|
|
305
304
|
languageService.getSemanticDiagnostics = (fileName) => {
|
|
306
305
|
return getSemanticDiagnostics(fileName)
|
|
307
|
-
.map(
|
|
308
|
-
.filter(notEmpty);
|
|
306
|
+
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
307
|
+
.filter(utils_1.notEmpty);
|
|
309
308
|
};
|
|
310
309
|
languageService.getSuggestionDiagnostics = (fileName) => {
|
|
311
310
|
return getSuggestionDiagnostics(fileName)
|
|
312
|
-
.map(
|
|
313
|
-
.filter(notEmpty);
|
|
311
|
+
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
312
|
+
.filter(utils_1.notEmpty);
|
|
314
313
|
};
|
|
315
314
|
languageService.getDefinitionAndBoundSpan = (fileName, position) => {
|
|
316
315
|
const unresolved = linkedCodeFeatureWorker(fileName, position, language_core_1.isDefinitionEnabled, position => getDefinitionAndBoundSpan(fileName, position), function* (result) {
|
|
@@ -319,15 +318,15 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
319
318
|
}
|
|
320
319
|
});
|
|
321
320
|
const textSpan = unresolved
|
|
322
|
-
.map(s => transformSpan(fileName, s.textSpan, language_core_1.isDefinitionEnabled)?.textSpan)
|
|
323
|
-
.filter(notEmpty)[0];
|
|
321
|
+
.map(s => (0, transform_1.transformSpan)(files, fileName, s.textSpan, language_core_1.isDefinitionEnabled)?.textSpan)
|
|
322
|
+
.filter(utils_1.notEmpty)[0];
|
|
324
323
|
if (!textSpan)
|
|
325
324
|
return;
|
|
326
325
|
const definitions = unresolved
|
|
327
326
|
.map(s => s.definitions
|
|
328
|
-
?.map(s => transformDocumentSpan(s, language_core_1.isDefinitionEnabled, s.fileName !== fileName))
|
|
329
|
-
.filter(notEmpty))
|
|
330
|
-
.filter(notEmpty)
|
|
327
|
+
?.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isDefinitionEnabled, s.fileName !== fileName))
|
|
328
|
+
.filter(utils_1.notEmpty))
|
|
329
|
+
.filter(utils_1.notEmpty)
|
|
331
330
|
.flat();
|
|
332
331
|
return {
|
|
333
332
|
textSpan,
|
|
@@ -345,17 +344,17 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
345
344
|
const resolved = unresolved
|
|
346
345
|
.flat()
|
|
347
346
|
.map(symbol => {
|
|
348
|
-
const definition = transformDocumentSpan(symbol.definition, language_core_1.isDefinitionEnabled);
|
|
347
|
+
const definition = (0, transform_1.transformDocumentSpan)(files, symbol.definition, language_core_1.isDefinitionEnabled);
|
|
349
348
|
if (definition) {
|
|
350
349
|
return {
|
|
351
350
|
definition,
|
|
352
351
|
references: symbol.references
|
|
353
|
-
.map(r => transformDocumentSpan(r, language_core_1.isReferencesEnabled))
|
|
354
|
-
.filter(notEmpty),
|
|
352
|
+
.map(r => (0, transform_1.transformDocumentSpan)(files, r, language_core_1.isReferencesEnabled))
|
|
353
|
+
.filter(utils_1.notEmpty),
|
|
355
354
|
};
|
|
356
355
|
}
|
|
357
356
|
})
|
|
358
|
-
.filter(notEmpty);
|
|
357
|
+
.filter(utils_1.notEmpty);
|
|
359
358
|
return (0, dedupe_1.dedupeReferencedSymbols)(resolved);
|
|
360
359
|
};
|
|
361
360
|
languageService.getDefinitionAtPosition = (fileName, position) => {
|
|
@@ -366,8 +365,8 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
366
365
|
});
|
|
367
366
|
const resolved = unresolved
|
|
368
367
|
.flat()
|
|
369
|
-
.map(s => transformDocumentSpan(s, language_core_1.isDefinitionEnabled, s.fileName !== fileName))
|
|
370
|
-
.filter(notEmpty);
|
|
368
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isDefinitionEnabled, s.fileName !== fileName))
|
|
369
|
+
.filter(utils_1.notEmpty);
|
|
371
370
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
372
371
|
};
|
|
373
372
|
languageService.getTypeDefinitionAtPosition = (fileName, position) => {
|
|
@@ -378,8 +377,8 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
378
377
|
});
|
|
379
378
|
const resolved = unresolved
|
|
380
379
|
.flat()
|
|
381
|
-
.map(s => transformDocumentSpan(s, language_core_1.isTypeDefinitionEnabled))
|
|
382
|
-
.filter(notEmpty);
|
|
380
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isTypeDefinitionEnabled))
|
|
381
|
+
.filter(utils_1.notEmpty);
|
|
383
382
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
384
383
|
};
|
|
385
384
|
languageService.getImplementationAtPosition = (fileName, position) => {
|
|
@@ -390,8 +389,8 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
390
389
|
});
|
|
391
390
|
const resolved = unresolved
|
|
392
391
|
.flat()
|
|
393
|
-
.map(s => transformDocumentSpan(s, language_core_1.isImplementationEnabled))
|
|
394
|
-
.filter(notEmpty);
|
|
392
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isImplementationEnabled))
|
|
393
|
+
.filter(utils_1.notEmpty);
|
|
395
394
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
396
395
|
};
|
|
397
396
|
languageService.findRenameLocations = (fileName, position, findInStrings, findInComments, preferences) => {
|
|
@@ -402,8 +401,8 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
402
401
|
});
|
|
403
402
|
const resolved = unresolved
|
|
404
403
|
.flat()
|
|
405
|
-
.map(s => transformDocumentSpan(s, language_core_1.isRenameEnabled))
|
|
406
|
-
.filter(notEmpty);
|
|
404
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isRenameEnabled))
|
|
405
|
+
.filter(utils_1.notEmpty);
|
|
407
406
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
408
407
|
};
|
|
409
408
|
languageService.getReferencesAtPosition = (fileName, position) => {
|
|
@@ -414,21 +413,21 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
414
413
|
});
|
|
415
414
|
const resolved = unresolved
|
|
416
415
|
.flat()
|
|
417
|
-
.map(s => transformDocumentSpan(s, language_core_1.isReferencesEnabled))
|
|
418
|
-
.filter(notEmpty);
|
|
416
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isReferencesEnabled))
|
|
417
|
+
.filter(utils_1.notEmpty);
|
|
419
418
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
420
419
|
};
|
|
421
420
|
languageService.getCompletionsAtPosition = (fileName, position, options, formattingSettings) => {
|
|
422
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
421
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
423
422
|
if (virtualFile) {
|
|
424
423
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
425
424
|
if ((0, language_core_1.isCompletionEnabled)(mapping.data)) {
|
|
426
|
-
const result = getCompletionsAtPosition(fileName, generateOffset +
|
|
425
|
+
const result = getCompletionsAtPosition(fileName, generateOffset + sourceFile.snapshot.getLength(), options, formattingSettings);
|
|
427
426
|
if (result) {
|
|
428
427
|
for (const entry of result.entries) {
|
|
429
|
-
entry.replacementSpan = transformSpan(fileName, entry.replacementSpan, language_core_1.isCompletionEnabled)?.textSpan;
|
|
428
|
+
entry.replacementSpan = (0, transform_1.transformSpan)(files, fileName, entry.replacementSpan, language_core_1.isCompletionEnabled)?.textSpan;
|
|
430
429
|
}
|
|
431
|
-
result.optionalReplacementSpan = transformSpan(fileName, result.optionalReplacementSpan, language_core_1.isCompletionEnabled)?.textSpan;
|
|
430
|
+
result.optionalReplacementSpan = (0, transform_1.transformSpan)(files, fileName, result.optionalReplacementSpan, language_core_1.isCompletionEnabled)?.textSpan;
|
|
432
431
|
}
|
|
433
432
|
return result;
|
|
434
433
|
}
|
|
@@ -442,13 +441,13 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
442
441
|
const details = getCompletionEntryDetails(fileName, position, entryName, formatOptions, source, preferences, data);
|
|
443
442
|
if (details?.codeActions) {
|
|
444
443
|
for (const codeAction of details.codeActions) {
|
|
445
|
-
codeAction.changes = codeAction.changes.map(edit => transformFileTextChanges(edit, language_core_1.isCodeLensEnabled)).filter(notEmpty);
|
|
444
|
+
codeAction.changes = codeAction.changes.map(edit => (0, transform_1.transformFileTextChanges)(files, edit, language_core_1.isCodeLensEnabled)).filter(utils_1.notEmpty);
|
|
446
445
|
}
|
|
447
446
|
}
|
|
448
447
|
return details;
|
|
449
448
|
};
|
|
450
449
|
languageService.provideInlayHints = (fileName, span, preferences) => {
|
|
451
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
450
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
452
451
|
if (virtualFile) {
|
|
453
452
|
let start;
|
|
454
453
|
let end;
|
|
@@ -464,14 +463,12 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
464
463
|
start = 0;
|
|
465
464
|
end = 0;
|
|
466
465
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
end += sourceFile.snapshot.getLength();
|
|
470
|
-
}
|
|
466
|
+
start += sourceFile.snapshot.getLength();
|
|
467
|
+
end += sourceFile.snapshot.getLength();
|
|
471
468
|
const result = provideInlayHints(fileName, { start, length: end - start }, preferences);
|
|
472
469
|
const hints = [];
|
|
473
470
|
for (const hint of result) {
|
|
474
|
-
for (const [sourcePosition, mapping] of map.getSourceOffsets(hint.position -
|
|
471
|
+
for (const [sourcePosition, mapping] of map.getSourceOffsets(hint.position - sourceFile.snapshot.getLength())) {
|
|
475
472
|
if ((0, language_core_1.isInlayHintsEnabled)(mapping.data)) {
|
|
476
473
|
hints.push({
|
|
477
474
|
...hint,
|
|
@@ -490,18 +487,18 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
490
487
|
languageService.getFileReferences = (fileName) => {
|
|
491
488
|
const unresolved = getFileReferences(fileName);
|
|
492
489
|
const resolved = unresolved
|
|
493
|
-
.map(s => transformDocumentSpan(s, language_core_1.isReferencesEnabled))
|
|
494
|
-
.filter(notEmpty);
|
|
490
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isReferencesEnabled))
|
|
491
|
+
.filter(utils_1.notEmpty);
|
|
495
492
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
496
493
|
};
|
|
497
494
|
function linkedCodeFeatureWorker(fileName, position, filter, worker, getLinkedCodes) {
|
|
498
495
|
let results = [];
|
|
499
496
|
const processedFilePositions = new Set();
|
|
500
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
497
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
501
498
|
if (virtualFile) {
|
|
502
499
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
503
500
|
if (filter(mapping.data)) {
|
|
504
|
-
process(fileName, generateOffset +
|
|
501
|
+
process(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
505
502
|
}
|
|
506
503
|
}
|
|
507
504
|
}
|
|
@@ -519,167 +516,18 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
519
516
|
results = results.concat(result);
|
|
520
517
|
for (const ref of getLinkedCodes(result)) {
|
|
521
518
|
processedFilePositions.add(ref[0] + ':' + ref[1]);
|
|
522
|
-
const [virtualFile, sourceFile] = getVirtualFileAndMap(ref[0]);
|
|
519
|
+
const [virtualFile, sourceFile] = (0, utils_1.getVirtualFileAndMap)(files, ref[0]);
|
|
523
520
|
if (!virtualFile)
|
|
524
521
|
continue;
|
|
525
|
-
const linkedCodeMap =
|
|
522
|
+
const linkedCodeMap = files.getLinkedCodeMap(virtualFile);
|
|
526
523
|
if (!linkedCodeMap)
|
|
527
524
|
continue;
|
|
528
|
-
for (const linkedCodeOffset of linkedCodeMap.getLinkedOffsets(ref[1] -
|
|
529
|
-
process(ref[0], linkedCodeOffset +
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
// transforms
|
|
535
|
-
function transformCallHierarchyItem(item, filter) {
|
|
536
|
-
const span = transformSpan(item.file, item.span, filter);
|
|
537
|
-
const selectionSpan = transformSpan(item.file, item.selectionSpan, filter);
|
|
538
|
-
return {
|
|
539
|
-
...item,
|
|
540
|
-
span: span?.textSpan ?? { start: 0, length: 0 },
|
|
541
|
-
selectionSpan: selectionSpan?.textSpan ?? { start: 0, length: 0 },
|
|
542
|
-
};
|
|
543
|
-
}
|
|
544
|
-
function transformDiagnostic(diagnostic) {
|
|
545
|
-
if (!transformedDiagnostics.has(diagnostic)) {
|
|
546
|
-
if (diagnostic.start !== undefined && diagnostic.file) {
|
|
547
|
-
transformedDiagnostics.set(diagnostic, undefined);
|
|
548
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(diagnostic.file?.fileName);
|
|
549
|
-
if (virtualFile) {
|
|
550
|
-
for (const [sourceOffset, mapping] of map.getSourceOffsets(diagnostic.start - (isTsPlugin ? sourceFile.snapshot.getLength() : 0))) {
|
|
551
|
-
if ((0, language_core_1.shouldReportDiagnostics)(mapping.data)) {
|
|
552
|
-
transformedDiagnostics.set(diagnostic, {
|
|
553
|
-
...diagnostic,
|
|
554
|
-
start: sourceOffset,
|
|
555
|
-
});
|
|
556
|
-
break;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
525
|
+
for (const linkedCodeOffset of linkedCodeMap.getLinkedOffsets(ref[1] - sourceFile.snapshot.getLength())) {
|
|
526
|
+
process(ref[0], linkedCodeOffset + sourceFile.snapshot.getLength());
|
|
559
527
|
}
|
|
560
|
-
else {
|
|
561
|
-
transformedDiagnostics.set(diagnostic, diagnostic);
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
else {
|
|
565
|
-
transformedDiagnostics.set(diagnostic, diagnostic);
|
|
566
|
-
}
|
|
567
|
-
if (diagnostic.relatedInformation) {
|
|
568
|
-
diagnostic.relatedInformation = diagnostic.relatedInformation
|
|
569
|
-
.map(transformDiagnostic)
|
|
570
|
-
.filter(notEmpty);
|
|
571
528
|
}
|
|
572
529
|
}
|
|
573
|
-
return transformedDiagnostics.get(diagnostic);
|
|
574
|
-
}
|
|
575
|
-
function transformFileTextChanges(changes, filter) {
|
|
576
|
-
const [_, source] = getVirtualFileAndMap(changes.fileName);
|
|
577
|
-
if (source) {
|
|
578
|
-
return {
|
|
579
|
-
...changes,
|
|
580
|
-
fileName: source.fileName,
|
|
581
|
-
textChanges: changes.textChanges.map(c => {
|
|
582
|
-
const span = transformSpan(changes.fileName, c.span, filter);
|
|
583
|
-
if (span) {
|
|
584
|
-
return {
|
|
585
|
-
...c,
|
|
586
|
-
span: span.textSpan,
|
|
587
|
-
};
|
|
588
|
-
}
|
|
589
|
-
}).filter(notEmpty),
|
|
590
|
-
};
|
|
591
|
-
}
|
|
592
|
-
else {
|
|
593
|
-
return changes;
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
function transformDocumentSpan(documentSpan, filter, shouldFallback) {
|
|
597
|
-
let textSpan = transformSpan(documentSpan.fileName, documentSpan.textSpan, filter);
|
|
598
|
-
if (!textSpan && shouldFallback) {
|
|
599
|
-
const [virtualFile, source] = getVirtualFileAndMap(documentSpan.fileName);
|
|
600
|
-
if (virtualFile) {
|
|
601
|
-
textSpan = {
|
|
602
|
-
fileName: source.fileName,
|
|
603
|
-
textSpan: { start: 0, length: 0 },
|
|
604
|
-
};
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
if (!textSpan)
|
|
608
|
-
return;
|
|
609
|
-
const contextSpan = transformSpan(documentSpan.fileName, documentSpan.contextSpan, filter);
|
|
610
|
-
const originalTextSpan = transformSpan(documentSpan.originalFileName, documentSpan.originalTextSpan, filter);
|
|
611
|
-
const originalContextSpan = transformSpan(documentSpan.originalFileName, documentSpan.originalContextSpan, filter);
|
|
612
|
-
return {
|
|
613
|
-
...documentSpan,
|
|
614
|
-
fileName: textSpan.fileName,
|
|
615
|
-
textSpan: textSpan.textSpan,
|
|
616
|
-
contextSpan: contextSpan?.textSpan,
|
|
617
|
-
originalFileName: originalTextSpan?.fileName,
|
|
618
|
-
originalTextSpan: originalTextSpan?.textSpan,
|
|
619
|
-
originalContextSpan: originalContextSpan?.textSpan,
|
|
620
|
-
};
|
|
621
|
-
}
|
|
622
|
-
function transformSpan(fileName, textSpan, filter) {
|
|
623
|
-
if (!fileName)
|
|
624
|
-
return;
|
|
625
|
-
if (!textSpan)
|
|
626
|
-
return;
|
|
627
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
628
|
-
if (virtualFile) {
|
|
629
|
-
for (const sourceStart of map.getSourceOffsets(textSpan.start - (isTsPlugin ? sourceFile.snapshot.getLength() : 0))) {
|
|
630
|
-
if (filter(sourceStart[1].data)) {
|
|
631
|
-
for (const sourceEnd of map.getSourceOffsets(textSpan.start + textSpan.length - (isTsPlugin ? sourceFile.snapshot.getLength() : 0))) {
|
|
632
|
-
if (filter(sourceEnd[1].data)) {
|
|
633
|
-
return {
|
|
634
|
-
fileName: sourceFile.fileName,
|
|
635
|
-
textSpan: {
|
|
636
|
-
start: sourceStart[0],
|
|
637
|
-
length: sourceEnd[0] - sourceStart[0],
|
|
638
|
-
},
|
|
639
|
-
};
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
else {
|
|
646
|
-
return {
|
|
647
|
-
fileName,
|
|
648
|
-
textSpan,
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
function getVirtualFileAndMap(fileName) {
|
|
653
|
-
if (isTsPlugin) {
|
|
654
|
-
const sourceFile = virtualFiles.getSourceFile(fileName);
|
|
655
|
-
if (sourceFile?.virtualFile) {
|
|
656
|
-
for (const virtualFile of (0, language_core_1.forEachEmbeddedFile)(sourceFile.virtualFile[0])) {
|
|
657
|
-
const ext = virtualFile.fileName.substring(fileName.length);
|
|
658
|
-
if (virtualFile.typescript && (ext === '.d.ts' || ext.match(/^\.(js|ts)x?$/))) {
|
|
659
|
-
for (const map of virtualFiles.getMaps(virtualFile)) {
|
|
660
|
-
if (map[1][0] === sourceFile.snapshot) {
|
|
661
|
-
return [virtualFile, sourceFile, map[1][1]];
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
else {
|
|
669
|
-
const [virtualFile, sourceFile] = virtualFiles.getVirtualFile(fileName);
|
|
670
|
-
if (virtualFile) {
|
|
671
|
-
for (const map of virtualFiles.getMaps(virtualFile)) {
|
|
672
|
-
if (map[1][0] === sourceFile.snapshot) {
|
|
673
|
-
return [virtualFile, sourceFile, map[1][1]];
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
return [undefined, undefined, undefined];
|
|
679
530
|
}
|
|
680
531
|
}
|
|
681
532
|
exports.decorateLanguageService = decorateLanguageService;
|
|
682
|
-
function notEmpty(value) {
|
|
683
|
-
return value !== null && value !== undefined;
|
|
684
|
-
}
|
|
685
533
|
//# sourceMappingURL=decorateLanguageService.js.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decorateProgram = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
const transform_1 = require("./transform");
|
|
6
|
+
function decorateProgram(files, program) {
|
|
7
|
+
const emit = program.emit;
|
|
8
|
+
// for tsc --noEmit
|
|
9
|
+
const getSyntacticDiagnostics = program.getSyntacticDiagnostics;
|
|
10
|
+
const getSemanticDiagnostics = program.getSemanticDiagnostics;
|
|
11
|
+
const getGlobalDiagnostics = program.getGlobalDiagnostics;
|
|
12
|
+
// for tsc --noEmit --watch
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
const getBindAndCheckDiagnostics = program.getBindAndCheckDiagnostics;
|
|
15
|
+
program.emit = (targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) => {
|
|
16
|
+
const result = emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers);
|
|
17
|
+
return {
|
|
18
|
+
emitSkipped: result.emitSkipped,
|
|
19
|
+
emittedFiles: result.emittedFiles,
|
|
20
|
+
diagnostics: result.diagnostics
|
|
21
|
+
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
22
|
+
.filter(utils_1.notEmpty),
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
program.getSyntacticDiagnostics = (sourceFile, cancellationToken) => {
|
|
26
|
+
return getSyntacticDiagnostics(sourceFile, cancellationToken)
|
|
27
|
+
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
28
|
+
.filter(utils_1.notEmpty);
|
|
29
|
+
};
|
|
30
|
+
program.getSemanticDiagnostics = (sourceFile, cancellationToken) => {
|
|
31
|
+
return getSemanticDiagnostics(sourceFile, cancellationToken)
|
|
32
|
+
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
33
|
+
.filter(utils_1.notEmpty);
|
|
34
|
+
};
|
|
35
|
+
program.getGlobalDiagnostics = (cancellationToken) => {
|
|
36
|
+
return getGlobalDiagnostics(cancellationToken)
|
|
37
|
+
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
38
|
+
.filter(utils_1.notEmpty);
|
|
39
|
+
};
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
program.getBindAndCheckDiagnostics = (sourceFile, cancellationToken) => {
|
|
42
|
+
return getBindAndCheckDiagnostics(sourceFile, cancellationToken)
|
|
43
|
+
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
44
|
+
.filter(utils_1.notEmpty);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
exports.decorateProgram = decorateProgram;
|
|
48
|
+
//# sourceMappingURL=decorateProgram.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
+
import { LanguagePlugin } from '@volar/language-core';
|
|
3
|
+
export declare function proxyCreateProgram(ts: typeof import('typescript'), original: typeof ts['createProgram'], extensions: string[], getLanguagePlugins: (ts: typeof import('typescript/lib/tsserverlibrary'), options: ts.CreateProgramOptions) => LanguagePlugin[]): typeof import("typescript").createProgram;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.proxyCreateProgram = void 0;
|
|
4
|
+
const decorateProgram_1 = require("./decorateProgram");
|
|
5
|
+
const language_core_1 = require("@volar/language-core");
|
|
6
|
+
function proxyCreateProgram(ts, original, extensions, getLanguagePlugins) {
|
|
7
|
+
return new Proxy(original, {
|
|
8
|
+
apply: (target, thisArg, args) => {
|
|
9
|
+
const options = args[0];
|
|
10
|
+
assert(!!options.host, '!!options.host');
|
|
11
|
+
const originalHost = options.host;
|
|
12
|
+
options.host = { ...originalHost };
|
|
13
|
+
options.options.allowArbitraryExtensions = true;
|
|
14
|
+
const sourceFileToSnapshotMap = new WeakMap();
|
|
15
|
+
const files = (0, language_core_1.createFileProvider)(getLanguagePlugins(ts, options), ts.sys.useCaseSensitiveFileNames, fileName => {
|
|
16
|
+
let snapshot;
|
|
17
|
+
assert(originalSourceFiles.has(fileName), `originalSourceFiles.has(${fileName})`);
|
|
18
|
+
const sourceFile = originalSourceFiles.get(fileName);
|
|
19
|
+
if (sourceFile) {
|
|
20
|
+
snapshot = sourceFileToSnapshotMap.get(sourceFile);
|
|
21
|
+
if (!snapshot) {
|
|
22
|
+
snapshot = {
|
|
23
|
+
getChangeRange() {
|
|
24
|
+
return undefined;
|
|
25
|
+
},
|
|
26
|
+
getLength() {
|
|
27
|
+
return sourceFile.text.length;
|
|
28
|
+
},
|
|
29
|
+
getText(start, end) {
|
|
30
|
+
return sourceFile.text.substring(start, end);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
sourceFileToSnapshotMap.set(sourceFile, snapshot);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (snapshot) {
|
|
37
|
+
files.updateSourceFile(fileName, (0, language_core_1.resolveCommonLanguageId)(fileName), snapshot);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
files.deleteSourceFile(fileName);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
const originalSourceFiles = new Map();
|
|
44
|
+
const parsedSourceFiles = new WeakMap();
|
|
45
|
+
const arbitraryExtensions = extensions.map(ext => `.d${ext}.ts`);
|
|
46
|
+
const moduleResolutionHost = {
|
|
47
|
+
...originalHost,
|
|
48
|
+
fileExists(fileName) {
|
|
49
|
+
for (let i = 0; i < arbitraryExtensions.length; i++) {
|
|
50
|
+
if (fileName.endsWith(arbitraryExtensions[i])) {
|
|
51
|
+
return originalHost.fileExists(fileName.slice(0, -arbitraryExtensions[i].length) + extensions[i]);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return originalHost.fileExists(fileName);
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
options.host.getSourceFile = (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => {
|
|
58
|
+
const originalSourceFile = originalHost.getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
|
|
59
|
+
originalSourceFiles.set(fileName, originalSourceFile);
|
|
60
|
+
if (originalSourceFile && extensions.some(ext => fileName.endsWith(ext))) {
|
|
61
|
+
let sourceFile2 = parsedSourceFiles.get(originalSourceFile);
|
|
62
|
+
if (!sourceFile2) {
|
|
63
|
+
const sourceFile = files.getSourceFile(fileName);
|
|
64
|
+
assert(!!sourceFile, '!!sourceFile');
|
|
65
|
+
let patchedText = originalSourceFile.text.split('\n').map(line => ' '.repeat(line.length)).join('\n');
|
|
66
|
+
let scriptKind = ts.ScriptKind.TS;
|
|
67
|
+
const virtualFile = sourceFile.virtualFile?.[0];
|
|
68
|
+
if (virtualFile) {
|
|
69
|
+
for (const file of (0, language_core_1.forEachEmbeddedFile)(virtualFile)) {
|
|
70
|
+
if (file.typescript) {
|
|
71
|
+
scriptKind = file.typescript.scriptKind;
|
|
72
|
+
patchedText += file.snapshot.getText(0, file.snapshot.getLength());
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
sourceFile2 = ts.createSourceFile(sourceFile.fileName, patchedText, 99, true, scriptKind);
|
|
78
|
+
// @ts-expect-error
|
|
79
|
+
sourceFile2.version = originalSourceFile.version;
|
|
80
|
+
parsedSourceFiles.set(originalSourceFile, sourceFile2);
|
|
81
|
+
}
|
|
82
|
+
return sourceFile2;
|
|
83
|
+
}
|
|
84
|
+
return originalSourceFile;
|
|
85
|
+
};
|
|
86
|
+
options.host.resolveModuleNameLiterals = (moduleNames, containingFile, redirectedReference, options) => {
|
|
87
|
+
return moduleNames.map(name => {
|
|
88
|
+
return resolveModuleName(name.text, containingFile, options, redirectedReference);
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
options.host.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference, options) => {
|
|
92
|
+
return moduleNames.map(name => {
|
|
93
|
+
return resolveModuleName(name, containingFile, options, redirectedReference).resolvedModule;
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
const program = Reflect.apply(target, thisArg, [options]);
|
|
97
|
+
(0, decorateProgram_1.decorateProgram)(files, program);
|
|
98
|
+
return program;
|
|
99
|
+
function resolveModuleName(name, containingFile, options, redirectedReference) {
|
|
100
|
+
const resolved = ts.resolveModuleName(name, containingFile, options, moduleResolutionHost, originalHost.getModuleResolutionCache?.(), redirectedReference);
|
|
101
|
+
if (resolved.resolvedModule) {
|
|
102
|
+
for (let i = 0; i < arbitraryExtensions.length; i++) {
|
|
103
|
+
if (resolved.resolvedModule.resolvedFileName.endsWith(arbitraryExtensions[i])) {
|
|
104
|
+
const sourceFileName = resolved.resolvedModule.resolvedFileName.slice(0, -arbitraryExtensions[i].length) + extensions[i];
|
|
105
|
+
resolved.resolvedModule.resolvedFileName = sourceFileName;
|
|
106
|
+
resolved.resolvedModule.extension = extensions[i];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return resolved;
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
exports.proxyCreateProgram = proxyCreateProgram;
|
|
116
|
+
function assert(condition, message) {
|
|
117
|
+
if (!condition) {
|
|
118
|
+
console.error(message);
|
|
119
|
+
throw new Error(message);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=proxyCreateProgram.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FileProvider, CodeInformation } from '@volar/language-core';
|
|
2
|
+
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
3
|
+
export declare function transformCallHierarchyItem(files: FileProvider, item: ts.CallHierarchyItem, filter: (data: CodeInformation) => boolean): ts.CallHierarchyItem;
|
|
4
|
+
export declare function transformDiagnostic<T extends ts.Diagnostic>(files: FileProvider, diagnostic: T): T | undefined;
|
|
5
|
+
export declare function transformFileTextChanges(files: FileProvider, changes: ts.FileTextChanges, filter: (data: CodeInformation) => boolean): ts.FileTextChanges | undefined;
|
|
6
|
+
export declare function transformDocumentSpan<T extends ts.DocumentSpan>(files: FileProvider, documentSpan: T, filter: (data: CodeInformation) => boolean, shouldFallback?: boolean): T | undefined;
|
|
7
|
+
export declare function transformSpan(files: FileProvider, fileName: string | undefined, textSpan: ts.TextSpan | undefined, filter: (data: CodeInformation) => boolean): {
|
|
8
|
+
fileName: string;
|
|
9
|
+
textSpan: ts.TextSpan;
|
|
10
|
+
} | undefined;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformSpan = exports.transformDocumentSpan = exports.transformFileTextChanges = exports.transformDiagnostic = exports.transformCallHierarchyItem = void 0;
|
|
4
|
+
const language_core_1 = require("@volar/language-core");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
const transformedDiagnostics = new WeakMap();
|
|
7
|
+
function transformCallHierarchyItem(files, item, filter) {
|
|
8
|
+
const span = transformSpan(files, item.file, item.span, filter);
|
|
9
|
+
const selectionSpan = transformSpan(files, item.file, item.selectionSpan, filter);
|
|
10
|
+
return {
|
|
11
|
+
...item,
|
|
12
|
+
span: span?.textSpan ?? { start: 0, length: 0 },
|
|
13
|
+
selectionSpan: selectionSpan?.textSpan ?? { start: 0, length: 0 },
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
exports.transformCallHierarchyItem = transformCallHierarchyItem;
|
|
17
|
+
function transformDiagnostic(files, diagnostic) {
|
|
18
|
+
if (!transformedDiagnostics.has(diagnostic)) {
|
|
19
|
+
transformedDiagnostics.set(diagnostic, undefined);
|
|
20
|
+
const { relatedInformation } = diagnostic;
|
|
21
|
+
if (relatedInformation) {
|
|
22
|
+
diagnostic.relatedInformation = relatedInformation
|
|
23
|
+
.map(d => transformDiagnostic(files, d))
|
|
24
|
+
.filter(utils_1.notEmpty);
|
|
25
|
+
}
|
|
26
|
+
if (diagnostic.file !== undefined
|
|
27
|
+
&& diagnostic.start !== undefined
|
|
28
|
+
&& diagnostic.length !== undefined) {
|
|
29
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, diagnostic.file.fileName);
|
|
30
|
+
if (virtualFile) {
|
|
31
|
+
const sourceRange = transformRange(sourceFile, map, diagnostic.start, diagnostic.start + diagnostic.length, language_core_1.shouldReportDiagnostics);
|
|
32
|
+
if (sourceRange) {
|
|
33
|
+
transformedDiagnostics.set(diagnostic, {
|
|
34
|
+
...diagnostic,
|
|
35
|
+
start: sourceRange[0],
|
|
36
|
+
length: sourceRange[1] - sourceRange[0],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
transformedDiagnostics.set(diagnostic, diagnostic);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
transformedDiagnostics.set(diagnostic, diagnostic);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return transformedDiagnostics.get(diagnostic);
|
|
49
|
+
}
|
|
50
|
+
exports.transformDiagnostic = transformDiagnostic;
|
|
51
|
+
function transformFileTextChanges(files, changes, filter) {
|
|
52
|
+
const [_, source] = (0, utils_1.getVirtualFileAndMap)(files, changes.fileName);
|
|
53
|
+
if (source) {
|
|
54
|
+
return {
|
|
55
|
+
...changes,
|
|
56
|
+
fileName: source.fileName,
|
|
57
|
+
textChanges: changes.textChanges.map(c => {
|
|
58
|
+
const span = transformSpan(files, changes.fileName, c.span, filter);
|
|
59
|
+
if (span) {
|
|
60
|
+
return {
|
|
61
|
+
...c,
|
|
62
|
+
span: span.textSpan,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}).filter(utils_1.notEmpty),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
return changes;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.transformFileTextChanges = transformFileTextChanges;
|
|
73
|
+
function transformDocumentSpan(files, documentSpan, filter, shouldFallback) {
|
|
74
|
+
let textSpan = transformSpan(files, documentSpan.fileName, documentSpan.textSpan, filter);
|
|
75
|
+
if (!textSpan && shouldFallback) {
|
|
76
|
+
const [virtualFile, source] = (0, utils_1.getVirtualFileAndMap)(files, documentSpan.fileName);
|
|
77
|
+
if (virtualFile) {
|
|
78
|
+
textSpan = {
|
|
79
|
+
fileName: source.fileName,
|
|
80
|
+
textSpan: { start: 0, length: 0 },
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (!textSpan)
|
|
85
|
+
return;
|
|
86
|
+
const contextSpan = transformSpan(files, documentSpan.fileName, documentSpan.contextSpan, filter);
|
|
87
|
+
const originalTextSpan = transformSpan(files, documentSpan.originalFileName, documentSpan.originalTextSpan, filter);
|
|
88
|
+
const originalContextSpan = transformSpan(files, documentSpan.originalFileName, documentSpan.originalContextSpan, filter);
|
|
89
|
+
return {
|
|
90
|
+
...documentSpan,
|
|
91
|
+
fileName: textSpan.fileName,
|
|
92
|
+
textSpan: textSpan.textSpan,
|
|
93
|
+
contextSpan: contextSpan?.textSpan,
|
|
94
|
+
originalFileName: originalTextSpan?.fileName,
|
|
95
|
+
originalTextSpan: originalTextSpan?.textSpan,
|
|
96
|
+
originalContextSpan: originalContextSpan?.textSpan,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
exports.transformDocumentSpan = transformDocumentSpan;
|
|
100
|
+
function transformSpan(files, fileName, textSpan, filter) {
|
|
101
|
+
if (!fileName)
|
|
102
|
+
return;
|
|
103
|
+
if (!textSpan)
|
|
104
|
+
return;
|
|
105
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
106
|
+
if (virtualFile) {
|
|
107
|
+
const sourceRange = transformRange(sourceFile, map, textSpan.start, textSpan.start + textSpan.length, filter);
|
|
108
|
+
if (sourceRange) {
|
|
109
|
+
return {
|
|
110
|
+
fileName: sourceFile.fileName,
|
|
111
|
+
textSpan: {
|
|
112
|
+
start: sourceRange[0],
|
|
113
|
+
length: sourceRange[1] - sourceRange[0],
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
return {
|
|
120
|
+
fileName,
|
|
121
|
+
textSpan,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.transformSpan = transformSpan;
|
|
126
|
+
function transformRange(sourceFile, map, start, end, filter) {
|
|
127
|
+
for (const sourceStart of map.getSourceOffsets(start - sourceFile.snapshot.getLength())) {
|
|
128
|
+
if (filter(sourceStart[1].data)) {
|
|
129
|
+
for (const sourceEnd of map.getSourceOffsets(end - sourceFile.snapshot.getLength())) {
|
|
130
|
+
if (sourceEnd > sourceStart && filter(sourceEnd[1].data)) {
|
|
131
|
+
return [sourceStart[0], sourceEnd[0]];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=transform.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { FileProvider } from '@volar/language-core';
|
|
2
|
+
export declare function notEmpty<T>(value: T | null | undefined): value is T;
|
|
3
|
+
export declare function getVirtualFileAndMap(files: FileProvider, fileName: string): readonly [import("@volar/language-core").VirtualFile, import("@volar/language-core").SourceFile, import("@volar/language-core").SourceMap<import("@volar/language-core").CodeInformation>] | readonly [undefined, undefined, undefined];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getVirtualFileAndMap = exports.notEmpty = void 0;
|
|
4
|
+
const language_core_1 = require("@volar/language-core");
|
|
5
|
+
function notEmpty(value) {
|
|
6
|
+
return value !== null && value !== undefined;
|
|
7
|
+
}
|
|
8
|
+
exports.notEmpty = notEmpty;
|
|
9
|
+
function getVirtualFileAndMap(files, fileName) {
|
|
10
|
+
const sourceFile = files.getSourceFile(fileName);
|
|
11
|
+
if (sourceFile?.virtualFile) {
|
|
12
|
+
for (const virtualFile of (0, language_core_1.forEachEmbeddedFile)(sourceFile.virtualFile[0])) {
|
|
13
|
+
const ext = virtualFile.fileName.substring(fileName.length);
|
|
14
|
+
if (virtualFile.typescript && (ext === '.d.ts' || ext.match(/^\.(js|ts)x?$/))) {
|
|
15
|
+
for (const map of files.getMaps(virtualFile)) {
|
|
16
|
+
if (map[1][0] === sourceFile.snapshot) {
|
|
17
|
+
return [virtualFile, sourceFile, map[1][1]];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return [undefined, undefined, undefined];
|
|
24
|
+
}
|
|
25
|
+
exports.getVirtualFileAndMap = getVirtualFileAndMap;
|
|
26
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
+
import { LanguagePlugin } from '@volar/language-core';
|
|
3
|
+
export declare function createAsyncTSServerPlugin(extensions: string[], scriptKind: ts.ScriptKind, loadLanguagePlugins: (ts: typeof import('typescript/lib/tsserverlibrary'), info: ts.server.PluginCreateInfo) => Promise<LanguagePlugin[]>): ts.server.PluginModuleFactory;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAsyncTSServerPlugin = void 0;
|
|
4
|
+
const decorateLanguageService_1 = require("../node/decorateLanguageService");
|
|
5
|
+
const decorateLanguageServiceHost_1 = require("../node/decorateLanguageServiceHost");
|
|
6
|
+
const language_core_1 = require("@volar/language-core");
|
|
7
|
+
const createTSServerPlugin_1 = require("./createTSServerPlugin");
|
|
8
|
+
const externalFiles = new WeakMap();
|
|
9
|
+
function createAsyncTSServerPlugin(extensions, scriptKind, loadLanguagePlugins) {
|
|
10
|
+
return (modules) => {
|
|
11
|
+
const { typescript: ts } = modules;
|
|
12
|
+
const pluginModule = {
|
|
13
|
+
create(info) {
|
|
14
|
+
const emptySnapshot = ts.ScriptSnapshot.fromString('');
|
|
15
|
+
const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
|
|
16
|
+
const getScriptVersion = info.languageServiceHost.getScriptVersion.bind(info.languageServiceHost);
|
|
17
|
+
const getScriptKind = info.languageServiceHost.getScriptKind?.bind(info.languageServiceHost);
|
|
18
|
+
const getProjectVersion = info.languageServiceHost.getProjectVersion?.bind(info.languageServiceHost);
|
|
19
|
+
let initialized = false;
|
|
20
|
+
info.languageServiceHost.getScriptSnapshot = (fileName) => {
|
|
21
|
+
if (!initialized && extensions.some(ext => fileName.endsWith(ext))) {
|
|
22
|
+
return emptySnapshot;
|
|
23
|
+
}
|
|
24
|
+
return getScriptSnapshot(fileName);
|
|
25
|
+
};
|
|
26
|
+
info.languageServiceHost.getScriptVersion = (fileName) => {
|
|
27
|
+
if (!initialized && extensions.some(ext => fileName.endsWith(ext))) {
|
|
28
|
+
return 'initializing...';
|
|
29
|
+
}
|
|
30
|
+
return getScriptVersion(fileName);
|
|
31
|
+
};
|
|
32
|
+
if (getScriptKind) {
|
|
33
|
+
info.languageServiceHost.getScriptKind = (fileName) => {
|
|
34
|
+
if (!initialized && extensions.some(ext => fileName.endsWith(ext))) {
|
|
35
|
+
return scriptKind; // TODO: bypass upstream bug
|
|
36
|
+
}
|
|
37
|
+
return getScriptKind(fileName);
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (getProjectVersion) {
|
|
41
|
+
info.languageServiceHost.getProjectVersion = () => {
|
|
42
|
+
if (!initialized) {
|
|
43
|
+
return getProjectVersion() + ',initializing...';
|
|
44
|
+
}
|
|
45
|
+
return getProjectVersion();
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
loadLanguagePlugins(ts, info).then(languagePlugins => {
|
|
49
|
+
const files = (0, language_core_1.createFileProvider)(languagePlugins, ts.sys.useCaseSensitiveFileNames, (fileName) => {
|
|
50
|
+
const snapshot = getScriptSnapshot(fileName);
|
|
51
|
+
if (snapshot) {
|
|
52
|
+
files.updateSourceFile(fileName, (0, language_core_1.resolveCommonLanguageId)(fileName), snapshot);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
files.deleteSourceFile(fileName);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
(0, decorateLanguageService_1.decorateLanguageService)(files, info.languageService);
|
|
59
|
+
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(files, info.languageServiceHost, ts, extensions);
|
|
60
|
+
info.project.markAsDirty();
|
|
61
|
+
initialized = true;
|
|
62
|
+
});
|
|
63
|
+
return info.languageService;
|
|
64
|
+
},
|
|
65
|
+
getExternalFiles(project, updateLevel = 0) {
|
|
66
|
+
if (updateLevel >= (1)
|
|
67
|
+
|| !externalFiles.has(project)) {
|
|
68
|
+
const oldFiles = externalFiles.get(project);
|
|
69
|
+
const newFiles = (0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, extensions);
|
|
70
|
+
externalFiles.set(project, newFiles);
|
|
71
|
+
if (oldFiles && !(0, createTSServerPlugin_1.arrayItemsEqual)(oldFiles, newFiles)) {
|
|
72
|
+
project.refreshDiagnostics();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return externalFiles.get(project);
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
return pluginModule;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
exports.createAsyncTSServerPlugin = createAsyncTSServerPlugin;
|
|
82
|
+
//# sourceMappingURL=createAsyncTSServerPlugin.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
+
import { LanguagePlugin } from '@volar/language-core';
|
|
3
|
+
export declare function createTSServerPlugin(init: (ts: typeof import('typescript/lib/tsserverlibrary'), info: ts.server.PluginCreateInfo) => {
|
|
4
|
+
languagePlugins: LanguagePlugin[];
|
|
5
|
+
extensions: string[];
|
|
6
|
+
}): ts.server.PluginModuleFactory;
|
|
7
|
+
export declare function arrayItemsEqual(a: string[], b: string[]): boolean;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.arrayItemsEqual = exports.createTSServerPlugin = void 0;
|
|
4
|
+
const decorateLanguageService_1 = require("../node/decorateLanguageService");
|
|
5
|
+
const decorateLanguageServiceHost_1 = require("../node/decorateLanguageServiceHost");
|
|
6
|
+
const language_core_1 = require("@volar/language-core");
|
|
7
|
+
const externalFiles = new WeakMap();
|
|
8
|
+
const projectExternalFileExtensions = new WeakMap();
|
|
9
|
+
function createTSServerPlugin(init) {
|
|
10
|
+
return (modules) => {
|
|
11
|
+
const { typescript: ts } = modules;
|
|
12
|
+
const pluginModule = {
|
|
13
|
+
create(info) {
|
|
14
|
+
const { languagePlugins, extensions } = init(ts, info);
|
|
15
|
+
projectExternalFileExtensions.set(info.project, extensions);
|
|
16
|
+
const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
|
|
17
|
+
const files = (0, language_core_1.createFileProvider)(languagePlugins, ts.sys.useCaseSensitiveFileNames, fileName => {
|
|
18
|
+
const snapshot = getScriptSnapshot(fileName);
|
|
19
|
+
if (snapshot) {
|
|
20
|
+
files.updateSourceFile(fileName, (0, language_core_1.resolveCommonLanguageId)(fileName), snapshot);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
files.deleteSourceFile(fileName);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
(0, decorateLanguageService_1.decorateLanguageService)(files, info.languageService);
|
|
27
|
+
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(files, info.languageServiceHost, ts, extensions);
|
|
28
|
+
return info.languageService;
|
|
29
|
+
},
|
|
30
|
+
getExternalFiles(project, updateLevel = 0) {
|
|
31
|
+
if (updateLevel >= (1)
|
|
32
|
+
|| !externalFiles.has(project)) {
|
|
33
|
+
const oldFiles = externalFiles.get(project);
|
|
34
|
+
const newFiles = (0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, projectExternalFileExtensions.get(project));
|
|
35
|
+
externalFiles.set(project, newFiles);
|
|
36
|
+
if (oldFiles && !arrayItemsEqual(oldFiles, newFiles)) {
|
|
37
|
+
project.refreshDiagnostics();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return externalFiles.get(project);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
return pluginModule;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
exports.createTSServerPlugin = createTSServerPlugin;
|
|
47
|
+
function arrayItemsEqual(a, b) {
|
|
48
|
+
if (a.length !== b.length) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
const set = new Set(a);
|
|
52
|
+
for (const file of b) {
|
|
53
|
+
if (!set.has(file)) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
exports.arrayItemsEqual = arrayItemsEqual;
|
|
60
|
+
//# sourceMappingURL=createTSServerPlugin.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
+
import type { LanguagePlugin } from '@volar/language-core';
|
|
3
|
+
export declare let getLanguagePlugins: (ts: typeof import('typescript/lib/tsserverlibrary'), options: ts.CreateProgramOptions) => LanguagePlugin[];
|
|
4
|
+
export declare function runTsc(tscPath: string, extensions: string[], _getLanguagePlugins: typeof getLanguagePlugins): void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runTsc = exports.getLanguagePlugins = void 0;
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
let getLanguagePlugins = () => [];
|
|
6
|
+
exports.getLanguagePlugins = getLanguagePlugins;
|
|
7
|
+
function runTsc(tscPath, extensions, _getLanguagePlugins) {
|
|
8
|
+
exports.getLanguagePlugins = _getLanguagePlugins;
|
|
9
|
+
const proxyApiPath = require.resolve('../node/proxyCreateProgram');
|
|
10
|
+
const currentFilePath = require.resolve('./runTsc');
|
|
11
|
+
const readFileSync = fs.readFileSync;
|
|
12
|
+
fs.readFileSync = (...args) => {
|
|
13
|
+
if (args[0] === tscPath) {
|
|
14
|
+
let tsc = readFileSync(...args);
|
|
15
|
+
// add allow extensions
|
|
16
|
+
const extsText = extensions.map(ext => `"${ext}"`).join(', ');
|
|
17
|
+
tsc = replace(tsc, /supportedTSExtensions = .*(?=;)/, s => s + `.concat([[${extsText}]])`);
|
|
18
|
+
tsc = replace(tsc, /supportedJSExtensions = .*(?=;)/, s => s + `.concat([[${extsText}]])`);
|
|
19
|
+
tsc = replace(tsc, /allSupportedExtensions = .*(?=;)/, s => s + `.concat([[${extsText}]])`);
|
|
20
|
+
// proxy createProgram
|
|
21
|
+
tsc = replace(tsc, /function createProgram\(.+\) {/, s => `var createProgram = require(${JSON.stringify(proxyApiPath)}).proxyCreateProgram(`
|
|
22
|
+
+ `new Proxy({}, { get(_target, p, _receiver) {return eval(p); } } ), `
|
|
23
|
+
+ `_createProgram, `
|
|
24
|
+
+ `[${extsText}], `
|
|
25
|
+
+ `require(${JSON.stringify(currentFilePath)}).getLanguagePlugins`
|
|
26
|
+
+ `);\n`
|
|
27
|
+
+ s.replace('createProgram', '_createProgram'));
|
|
28
|
+
return tsc;
|
|
29
|
+
}
|
|
30
|
+
return readFileSync(...args);
|
|
31
|
+
};
|
|
32
|
+
require(tscPath);
|
|
33
|
+
}
|
|
34
|
+
exports.runTsc = runTsc;
|
|
35
|
+
function replace(text, ...[search, replace]) {
|
|
36
|
+
const before = text;
|
|
37
|
+
text = text.replace(search, replace);
|
|
38
|
+
const after = text;
|
|
39
|
+
if (after === before) {
|
|
40
|
+
throw 'Search string not found: ' + JSON.stringify(search.toString());
|
|
41
|
+
}
|
|
42
|
+
return after;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=runTsc.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volar/typescript",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.js",
|
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
"directory": "packages/typescript"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@volar/language-core": "2.0.0-alpha.
|
|
15
|
+
"@volar/language-core": "2.0.0-alpha.4",
|
|
16
16
|
"path-browserify": "^1.0.1"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
+
"@types/node": "latest",
|
|
19
20
|
"@types/path-browserify": "latest",
|
|
20
|
-
"@volar/language-service": "2.0.0-alpha.
|
|
21
|
+
"@volar/language-service": "2.0.0-alpha.4"
|
|
21
22
|
},
|
|
22
|
-
"gitHead": "
|
|
23
|
+
"gitHead": "4d07249613d0cc5de4197e90c741a64adf92b84b"
|
|
23
24
|
}
|