@litsx/typescript 0.6.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/README.md +85 -0
- package/dist/authored-semantics.cjs +18567 -0
- package/dist/authored-semantics.cjs.map +1 -0
- package/dist/editor-session.cjs +1345 -0
- package/dist/editor-session.cjs.map +1 -0
- package/dist/index.cjs +841 -0
- package/dist/index.cjs.map +1 -0
- package/dist/litsx-tsc.js +18025 -0
- package/dist/typecheck.cjs +931 -0
- package/dist/typecheck.cjs.map +1 -0
- package/dist/virtualization.cjs +113 -0
- package/dist/virtualization.cjs.map +1 -0
- package/package.json +76 -0
- package/src/authored-semantics.js +1543 -0
- package/src/editor-session.js +1360 -0
- package/src/index.js +844 -0
- package/src/litsx-tsc.js +4 -0
- package/src/typecheck.js +535 -0
- package/src/virtualization.js +125 -0
- package/tsserver-plugin.cjs +11 -0
|
@@ -0,0 +1,931 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var url = require('url');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
var ts = require('typescript');
|
|
6
|
+
var module$1 = require('module');
|
|
7
|
+
var virtualization = require('./virtualization.cjs');
|
|
8
|
+
var authoredSemantics = require('./authored-semantics.cjs');
|
|
9
|
+
|
|
10
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
11
|
+
const PROJECT_SESSION_CACHE = new Map();
|
|
12
|
+
const SESSION_CACHE_LIMIT = 50;
|
|
13
|
+
const EXTRA_FILE_EXTENSIONS = [
|
|
14
|
+
{
|
|
15
|
+
extension: ".litsx",
|
|
16
|
+
isMixedContent: false,
|
|
17
|
+
scriptKind: 4,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
extension: ".litsx.jsx",
|
|
21
|
+
isMixedContent: false,
|
|
22
|
+
scriptKind: 2,
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
(() => {
|
|
26
|
+
try {
|
|
27
|
+
return module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('typecheck.cjs', document.baseURI).href)));
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
})();
|
|
32
|
+
|
|
33
|
+
function trimCacheToLimit$1(cache, limit) {
|
|
34
|
+
while (cache.size > limit) {
|
|
35
|
+
const oldestKey = cache.keys().next().value;
|
|
36
|
+
if (oldestKey == null) break;
|
|
37
|
+
cache.delete(oldestKey);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function normalizeFilePath(value) {
|
|
42
|
+
if (!value) return "";
|
|
43
|
+
return String(value).replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function inferScriptKind(ts, filePath) {
|
|
47
|
+
const normalized = normalizeFilePath(filePath);
|
|
48
|
+
|
|
49
|
+
if (normalized.endsWith(".litsx")) {
|
|
50
|
+
return ts.ScriptKind.TSX;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (normalized.endsWith(".litsx.jsx")) {
|
|
54
|
+
return ts.ScriptKind.JSX;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (normalized.endsWith(".tsx")) {
|
|
58
|
+
return ts.ScriptKind.TSX;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (normalized.endsWith(".jsx")) {
|
|
62
|
+
return ts.ScriptKind.JSX;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (normalized.endsWith(".ts")) {
|
|
66
|
+
return ts.ScriptKind.TS;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (normalized.endsWith(".js")) {
|
|
70
|
+
return ts.ScriptKind.JS;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function createSourceTextCache() {
|
|
77
|
+
return new Map();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function createSourceFileCache() {
|
|
81
|
+
return new Map();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function createSessionBase({
|
|
85
|
+
kind,
|
|
86
|
+
key,
|
|
87
|
+
typescript,
|
|
88
|
+
}) {
|
|
89
|
+
return {
|
|
90
|
+
kind,
|
|
91
|
+
key,
|
|
92
|
+
typescript,
|
|
93
|
+
host: null,
|
|
94
|
+
hostConfigKey: null,
|
|
95
|
+
program: null,
|
|
96
|
+
programKey: null,
|
|
97
|
+
overlayFiles: new Map(),
|
|
98
|
+
semanticCaches: new Map(),
|
|
99
|
+
sourceTextCache: createSourceTextCache(),
|
|
100
|
+
sourceFileCache: createSourceFileCache(),
|
|
101
|
+
invalidate({ host = false } = {}) {
|
|
102
|
+
this.program = null;
|
|
103
|
+
this.programKey = null;
|
|
104
|
+
this.semanticCaches.clear();
|
|
105
|
+
if (host) {
|
|
106
|
+
this.host = null;
|
|
107
|
+
this.hostConfigKey = null;
|
|
108
|
+
this.sourceTextCache.clear();
|
|
109
|
+
this.sourceFileCache.clear();
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
getSemanticCache(name, factory = () => new Map()) {
|
|
113
|
+
if (!this.semanticCaches.has(name)) {
|
|
114
|
+
this.semanticCaches.set(name, factory());
|
|
115
|
+
}
|
|
116
|
+
return this.semanticCaches.get(name);
|
|
117
|
+
},
|
|
118
|
+
setOverlayFile(fileName, sourceText) {
|
|
119
|
+
this.overlayFiles.set(normalizeFilePath(fileName), sourceText);
|
|
120
|
+
},
|
|
121
|
+
clearOverlayFile(fileName) {
|
|
122
|
+
this.overlayFiles.delete(normalizeFilePath(fileName));
|
|
123
|
+
},
|
|
124
|
+
clearOverlayFiles() {
|
|
125
|
+
this.overlayFiles.clear();
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function getCachedSourceText(session, fileName, sourceText, transformKey, transform) {
|
|
131
|
+
const normalizedFileName = normalizeFilePath(fileName);
|
|
132
|
+
const cacheKey = `${normalizedFileName}:${transformKey}`;
|
|
133
|
+
const cached = session.sourceTextCache.get(cacheKey);
|
|
134
|
+
if (cached?.sourceText === sourceText) {
|
|
135
|
+
return cached.transformedText;
|
|
136
|
+
}
|
|
137
|
+
const transformedText = transform ? transform(fileName, sourceText) : sourceText;
|
|
138
|
+
session.sourceTextCache.set(cacheKey, {
|
|
139
|
+
sourceText,
|
|
140
|
+
transformedText,
|
|
141
|
+
});
|
|
142
|
+
return transformedText;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function getCachedSourceFile(session, fileName, sourceText, languageVersion, scriptKind, transformKey, transform) {
|
|
146
|
+
const normalizedFileName = normalizeFilePath(fileName);
|
|
147
|
+
const transformedText = getCachedSourceText(
|
|
148
|
+
session,
|
|
149
|
+
fileName,
|
|
150
|
+
sourceText,
|
|
151
|
+
transformKey,
|
|
152
|
+
transform,
|
|
153
|
+
);
|
|
154
|
+
const cacheKey = `${normalizedFileName}:${String(languageVersion)}:${String(scriptKind ?? "")}:${transformKey}`;
|
|
155
|
+
let fileCache = session.sourceFileCache.get(cacheKey);
|
|
156
|
+
if (!fileCache) {
|
|
157
|
+
fileCache = new Map();
|
|
158
|
+
session.sourceFileCache.set(cacheKey, fileCache);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const cachedSourceFile = fileCache.get(sourceText);
|
|
162
|
+
if (cachedSourceFile) {
|
|
163
|
+
return cachedSourceFile;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const sourceFile = session.typescript.createSourceFile(
|
|
167
|
+
fileName,
|
|
168
|
+
transformedText,
|
|
169
|
+
languageVersion,
|
|
170
|
+
true,
|
|
171
|
+
scriptKind ?? inferScriptKind(session.typescript, fileName),
|
|
172
|
+
);
|
|
173
|
+
fileCache.set(sourceText, sourceFile);
|
|
174
|
+
return sourceFile;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function attachSourceFileVersion(sourceFile, version) {
|
|
178
|
+
if (!sourceFile || typeof sourceFile !== "object") {
|
|
179
|
+
return sourceFile;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (sourceFile.version == null) {
|
|
183
|
+
sourceFile.version = version;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return sourceFile;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function createProjectHost(session, config) {
|
|
190
|
+
const ts = session.typescript;
|
|
191
|
+
const host =
|
|
192
|
+
typeof ts.createIncrementalCompilerHost === "function"
|
|
193
|
+
? ts.createIncrementalCompilerHost(config.parsedCommandLine.options)
|
|
194
|
+
: ts.createCompilerHost(config.parsedCommandLine.options);
|
|
195
|
+
const originalReadFile = host.readFile.bind(host);
|
|
196
|
+
const originalGetSourceFile = host.getSourceFile.bind(host);
|
|
197
|
+
host.extraFileExtensions = EXTRA_FILE_EXTENSIONS;
|
|
198
|
+
|
|
199
|
+
if (typeof host.useCaseSensitiveFileNames !== "function") {
|
|
200
|
+
host.useCaseSensitiveFileNames = () => ts.sys.useCaseSensitiveFileNames;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
session.readFile = (fileName) => originalReadFile(fileName);
|
|
204
|
+
|
|
205
|
+
host.readFile = (fileName) => {
|
|
206
|
+
const normalizedFileName = normalizeFilePath(fileName);
|
|
207
|
+
if (session.overlayFiles.has(normalizedFileName)) {
|
|
208
|
+
return session.overlayFiles.get(normalizedFileName);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const sourceText = originalReadFile(fileName);
|
|
212
|
+
if (typeof sourceText !== "string") {
|
|
213
|
+
return sourceText;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return getCachedSourceText(session, fileName, sourceText, "project", null);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
host.getSourceFile = (
|
|
220
|
+
fileName,
|
|
221
|
+
languageVersion,
|
|
222
|
+
onError,
|
|
223
|
+
shouldCreateNewSourceFile,
|
|
224
|
+
scriptKind,
|
|
225
|
+
) => {
|
|
226
|
+
const normalizedFileName = normalizeFilePath(fileName);
|
|
227
|
+
if (session.overlayFiles.has(normalizedFileName)) {
|
|
228
|
+
const sourceText = session.overlayFiles.get(normalizedFileName);
|
|
229
|
+
return attachSourceFileVersion(
|
|
230
|
+
getCachedSourceFile(
|
|
231
|
+
session,
|
|
232
|
+
fileName,
|
|
233
|
+
sourceText,
|
|
234
|
+
languageVersion,
|
|
235
|
+
scriptKind,
|
|
236
|
+
"overlay",
|
|
237
|
+
null,
|
|
238
|
+
),
|
|
239
|
+
sourceText,
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const sourceText = originalReadFile(fileName);
|
|
244
|
+
if (typeof sourceText !== "string") {
|
|
245
|
+
return attachSourceFileVersion(
|
|
246
|
+
originalGetSourceFile(
|
|
247
|
+
fileName,
|
|
248
|
+
languageVersion,
|
|
249
|
+
onError,
|
|
250
|
+
shouldCreateNewSourceFile,
|
|
251
|
+
scriptKind,
|
|
252
|
+
),
|
|
253
|
+
"",
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return attachSourceFileVersion(
|
|
258
|
+
getCachedSourceFile(
|
|
259
|
+
session,
|
|
260
|
+
fileName,
|
|
261
|
+
sourceText,
|
|
262
|
+
languageVersion,
|
|
263
|
+
scriptKind,
|
|
264
|
+
"project",
|
|
265
|
+
null,
|
|
266
|
+
),
|
|
267
|
+
sourceText,
|
|
268
|
+
);
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
return host;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function createProjectProgramKey(parsedCommandLine) {
|
|
275
|
+
return JSON.stringify({
|
|
276
|
+
options: parsedCommandLine.options,
|
|
277
|
+
fileNames: parsedCommandLine.fileNames,
|
|
278
|
+
projectReferences: parsedCommandLine.projectReferences?.map((reference) => reference.path),
|
|
279
|
+
projectVersion: parsedCommandLine.projectVersion,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function createProjectHostKey(config) {
|
|
284
|
+
return JSON.stringify({
|
|
285
|
+
options: config.parsedCommandLine.options,
|
|
286
|
+
fileNames: config.parsedCommandLine.fileNames,
|
|
287
|
+
projectReferences: config.parsedCommandLine.projectReferences?.map((reference) => reference.path),
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function attachProjectSessionMethods(session, config) {
|
|
292
|
+
function ensureHost() {
|
|
293
|
+
const hostKey = createProjectHostKey(config);
|
|
294
|
+
if (!session.host || session.hostConfigKey !== hostKey) {
|
|
295
|
+
session.host = createProjectHost(session, config);
|
|
296
|
+
session.hostConfigKey = hostKey;
|
|
297
|
+
session.program = null;
|
|
298
|
+
session.programKey = null;
|
|
299
|
+
session.semanticCaches.clear();
|
|
300
|
+
}
|
|
301
|
+
return session.host;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
session.refresh = (nextConfig = {}) => {
|
|
305
|
+
config = {
|
|
306
|
+
...config,
|
|
307
|
+
...nextConfig,
|
|
308
|
+
};
|
|
309
|
+
ensureHost();
|
|
310
|
+
return session;
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
session.getProgram = () => {
|
|
314
|
+
const programKey = createProjectProgramKey(config.parsedCommandLine);
|
|
315
|
+
ensureHost();
|
|
316
|
+
|
|
317
|
+
const builderProgram =
|
|
318
|
+
session.program &&
|
|
319
|
+
typeof session.typescript.createIncrementalProgram === "function"
|
|
320
|
+
? session.typescript.createIncrementalProgram({
|
|
321
|
+
rootNames: config.parsedCommandLine.fileNames,
|
|
322
|
+
options: config.parsedCommandLine.options,
|
|
323
|
+
projectReferences: config.parsedCommandLine.projectReferences,
|
|
324
|
+
host: session.host,
|
|
325
|
+
oldProgram: session.program,
|
|
326
|
+
})
|
|
327
|
+
: null;
|
|
328
|
+
|
|
329
|
+
const program = builderProgram
|
|
330
|
+
? (typeof builderProgram.getProgram === "function"
|
|
331
|
+
? builderProgram.getProgram()
|
|
332
|
+
: builderProgram)
|
|
333
|
+
: session.typescript.createProgram({
|
|
334
|
+
rootNames: config.parsedCommandLine.fileNames,
|
|
335
|
+
options: config.parsedCommandLine.options,
|
|
336
|
+
projectReferences: config.parsedCommandLine.projectReferences,
|
|
337
|
+
host: session.host,
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
if (session.program !== program) {
|
|
341
|
+
session.semanticCaches.clear();
|
|
342
|
+
}
|
|
343
|
+
session.program = program;
|
|
344
|
+
session.programKey = programKey;
|
|
345
|
+
return program;
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function attachCommonSessionMethods(session) {
|
|
349
|
+
session.getChecker = (...args) => session.getProgram(...args).getTypeChecker();
|
|
350
|
+
session.getSourceFile = (fileName, ...args) => session.getProgram(...args).getSourceFile(fileName);
|
|
351
|
+
session.getTypeResolver = (fileName, sourceText) => {
|
|
352
|
+
session.setOverlayFile(fileName, sourceText);
|
|
353
|
+
const program =
|
|
354
|
+
session.kind === "project"
|
|
355
|
+
? session.getProgram()
|
|
356
|
+
: session.kind === "standalone"
|
|
357
|
+
? session.getProgram(fileName)
|
|
358
|
+
: session.getProgram(sourceText);
|
|
359
|
+
const sourceFile = program.getSourceFile(fileName);
|
|
360
|
+
if (!sourceFile) {
|
|
361
|
+
session.clearOverlayFile(fileName);
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
return {
|
|
365
|
+
filename: normalizeFilePath(fileName),
|
|
366
|
+
sourceFile,
|
|
367
|
+
checker: program.getTypeChecker(),
|
|
368
|
+
program,
|
|
369
|
+
getSemanticCache(name, factory) {
|
|
370
|
+
return session.getSemanticCache(name, factory);
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function createProjectTsSession(config) {
|
|
377
|
+
const session = createSessionBase({
|
|
378
|
+
kind: "project",
|
|
379
|
+
key: config.sessionKey,
|
|
380
|
+
typescript: config.typescript,
|
|
381
|
+
});
|
|
382
|
+
attachProjectSessionMethods(session, config);
|
|
383
|
+
attachCommonSessionMethods(session);
|
|
384
|
+
return session;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function getOrCreateProjectTsSession(key, config) {
|
|
388
|
+
const cached = PROJECT_SESSION_CACHE.get(key);
|
|
389
|
+
if (cached) {
|
|
390
|
+
PROJECT_SESSION_CACHE.delete(key);
|
|
391
|
+
PROJECT_SESSION_CACHE.set(key, cached);
|
|
392
|
+
cached.refresh(config);
|
|
393
|
+
return cached;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const session = createProjectTsSession({
|
|
397
|
+
...config,
|
|
398
|
+
sessionKey: key,
|
|
399
|
+
});
|
|
400
|
+
PROJECT_SESSION_CACHE.set(key, session);
|
|
401
|
+
trimCacheToLimit$1(PROJECT_SESSION_CACHE, SESSION_CACHE_LIMIT);
|
|
402
|
+
return session;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const PROFILE_ENABLED = process.env.LITSX_PROFILE === "1";
|
|
406
|
+
const PARSED_COMMAND_LINE_CACHE = new Map();
|
|
407
|
+
const TYPECHECK_SESSION_BY_PROJECT = new Map();
|
|
408
|
+
const TYPECHECK_SESSION_CACHE_LIMIT = 20;
|
|
409
|
+
const FORMAT_HOST = createFormatHost();
|
|
410
|
+
const LITSX_EXTRA_FILE_EXTENSIONS = [
|
|
411
|
+
{
|
|
412
|
+
extension: ".litsx",
|
|
413
|
+
isMixedContent: false,
|
|
414
|
+
scriptKind: ts.ScriptKind.TSX,
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
extension: ".litsx.jsx",
|
|
418
|
+
isMixedContent: false,
|
|
419
|
+
scriptKind: ts.ScriptKind.JSX,
|
|
420
|
+
},
|
|
421
|
+
];
|
|
422
|
+
|
|
423
|
+
function profilePhase(namespace, name, callback) {
|
|
424
|
+
if (!PROFILE_ENABLED) {
|
|
425
|
+
return callback();
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const start = performance.now();
|
|
429
|
+
try {
|
|
430
|
+
return callback();
|
|
431
|
+
} finally {
|
|
432
|
+
globalThis.__litsxProfileEvents ??= [];
|
|
433
|
+
globalThis.__litsxProfileEvents.push({
|
|
434
|
+
namespace,
|
|
435
|
+
name,
|
|
436
|
+
durationMs: performance.now() - start,
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function isRelevantFile(fileName) {
|
|
442
|
+
return /\.(jsx|tsx|litsx)$/.test(fileName) || fileName.endsWith(".litsx.jsx");
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function getPluginsForFile(fileName) {
|
|
446
|
+
return (fileName.endsWith(".tsx") || fileName.endsWith(".litsx")) ? ["typescript"] : [];
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function getAdditionalLitsxFileNames(tsconfigPath, configJson, basePath) {
|
|
450
|
+
const configuredFiles = Array.isArray(configJson?.files)
|
|
451
|
+
? configJson.files
|
|
452
|
+
.filter((file) => file.endsWith(".litsx") || file.endsWith(".litsx.jsx"))
|
|
453
|
+
.map((file) => path.resolve(basePath, file))
|
|
454
|
+
: [];
|
|
455
|
+
|
|
456
|
+
const explicitlyIncludedFiles = Array.isArray(configJson?.include)
|
|
457
|
+
? configJson.include
|
|
458
|
+
.filter((pattern) => pattern.endsWith(".litsx") || pattern.endsWith(".litsx.jsx"))
|
|
459
|
+
.map((pattern) => path.resolve(basePath, pattern))
|
|
460
|
+
.filter((fileName) => ts.sys.fileExists(fileName))
|
|
461
|
+
: [];
|
|
462
|
+
|
|
463
|
+
const includedFiles = ts.sys.readDirectory(
|
|
464
|
+
basePath,
|
|
465
|
+
[".litsx", ".litsx.jsx"],
|
|
466
|
+
configJson?.exclude,
|
|
467
|
+
configJson?.include ?? ["**/*"],
|
|
468
|
+
);
|
|
469
|
+
|
|
470
|
+
return [...new Set([...configuredFiles, ...explicitlyIncludedFiles, ...includedFiles])]
|
|
471
|
+
.filter((fileName) => fileName !== tsconfigPath)
|
|
472
|
+
.sort();
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function trimCacheToLimit(cache, limit) {
|
|
476
|
+
while (cache.size > limit) {
|
|
477
|
+
const oldestKey = cache.keys().next().value;
|
|
478
|
+
if (oldestKey == null) break;
|
|
479
|
+
cache.delete(oldestKey);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function getFileVersion(filePath) {
|
|
484
|
+
try {
|
|
485
|
+
const stats = ts.sys.getModifiedTime?.(filePath);
|
|
486
|
+
if (stats instanceof Date) {
|
|
487
|
+
return String(stats.getTime());
|
|
488
|
+
}
|
|
489
|
+
} catch {}
|
|
490
|
+
|
|
491
|
+
try {
|
|
492
|
+
const content = ts.sys.readFile(filePath);
|
|
493
|
+
return typeof content === "string" ? String(content.length) : null;
|
|
494
|
+
} catch {
|
|
495
|
+
return null;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function createNormalizedArgKey(rawArgs) {
|
|
500
|
+
return rawArgs.join("\0");
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function createSessionKey(projectPath, rawArgs) {
|
|
504
|
+
return `${projectPath || "<no-project>"}:${createNormalizedArgKey(rawArgs)}`;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
function createVirtualizationState() {
|
|
508
|
+
const cache = new Map();
|
|
509
|
+
const sourceFileCache = new Map();
|
|
510
|
+
|
|
511
|
+
function normalizeFileName(fileName) {
|
|
512
|
+
return path.resolve(fileName);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function get(fileName) {
|
|
516
|
+
return cache.get(normalizeFileName(fileName)) ?? null;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function clear(fileName) {
|
|
520
|
+
const normalizedFileName = normalizeFileName(fileName);
|
|
521
|
+
cache.delete(normalizedFileName);
|
|
522
|
+
sourceFileCache.delete(normalizedFileName);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function buildVirtualizationRecord(fileName, sourceText) {
|
|
526
|
+
const normalizedFileName = normalizeFileName(fileName);
|
|
527
|
+
const cachedRecord = cache.get(normalizedFileName) ?? null;
|
|
528
|
+
|
|
529
|
+
if (cachedRecord?.sourceText === sourceText) {
|
|
530
|
+
return cachedRecord;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (!isRelevantFile(fileName) || !authoredSemantics.looksLikeLitsxJsx(sourceText)) {
|
|
534
|
+
clear(fileName);
|
|
535
|
+
return null;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const parserPlugins = getPluginsForFile(fileName);
|
|
539
|
+
const virtualization$1 = profilePhase(
|
|
540
|
+
"typescript-typecheck",
|
|
541
|
+
"tooling-virtualization",
|
|
542
|
+
() => virtualization.createToolingVirtualLitsxSource(sourceText, {
|
|
543
|
+
plugins: parserPlugins,
|
|
544
|
+
}),
|
|
545
|
+
);
|
|
546
|
+
|
|
547
|
+
if (virtualization$1.code === sourceText) {
|
|
548
|
+
clear(fileName);
|
|
549
|
+
return null;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const record = {
|
|
553
|
+
...virtualization$1,
|
|
554
|
+
sourceText,
|
|
555
|
+
parserPlugins,
|
|
556
|
+
virtualizedText: virtualization$1.code,
|
|
557
|
+
};
|
|
558
|
+
cache.set(normalizedFileName, record);
|
|
559
|
+
return record;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return {
|
|
563
|
+
get,
|
|
564
|
+
getOrBuild(fileName, sourceText) {
|
|
565
|
+
return buildVirtualizationRecord(fileName, sourceText);
|
|
566
|
+
},
|
|
567
|
+
getVirtualizedText(fileName, sourceText) {
|
|
568
|
+
const virtualization = buildVirtualizationRecord(fileName, sourceText);
|
|
569
|
+
return virtualization?.virtualizedText ?? sourceText;
|
|
570
|
+
},
|
|
571
|
+
getOrCreateSourceFile(fileName, sourceText, languageVersion, scriptKind) {
|
|
572
|
+
const normalizedFileName = normalizeFileName(fileName);
|
|
573
|
+
const virtualizedText = this.getVirtualizedText(fileName, sourceText);
|
|
574
|
+
const cacheKey = `${String(languageVersion)}:${String(scriptKind ?? "")}:${sourceText}`;
|
|
575
|
+
let fileCache = sourceFileCache.get(normalizedFileName);
|
|
576
|
+
if (!fileCache) {
|
|
577
|
+
fileCache = new Map();
|
|
578
|
+
sourceFileCache.set(normalizedFileName, fileCache);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const cachedSourceFile = fileCache.get(cacheKey);
|
|
582
|
+
if (cachedSourceFile) {
|
|
583
|
+
return cachedSourceFile;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const sourceFile = ts.createSourceFile(
|
|
587
|
+
fileName,
|
|
588
|
+
virtualizedText,
|
|
589
|
+
languageVersion,
|
|
590
|
+
true,
|
|
591
|
+
scriptKind,
|
|
592
|
+
);
|
|
593
|
+
fileCache.set(cacheKey, sourceFile);
|
|
594
|
+
return sourceFile;
|
|
595
|
+
},
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
function remapMessageText(messageText) {
|
|
600
|
+
if (typeof messageText === "string") {
|
|
601
|
+
return authoredSemantics.remapVirtualText(messageText);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
if (!messageText || typeof messageText !== "object") {
|
|
605
|
+
return messageText;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
return {
|
|
609
|
+
...messageText,
|
|
610
|
+
messageText: remapMessageText(messageText.messageText),
|
|
611
|
+
next: messageText.next?.map(remapMessageText),
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function remapDiagnostic(diagnostic, virtualizationState) {
|
|
616
|
+
const fileName = diagnostic.file?.fileName;
|
|
617
|
+
const virtualization$1 = fileName ? virtualizationState.get(fileName) : null;
|
|
618
|
+
|
|
619
|
+
if (!virtualization$1 || typeof diagnostic.start !== "number") {
|
|
620
|
+
return {
|
|
621
|
+
...diagnostic,
|
|
622
|
+
messageText: remapMessageText(diagnostic.messageText),
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const remappedSpan = virtualization.remapToolingTextSpanToOriginal(
|
|
627
|
+
{
|
|
628
|
+
start: diagnostic.start,
|
|
629
|
+
length: diagnostic.length ?? 0,
|
|
630
|
+
},
|
|
631
|
+
virtualization$1,
|
|
632
|
+
);
|
|
633
|
+
|
|
634
|
+
return {
|
|
635
|
+
...diagnostic,
|
|
636
|
+
start: remappedSpan.start,
|
|
637
|
+
length: remappedSpan.length,
|
|
638
|
+
messageText: remapMessageText(diagnostic.messageText),
|
|
639
|
+
relatedInformation: diagnostic.relatedInformation?.map((info) => {
|
|
640
|
+
if (!info.file || typeof info.start !== "number") {
|
|
641
|
+
return {
|
|
642
|
+
...info,
|
|
643
|
+
messageText: remapMessageText(info.messageText),
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
const infoVirtualization = virtualizationState.get(info.file.fileName);
|
|
648
|
+
if (!infoVirtualization) {
|
|
649
|
+
return {
|
|
650
|
+
...info,
|
|
651
|
+
messageText: remapMessageText(info.messageText),
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
const infoSpan = virtualization.remapToolingTextSpanToOriginal(
|
|
656
|
+
{
|
|
657
|
+
start: info.start,
|
|
658
|
+
length: info.length ?? 0,
|
|
659
|
+
},
|
|
660
|
+
infoVirtualization,
|
|
661
|
+
);
|
|
662
|
+
|
|
663
|
+
return {
|
|
664
|
+
...info,
|
|
665
|
+
start: infoSpan.start,
|
|
666
|
+
length: infoSpan.length,
|
|
667
|
+
messageText: remapMessageText(info.messageText),
|
|
668
|
+
};
|
|
669
|
+
}),
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
function createFormatHost() {
|
|
674
|
+
return {
|
|
675
|
+
getCanonicalFileName(fileName) {
|
|
676
|
+
return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
|
|
677
|
+
},
|
|
678
|
+
getCurrentDirectory() {
|
|
679
|
+
return ts.sys.getCurrentDirectory();
|
|
680
|
+
},
|
|
681
|
+
getNewLine() {
|
|
682
|
+
return ts.sys.newLine;
|
|
683
|
+
},
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
function resolveParsedCommandLine(rawArgs) {
|
|
688
|
+
const parsedCommandLine = ts.parseCommandLine(rawArgs);
|
|
689
|
+
|
|
690
|
+
if (parsedCommandLine.errors.length > 0) {
|
|
691
|
+
return parsedCommandLine;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
const projectPath = parsedCommandLine.options.project
|
|
695
|
+
? path.resolve(parsedCommandLine.options.project)
|
|
696
|
+
: ts.findConfigFile(process.cwd(), ts.sys.fileExists, "tsconfig.json");
|
|
697
|
+
|
|
698
|
+
if (!projectPath) {
|
|
699
|
+
return {
|
|
700
|
+
...parsedCommandLine,
|
|
701
|
+
errors: [
|
|
702
|
+
{
|
|
703
|
+
category: ts.DiagnosticCategory.Error,
|
|
704
|
+
code: 5083,
|
|
705
|
+
file: undefined,
|
|
706
|
+
start: undefined,
|
|
707
|
+
length: undefined,
|
|
708
|
+
messageText: "Cannot find a tsconfig.json file.",
|
|
709
|
+
},
|
|
710
|
+
],
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const configFile = ts.readConfigFile(projectPath, ts.sys.readFile);
|
|
715
|
+
if (configFile.error) {
|
|
716
|
+
return {
|
|
717
|
+
...parsedCommandLine,
|
|
718
|
+
errors: [configFile.error],
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const configHost = {
|
|
723
|
+
...ts.sys,
|
|
724
|
+
onUnRecoverableConfigFileDiagnostic() {},
|
|
725
|
+
};
|
|
726
|
+
const projectVersion = getFileVersion(projectPath) ?? "unknown";
|
|
727
|
+
const cacheKey = `${projectPath}:${projectVersion}:${createNormalizedArgKey(rawArgs)}`;
|
|
728
|
+
const cached = PARSED_COMMAND_LINE_CACHE.get(cacheKey);
|
|
729
|
+
if (cached) {
|
|
730
|
+
PARSED_COMMAND_LINE_CACHE.delete(cacheKey);
|
|
731
|
+
PARSED_COMMAND_LINE_CACHE.set(cacheKey, cached);
|
|
732
|
+
return cached;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
const resolved = {
|
|
736
|
+
...ts.parseJsonConfigFileContent(
|
|
737
|
+
configFile.config,
|
|
738
|
+
configHost,
|
|
739
|
+
path.dirname(projectPath),
|
|
740
|
+
parsedCommandLine.options,
|
|
741
|
+
projectPath,
|
|
742
|
+
undefined,
|
|
743
|
+
LITSX_EXTRA_FILE_EXTENSIONS,
|
|
744
|
+
),
|
|
745
|
+
projectPath,
|
|
746
|
+
projectVersion,
|
|
747
|
+
__litsxSessionKey: createSessionKey(projectPath, rawArgs),
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
if (!Object.hasOwn(configFile.config?.compilerOptions || {}, "types")) {
|
|
751
|
+
resolved.options = {
|
|
752
|
+
...resolved.options,
|
|
753
|
+
// Preserve TypeScript 5.x ambient @types loading for litsx-tsc when
|
|
754
|
+
// projects haven't opted into an explicit `types` list yet.
|
|
755
|
+
types: ["*"],
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
resolved.fileNames = [
|
|
760
|
+
...new Set([
|
|
761
|
+
...resolved.fileNames,
|
|
762
|
+
...getAdditionalLitsxFileNames(projectPath, configFile.config, path.dirname(projectPath)),
|
|
763
|
+
]),
|
|
764
|
+
].sort();
|
|
765
|
+
|
|
766
|
+
if (resolved.fileNames.some((fileName) => fileName.endsWith(".litsx") || fileName.endsWith(".litsx.jsx"))) {
|
|
767
|
+
resolved.options = {
|
|
768
|
+
...resolved.options,
|
|
769
|
+
allowNonTsExtensions: true,
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
if (resolved.fileNames.length > 0 && Array.isArray(resolved.errors)) {
|
|
774
|
+
resolved.errors = resolved.errors.filter((error) => error?.code !== 18003);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
PARSED_COMMAND_LINE_CACHE.set(cacheKey, resolved);
|
|
778
|
+
trimCacheToLimit(PARSED_COMMAND_LINE_CACHE, TYPECHECK_SESSION_CACHE_LIMIT);
|
|
779
|
+
return resolved;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
function createTypecheckSession(parsedCommandLine, projectSession = null) {
|
|
783
|
+
const virtualizationState = createVirtualizationState();
|
|
784
|
+
return {
|
|
785
|
+
parsedCommandLine,
|
|
786
|
+
sessionKey: parsedCommandLine.__litsxSessionKey,
|
|
787
|
+
virtualizationState,
|
|
788
|
+
diagnosticsCacheKey: null,
|
|
789
|
+
diagnosticsCacheResult: null,
|
|
790
|
+
projectSession: projectSession || getOrCreateProjectTsSession(parsedCommandLine.__litsxSessionKey, {
|
|
791
|
+
typescript: ts,
|
|
792
|
+
parsedCommandLine,
|
|
793
|
+
}),
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
function getTypecheckSession(parsedCommandLine, projectSession = null) {
|
|
798
|
+
const sessionKey =
|
|
799
|
+
parsedCommandLine.__litsxSessionKey ||
|
|
800
|
+
createSessionKey(parsedCommandLine.projectPath, []);
|
|
801
|
+
const cached = TYPECHECK_SESSION_BY_PROJECT.get(sessionKey);
|
|
802
|
+
if (cached) {
|
|
803
|
+
cached.parsedCommandLine = parsedCommandLine;
|
|
804
|
+
if (projectSession) {
|
|
805
|
+
cached.projectSession = projectSession;
|
|
806
|
+
cached.diagnosticsCacheKey = null;
|
|
807
|
+
cached.diagnosticsCacheResult = null;
|
|
808
|
+
}
|
|
809
|
+
cached.projectSession.refresh({
|
|
810
|
+
parsedCommandLine,
|
|
811
|
+
});
|
|
812
|
+
TYPECHECK_SESSION_BY_PROJECT.delete(sessionKey);
|
|
813
|
+
TYPECHECK_SESSION_BY_PROJECT.set(sessionKey, cached);
|
|
814
|
+
return cached;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
const session = createTypecheckSession(parsedCommandLine, projectSession);
|
|
818
|
+
TYPECHECK_SESSION_BY_PROJECT.set(sessionKey, session);
|
|
819
|
+
trimCacheToLimit(TYPECHECK_SESSION_BY_PROJECT, TYPECHECK_SESSION_CACHE_LIMIT);
|
|
820
|
+
return session;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
function createLitsxTypecheckSession(rawArgs = process.argv.slice(2), options = {}) {
|
|
824
|
+
const parsedCommandLine = resolveParsedCommandLine(rawArgs);
|
|
825
|
+
return getTypecheckSession(parsedCommandLine, options.projectSession);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
function createDiagnosticsCacheKey(session) {
|
|
829
|
+
const parsedCommandLine = session.parsedCommandLine;
|
|
830
|
+
const fileVersions = parsedCommandLine.fileNames.map((fileName) => (
|
|
831
|
+
`${fileName}:${getFileVersion(fileName) ?? "missing"}`
|
|
832
|
+
));
|
|
833
|
+
return `${parsedCommandLine.projectVersion || "unknown"}\0${fileVersions.join("\0")}`;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
function runTypecheckSession(session) {
|
|
837
|
+
const parsedCommandLine = session.parsedCommandLine;
|
|
838
|
+
|
|
839
|
+
if (parsedCommandLine.errors?.length) {
|
|
840
|
+
const output = ts.formatDiagnosticsWithColorAndContext(parsedCommandLine.errors, FORMAT_HOST);
|
|
841
|
+
if (output) {
|
|
842
|
+
process.stderr.write(output);
|
|
843
|
+
}
|
|
844
|
+
return 1;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
const virtualizationState = session.virtualizationState;
|
|
848
|
+
session.projectSession.refresh({
|
|
849
|
+
parsedCommandLine,
|
|
850
|
+
});
|
|
851
|
+
for (const fileName of parsedCommandLine.fileNames) {
|
|
852
|
+
const sourceText = session.projectSession.readFile?.(fileName) ?? ts.sys.readFile(fileName);
|
|
853
|
+
if (typeof sourceText !== "string") {
|
|
854
|
+
session.projectSession.clearOverlayFile(fileName);
|
|
855
|
+
continue;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
const virtualizedText = virtualizationState.getVirtualizedText(fileName, sourceText);
|
|
859
|
+
if (virtualizedText === sourceText) {
|
|
860
|
+
session.projectSession.clearOverlayFile(fileName);
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
session.projectSession.setOverlayFile(fileName, virtualizedText);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
const program = profilePhase(
|
|
868
|
+
"typescript-typecheck",
|
|
869
|
+
"create-program",
|
|
870
|
+
() => session.projectSession.getProgram(),
|
|
871
|
+
);
|
|
872
|
+
|
|
873
|
+
const diagnosticsCacheKey = profilePhase(
|
|
874
|
+
"typescript-typecheck",
|
|
875
|
+
"diagnostic-cache-key",
|
|
876
|
+
() => createDiagnosticsCacheKey(session),
|
|
877
|
+
);
|
|
878
|
+
|
|
879
|
+
if (
|
|
880
|
+
session.diagnosticsCacheKey === diagnosticsCacheKey &&
|
|
881
|
+
session.diagnosticsCacheResult
|
|
882
|
+
) {
|
|
883
|
+
const cachedResult = session.diagnosticsCacheResult;
|
|
884
|
+
if (cachedResult.output) {
|
|
885
|
+
process.stderr.write(cachedResult.output);
|
|
886
|
+
}
|
|
887
|
+
return cachedResult.exitCode;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
const diagnostics = profilePhase(
|
|
891
|
+
"typescript-typecheck",
|
|
892
|
+
"diagnostics",
|
|
893
|
+
() => ts.getPreEmitDiagnostics(program),
|
|
894
|
+
)
|
|
895
|
+
.map((diagnostic) => remapDiagnostic(diagnostic, virtualizationState));
|
|
896
|
+
|
|
897
|
+
if (diagnostics.length > 0) {
|
|
898
|
+
const output = ts.formatDiagnosticsWithColorAndContext(diagnostics, FORMAT_HOST);
|
|
899
|
+
if (output) {
|
|
900
|
+
process.stderr.write(output);
|
|
901
|
+
}
|
|
902
|
+
session.diagnosticsCacheKey = diagnosticsCacheKey;
|
|
903
|
+
session.diagnosticsCacheResult = {
|
|
904
|
+
exitCode: 1,
|
|
905
|
+
output,
|
|
906
|
+
};
|
|
907
|
+
return 1;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
session.diagnosticsCacheKey = diagnosticsCacheKey;
|
|
911
|
+
session.diagnosticsCacheResult = {
|
|
912
|
+
exitCode: 0,
|
|
913
|
+
output: "",
|
|
914
|
+
};
|
|
915
|
+
return 0;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
function runLitsxTypecheck(rawArgs = process.argv.slice(2)) {
|
|
919
|
+
const session = Array.isArray(rawArgs)
|
|
920
|
+
? createLitsxTypecheckSession(rawArgs)
|
|
921
|
+
: rawArgs;
|
|
922
|
+
return runTypecheckSession(session);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
if (process.argv[1] && url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('typecheck.cjs', document.baseURI).href))) === path.resolve(process.argv[1])) {
|
|
926
|
+
process.exitCode = runLitsxTypecheck(process.argv.slice(2));
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
exports.createLitsxTypecheckSession = createLitsxTypecheckSession;
|
|
930
|
+
exports.runLitsxTypecheck = runLitsxTypecheck;
|
|
931
|
+
//# sourceMappingURL=typecheck.cjs.map
|