@volar/typescript 1.9.1 → 1.10.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/out/languageServiceHost.d.ts +2 -1
- package/out/languageServiceHost.js +51 -3
- package/out/sys.js +50 -41
- package/package.json +4 -4
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { LanguageContext } from '@volar/language-core';
|
|
2
2
|
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
3
|
+
import { ServiceEnvironment } from '@volar/language-service';
|
|
3
4
|
export declare function createLanguageServiceHost(ctx: LanguageContext, ts: typeof import('typescript/lib/tsserverlibrary'), sys: ts.System & {
|
|
4
5
|
version?: number;
|
|
5
|
-
}): ts.LanguageServiceHost;
|
|
6
|
+
}, env: ServiceEnvironment | undefined): ts.LanguageServiceHost;
|
|
@@ -4,7 +4,7 @@ exports.createLanguageServiceHost = void 0;
|
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
const utilities_1 = require("./typescript/utilities");
|
|
6
6
|
const fileVersions = new Map();
|
|
7
|
-
function createLanguageServiceHost(ctx, ts, sys) {
|
|
7
|
+
function createLanguageServiceHost(ctx, ts, sys, env) {
|
|
8
8
|
let lastProjectVersion;
|
|
9
9
|
let tsProjectVersion = 0;
|
|
10
10
|
let tsFileNames = [];
|
|
@@ -15,8 +15,6 @@ function createLanguageServiceHost(ctx, ts, sys) {
|
|
|
15
15
|
getCancellationToken: ctx.host.getCancellationToken ? () => ctx.host.getCancellationToken() : undefined,
|
|
16
16
|
getLocalizedDiagnosticMessages: ctx.host.getLocalizedDiagnosticMessages ? () => ctx.host.getLocalizedDiagnosticMessages() : undefined,
|
|
17
17
|
getProjectReferences: ctx.host.getProjectReferences ? () => ctx.host.getProjectReferences() : undefined,
|
|
18
|
-
resolveModuleNames: ctx.host.resolveModuleNames ? (...args) => ctx.host.resolveModuleNames(...args) : undefined,
|
|
19
|
-
resolveModuleNameLiterals: ctx.host.resolveModuleNameLiterals ? (...args) => ctx.host.resolveModuleNameLiterals(...args) : undefined,
|
|
20
18
|
getDefaultLibFileName: (options) => {
|
|
21
19
|
try {
|
|
22
20
|
return ts.getDefaultLibFilePath(options);
|
|
@@ -68,6 +66,35 @@ function createLanguageServiceHost(ctx, ts, sys) {
|
|
|
68
66
|
},
|
|
69
67
|
};
|
|
70
68
|
const fsFileSnapshots = new Map();
|
|
69
|
+
if (ctx.host.resolveModuleName) {
|
|
70
|
+
// TODO: can this share between monorepo packages?
|
|
71
|
+
const moduleCache = ts.createModuleResolutionCache(_tsHost.getCurrentDirectory(), _tsHost.useCaseSensitiveFileNames ? s => s : s => s.toLowerCase(), _tsHost.getCompilationSettings());
|
|
72
|
+
const watching = !!env?.onDidChangeWatchedFiles?.(() => {
|
|
73
|
+
moduleCache.clear();
|
|
74
|
+
});
|
|
75
|
+
let lastProjectVersion = ctx.host.getProjectVersion();
|
|
76
|
+
_tsHost.resolveModuleNameLiterals = (moduleLiterals, containingFile, redirectedReference, options, sourceFile) => {
|
|
77
|
+
if (!watching && lastProjectVersion !== ctx.host.getProjectVersion()) {
|
|
78
|
+
lastProjectVersion = ctx.host.getProjectVersion();
|
|
79
|
+
moduleCache.clear();
|
|
80
|
+
}
|
|
81
|
+
return moduleLiterals.map((moduleLiteral) => {
|
|
82
|
+
let moduleName = moduleLiteral.text;
|
|
83
|
+
moduleName = ctx.host.resolveModuleName(moduleName, sourceFile.impliedNodeFormat);
|
|
84
|
+
return ts.resolveModuleName(moduleName, containingFile, options, _tsHost, moduleCache, redirectedReference, sourceFile.impliedNodeFormat);
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
_tsHost.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference, options, sourceFile) => {
|
|
88
|
+
if (!watching && lastProjectVersion !== ctx.host.getProjectVersion()) {
|
|
89
|
+
lastProjectVersion = ctx.host.getProjectVersion();
|
|
90
|
+
moduleCache.clear();
|
|
91
|
+
}
|
|
92
|
+
return moduleNames.map((moduleName) => {
|
|
93
|
+
moduleName = ctx.host.resolveModuleName(moduleName, sourceFile?.impliedNodeFormat);
|
|
94
|
+
return ts.resolveModuleName(moduleName, containingFile, options, _tsHost, moduleCache, redirectedReference, sourceFile?.impliedNodeFormat).resolvedModule;
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
}
|
|
71
98
|
let oldTsVirtualFileSnapshots = new Set();
|
|
72
99
|
let oldOtherVirtualFileSnapshots = new Set();
|
|
73
100
|
return new Proxy(_tsHost, {
|
|
@@ -212,6 +239,27 @@ function createLanguageServiceHost(ctx, ts, sys) {
|
|
|
212
239
|
|| tsFileNames.some(fileName => fileName.toLowerCase().startsWith(dirName.toLowerCase()));
|
|
213
240
|
}
|
|
214
241
|
function fileExists(fileName) {
|
|
242
|
+
// fill external virtual files
|
|
243
|
+
const ext = fileName.substring(fileName.lastIndexOf('.'));
|
|
244
|
+
if (ext === '.js'
|
|
245
|
+
|| ext === '.ts'
|
|
246
|
+
|| ext === '.jsx'
|
|
247
|
+
|| ext === '.tsx') {
|
|
248
|
+
/**
|
|
249
|
+
* If try to access a external .vue file that outside of the project,
|
|
250
|
+
* the file will not process by language service host,
|
|
251
|
+
* so virtual file will not be created.
|
|
252
|
+
*
|
|
253
|
+
* We try to create virtual file here.
|
|
254
|
+
*/
|
|
255
|
+
const sourceFileName = fileName.substring(0, fileName.lastIndexOf('.'));
|
|
256
|
+
if (!ctx.virtualFiles.hasSource(sourceFileName)) {
|
|
257
|
+
const scriptSnapshot = getScriptSnapshot(sourceFileName);
|
|
258
|
+
if (scriptSnapshot) {
|
|
259
|
+
ctx.virtualFiles.updateSource(sourceFileName, scriptSnapshot, ctx.host.getLanguageId?.(sourceFileName));
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
215
263
|
// virtual files
|
|
216
264
|
if (ctx.virtualFiles.hasVirtualFile(fileName)) {
|
|
217
265
|
return true;
|
package/out/sys.js
CHANGED
|
@@ -6,12 +6,12 @@ const utilities_1 = require("./typescript/utilities");
|
|
|
6
6
|
let currentCwd = '';
|
|
7
7
|
function createSys(ts, env) {
|
|
8
8
|
let version = 0;
|
|
9
|
-
const rootPath = env.uriToFileName(env.
|
|
9
|
+
const rootPath = env.uriToFileName(env.workspaceUri.toString());
|
|
10
10
|
const sys = ts.sys;
|
|
11
11
|
const root = {
|
|
12
12
|
dirs: {},
|
|
13
13
|
files: {},
|
|
14
|
-
|
|
14
|
+
requestedRead: false,
|
|
15
15
|
};
|
|
16
16
|
const promises = new Set();
|
|
17
17
|
const fileWatcher = env.onDidChangeWatchedFiles?.(({ changes }) => {
|
|
@@ -22,14 +22,24 @@ function createSys(ts, env) {
|
|
|
22
22
|
const dir = getDir(dirName);
|
|
23
23
|
if (dir.files[baseName]) { // is requested file
|
|
24
24
|
version++;
|
|
25
|
-
if (change.type === 1) {
|
|
26
|
-
dir.files[baseName] = {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
if (change.type === 1 || change.type === 2) {
|
|
26
|
+
dir.files[baseName] = {
|
|
27
|
+
stat: {
|
|
28
|
+
type: 1,
|
|
29
|
+
ctime: Date.now(),
|
|
30
|
+
mtime: Date.now(),
|
|
31
|
+
size: -1,
|
|
32
|
+
},
|
|
33
|
+
requestedStat: false,
|
|
34
|
+
};
|
|
30
35
|
}
|
|
31
36
|
else if (change.type === 3) {
|
|
32
|
-
dir.files[baseName] = {
|
|
37
|
+
dir.files[baseName] = {
|
|
38
|
+
stat: undefined,
|
|
39
|
+
text: undefined,
|
|
40
|
+
requestedStat: true,
|
|
41
|
+
requestedText: true,
|
|
42
|
+
};
|
|
33
43
|
}
|
|
34
44
|
}
|
|
35
45
|
}
|
|
@@ -117,20 +127,24 @@ function createSys(ts, env) {
|
|
|
117
127
|
function getModifiedTime(fileName) {
|
|
118
128
|
fileName = resolvePath(fileName);
|
|
119
129
|
const file = getFile(fileName);
|
|
120
|
-
if (file.
|
|
121
|
-
file.
|
|
130
|
+
if (!file.requestedStat) {
|
|
131
|
+
file.requestedStat = true;
|
|
122
132
|
handleStat(fileName, file);
|
|
123
133
|
}
|
|
124
|
-
return file.
|
|
134
|
+
return file.stat ? new Date(file.stat.mtime) : new Date(0);
|
|
125
135
|
}
|
|
126
136
|
function fileExists(fileName) {
|
|
127
137
|
fileName = resolvePath(fileName);
|
|
128
138
|
const file = getFile(fileName);
|
|
129
|
-
|
|
130
|
-
|
|
139
|
+
const exists = () => file.text !== undefined || file.stat?.type === 1;
|
|
140
|
+
if (exists()) {
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
if (!file.requestedStat) {
|
|
144
|
+
file.requestedStat = true;
|
|
131
145
|
handleStat(fileName, file);
|
|
132
146
|
}
|
|
133
|
-
return
|
|
147
|
+
return exists();
|
|
134
148
|
}
|
|
135
149
|
function handleStat(fileName, file) {
|
|
136
150
|
const result = env.fs?.stat(env.fileNameToUri(fileName));
|
|
@@ -139,21 +153,14 @@ function createSys(ts, env) {
|
|
|
139
153
|
promises.add(promise);
|
|
140
154
|
result.then(result => {
|
|
141
155
|
promises.delete(promise);
|
|
142
|
-
file.
|
|
143
|
-
if (result) {
|
|
144
|
-
file.modifiedTime = new Date(result.mtime);
|
|
145
|
-
}
|
|
146
|
-
if (file.exists) {
|
|
147
|
-
file.requested = false;
|
|
156
|
+
if (file.stat?.type !== result?.type || file.stat?.mtime !== result?.mtime) {
|
|
148
157
|
version++;
|
|
149
158
|
}
|
|
159
|
+
file.stat = result;
|
|
150
160
|
});
|
|
151
161
|
}
|
|
152
162
|
else {
|
|
153
|
-
file.
|
|
154
|
-
if (result) {
|
|
155
|
-
file.modifiedTime = new Date(result.mtime);
|
|
156
|
-
}
|
|
163
|
+
file.stat = result;
|
|
157
164
|
}
|
|
158
165
|
}
|
|
159
166
|
function getFile(fileName) {
|
|
@@ -178,7 +185,7 @@ function createSys(ts, env) {
|
|
|
178
185
|
readDirectoryWorker(dirPath);
|
|
179
186
|
const dir = getDir(dirPath);
|
|
180
187
|
return {
|
|
181
|
-
files: [...Object.entries(dir.files)].filter(([_, file]) => file.
|
|
188
|
+
files: [...Object.entries(dir.files)].filter(([_, file]) => file.stat?.type === 1).map(([name]) => name),
|
|
182
189
|
directories: [...Object.entries(dir.dirs)].filter(([_, dir]) => dir.exists).map(([name]) => name),
|
|
183
190
|
};
|
|
184
191
|
}, sys?.realpath ? (path => sys.realpath(path)) : (path => path));
|
|
@@ -188,10 +195,10 @@ function createSys(ts, env) {
|
|
|
188
195
|
const name = path_1.posix.basename(fileName);
|
|
189
196
|
dir.files[name] ??= {};
|
|
190
197
|
const file = dir.files[name];
|
|
191
|
-
if (file.
|
|
198
|
+
if (file.requestedText) {
|
|
192
199
|
return;
|
|
193
200
|
}
|
|
194
|
-
file.
|
|
201
|
+
file.requestedText = true;
|
|
195
202
|
const uri = env.fileNameToUri(fileName);
|
|
196
203
|
const result = env.fs?.readFile(uri, encoding);
|
|
197
204
|
if (typeof result === 'object' && 'then' in result) {
|
|
@@ -200,29 +207,24 @@ function createSys(ts, env) {
|
|
|
200
207
|
result.then(result => {
|
|
201
208
|
promises.delete(promise);
|
|
202
209
|
if (result !== undefined) {
|
|
203
|
-
file.exists = true;
|
|
204
210
|
file.text = result;
|
|
211
|
+
if (file.stat) {
|
|
212
|
+
file.stat.mtime++;
|
|
213
|
+
}
|
|
205
214
|
version++;
|
|
206
215
|
}
|
|
207
|
-
else {
|
|
208
|
-
file.exists = false;
|
|
209
|
-
}
|
|
210
216
|
});
|
|
211
217
|
}
|
|
212
218
|
else if (result !== undefined) {
|
|
213
|
-
file.exists = true;
|
|
214
219
|
file.text = result;
|
|
215
220
|
}
|
|
216
|
-
else {
|
|
217
|
-
file.exists = false;
|
|
218
|
-
}
|
|
219
221
|
}
|
|
220
222
|
function readDirectoryWorker(dirName) {
|
|
221
223
|
const dir = getDir(dirName);
|
|
222
|
-
if (dir.
|
|
224
|
+
if (dir.requestedRead) {
|
|
223
225
|
return;
|
|
224
226
|
}
|
|
225
|
-
dir.
|
|
227
|
+
dir.requestedRead = true;
|
|
226
228
|
const result = env.fs?.readDirectory(env.fileNameToUri(dirName || '.'));
|
|
227
229
|
if (typeof result === 'object' && 'then' in result) {
|
|
228
230
|
const promise = result;
|
|
@@ -253,10 +255,12 @@ function createSys(ts, env) {
|
|
|
253
255
|
promises.delete(promise);
|
|
254
256
|
if (stat?.type === 1) {
|
|
255
257
|
dir.files[name] ??= {};
|
|
256
|
-
|
|
257
|
-
|
|
258
|
+
const file = dir.files[name];
|
|
259
|
+
if (stat.type !== file.stat?.type || stat.mtime !== file.stat.mtime) {
|
|
258
260
|
version++;
|
|
259
261
|
}
|
|
262
|
+
file.stat = stat;
|
|
263
|
+
file.requestedStat = true;
|
|
260
264
|
}
|
|
261
265
|
else if (stat?.type === 2) {
|
|
262
266
|
const childDir = getDirFromDir(dir, name);
|
|
@@ -273,8 +277,13 @@ function createSys(ts, env) {
|
|
|
273
277
|
}
|
|
274
278
|
if (fileType === 1) {
|
|
275
279
|
dir.files[name] ??= {};
|
|
276
|
-
if (!dir.files[name].
|
|
277
|
-
dir.files[name].
|
|
280
|
+
if (!dir.files[name].stat) {
|
|
281
|
+
dir.files[name].stat = {
|
|
282
|
+
type: 1,
|
|
283
|
+
mtime: 0,
|
|
284
|
+
ctime: 0,
|
|
285
|
+
size: 0,
|
|
286
|
+
};
|
|
278
287
|
updated = true;
|
|
279
288
|
}
|
|
280
289
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volar/typescript",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"main": "out/index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
"directory": "packages/typescript"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@volar/language-core": "1.
|
|
16
|
+
"@volar/language-core": "1.10.0"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@volar/language-service": "1.
|
|
19
|
+
"@volar/language-service": "1.10.0"
|
|
20
20
|
},
|
|
21
|
-
"gitHead": "
|
|
21
|
+
"gitHead": "c25bdec20ee11d278049a738743c694431f08796"
|
|
22
22
|
}
|