@volar/typescript 2.0.0-alpha.8 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/documentRegistry.d.ts +2 -2
- package/lib/node/decorateLanguageService.d.ts +3 -3
- package/lib/node/decorateLanguageService.js +47 -42
- package/lib/node/decorateLanguageServiceHost.d.ts +4 -4
- package/lib/node/decorateLanguageServiceHost.js +15 -15
- package/lib/node/decorateProgram.d.ts +3 -3
- package/lib/node/decorateProgram.js +1 -1
- package/lib/node/dedupe.d.ts +1 -1
- package/lib/node/proxyCreateProgram.d.ts +2 -2
- package/lib/node/proxyCreateProgram.js +10 -13
- package/lib/node/transform.d.ts +7 -7
- package/lib/node/transform.js +12 -10
- package/lib/node/utils.d.ts +6 -2
- package/lib/node/utils.js +7 -10
- package/lib/protocol/createProject.d.ts +6 -3
- package/lib/protocol/createProject.js +95 -119
- package/lib/protocol/createSys.d.ts +3 -3
- package/lib/protocol/createSys.js +11 -11
- package/lib/quickstart/createAsyncLanguageServicePlugin.d.ts +3 -0
- package/lib/quickstart/createAsyncLanguageServicePlugin.js +89 -0
- package/lib/quickstart/createAsyncTSServerPlugin.d.ts +3 -0
- package/lib/quickstart/createAsyncTSServerPlugin.js +89 -0
- package/lib/quickstart/createLanguageServicePlugin.d.ts +4 -0
- package/lib/quickstart/createLanguageServicePlugin.js +70 -0
- package/lib/quickstart/createTSServerPlugin.d.ts +4 -0
- package/lib/quickstart/createTSServerPlugin.js +70 -0
- package/lib/{starters → quickstart}/runTsc.d.ts +2 -2
- package/lib/typescript/core.js +16 -8
- package/lib/typescript/path.js +42 -21
- package/lib/typescript/utilities.js +6 -3
- package/lib/utils/resolveModuleName.d.ts +3 -0
- package/lib/utils/resolveModuleName.js +47 -0
- package/package.json +4 -4
- package/lib/protocol/getProgram.d.ts +0 -3
- package/lib/protocol/getProgram.js +0 -146
- package/lib/starters/createAsyncTSServerPlugin.d.ts +0 -3
- package/lib/starters/createAsyncTSServerPlugin.js +0 -82
- package/lib/starters/createTSServerPlugin.d.ts +0 -7
- package/lib/starters/createTSServerPlugin.js +0 -60
- /package/lib/{starters → quickstart}/runTsc.js +0 -0
|
@@ -4,11 +4,11 @@ exports.createLanguage = void 0;
|
|
|
4
4
|
const language_core_1 = require("@volar/language-core");
|
|
5
5
|
const language_core_2 = require("@volar/language-core");
|
|
6
6
|
const path = require("path-browserify");
|
|
7
|
-
const utilities_1 = require("../typescript/utilities");
|
|
8
7
|
const scriptVersions = new Map();
|
|
9
8
|
const fsFileSnapshots = new Map();
|
|
10
|
-
function createLanguage(ts, sys,
|
|
11
|
-
const files = (0, language_core_1.
|
|
9
|
+
function createLanguage(ts, sys, languagePlugins, configFileName, projectHost, { fileIdToFileName, fileNameToFileId }) {
|
|
10
|
+
const files = (0, language_core_1.createFileRegistry)(languagePlugins, sys.useCaseSensitiveFileNames, fileId => {
|
|
11
|
+
const fileName = fileIdToFileName(fileId);
|
|
12
12
|
// opened files
|
|
13
13
|
let snapshot = projectHost.getScriptSnapshot(fileName);
|
|
14
14
|
if (!snapshot) {
|
|
@@ -28,19 +28,19 @@ function createLanguage(ts, sys, languages, configFileName, projectHost) {
|
|
|
28
28
|
snapshot = fsFileSnapshots.get(fileName)?.[1];
|
|
29
29
|
}
|
|
30
30
|
if (snapshot) {
|
|
31
|
-
files.
|
|
31
|
+
files.set(fileId, projectHost.getLanguageId(fileId), snapshot);
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
|
-
files.
|
|
34
|
+
files.delete(fileId);
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
37
|
let languageServiceHost = createLanguageServiceHost();
|
|
38
|
-
for (const language of
|
|
38
|
+
for (const language of languagePlugins) {
|
|
39
39
|
if (language.typescript?.resolveLanguageServiceHost) {
|
|
40
40
|
languageServiceHost = language.typescript.resolveLanguageServiceHost(languageServiceHost);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
if (
|
|
43
|
+
if (languagePlugins.some(language => language.typescript?.extraFileExtensions.length)) {
|
|
44
44
|
// TODO: can this share between monorepo packages?
|
|
45
45
|
const moduleCache = ts.createModuleResolutionCache(languageServiceHost.getCurrentDirectory(), languageServiceHost.useCaseSensitiveFileNames ? s => s : s => s.toLowerCase(), languageServiceHost.getCompilationSettings());
|
|
46
46
|
let lastSysVersion = 'version' in sys ? sys.version : undefined;
|
|
@@ -49,28 +49,40 @@ function createLanguage(ts, sys, languages, configFileName, projectHost) {
|
|
|
49
49
|
lastSysVersion = sys.version;
|
|
50
50
|
moduleCache.clear();
|
|
51
51
|
}
|
|
52
|
-
return moduleLiterals.map(
|
|
52
|
+
return moduleLiterals.map(moduleLiteral => {
|
|
53
53
|
let moduleName = moduleLiteral.text;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
let extraFileExtension;
|
|
55
|
+
let isPatchResult = false;
|
|
56
|
+
for (const language of languagePlugins) {
|
|
57
|
+
extraFileExtension = language.typescript?.extraFileExtensions.find(ext => moduleName.endsWith('.' + ext.extension))?.extension;
|
|
58
|
+
if (extraFileExtension) {
|
|
59
|
+
break;
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
62
|
+
const result = ts.resolveModuleName(moduleName, containingFile, options, {
|
|
63
|
+
...languageServiceHost,
|
|
64
|
+
fileExists(fileName) {
|
|
65
|
+
if (extraFileExtension && fileName.endsWith('.d.ts')) {
|
|
66
|
+
const patchResult = languageServiceHost.fileExists(fileName.slice(0, -5));
|
|
67
|
+
if (patchResult) {
|
|
68
|
+
isPatchResult = true;
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return sys.fileExists(fileName);
|
|
73
|
+
},
|
|
74
|
+
}, moduleCache, redirectedReference, sourceFile.impliedNodeFormat);
|
|
75
|
+
if (isPatchResult && result.resolvedModule) {
|
|
76
|
+
result.resolvedModule.resolvedFileName = result.resolvedModule.resolvedFileName.slice(0, -5);
|
|
77
|
+
const sourceFile = files.get(fileNameToFileId(result.resolvedModule.resolvedFileName));
|
|
78
|
+
if (sourceFile?.generated) {
|
|
79
|
+
const tsCode = sourceFile.generated.languagePlugin.typescript?.getScript(sourceFile.generated.code);
|
|
80
|
+
if (tsCode) {
|
|
81
|
+
result.resolvedModule.extension = tsCode.extension;
|
|
82
|
+
}
|
|
71
83
|
}
|
|
72
84
|
}
|
|
73
|
-
return
|
|
85
|
+
return result;
|
|
74
86
|
});
|
|
75
87
|
};
|
|
76
88
|
}
|
|
@@ -81,7 +93,6 @@ function createLanguage(ts, sys, languages, configFileName, projectHost) {
|
|
|
81
93
|
sys,
|
|
82
94
|
projectHost,
|
|
83
95
|
languageServiceHost,
|
|
84
|
-
synchronizeFileSystem: 'sync' in sys ? () => sys.sync() : undefined,
|
|
85
96
|
},
|
|
86
97
|
};
|
|
87
98
|
function createLanguageServiceHost() {
|
|
@@ -93,10 +104,18 @@ function createLanguage(ts, sys, languages, configFileName, projectHost) {
|
|
|
93
104
|
const languageServiceHost = {
|
|
94
105
|
...sys,
|
|
95
106
|
getCurrentDirectory: projectHost.getCurrentDirectory,
|
|
96
|
-
getCompilationSettings
|
|
107
|
+
getCompilationSettings() {
|
|
108
|
+
const options = projectHost.getCompilationSettings();
|
|
109
|
+
if (languagePlugins.some(language => language.typescript?.extraFileExtensions.length)
|
|
110
|
+
&& !options.allowNonTsExtensions) {
|
|
111
|
+
console.warn('`allowNonTsExtensions` must be `true`.');
|
|
112
|
+
options.allowNonTsExtensions ??= true;
|
|
113
|
+
}
|
|
114
|
+
return options;
|
|
115
|
+
},
|
|
97
116
|
getLocalizedDiagnosticMessages: projectHost.getLocalizedDiagnosticMessages,
|
|
98
117
|
getProjectReferences: projectHost.getProjectReferences,
|
|
99
|
-
getDefaultLibFileName:
|
|
118
|
+
getDefaultLibFileName: options => {
|
|
100
119
|
try {
|
|
101
120
|
return ts.getDefaultLibFilePath(options);
|
|
102
121
|
}
|
|
@@ -114,54 +133,28 @@ function createLanguage(ts, sys, languages, configFileName, projectHost) {
|
|
|
114
133
|
getTypeRootsVersion: () => {
|
|
115
134
|
return 'version' in sys ? sys.version : -1; // TODO: only update for /node_modules changes?
|
|
116
135
|
},
|
|
117
|
-
// need sync
|
|
118
136
|
getDirectories(dirName) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
137
|
+
return sys.getDirectories(dirName);
|
|
138
|
+
},
|
|
139
|
+
readDirectory(dirName, extensions, excludes, includes, depth) {
|
|
140
|
+
const exts = new Set(extensions);
|
|
141
|
+
for (const languagePlugin of languagePlugins) {
|
|
142
|
+
for (const ext of languagePlugin.typescript?.extraFileExtensions ?? []) {
|
|
143
|
+
exts.add('.' + ext.extension);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
extensions = [...exts];
|
|
147
|
+
return sys.readDirectory(dirName, extensions, excludes, includes, depth);
|
|
124
148
|
},
|
|
125
149
|
readFile(fileName) {
|
|
126
|
-
syncSourceFile(fileName);
|
|
127
150
|
const snapshot = getScriptSnapshot(fileName);
|
|
128
151
|
if (snapshot) {
|
|
129
152
|
return snapshot.getText(0, snapshot.getLength());
|
|
130
153
|
}
|
|
131
154
|
},
|
|
132
155
|
fileExists(fileName) {
|
|
133
|
-
syncSourceFile(fileName);
|
|
134
156
|
return getScriptVersion(fileName) !== '';
|
|
135
157
|
},
|
|
136
|
-
readDirectory(dirName, extensions, excludes, includes, depth) {
|
|
137
|
-
syncProject();
|
|
138
|
-
let matches = (0, utilities_1.matchFiles)(dirName, extensions, excludes, includes, sys?.useCaseSensitiveFileNames ?? false, projectHost.getCurrentDirectory(), depth, (dirPath) => {
|
|
139
|
-
const files = [];
|
|
140
|
-
for (const fileName of tsFileRegistry.keys()) {
|
|
141
|
-
if (fileName.toLowerCase().startsWith(dirPath.toLowerCase())) {
|
|
142
|
-
const baseName = fileName.substring(dirPath.length);
|
|
143
|
-
if (baseName.indexOf('/') === -1) {
|
|
144
|
-
files.push(baseName);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
return {
|
|
149
|
-
files,
|
|
150
|
-
directories: getVirtualFileDirectories(dirPath),
|
|
151
|
-
};
|
|
152
|
-
}, sys?.realpath ? (path => sys.realpath(path)) : (path => path));
|
|
153
|
-
matches = matches.map(match => {
|
|
154
|
-
const [_, source] = files.getVirtualFile(match);
|
|
155
|
-
if (source) {
|
|
156
|
-
return source.fileName;
|
|
157
|
-
}
|
|
158
|
-
return match;
|
|
159
|
-
});
|
|
160
|
-
return [...new Set([
|
|
161
|
-
...matches,
|
|
162
|
-
...sys.readDirectory(dirName, extensions, excludes, includes, depth),
|
|
163
|
-
])];
|
|
164
|
-
},
|
|
165
158
|
getProjectVersion() {
|
|
166
159
|
syncProject();
|
|
167
160
|
return tsProjectVersion + ('version' in sys ? `:${sys.version}` : '');
|
|
@@ -171,14 +164,12 @@ function createLanguage(ts, sys, languages, configFileName, projectHost) {
|
|
|
171
164
|
return [...tsFileRegistry.keys()];
|
|
172
165
|
},
|
|
173
166
|
getScriptKind(fileName) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (sourceFile?.virtualFile) {
|
|
181
|
-
return ts.ScriptKind.Deferred;
|
|
167
|
+
const sourceFile = files.get(fileNameToFileId(fileName));
|
|
168
|
+
if (sourceFile?.generated) {
|
|
169
|
+
const tsCode = sourceFile.generated.languagePlugin.typescript?.getScript(sourceFile.generated.code);
|
|
170
|
+
if (tsCode) {
|
|
171
|
+
return tsCode.scriptKind;
|
|
172
|
+
}
|
|
182
173
|
}
|
|
183
174
|
switch (path.extname(fileName)) {
|
|
184
175
|
case '.js':
|
|
@@ -203,34 +194,26 @@ function createLanguage(ts, sys, languages, configFileName, projectHost) {
|
|
|
203
194
|
getScriptSnapshot,
|
|
204
195
|
};
|
|
205
196
|
return languageServiceHost;
|
|
206
|
-
function syncSourceFile(tsFileName) {
|
|
207
|
-
for (const language of languages) {
|
|
208
|
-
const sourceFileName = language.typescript?.resolveSourceFileName(tsFileName);
|
|
209
|
-
if (sourceFileName) {
|
|
210
|
-
files.getSourceFile(sourceFileName); // trigger sync
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
197
|
function syncProject() {
|
|
215
198
|
const newProjectVersion = projectHost.getProjectVersion?.();
|
|
216
199
|
const shouldUpdate = newProjectVersion === undefined || newProjectVersion !== lastProjectVersion;
|
|
217
|
-
if (!shouldUpdate)
|
|
200
|
+
if (!shouldUpdate) {
|
|
218
201
|
return;
|
|
202
|
+
}
|
|
219
203
|
lastProjectVersion = newProjectVersion;
|
|
220
204
|
const newTsVirtualFileSnapshots = new Set();
|
|
221
205
|
const newOtherVirtualFileSnapshots = new Set();
|
|
222
206
|
const tsFileNamesSet = new Set();
|
|
223
207
|
for (const fileName of projectHost.getScriptFileNames()) {
|
|
224
|
-
const sourceFile = files.
|
|
225
|
-
if (sourceFile?.
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
208
|
+
const sourceFile = files.get(fileNameToFileId(fileName));
|
|
209
|
+
if (sourceFile?.generated) {
|
|
210
|
+
const script = sourceFile.generated.languagePlugin.typescript?.getScript(sourceFile.generated.code);
|
|
211
|
+
if (script) {
|
|
212
|
+
newTsVirtualFileSnapshots.add(script.code.snapshot);
|
|
213
|
+
tsFileNamesSet.add(fileName); // virtual .ts
|
|
214
|
+
}
|
|
215
|
+
for (const file of (0, language_core_2.forEachEmbeddedCode)(sourceFile.generated.code)) {
|
|
216
|
+
newOtherVirtualFileSnapshots.add(file.snapshot);
|
|
234
217
|
}
|
|
235
218
|
}
|
|
236
219
|
else {
|
|
@@ -252,33 +235,36 @@ function createLanguage(ts, sys, languages, configFileName, projectHost) {
|
|
|
252
235
|
}
|
|
253
236
|
}
|
|
254
237
|
function getScriptSnapshot(fileName) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
238
|
+
const sourceFile = files.get(fileNameToFileId(fileName));
|
|
239
|
+
if (sourceFile?.generated) {
|
|
240
|
+
const script = sourceFile.generated.languagePlugin.typescript?.getScript(sourceFile.generated.code);
|
|
241
|
+
if (script) {
|
|
242
|
+
return script.code.snapshot;
|
|
243
|
+
}
|
|
259
244
|
}
|
|
260
|
-
|
|
261
|
-
if (sourceFile && !sourceFile.virtualFile) {
|
|
245
|
+
else if (sourceFile) {
|
|
262
246
|
return sourceFile.snapshot;
|
|
263
247
|
}
|
|
264
248
|
}
|
|
265
249
|
function getScriptVersion(fileName) {
|
|
266
|
-
syncSourceFile(fileName);
|
|
267
250
|
if (!scriptVersions.has(fileName)) {
|
|
268
251
|
scriptVersions.set(fileName, { lastVersion: 0, map: new WeakMap() });
|
|
269
252
|
}
|
|
270
253
|
const version = scriptVersions.get(fileName);
|
|
271
|
-
const
|
|
272
|
-
if (
|
|
273
|
-
|
|
274
|
-
|
|
254
|
+
const sourceFile = files.get(fileNameToFileId(fileName));
|
|
255
|
+
if (sourceFile?.generated) {
|
|
256
|
+
const script = sourceFile.generated.languagePlugin.typescript?.getScript(sourceFile.generated.code);
|
|
257
|
+
if (script) {
|
|
258
|
+
if (!version.map.has(script.code.snapshot)) {
|
|
259
|
+
version.map.set(script.code.snapshot, version.lastVersion++);
|
|
260
|
+
}
|
|
261
|
+
return version.map.get(script.code.snapshot).toString();
|
|
275
262
|
}
|
|
276
|
-
return version.map.get(virtualFile.snapshot).toString();
|
|
277
263
|
}
|
|
278
264
|
const isOpenedFile = !!projectHost.getScriptSnapshot(fileName);
|
|
279
265
|
if (isOpenedFile) {
|
|
280
|
-
const sourceFile = files.
|
|
281
|
-
if (sourceFile && !sourceFile.
|
|
266
|
+
const sourceFile = files.get(fileNameToFileId(fileName));
|
|
267
|
+
if (sourceFile && !sourceFile.generated) {
|
|
282
268
|
if (!version.map.has(sourceFile.snapshot)) {
|
|
283
269
|
version.map.set(sourceFile.snapshot, version.lastVersion++);
|
|
284
270
|
}
|
|
@@ -290,27 +276,17 @@ function createLanguage(ts, sys, languages, configFileName, projectHost) {
|
|
|
290
276
|
}
|
|
291
277
|
return '';
|
|
292
278
|
}
|
|
293
|
-
function getVirtualFileDirectories(dirName) {
|
|
294
|
-
const names = new Set();
|
|
295
|
-
for (const fileName of tsFileRegistry.keys()) {
|
|
296
|
-
if (fileName.toLowerCase().startsWith(dirName.toLowerCase())) {
|
|
297
|
-
const path = fileName.substring(dirName.length);
|
|
298
|
-
if (path.indexOf('/') >= 0) {
|
|
299
|
-
names.add(path.split('/')[0]);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return [...names];
|
|
304
|
-
}
|
|
305
279
|
}
|
|
306
280
|
}
|
|
307
281
|
exports.createLanguage = createLanguage;
|
|
308
282
|
function setEquals(a, b) {
|
|
309
|
-
if (a.size !== b.size)
|
|
283
|
+
if (a.size !== b.size) {
|
|
310
284
|
return false;
|
|
285
|
+
}
|
|
311
286
|
for (const item of a) {
|
|
312
|
-
if (!b.has(item))
|
|
287
|
+
if (!b.has(item)) {
|
|
313
288
|
return false;
|
|
289
|
+
}
|
|
314
290
|
}
|
|
315
291
|
return true;
|
|
316
292
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ServiceEnvironment, Disposable } from '@volar/language-service';
|
|
2
|
-
import type * as ts from 'typescript
|
|
3
|
-
export declare function createSys(ts: typeof import('typescript
|
|
1
|
+
import type { ServiceEnvironment, Disposable, TypeScriptProjectHost } from '@volar/language-service';
|
|
2
|
+
import type * as ts from 'typescript';
|
|
3
|
+
export declare function createSys(ts: typeof import('typescript'), env: ServiceEnvironment, projectHost: TypeScriptProjectHost): ts.System & {
|
|
4
4
|
version: number;
|
|
5
5
|
sync(): Promise<number>;
|
|
6
6
|
} & Disposable;
|
|
@@ -4,9 +4,9 @@ exports.createSys = void 0;
|
|
|
4
4
|
const path = require("path-browserify");
|
|
5
5
|
const utilities_1 = require("../typescript/utilities");
|
|
6
6
|
let currentCwd = '';
|
|
7
|
-
function createSys(ts, env,
|
|
7
|
+
function createSys(ts, env, projectHost) {
|
|
8
8
|
let version = 0;
|
|
9
|
-
const rootPath =
|
|
9
|
+
const rootPath = projectHost.getCurrentDirectory();
|
|
10
10
|
const sys = ts.sys;
|
|
11
11
|
const root = {
|
|
12
12
|
dirs: new Map(),
|
|
@@ -16,7 +16,7 @@ function createSys(ts, env, currentDirectory) {
|
|
|
16
16
|
const promises = new Set();
|
|
17
17
|
const fileWatcher = env.onDidChangeWatchedFiles?.(({ changes }) => {
|
|
18
18
|
for (const change of changes) {
|
|
19
|
-
const fileName = env.uriToFileName(change.uri);
|
|
19
|
+
const fileName = env.typescript.uriToFileName(change.uri);
|
|
20
20
|
const dirName = path.dirname(fileName);
|
|
21
21
|
const baseName = path.basename(fileName);
|
|
22
22
|
const dir = getDir(dirName);
|
|
@@ -107,7 +107,7 @@ function createSys(ts, env, currentDirectory) {
|
|
|
107
107
|
const dir = getDir(dirName);
|
|
108
108
|
if (dir.exists === undefined) {
|
|
109
109
|
dir.exists = false;
|
|
110
|
-
const result = env.fs?.stat(env.fileNameToUri(dirName));
|
|
110
|
+
const result = env.fs?.stat(env.typescript.fileNameToUri(dirName));
|
|
111
111
|
if (typeof result === 'object' && 'then' in result) {
|
|
112
112
|
const promise = result;
|
|
113
113
|
promises.add(promise);
|
|
@@ -148,7 +148,7 @@ function createSys(ts, env, currentDirectory) {
|
|
|
148
148
|
return exists();
|
|
149
149
|
}
|
|
150
150
|
function handleStat(fileName, file) {
|
|
151
|
-
const result = env.fs?.stat(env.fileNameToUri(fileName));
|
|
151
|
+
const result = env.fs?.stat(env.typescript.fileNameToUri(fileName));
|
|
152
152
|
if (typeof result === 'object' && 'then' in result) {
|
|
153
153
|
const promise = result;
|
|
154
154
|
promises.add(promise);
|
|
@@ -184,7 +184,7 @@ function createSys(ts, env, currentDirectory) {
|
|
|
184
184
|
}
|
|
185
185
|
function readDirectory(dirName, extensions, excludes, includes, depth) {
|
|
186
186
|
dirName = resolvePath(dirName);
|
|
187
|
-
const matches = (0, utilities_1.matchFiles)(dirName, extensions, excludes, includes, sys?.useCaseSensitiveFileNames ?? false, rootPath, depth,
|
|
187
|
+
const matches = (0, utilities_1.matchFiles)(dirName, extensions, excludes, includes, sys?.useCaseSensitiveFileNames ?? false, rootPath, depth, dirPath => {
|
|
188
188
|
dirPath = resolvePath(dirPath);
|
|
189
189
|
readDirectoryWorker(dirPath);
|
|
190
190
|
const dir = getDir(dirPath);
|
|
@@ -205,7 +205,7 @@ function createSys(ts, env, currentDirectory) {
|
|
|
205
205
|
return;
|
|
206
206
|
}
|
|
207
207
|
file.requestedText = true;
|
|
208
|
-
const uri = env.fileNameToUri(fileName);
|
|
208
|
+
const uri = env.typescript.fileNameToUri(fileName);
|
|
209
209
|
const result = env.fs?.readFile(uri, encoding);
|
|
210
210
|
if (typeof result === 'object' && 'then' in result) {
|
|
211
211
|
const promise = result;
|
|
@@ -231,11 +231,11 @@ function createSys(ts, env, currentDirectory) {
|
|
|
231
231
|
return;
|
|
232
232
|
}
|
|
233
233
|
dir.requestedRead = true;
|
|
234
|
-
const result = env.fs?.readDirectory(env.fileNameToUri(dirName || '.'));
|
|
234
|
+
const result = env.fs?.readDirectory(env.typescript.fileNameToUri(dirName || '.'));
|
|
235
235
|
if (typeof result === 'object' && 'then' in result) {
|
|
236
236
|
const promise = result;
|
|
237
237
|
promises.add(promise);
|
|
238
|
-
result.then(
|
|
238
|
+
result.then(result => {
|
|
239
239
|
promises.delete(promise);
|
|
240
240
|
if (onReadDirectoryResult(dirName, dir, result)) {
|
|
241
241
|
version++;
|
|
@@ -253,11 +253,11 @@ function createSys(ts, env, currentDirectory) {
|
|
|
253
253
|
for (const [name, _fileType] of result) {
|
|
254
254
|
let fileType = _fileType;
|
|
255
255
|
if (fileType === 64) {
|
|
256
|
-
const stat = env.fs?.stat(env.fileNameToUri(dirName + '/' + name));
|
|
256
|
+
const stat = env.fs?.stat(env.typescript.fileNameToUri(dirName + '/' + name));
|
|
257
257
|
if (typeof stat === 'object' && 'then' in stat) {
|
|
258
258
|
const promise = stat;
|
|
259
259
|
promises.add(promise);
|
|
260
|
-
stat.then(
|
|
260
|
+
stat.then(stat => {
|
|
261
261
|
promises.delete(promise);
|
|
262
262
|
if (stat?.type === 1) {
|
|
263
263
|
let file = dir.files.get(name);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type * as ts from 'typescript';
|
|
2
|
+
import { LanguagePlugin } from '@volar/language-core';
|
|
3
|
+
export declare function createAsyncLanguageServicePlugin(extensions: string[], scriptKind: ts.ScriptKind, loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => Promise<LanguagePlugin[]>): ts.server.PluginModuleFactory;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAsyncLanguageServicePlugin = 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 createLanguageServicePlugin_1 = require("./createLanguageServicePlugin");
|
|
8
|
+
const externalFiles = new WeakMap();
|
|
9
|
+
const decoratedLanguageServices = new WeakSet();
|
|
10
|
+
const decoratedLanguageServiceHosts = new WeakSet();
|
|
11
|
+
function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePlugins) {
|
|
12
|
+
return modules => {
|
|
13
|
+
const { typescript: ts } = modules;
|
|
14
|
+
const pluginModule = {
|
|
15
|
+
create(info) {
|
|
16
|
+
if (!decoratedLanguageServices.has(info.languageService)
|
|
17
|
+
&& !decoratedLanguageServiceHosts.has(info.languageServiceHost)) {
|
|
18
|
+
decoratedLanguageServices.add(info.languageService);
|
|
19
|
+
decoratedLanguageServiceHosts.add(info.languageServiceHost);
|
|
20
|
+
const emptySnapshot = ts.ScriptSnapshot.fromString('');
|
|
21
|
+
const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
|
|
22
|
+
const getScriptVersion = info.languageServiceHost.getScriptVersion.bind(info.languageServiceHost);
|
|
23
|
+
const getScriptKind = info.languageServiceHost.getScriptKind?.bind(info.languageServiceHost);
|
|
24
|
+
const getProjectVersion = info.languageServiceHost.getProjectVersion?.bind(info.languageServiceHost);
|
|
25
|
+
let initialized = false;
|
|
26
|
+
info.languageServiceHost.getScriptSnapshot = fileName => {
|
|
27
|
+
if (!initialized && extensions.some(ext => fileName.endsWith(ext))) {
|
|
28
|
+
return emptySnapshot;
|
|
29
|
+
}
|
|
30
|
+
return getScriptSnapshot(fileName);
|
|
31
|
+
};
|
|
32
|
+
info.languageServiceHost.getScriptVersion = fileName => {
|
|
33
|
+
if (!initialized && extensions.some(ext => fileName.endsWith(ext))) {
|
|
34
|
+
return 'initializing...';
|
|
35
|
+
}
|
|
36
|
+
return getScriptVersion(fileName);
|
|
37
|
+
};
|
|
38
|
+
if (getScriptKind) {
|
|
39
|
+
info.languageServiceHost.getScriptKind = fileName => {
|
|
40
|
+
if (!initialized && extensions.some(ext => fileName.endsWith(ext))) {
|
|
41
|
+
return scriptKind; // TODO: bypass upstream bug
|
|
42
|
+
}
|
|
43
|
+
return getScriptKind(fileName);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (getProjectVersion) {
|
|
47
|
+
info.languageServiceHost.getProjectVersion = () => {
|
|
48
|
+
if (!initialized) {
|
|
49
|
+
return getProjectVersion() + ',initializing...';
|
|
50
|
+
}
|
|
51
|
+
return getProjectVersion();
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
loadLanguagePlugins(ts, info).then(languagePlugins => {
|
|
55
|
+
const files = (0, language_core_1.createFileRegistry)(languagePlugins, ts.sys.useCaseSensitiveFileNames, fileName => {
|
|
56
|
+
const snapshot = getScriptSnapshot(fileName);
|
|
57
|
+
if (snapshot) {
|
|
58
|
+
files.set(fileName, (0, language_core_1.resolveCommonLanguageId)(fileName), snapshot);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
files.delete(fileName);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
(0, decorateLanguageService_1.decorateLanguageService)(files, info.languageService);
|
|
65
|
+
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(files, info.languageServiceHost, ts);
|
|
66
|
+
info.project.markAsDirty();
|
|
67
|
+
initialized = true;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return info.languageService;
|
|
71
|
+
},
|
|
72
|
+
getExternalFiles(project, updateLevel = 0) {
|
|
73
|
+
if (updateLevel >= (1)
|
|
74
|
+
|| !externalFiles.has(project)) {
|
|
75
|
+
const oldFiles = externalFiles.get(project);
|
|
76
|
+
const newFiles = (0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, extensions);
|
|
77
|
+
externalFiles.set(project, newFiles);
|
|
78
|
+
if (oldFiles && !(0, createLanguageServicePlugin_1.arrayItemsEqual)(oldFiles, newFiles)) {
|
|
79
|
+
project.refreshDiagnostics();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return externalFiles.get(project);
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
return pluginModule;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
exports.createAsyncLanguageServicePlugin = createAsyncLanguageServicePlugin;
|
|
89
|
+
//# sourceMappingURL=createAsyncLanguageServicePlugin.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type * as ts from 'typescript';
|
|
2
|
+
import { LanguagePlugin } from '@volar/language-core';
|
|
3
|
+
export declare function createAsyncTSServerPlugin(extensions: string[], scriptKind: ts.ScriptKind, loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => Promise<LanguagePlugin[]>): ts.server.PluginModuleFactory;
|
|
@@ -0,0 +1,89 @@
|
|
|
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
|
+
const decoratedLanguageServices = new WeakSet();
|
|
10
|
+
const decoratedLanguageServiceHosts = new WeakSet();
|
|
11
|
+
function createAsyncTSServerPlugin(extensions, scriptKind, loadLanguagePlugins) {
|
|
12
|
+
return modules => {
|
|
13
|
+
const { typescript: ts } = modules;
|
|
14
|
+
const pluginModule = {
|
|
15
|
+
create(info) {
|
|
16
|
+
if (!decoratedLanguageServices.has(info.languageService)
|
|
17
|
+
&& !decoratedLanguageServiceHosts.has(info.languageServiceHost)) {
|
|
18
|
+
decoratedLanguageServices.add(info.languageService);
|
|
19
|
+
decoratedLanguageServiceHosts.add(info.languageServiceHost);
|
|
20
|
+
const emptySnapshot = ts.ScriptSnapshot.fromString('');
|
|
21
|
+
const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
|
|
22
|
+
const getScriptVersion = info.languageServiceHost.getScriptVersion.bind(info.languageServiceHost);
|
|
23
|
+
const getScriptKind = info.languageServiceHost.getScriptKind?.bind(info.languageServiceHost);
|
|
24
|
+
const getProjectVersion = info.languageServiceHost.getProjectVersion?.bind(info.languageServiceHost);
|
|
25
|
+
let initialized = false;
|
|
26
|
+
info.languageServiceHost.getScriptSnapshot = fileName => {
|
|
27
|
+
if (!initialized && extensions.some(ext => fileName.endsWith(ext))) {
|
|
28
|
+
return emptySnapshot;
|
|
29
|
+
}
|
|
30
|
+
return getScriptSnapshot(fileName);
|
|
31
|
+
};
|
|
32
|
+
info.languageServiceHost.getScriptVersion = fileName => {
|
|
33
|
+
if (!initialized && extensions.some(ext => fileName.endsWith(ext))) {
|
|
34
|
+
return 'initializing...';
|
|
35
|
+
}
|
|
36
|
+
return getScriptVersion(fileName);
|
|
37
|
+
};
|
|
38
|
+
if (getScriptKind) {
|
|
39
|
+
info.languageServiceHost.getScriptKind = fileName => {
|
|
40
|
+
if (!initialized && extensions.some(ext => fileName.endsWith(ext))) {
|
|
41
|
+
return scriptKind; // TODO: bypass upstream bug
|
|
42
|
+
}
|
|
43
|
+
return getScriptKind(fileName);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (getProjectVersion) {
|
|
47
|
+
info.languageServiceHost.getProjectVersion = () => {
|
|
48
|
+
if (!initialized) {
|
|
49
|
+
return getProjectVersion() + ',initializing...';
|
|
50
|
+
}
|
|
51
|
+
return getProjectVersion();
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
loadLanguagePlugins(ts, info).then(languagePlugins => {
|
|
55
|
+
const files = (0, language_core_1.createFileRegistry)(languagePlugins, ts.sys.useCaseSensitiveFileNames, fileName => {
|
|
56
|
+
const snapshot = getScriptSnapshot(fileName);
|
|
57
|
+
if (snapshot) {
|
|
58
|
+
files.set(fileName, (0, language_core_1.resolveCommonLanguageId)(fileName), snapshot);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
files.delete(fileName);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
(0, decorateLanguageService_1.decorateLanguageService)(files, info.languageService);
|
|
65
|
+
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(files, info.languageServiceHost, ts);
|
|
66
|
+
info.project.markAsDirty();
|
|
67
|
+
initialized = true;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return info.languageService;
|
|
71
|
+
},
|
|
72
|
+
getExternalFiles(project, updateLevel = 0) {
|
|
73
|
+
if (updateLevel >= (1)
|
|
74
|
+
|| !externalFiles.has(project)) {
|
|
75
|
+
const oldFiles = externalFiles.get(project);
|
|
76
|
+
const newFiles = (0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, extensions);
|
|
77
|
+
externalFiles.set(project, newFiles);
|
|
78
|
+
if (oldFiles && !(0, createTSServerPlugin_1.arrayItemsEqual)(oldFiles, newFiles)) {
|
|
79
|
+
project.refreshDiagnostics();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return externalFiles.get(project);
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
return pluginModule;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
exports.createAsyncTSServerPlugin = createAsyncTSServerPlugin;
|
|
89
|
+
//# sourceMappingURL=createAsyncTSServerPlugin.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type * as ts from 'typescript';
|
|
2
|
+
import { LanguagePlugin } from '@volar/language-core';
|
|
3
|
+
export declare function createLanguageServicePlugin(loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => LanguagePlugin[]): ts.server.PluginModuleFactory;
|
|
4
|
+
export declare function arrayItemsEqual(a: string[], b: string[]): boolean;
|