@volar/typescript 2.0.0-alpha.2 → 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 +111 -240
- 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/protocol/createProject.js +0 -1
- 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,20 +3,44 @@ 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) {
|
|
9
|
+
// ignored methods
|
|
10
|
+
const { getNavigationTree, getOutliningSpans, } = languageService;
|
|
11
|
+
languageService.getNavigationTree = (fileName) => {
|
|
12
|
+
const [virtualFile] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
13
|
+
if (virtualFile) {
|
|
14
|
+
const tree = getNavigationTree(fileName);
|
|
15
|
+
tree.childItems = undefined;
|
|
16
|
+
return tree;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
return getNavigationTree(fileName);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
languageService.getOutliningSpans = (fileName) => {
|
|
23
|
+
const [virtualFile] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
24
|
+
if (virtualFile) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
return getOutliningSpans(fileName);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
// methods
|
|
8
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;
|
|
9
33
|
languageService.prepareCallHierarchy = (fileName, position) => {
|
|
10
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
34
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
11
35
|
if (virtualFile) {
|
|
12
36
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
13
37
|
if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
|
|
14
|
-
const item = prepareCallHierarchy(fileName, generateOffset +
|
|
38
|
+
const item = prepareCallHierarchy(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
15
39
|
if (Array.isArray(item)) {
|
|
16
|
-
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));
|
|
17
41
|
}
|
|
18
42
|
else if (item) {
|
|
19
|
-
return transformCallHierarchyItem(item, language_core_1.isCallHierarchyEnabled);
|
|
43
|
+
return (0, transform_1.transformCallHierarchyItem)(files, item, language_core_1.isCallHierarchyEnabled);
|
|
20
44
|
}
|
|
21
45
|
}
|
|
22
46
|
}
|
|
@@ -27,11 +51,11 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
27
51
|
};
|
|
28
52
|
languageService.provideCallHierarchyIncomingCalls = (fileName, position) => {
|
|
29
53
|
let calls = [];
|
|
30
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
54
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
31
55
|
if (virtualFile) {
|
|
32
56
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
33
57
|
if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
|
|
34
|
-
calls = provideCallHierarchyIncomingCalls(fileName, generateOffset +
|
|
58
|
+
calls = provideCallHierarchyIncomingCalls(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
35
59
|
}
|
|
36
60
|
}
|
|
37
61
|
}
|
|
@@ -40,10 +64,10 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
40
64
|
}
|
|
41
65
|
return calls
|
|
42
66
|
.map(call => {
|
|
43
|
-
const from = transformCallHierarchyItem(call.from, language_core_1.isCallHierarchyEnabled);
|
|
67
|
+
const from = (0, transform_1.transformCallHierarchyItem)(files, call.from, language_core_1.isCallHierarchyEnabled);
|
|
44
68
|
const fromSpans = call.fromSpans
|
|
45
|
-
.map(span => transformSpan(call.from.file, span, language_core_1.isCallHierarchyEnabled)?.textSpan)
|
|
46
|
-
.filter(notEmpty);
|
|
69
|
+
.map(span => (0, transform_1.transformSpan)(files, call.from.file, span, language_core_1.isCallHierarchyEnabled)?.textSpan)
|
|
70
|
+
.filter(utils_1.notEmpty);
|
|
47
71
|
return {
|
|
48
72
|
from,
|
|
49
73
|
fromSpans,
|
|
@@ -52,11 +76,11 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
52
76
|
};
|
|
53
77
|
languageService.provideCallHierarchyOutgoingCalls = (fileName, position) => {
|
|
54
78
|
let calls = [];
|
|
55
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
79
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
56
80
|
if (virtualFile) {
|
|
57
81
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
58
82
|
if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
|
|
59
|
-
calls = provideCallHierarchyOutgoingCalls(fileName, generateOffset +
|
|
83
|
+
calls = provideCallHierarchyOutgoingCalls(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
60
84
|
}
|
|
61
85
|
}
|
|
62
86
|
}
|
|
@@ -65,10 +89,10 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
65
89
|
}
|
|
66
90
|
return calls
|
|
67
91
|
.map(call => {
|
|
68
|
-
const to = transformCallHierarchyItem(call.to, language_core_1.isCallHierarchyEnabled);
|
|
92
|
+
const to = (0, transform_1.transformCallHierarchyItem)(files, call.to, language_core_1.isCallHierarchyEnabled);
|
|
69
93
|
const fromSpans = call.fromSpans
|
|
70
|
-
.map(span => transformSpan(fileName, span, language_core_1.isCallHierarchyEnabled)?.textSpan)
|
|
71
|
-
.filter(notEmpty);
|
|
94
|
+
.map(span => (0, transform_1.transformSpan)(files, fileName, span, language_core_1.isCallHierarchyEnabled)?.textSpan)
|
|
95
|
+
.filter(utils_1.notEmpty);
|
|
72
96
|
return {
|
|
73
97
|
to,
|
|
74
98
|
fromSpans,
|
|
@@ -78,18 +102,18 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
78
102
|
languageService.organizeImports = (args, formatOptions, preferences) => {
|
|
79
103
|
const unresolved = organizeImports(args, formatOptions, preferences);
|
|
80
104
|
const resolved = unresolved
|
|
81
|
-
.map(changes => transformFileTextChanges(changes, language_core_1.isCodeActionsEnabled))
|
|
82
|
-
.filter(notEmpty);
|
|
105
|
+
.map(changes => (0, transform_1.transformFileTextChanges)(files, changes, language_core_1.isCodeActionsEnabled))
|
|
106
|
+
.filter(utils_1.notEmpty);
|
|
83
107
|
return resolved;
|
|
84
108
|
};
|
|
85
109
|
languageService.getQuickInfoAtPosition = (fileName, position) => {
|
|
86
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
110
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
87
111
|
if (virtualFile) {
|
|
88
112
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
89
113
|
if ((0, language_core_1.isHoverEnabled)(mapping.data)) {
|
|
90
|
-
const result = getQuickInfoAtPosition(fileName, generateOffset +
|
|
114
|
+
const result = getQuickInfoAtPosition(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
91
115
|
if (result) {
|
|
92
|
-
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;
|
|
93
117
|
if (textSpan) {
|
|
94
118
|
return {
|
|
95
119
|
...result,
|
|
@@ -119,30 +143,30 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
119
143
|
...highlights,
|
|
120
144
|
highlightSpans: highlights.highlightSpans
|
|
121
145
|
.map(span => {
|
|
122
|
-
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;
|
|
123
147
|
if (textSpan) {
|
|
124
148
|
return {
|
|
125
149
|
...span,
|
|
126
|
-
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,
|
|
127
151
|
textSpan,
|
|
128
152
|
};
|
|
129
153
|
}
|
|
130
154
|
})
|
|
131
|
-
.filter(notEmpty),
|
|
155
|
+
.filter(utils_1.notEmpty),
|
|
132
156
|
};
|
|
133
157
|
});
|
|
134
158
|
return resolved;
|
|
135
159
|
};
|
|
136
160
|
languageService.getApplicableRefactors = (fileName, positionOrRange, preferences, triggerReason, kind, includeInteractiveActions) => {
|
|
137
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
161
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
138
162
|
if (virtualFile) {
|
|
139
163
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos)) {
|
|
140
164
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
141
165
|
const por = typeof positionOrRange === 'number'
|
|
142
|
-
? generateOffset +
|
|
166
|
+
? generateOffset + sourceFile.snapshot.getLength()
|
|
143
167
|
: {
|
|
144
|
-
pos: generateOffset +
|
|
145
|
-
end: generateOffset + positionOrRange.end - positionOrRange.pos +
|
|
168
|
+
pos: generateOffset + sourceFile.snapshot.getLength(),
|
|
169
|
+
end: generateOffset + positionOrRange.end - positionOrRange.pos + sourceFile.snapshot.getLength(),
|
|
146
170
|
};
|
|
147
171
|
return getApplicableRefactors(fileName, por, preferences, triggerReason, kind, includeInteractiveActions);
|
|
148
172
|
}
|
|
@@ -155,15 +179,15 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
155
179
|
};
|
|
156
180
|
languageService.getEditsForRefactor = (fileName, formatOptions, positionOrRange, refactorName, actionName, preferences) => {
|
|
157
181
|
let edits;
|
|
158
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
182
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
159
183
|
if (virtualFile) {
|
|
160
184
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos)) {
|
|
161
185
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
162
186
|
const por = typeof positionOrRange === 'number'
|
|
163
|
-
? generateOffset +
|
|
187
|
+
? generateOffset + sourceFile.snapshot.getLength()
|
|
164
188
|
: {
|
|
165
|
-
pos: generateOffset +
|
|
166
|
-
end: generateOffset + positionOrRange.end - positionOrRange.pos +
|
|
189
|
+
pos: generateOffset + sourceFile.snapshot.getLength(),
|
|
190
|
+
end: generateOffset + positionOrRange.end - positionOrRange.pos + sourceFile.snapshot.getLength(),
|
|
167
191
|
};
|
|
168
192
|
edits = getEditsForRefactor(fileName, formatOptions, por, refactorName, actionName, preferences);
|
|
169
193
|
}
|
|
@@ -174,19 +198,19 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
174
198
|
}
|
|
175
199
|
if (edits) {
|
|
176
200
|
edits.edits = edits.edits
|
|
177
|
-
.map(edit => transformFileTextChanges(edit, language_core_1.isCodeActionsEnabled))
|
|
178
|
-
.filter(notEmpty);
|
|
201
|
+
.map(edit => (0, transform_1.transformFileTextChanges)(files, edit, language_core_1.isCodeActionsEnabled))
|
|
202
|
+
.filter(utils_1.notEmpty);
|
|
179
203
|
return edits;
|
|
180
204
|
}
|
|
181
205
|
};
|
|
182
206
|
languageService.getRenameInfo = (fileName, position, options) => {
|
|
183
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
207
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
184
208
|
if (virtualFile) {
|
|
185
209
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
186
210
|
if ((0, language_core_1.isRenameEnabled)(mapping.data)) {
|
|
187
|
-
const info = getRenameInfo(fileName, generateOffset +
|
|
211
|
+
const info = getRenameInfo(fileName, generateOffset + sourceFile.snapshot.getLength(), options);
|
|
188
212
|
if (info.canRename) {
|
|
189
|
-
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);
|
|
190
214
|
if (span) {
|
|
191
215
|
info.triggerSpan = span.textSpan;
|
|
192
216
|
return info;
|
|
@@ -208,13 +232,13 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
208
232
|
};
|
|
209
233
|
languageService.getCodeFixesAtPosition = (fileName, start, end, errorCodes, formatOptions, preferences) => {
|
|
210
234
|
let fixes = [];
|
|
211
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
235
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
212
236
|
if (virtualFile) {
|
|
213
237
|
for (const [generateStart, mapping] of map.getGeneratedOffsets(start)) {
|
|
214
238
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
215
239
|
for (const [generateEnd, mapping] of map.getGeneratedOffsets(end)) {
|
|
216
240
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
217
|
-
fixes = getCodeFixesAtPosition(fileName, generateStart +
|
|
241
|
+
fixes = getCodeFixesAtPosition(fileName, generateStart + sourceFile.snapshot.getLength(), generateEnd + sourceFile.snapshot.getLength(), errorCodes, formatOptions, preferences);
|
|
218
242
|
break;
|
|
219
243
|
}
|
|
220
244
|
}
|
|
@@ -226,13 +250,13 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
226
250
|
fixes = getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences);
|
|
227
251
|
}
|
|
228
252
|
fixes = fixes.map(fix => {
|
|
229
|
-
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);
|
|
230
254
|
return fix;
|
|
231
255
|
});
|
|
232
256
|
return fixes;
|
|
233
257
|
};
|
|
234
258
|
languageService.getEncodedSemanticClassifications = (fileName, span, format) => {
|
|
235
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
259
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
236
260
|
if (virtualFile) {
|
|
237
261
|
let start;
|
|
238
262
|
let end;
|
|
@@ -248,16 +272,14 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
248
272
|
start = 0;
|
|
249
273
|
end = 0;
|
|
250
274
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
end += sourceFile.snapshot.getLength();
|
|
254
|
-
}
|
|
275
|
+
start += sourceFile.snapshot.getLength();
|
|
276
|
+
end += sourceFile.snapshot.getLength();
|
|
255
277
|
const result = getEncodedSemanticClassifications(fileName, { start, length: end - start }, format);
|
|
256
278
|
const spans = [];
|
|
257
279
|
for (let i = 0; i < result.spans.length; i += 3) {
|
|
258
|
-
for (const [sourceStart, mapping] of map.getSourceOffsets(result.spans[i] -
|
|
280
|
+
for (const [sourceStart, mapping] of map.getSourceOffsets(result.spans[i] - sourceFile.snapshot.getLength())) {
|
|
259
281
|
if ((0, language_core_1.isSemanticTokensEnabled)(mapping.data)) {
|
|
260
|
-
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())) {
|
|
261
283
|
if ((0, language_core_1.isSemanticTokensEnabled)(mapping.data)) {
|
|
262
284
|
spans.push(sourceStart, sourceEnd - sourceStart, result.spans[i + 2]);
|
|
263
285
|
break;
|
|
@@ -276,18 +298,18 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
276
298
|
};
|
|
277
299
|
languageService.getSyntacticDiagnostics = (fileName) => {
|
|
278
300
|
return getSyntacticDiagnostics(fileName)
|
|
279
|
-
.map(
|
|
280
|
-
.filter(notEmpty);
|
|
301
|
+
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
302
|
+
.filter(utils_1.notEmpty);
|
|
281
303
|
};
|
|
282
304
|
languageService.getSemanticDiagnostics = (fileName) => {
|
|
283
305
|
return getSemanticDiagnostics(fileName)
|
|
284
|
-
.map(
|
|
285
|
-
.filter(notEmpty);
|
|
306
|
+
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
307
|
+
.filter(utils_1.notEmpty);
|
|
286
308
|
};
|
|
287
309
|
languageService.getSuggestionDiagnostics = (fileName) => {
|
|
288
310
|
return getSuggestionDiagnostics(fileName)
|
|
289
|
-
.map(
|
|
290
|
-
.filter(notEmpty);
|
|
311
|
+
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
312
|
+
.filter(utils_1.notEmpty);
|
|
291
313
|
};
|
|
292
314
|
languageService.getDefinitionAndBoundSpan = (fileName, position) => {
|
|
293
315
|
const unresolved = linkedCodeFeatureWorker(fileName, position, language_core_1.isDefinitionEnabled, position => getDefinitionAndBoundSpan(fileName, position), function* (result) {
|
|
@@ -296,15 +318,15 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
296
318
|
}
|
|
297
319
|
});
|
|
298
320
|
const textSpan = unresolved
|
|
299
|
-
.map(s => transformSpan(fileName, s.textSpan, language_core_1.isDefinitionEnabled)?.textSpan)
|
|
300
|
-
.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];
|
|
301
323
|
if (!textSpan)
|
|
302
324
|
return;
|
|
303
325
|
const definitions = unresolved
|
|
304
326
|
.map(s => s.definitions
|
|
305
|
-
?.map(s => transformDocumentSpan(s, language_core_1.isDefinitionEnabled, s.fileName !== fileName))
|
|
306
|
-
.filter(notEmpty))
|
|
307
|
-
.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)
|
|
308
330
|
.flat();
|
|
309
331
|
return {
|
|
310
332
|
textSpan,
|
|
@@ -322,17 +344,17 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
322
344
|
const resolved = unresolved
|
|
323
345
|
.flat()
|
|
324
346
|
.map(symbol => {
|
|
325
|
-
const definition = transformDocumentSpan(symbol.definition, language_core_1.isDefinitionEnabled);
|
|
347
|
+
const definition = (0, transform_1.transformDocumentSpan)(files, symbol.definition, language_core_1.isDefinitionEnabled);
|
|
326
348
|
if (definition) {
|
|
327
349
|
return {
|
|
328
350
|
definition,
|
|
329
351
|
references: symbol.references
|
|
330
|
-
.map(r => transformDocumentSpan(r, language_core_1.isReferencesEnabled))
|
|
331
|
-
.filter(notEmpty),
|
|
352
|
+
.map(r => (0, transform_1.transformDocumentSpan)(files, r, language_core_1.isReferencesEnabled))
|
|
353
|
+
.filter(utils_1.notEmpty),
|
|
332
354
|
};
|
|
333
355
|
}
|
|
334
356
|
})
|
|
335
|
-
.filter(notEmpty);
|
|
357
|
+
.filter(utils_1.notEmpty);
|
|
336
358
|
return (0, dedupe_1.dedupeReferencedSymbols)(resolved);
|
|
337
359
|
};
|
|
338
360
|
languageService.getDefinitionAtPosition = (fileName, position) => {
|
|
@@ -343,8 +365,8 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
343
365
|
});
|
|
344
366
|
const resolved = unresolved
|
|
345
367
|
.flat()
|
|
346
|
-
.map(s => transformDocumentSpan(s, language_core_1.isDefinitionEnabled, s.fileName !== fileName))
|
|
347
|
-
.filter(notEmpty);
|
|
368
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isDefinitionEnabled, s.fileName !== fileName))
|
|
369
|
+
.filter(utils_1.notEmpty);
|
|
348
370
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
349
371
|
};
|
|
350
372
|
languageService.getTypeDefinitionAtPosition = (fileName, position) => {
|
|
@@ -355,8 +377,8 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
355
377
|
});
|
|
356
378
|
const resolved = unresolved
|
|
357
379
|
.flat()
|
|
358
|
-
.map(s => transformDocumentSpan(s, language_core_1.isTypeDefinitionEnabled))
|
|
359
|
-
.filter(notEmpty);
|
|
380
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isTypeDefinitionEnabled))
|
|
381
|
+
.filter(utils_1.notEmpty);
|
|
360
382
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
361
383
|
};
|
|
362
384
|
languageService.getImplementationAtPosition = (fileName, position) => {
|
|
@@ -367,8 +389,8 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
367
389
|
});
|
|
368
390
|
const resolved = unresolved
|
|
369
391
|
.flat()
|
|
370
|
-
.map(s => transformDocumentSpan(s, language_core_1.isImplementationEnabled))
|
|
371
|
-
.filter(notEmpty);
|
|
392
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isImplementationEnabled))
|
|
393
|
+
.filter(utils_1.notEmpty);
|
|
372
394
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
373
395
|
};
|
|
374
396
|
languageService.findRenameLocations = (fileName, position, findInStrings, findInComments, preferences) => {
|
|
@@ -379,8 +401,8 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
379
401
|
});
|
|
380
402
|
const resolved = unresolved
|
|
381
403
|
.flat()
|
|
382
|
-
.map(s => transformDocumentSpan(s, language_core_1.isRenameEnabled))
|
|
383
|
-
.filter(notEmpty);
|
|
404
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isRenameEnabled))
|
|
405
|
+
.filter(utils_1.notEmpty);
|
|
384
406
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
385
407
|
};
|
|
386
408
|
languageService.getReferencesAtPosition = (fileName, position) => {
|
|
@@ -391,21 +413,21 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
391
413
|
});
|
|
392
414
|
const resolved = unresolved
|
|
393
415
|
.flat()
|
|
394
|
-
.map(s => transformDocumentSpan(s, language_core_1.isReferencesEnabled))
|
|
395
|
-
.filter(notEmpty);
|
|
416
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isReferencesEnabled))
|
|
417
|
+
.filter(utils_1.notEmpty);
|
|
396
418
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
397
419
|
};
|
|
398
420
|
languageService.getCompletionsAtPosition = (fileName, position, options, formattingSettings) => {
|
|
399
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
421
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
400
422
|
if (virtualFile) {
|
|
401
423
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
402
424
|
if ((0, language_core_1.isCompletionEnabled)(mapping.data)) {
|
|
403
|
-
const result = getCompletionsAtPosition(fileName, generateOffset +
|
|
425
|
+
const result = getCompletionsAtPosition(fileName, generateOffset + sourceFile.snapshot.getLength(), options, formattingSettings);
|
|
404
426
|
if (result) {
|
|
405
427
|
for (const entry of result.entries) {
|
|
406
|
-
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;
|
|
407
429
|
}
|
|
408
|
-
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;
|
|
409
431
|
}
|
|
410
432
|
return result;
|
|
411
433
|
}
|
|
@@ -419,13 +441,13 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
419
441
|
const details = getCompletionEntryDetails(fileName, position, entryName, formatOptions, source, preferences, data);
|
|
420
442
|
if (details?.codeActions) {
|
|
421
443
|
for (const codeAction of details.codeActions) {
|
|
422
|
-
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);
|
|
423
445
|
}
|
|
424
446
|
}
|
|
425
447
|
return details;
|
|
426
448
|
};
|
|
427
449
|
languageService.provideInlayHints = (fileName, span, preferences) => {
|
|
428
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
450
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
429
451
|
if (virtualFile) {
|
|
430
452
|
let start;
|
|
431
453
|
let end;
|
|
@@ -441,14 +463,12 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
441
463
|
start = 0;
|
|
442
464
|
end = 0;
|
|
443
465
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
end += sourceFile.snapshot.getLength();
|
|
447
|
-
}
|
|
466
|
+
start += sourceFile.snapshot.getLength();
|
|
467
|
+
end += sourceFile.snapshot.getLength();
|
|
448
468
|
const result = provideInlayHints(fileName, { start, length: end - start }, preferences);
|
|
449
469
|
const hints = [];
|
|
450
470
|
for (const hint of result) {
|
|
451
|
-
for (const [sourcePosition, mapping] of map.getSourceOffsets(hint.position -
|
|
471
|
+
for (const [sourcePosition, mapping] of map.getSourceOffsets(hint.position - sourceFile.snapshot.getLength())) {
|
|
452
472
|
if ((0, language_core_1.isInlayHintsEnabled)(mapping.data)) {
|
|
453
473
|
hints.push({
|
|
454
474
|
...hint,
|
|
@@ -467,18 +487,18 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
467
487
|
languageService.getFileReferences = (fileName) => {
|
|
468
488
|
const unresolved = getFileReferences(fileName);
|
|
469
489
|
const resolved = unresolved
|
|
470
|
-
.map(s => transformDocumentSpan(s, language_core_1.isReferencesEnabled))
|
|
471
|
-
.filter(notEmpty);
|
|
490
|
+
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isReferencesEnabled))
|
|
491
|
+
.filter(utils_1.notEmpty);
|
|
472
492
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
473
493
|
};
|
|
474
494
|
function linkedCodeFeatureWorker(fileName, position, filter, worker, getLinkedCodes) {
|
|
475
495
|
let results = [];
|
|
476
496
|
const processedFilePositions = new Set();
|
|
477
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
497
|
+
const [virtualFile, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
478
498
|
if (virtualFile) {
|
|
479
499
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
480
500
|
if (filter(mapping.data)) {
|
|
481
|
-
process(fileName, generateOffset +
|
|
501
|
+
process(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
482
502
|
}
|
|
483
503
|
}
|
|
484
504
|
}
|
|
@@ -496,167 +516,18 @@ function decorateLanguageService(virtualFiles, languageService, isTsPlugin) {
|
|
|
496
516
|
results = results.concat(result);
|
|
497
517
|
for (const ref of getLinkedCodes(result)) {
|
|
498
518
|
processedFilePositions.add(ref[0] + ':' + ref[1]);
|
|
499
|
-
const [virtualFile, sourceFile] = getVirtualFileAndMap(ref[0]);
|
|
519
|
+
const [virtualFile, sourceFile] = (0, utils_1.getVirtualFileAndMap)(files, ref[0]);
|
|
500
520
|
if (!virtualFile)
|
|
501
521
|
continue;
|
|
502
|
-
const linkedCodeMap =
|
|
522
|
+
const linkedCodeMap = files.getLinkedCodeMap(virtualFile);
|
|
503
523
|
if (!linkedCodeMap)
|
|
504
524
|
continue;
|
|
505
|
-
for (const linkedCodeOffset of linkedCodeMap.getLinkedOffsets(ref[1] -
|
|
506
|
-
process(ref[0], linkedCodeOffset +
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
// transforms
|
|
512
|
-
function transformCallHierarchyItem(item, filter) {
|
|
513
|
-
const span = transformSpan(item.file, item.span, filter);
|
|
514
|
-
const selectionSpan = transformSpan(item.file, item.selectionSpan, filter);
|
|
515
|
-
return {
|
|
516
|
-
...item,
|
|
517
|
-
span: span?.textSpan ?? { start: 0, length: 0 },
|
|
518
|
-
selectionSpan: selectionSpan?.textSpan ?? { start: 0, length: 0 },
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
|
-
function transformDiagnostic(diagnostic) {
|
|
522
|
-
if (!transformedDiagnostics.has(diagnostic)) {
|
|
523
|
-
if (diagnostic.start !== undefined && diagnostic.file) {
|
|
524
|
-
transformedDiagnostics.set(diagnostic, undefined);
|
|
525
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(diagnostic.file?.fileName);
|
|
526
|
-
if (virtualFile) {
|
|
527
|
-
for (const [sourceOffset, mapping] of map.getSourceOffsets(diagnostic.start - (isTsPlugin ? sourceFile.snapshot.getLength() : 0))) {
|
|
528
|
-
if ((0, language_core_1.shouldReportDiagnostics)(mapping.data)) {
|
|
529
|
-
transformedDiagnostics.set(diagnostic, {
|
|
530
|
-
...diagnostic,
|
|
531
|
-
start: sourceOffset,
|
|
532
|
-
});
|
|
533
|
-
break;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
else {
|
|
538
|
-
transformedDiagnostics.set(diagnostic, diagnostic);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
else {
|
|
542
|
-
transformedDiagnostics.set(diagnostic, diagnostic);
|
|
543
|
-
}
|
|
544
|
-
if (diagnostic.relatedInformation) {
|
|
545
|
-
diagnostic.relatedInformation = diagnostic.relatedInformation
|
|
546
|
-
.map(transformDiagnostic)
|
|
547
|
-
.filter(notEmpty);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
return transformedDiagnostics.get(diagnostic);
|
|
551
|
-
}
|
|
552
|
-
function transformFileTextChanges(changes, filter) {
|
|
553
|
-
const [_, source] = getVirtualFileAndMap(changes.fileName);
|
|
554
|
-
if (source) {
|
|
555
|
-
return {
|
|
556
|
-
...changes,
|
|
557
|
-
fileName: source.fileName,
|
|
558
|
-
textChanges: changes.textChanges.map(c => {
|
|
559
|
-
const span = transformSpan(changes.fileName, c.span, filter);
|
|
560
|
-
if (span) {
|
|
561
|
-
return {
|
|
562
|
-
...c,
|
|
563
|
-
span: span.textSpan,
|
|
564
|
-
};
|
|
565
|
-
}
|
|
566
|
-
}).filter(notEmpty),
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
else {
|
|
570
|
-
return changes;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
function transformDocumentSpan(documentSpan, filter, shouldFallback) {
|
|
574
|
-
let textSpan = transformSpan(documentSpan.fileName, documentSpan.textSpan, filter);
|
|
575
|
-
if (!textSpan && shouldFallback) {
|
|
576
|
-
const [virtualFile, source] = getVirtualFileAndMap(documentSpan.fileName);
|
|
577
|
-
if (virtualFile) {
|
|
578
|
-
textSpan = {
|
|
579
|
-
fileName: source.fileName,
|
|
580
|
-
textSpan: { start: 0, length: 0 },
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
if (!textSpan)
|
|
585
|
-
return;
|
|
586
|
-
const contextSpan = transformSpan(documentSpan.fileName, documentSpan.contextSpan, filter);
|
|
587
|
-
const originalTextSpan = transformSpan(documentSpan.originalFileName, documentSpan.originalTextSpan, filter);
|
|
588
|
-
const originalContextSpan = transformSpan(documentSpan.originalFileName, documentSpan.originalContextSpan, filter);
|
|
589
|
-
return {
|
|
590
|
-
...documentSpan,
|
|
591
|
-
fileName: textSpan.fileName,
|
|
592
|
-
textSpan: textSpan.textSpan,
|
|
593
|
-
contextSpan: contextSpan?.textSpan,
|
|
594
|
-
originalFileName: originalTextSpan?.fileName,
|
|
595
|
-
originalTextSpan: originalTextSpan?.textSpan,
|
|
596
|
-
originalContextSpan: originalContextSpan?.textSpan,
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
function transformSpan(fileName, textSpan, filter) {
|
|
600
|
-
if (!fileName)
|
|
601
|
-
return;
|
|
602
|
-
if (!textSpan)
|
|
603
|
-
return;
|
|
604
|
-
const [virtualFile, sourceFile, map] = getVirtualFileAndMap(fileName);
|
|
605
|
-
if (virtualFile) {
|
|
606
|
-
for (const sourceStart of map.getSourceOffsets(textSpan.start - (isTsPlugin ? sourceFile.snapshot.getLength() : 0))) {
|
|
607
|
-
if (filter(sourceStart[1].data)) {
|
|
608
|
-
for (const sourceEnd of map.getSourceOffsets(textSpan.start + textSpan.length - (isTsPlugin ? sourceFile.snapshot.getLength() : 0))) {
|
|
609
|
-
if (filter(sourceEnd[1].data)) {
|
|
610
|
-
return {
|
|
611
|
-
fileName: sourceFile.fileName,
|
|
612
|
-
textSpan: {
|
|
613
|
-
start: sourceStart[0],
|
|
614
|
-
length: sourceEnd[0] - sourceStart[0],
|
|
615
|
-
},
|
|
616
|
-
};
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
else {
|
|
623
|
-
return {
|
|
624
|
-
fileName,
|
|
625
|
-
textSpan,
|
|
626
|
-
};
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
function getVirtualFileAndMap(fileName) {
|
|
630
|
-
if (isTsPlugin) {
|
|
631
|
-
const sourceFile = virtualFiles.getSourceFile(fileName);
|
|
632
|
-
if (sourceFile?.virtualFile) {
|
|
633
|
-
for (const virtualFile of (0, language_core_1.forEachEmbeddedFile)(sourceFile.virtualFile[0])) {
|
|
634
|
-
const ext = virtualFile.fileName.substring(fileName.length);
|
|
635
|
-
if (virtualFile.typescript && (ext === '.d.ts' || ext.match(/^\.(js|ts)x?$/))) {
|
|
636
|
-
for (const map of virtualFiles.getMaps(virtualFile)) {
|
|
637
|
-
if (map[1][0] === sourceFile.snapshot) {
|
|
638
|
-
return [virtualFile, sourceFile, map[1][1]];
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
}
|
|
525
|
+
for (const linkedCodeOffset of linkedCodeMap.getLinkedOffsets(ref[1] - sourceFile.snapshot.getLength())) {
|
|
526
|
+
process(ref[0], linkedCodeOffset + sourceFile.snapshot.getLength());
|
|
642
527
|
}
|
|
643
528
|
}
|
|
644
529
|
}
|
|
645
|
-
else {
|
|
646
|
-
const [virtualFile, sourceFile] = virtualFiles.getVirtualFile(fileName);
|
|
647
|
-
if (virtualFile) {
|
|
648
|
-
for (const map of virtualFiles.getMaps(virtualFile)) {
|
|
649
|
-
if (map[1][0] === sourceFile.snapshot) {
|
|
650
|
-
return [virtualFile, sourceFile, map[1][1]];
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
return [undefined, undefined, undefined];
|
|
656
530
|
}
|
|
657
531
|
}
|
|
658
532
|
exports.decorateLanguageService = decorateLanguageService;
|
|
659
|
-
function notEmpty(value) {
|
|
660
|
-
return value !== null && value !== undefined;
|
|
661
|
-
}
|
|
662
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
|
|
@@ -94,7 +94,6 @@ function createLanguage(ts, sys, languages, configFileName, projectHost) {
|
|
|
94
94
|
...sys,
|
|
95
95
|
getCurrentDirectory: projectHost.getCurrentDirectory,
|
|
96
96
|
getCompilationSettings: projectHost.getCompilationSettings,
|
|
97
|
-
getCancellationToken: projectHost.getCancellationToken,
|
|
98
97
|
getLocalizedDiagnosticMessages: projectHost.getLocalizedDiagnosticMessages,
|
|
99
98
|
getProjectReferences: projectHost.getProjectReferences,
|
|
100
99
|
getDefaultLibFileName: (options) => {
|
|
@@ -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
|
}
|