tsc-ts 0.0.8 → 0.0.10
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 +1 -1
- package/dist/api/compiler/ast.d.ts +2 -0
- package/dist/api/compiler/ast.js +3 -0
- package/dist/api/compiler/checker-calls.js +5 -1
- package/dist/api/compiler/checker-grammar.js +3 -2
- package/dist/api/compiler/checker-inference.js +8 -2
- package/dist/api/compiler/checker-members.js +8 -3
- package/dist/api/compiler/checker-source-file.d.ts +12 -0
- package/dist/api/compiler/checker-source-file.js +35 -0
- package/dist/api/compiler/checker-symbols.js +2 -1
- package/dist/api/compiler/checker-type-factory.js +8 -2
- package/dist/api/compiler/checker.d.ts +17 -1
- package/dist/api/compiler/checker.js +49 -1
- package/dist/api/compiler/compile-program.d.ts +26 -2
- package/dist/api/compiler/compile-program.js +100 -7
- package/dist/api/compiler/diagnostics.d.ts +22 -0
- package/dist/api/compiler/diagnostics.js +86 -4
- package/dist/api/compiler/file-loader.d.ts +13 -3
- package/dist/api/compiler/file-loader.js +106 -30
- package/dist/api/compiler/link-tables.d.ts +7 -0
- package/dist/api/compiler/link-tables.js +22 -0
- package/dist/api/compiler/parallel-parse.d.ts +3 -2
- package/dist/api/compiler/parallel-parse.js +17 -5
- package/dist/api/compiler/parser.js +15 -14
- package/dist/api/compiler/printer/emit-context.d.ts +2 -0
- package/dist/api/compiler/printer/emit-context.js +4 -0
- package/dist/api/compiler/printer/printer.d.ts +48 -2
- package/dist/api/compiler/printer/printer.js +238 -14
- package/dist/api/compiler/program-checker.d.ts +22 -0
- package/dist/api/compiler/program-checker.js +39 -2
- package/dist/api/compiler/program.d.ts +2 -6
- package/dist/api/compiler/program.js +5 -30
- package/dist/api/compiler/relations.js +10 -0
- package/dist/api/compiler/symbol.d.ts +1 -1
- package/dist/api/compiler/symbol.js +8 -10
- package/dist/api/library/diagnostics.d.ts +10 -0
- package/dist/api/library/diagnostics.js +20 -0
- package/package.json +9 -9
- package/src/compiler/ast.ts +3 -0
- package/src/compiler/checker-calls.ts +3 -1
- package/src/compiler/checker-grammar.ts +3 -2
- package/src/compiler/checker-inference.ts +7 -2
- package/src/compiler/checker-members.ts +9 -3
- package/src/compiler/checker-source-file.ts +34 -0
- package/src/compiler/checker-symbols.ts +2 -1
- package/src/compiler/checker-type-factory.ts +4 -2
- package/src/compiler/checker.ts +45 -1
- package/src/compiler/compile-program.ts +121 -7
- package/src/compiler/diagnostics.ts +84 -3
- package/src/compiler/file-loader.ts +106 -29
- package/src/compiler/incremental.ts +80 -13
- package/src/compiler/link-tables.ts +32 -0
- package/src/compiler/parallel-check.ts +326 -62
- package/src/compiler/parallel-emit.ts +320 -0
- package/src/compiler/parallel-parse.ts +16 -5
- package/src/compiler/parse-thread.ts +3 -0
- package/src/compiler/parser.ts +15 -16
- package/src/compiler/printer/emit-context.ts +5 -0
- package/src/compiler/printer/printer.ts +231 -16
- package/src/compiler/program-checker.ts +40 -2
- package/src/compiler/program.ts +5 -25
- package/src/compiler/relations.ts +7 -0
- package/src/compiler/symbol.ts +15 -10
- package/src/compiler/thread-entry.ts +61 -3
- package/src/compiler/tsc-build.ts +63 -9
- package/src/compiler/tsc-cli.ts +5 -0
- package/src/compiler/tsc-compile.ts +278 -3
- package/src/library/diagnostics.ts +23 -0
|
@@ -347,6 +347,11 @@ export class Diagnostic {
|
|
|
347
347
|
readonly reportsDeprecated: boolean;
|
|
348
348
|
skippedOnNoEmit = false;
|
|
349
349
|
repopulateInfo: RepopulateInfo | undefined = undefined;
|
|
350
|
+
/**
|
|
351
|
+
* What `formatDiagnostic` gives for this diagnostic in `formattedReports.format`, where the checker
|
|
352
|
+
* thread that found it formatted it (`packResult`); `''` otherwise.
|
|
353
|
+
*/
|
|
354
|
+
formatted = '';
|
|
350
355
|
|
|
351
356
|
constructor(
|
|
352
357
|
file: DiagnosticFile | undefined,
|
|
@@ -388,6 +393,7 @@ export class Diagnostic {
|
|
|
388
393
|
result.relatedInformation = this.relatedInformation;
|
|
389
394
|
result.skippedOnNoEmit = this.skippedOnNoEmit;
|
|
390
395
|
result.repopulateInfo = this.repopulateInfo;
|
|
396
|
+
result.formatted = this.formatted;
|
|
391
397
|
return result;
|
|
392
398
|
}
|
|
393
399
|
}
|
|
@@ -510,9 +516,13 @@ function compareRelatedInfo(a: readonly Diagnostic[], b: readonly Diagnostic[]):
|
|
|
510
516
|
/** The order tsc reports diagnostics in: by file, position, code, arguments, then elaboration. */
|
|
511
517
|
export function compareDiagnostics(a: Diagnostic, b: Diagnostic): number {
|
|
512
518
|
if (a === b) return 0;
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
519
|
+
const c = compareCodePoints(fileNameOf(a), fileNameOf(b));
|
|
520
|
+
return c !== 0 ? c : compareDiagnosticsInFile(a, b);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/** `compareDiagnostics` of two diagnostics whose files have the same name. */
|
|
524
|
+
function compareDiagnosticsInFile(a: Diagnostic, b: Diagnostic): number {
|
|
525
|
+
let c = a.pos - b.pos;
|
|
516
526
|
if (c !== 0) return c;
|
|
517
527
|
c = a.end - b.end;
|
|
518
528
|
if (c !== 0) return c;
|
|
@@ -527,6 +537,61 @@ export function compareDiagnostics(a: Diagnostic, b: Diagnostic): number {
|
|
|
527
537
|
return compareRelatedInfo(a.relatedInformation, b.relatedInformation);
|
|
528
538
|
}
|
|
529
539
|
|
|
540
|
+
/**
|
|
541
|
+
* `diagnostics` in the order of `compareDiagnostics`, equal ones in their order in `diagnostics`. File
|
|
542
|
+
* names are compared once per pair of files rather than once per pair of diagnostics: the distinct
|
|
543
|
+
* files are sorted by name, and each diagnostic sorts by its file's place in that order, then by the
|
|
544
|
+
* rest of `compareDiagnostics`. A program's diagnostics come a file at a time, so the files are found
|
|
545
|
+
* from the runs of one file.
|
|
546
|
+
*/
|
|
547
|
+
export function sortDiagnostics(diagnostics: readonly Diagnostic[]): Diagnostic[] {
|
|
548
|
+
const n = diagnostics.length;
|
|
549
|
+
if (n < 2) return diagnostics.slice();
|
|
550
|
+
const fileIndices = new Map<DiagnosticFile | undefined, number>();
|
|
551
|
+
const files: (DiagnosticFile | undefined)[] = [];
|
|
552
|
+
const fileOf: number[] = [];
|
|
553
|
+
let last: DiagnosticFile | undefined = undefined;
|
|
554
|
+
let lastIndex = -1;
|
|
555
|
+
for (let i = 0; i < n; i++) {
|
|
556
|
+
const file = diagnostics[i]!.file;
|
|
557
|
+
if (lastIndex < 0 || file !== last) {
|
|
558
|
+
let k = fileIndices.get(file);
|
|
559
|
+
if (k === undefined) {
|
|
560
|
+
k = files.length;
|
|
561
|
+
fileIndices.set(file, k);
|
|
562
|
+
files.push(file);
|
|
563
|
+
}
|
|
564
|
+
last = file;
|
|
565
|
+
lastIndex = k;
|
|
566
|
+
}
|
|
567
|
+
fileOf.push(lastIndex);
|
|
568
|
+
}
|
|
569
|
+
// Files with the same name share a rank, as they compare equal.
|
|
570
|
+
const nameOf = (k: number): string => {
|
|
571
|
+
const file = files[k];
|
|
572
|
+
return file === undefined ? '' : file.fileName;
|
|
573
|
+
};
|
|
574
|
+
const byName: number[] = [];
|
|
575
|
+
for (let k = 0; k < files.length; k++) byName.push(k);
|
|
576
|
+
byName.sort((x, y) => compareCodePoints(nameOf(x), nameOf(y)));
|
|
577
|
+
const rank: number[] = [];
|
|
578
|
+
for (let k = 0; k < files.length; k++) rank.push(0);
|
|
579
|
+
for (let k = 1; k < byName.length; k++)
|
|
580
|
+
rank[byName[k]!] = rank[byName[k - 1]!]! + (nameOf(byName[k]!) === nameOf(byName[k - 1]!) ? 0 : 1);
|
|
581
|
+
const order: number[] = [];
|
|
582
|
+
for (let i = 0; i < n; i++) order.push(i);
|
|
583
|
+
order.sort((x, y) => {
|
|
584
|
+
const c = rank[fileOf[x]!]! - rank[fileOf[y]!]!;
|
|
585
|
+
if (c !== 0) return c;
|
|
586
|
+
const a = diagnostics[x]!;
|
|
587
|
+
const b = diagnostics[y]!;
|
|
588
|
+
return a === b ? 0 : compareDiagnosticsInFile(a, b);
|
|
589
|
+
});
|
|
590
|
+
const sorted: Diagnostic[] = [];
|
|
591
|
+
for (const i of order) sorted.push(diagnostics[i]!);
|
|
592
|
+
return sorted;
|
|
593
|
+
}
|
|
594
|
+
|
|
530
595
|
function equalChain(a: readonly Diagnostic[], b: readonly Diagnostic[]): boolean {
|
|
531
596
|
if (a.length !== b.length) return false;
|
|
532
597
|
for (let i = 0; i < a.length; i++) {
|
|
@@ -625,13 +690,29 @@ function formatDiagnosticIn(diagnostic: Diagnostic, fileName: string, options: D
|
|
|
625
690
|
return result + flattenDiagnosticMessage(diagnostic, options.newLine, options.locale) + options.newLine;
|
|
626
691
|
}
|
|
627
692
|
|
|
693
|
+
/**
|
|
694
|
+
* The plain format the main thread reports a compilation's diagnostics in (`DiagnosticReporter.plainFormat`),
|
|
695
|
+
* which its checker threads receive a copy of and format the diagnostics they send back in
|
|
696
|
+
* (`Diagnostic.formatted`). Unset where diagnostics are reported with color and context, or not at all.
|
|
697
|
+
*/
|
|
698
|
+
export class FormattedReports {
|
|
699
|
+
format: DiagnosticFormatOptions | undefined = undefined;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
export const formattedReports = new FormattedReports();
|
|
703
|
+
|
|
628
704
|
/** `formatDiagnostic` of each diagnostic. */
|
|
629
705
|
export function formatDiagnostics(diagnostics: readonly Diagnostic[], options: DiagnosticFormatOptions): string {
|
|
630
706
|
let result = '';
|
|
707
|
+
const formatted = options === formattedReports.format;
|
|
631
708
|
// Sorted diagnostics come a file at a time: the relative name of the last file is kept.
|
|
632
709
|
let lastFile: DiagnosticFile | undefined = undefined;
|
|
633
710
|
let lastName = '';
|
|
634
711
|
for (const diagnostic of diagnostics) {
|
|
712
|
+
if (formatted && diagnostic.formatted !== '') {
|
|
713
|
+
result += diagnostic.formatted;
|
|
714
|
+
continue;
|
|
715
|
+
}
|
|
635
716
|
const file = diagnostic.file;
|
|
636
717
|
if (file !== undefined && file !== lastFile) {
|
|
637
718
|
lastFile = file;
|
|
@@ -216,7 +216,7 @@ export class LoadedFile {
|
|
|
216
216
|
readonly references: LoadedReference[],
|
|
217
217
|
readonly resolutionsInFile: ModeAwareCache<ResolvedModule> | undefined,
|
|
218
218
|
readonly typeResolutionsInFile: ModeAwareCache<ResolvedTypeReferenceDirective> | undefined,
|
|
219
|
-
readonly processingDiagnostics: ProcessingDiagnostic[],
|
|
219
|
+
readonly processingDiagnostics: readonly ProcessingDiagnostic[],
|
|
220
220
|
readonly importHelpersImportSpecifier: StringLiteral | undefined,
|
|
221
221
|
readonly jsxRuntimeImport: JsxRuntimeImport | undefined,
|
|
222
222
|
) {}
|
|
@@ -230,23 +230,34 @@ class SubTasksAhead {
|
|
|
230
230
|
) {}
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
/** Read in place of a task's lists it has not created. */
|
|
234
|
+
const noParseTasks: readonly ParseTask[] = [];
|
|
235
|
+
const noTraces: readonly MessageWithArgs[] = [];
|
|
236
|
+
const noProcessingDiagnostics: readonly ProcessingDiagnostic[] = [];
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* A file to load. Its lists are created on first use: most tasks never get sub-tasks, traces or processing
|
|
240
|
+
* diagnostics, and large programs create hundreds of thousands of tasks.
|
|
241
|
+
*/
|
|
233
242
|
class ParseTask {
|
|
234
243
|
path = '';
|
|
235
244
|
file: SourceFile | undefined = undefined;
|
|
236
245
|
redirectedParseTask: ParseTask | undefined = undefined;
|
|
237
|
-
subTasks: ParseTask[] =
|
|
246
|
+
subTasks: ParseTask[] | undefined = undefined;
|
|
238
247
|
loaded = false;
|
|
239
248
|
startedSubTasks = false;
|
|
240
249
|
metadata: SourceFileMetadata = libFileMetadata;
|
|
241
250
|
resolutionsInFile: ModeAwareCache<ResolvedModule> | undefined = undefined;
|
|
242
|
-
|
|
251
|
+
resolutionsTrace: MessageWithArgs[] | undefined = undefined;
|
|
243
252
|
typeResolutionsInFile: ModeAwareCache<ResolvedTypeReferenceDirective> | undefined = undefined;
|
|
244
|
-
|
|
245
|
-
|
|
253
|
+
typeResolutionsTrace: MessageWithArgs[] | undefined = undefined;
|
|
254
|
+
processingDiagnostics: ProcessingDiagnostic[] | undefined = undefined;
|
|
246
255
|
importHelpersImportSpecifier: StringLiteral | undefined = undefined;
|
|
247
256
|
jsxRuntimeImport: JsxRuntimeImport | undefined = undefined;
|
|
248
257
|
/** The task of the same file name that was loaded instead of this one. */
|
|
249
258
|
loadedTask: ParseTask | undefined = undefined;
|
|
259
|
+
/** Whether an import or a type reference directive adds the file (`ProcessedFiles.addedFiles`). */
|
|
260
|
+
readonly byImport: boolean;
|
|
250
261
|
|
|
251
262
|
constructor(
|
|
252
263
|
readonly normalizedFilePath: string,
|
|
@@ -257,7 +268,10 @@ class ParseTask {
|
|
|
257
268
|
/** A JavaScript file found in `node_modules`, loaded only within `maxNodeModuleJsDepth`. */
|
|
258
269
|
readonly elideOnDepth: boolean,
|
|
259
270
|
readonly packageId: PackageId | undefined,
|
|
260
|
-
) {
|
|
271
|
+
) {
|
|
272
|
+
const kind = includeReason !== undefined ? includeReason.kind : -1;
|
|
273
|
+
this.byImport = kind === FileIncludeKind.Import || kind === FileIncludeKind.TypeReferenceDirective;
|
|
274
|
+
}
|
|
261
275
|
|
|
262
276
|
addSubTask(
|
|
263
277
|
fileName: string,
|
|
@@ -267,18 +281,40 @@ class ParseTask {
|
|
|
267
281
|
elideOnDepth: boolean,
|
|
268
282
|
packageId: PackageId | undefined,
|
|
269
283
|
): void {
|
|
270
|
-
this.subTasks.push(
|
|
284
|
+
(this.subTasks ??= []).push(
|
|
271
285
|
new ParseTask(normalizePath(fileName), libFile, reason, false, increaseDepth, elideOnDepth, packageId),
|
|
272
286
|
);
|
|
273
287
|
}
|
|
288
|
+
|
|
289
|
+
addProcessingDiagnostic(diagnostic: ProcessingDiagnostic): void {
|
|
290
|
+
(this.processingDiagnostics ??= []).push(diagnostic);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/** Where module resolution traces go under `--traceResolution`; undefined without it. */
|
|
294
|
+
moduleTraces(trace: boolean): MessageWithArgs[] | undefined {
|
|
295
|
+
return trace ? (this.resolutionsTrace ??= []) : undefined;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** Where type reference resolution traces go under `--traceResolution`; undefined without it. */
|
|
299
|
+
typeTraces(trace: boolean): MessageWithArgs[] | undefined {
|
|
300
|
+
return trace ? (this.typeResolutionsTrace ??= []) : undefined;
|
|
301
|
+
}
|
|
274
302
|
}
|
|
275
303
|
|
|
304
|
+
const noData: readonly ParseTaskData[] = [];
|
|
305
|
+
|
|
276
306
|
/** The tasks of one path, by file name casing. */
|
|
277
307
|
class ParseTaskData {
|
|
278
308
|
readonly tasks = new Map<string, ParseTask>();
|
|
279
309
|
lowestDepth = Number.MAX_SAFE_INTEGER;
|
|
280
310
|
startedSubTasks = false;
|
|
281
311
|
packageId: PackageId | undefined = undefined;
|
|
312
|
+
/** The index of this path's file in the program's files, once collected; -1 for none. */
|
|
313
|
+
index = -1;
|
|
314
|
+
/** For a deduplicated package's path, the tasks of the copy kept (`collect`). */
|
|
315
|
+
keptCopy: ParseTaskData | undefined = undefined;
|
|
316
|
+
/** The paths the file's imports and type reference directives add, once collected. */
|
|
317
|
+
added: readonly ParseTaskData[] = noData;
|
|
282
318
|
|
|
283
319
|
constructor(task: ParseTask) {
|
|
284
320
|
this.tasks.set(task.normalizedFilePath, task);
|
|
@@ -396,6 +432,11 @@ export class ProcessedFiles {
|
|
|
396
432
|
* threads (`preparedPackageJsonLookups`); `undefined` where they may miss some.
|
|
397
433
|
*/
|
|
398
434
|
readonly preparedPackageJsons: readonly PackageJsonLookup[] | undefined,
|
|
435
|
+
/**
|
|
436
|
+
* The files each file's imports and type reference directives added to the program, by index into
|
|
437
|
+
* `files`, without the file itself.
|
|
438
|
+
*/
|
|
439
|
+
readonly addedFiles: readonly (readonly number[])[],
|
|
399
440
|
) {}
|
|
400
441
|
}
|
|
401
442
|
|
|
@@ -423,6 +464,8 @@ export function withReplacedFile(processed: ProcessedFiles, file: SourceFile): P
|
|
|
423
464
|
processed.redirectFilesByPath,
|
|
424
465
|
processed.projectReferenceMapper,
|
|
425
466
|
processed.preparedPackageJsons,
|
|
467
|
+
// The file has the same references (`canReplaceFile`), and keeps its index.
|
|
468
|
+
processed.addedFiles,
|
|
426
469
|
);
|
|
427
470
|
}
|
|
428
471
|
|
|
@@ -742,7 +785,7 @@ export class FileLoader {
|
|
|
742
785
|
return undefined;
|
|
743
786
|
}
|
|
744
787
|
const references: LoadedReference[] = [];
|
|
745
|
-
for (const sub of task.subTasks) {
|
|
788
|
+
for (const sub of task.subTasks ?? noParseTasks) {
|
|
746
789
|
references.push(
|
|
747
790
|
new LoadedReference(
|
|
748
791
|
sub.normalizedFilePath,
|
|
@@ -769,7 +812,7 @@ export class FileLoader {
|
|
|
769
812
|
references,
|
|
770
813
|
task.resolutionsInFile,
|
|
771
814
|
task.typeResolutionsInFile,
|
|
772
|
-
task.processingDiagnostics,
|
|
815
|
+
task.processingDiagnostics ?? noProcessingDiagnostics,
|
|
773
816
|
task.importHelpersImportSpecifier,
|
|
774
817
|
task.jsxRuntimeImport,
|
|
775
818
|
);
|
|
@@ -857,7 +900,7 @@ export class FileLoader {
|
|
|
857
900
|
return;
|
|
858
901
|
}
|
|
859
902
|
const task = new ParseTask(absolute, undefined, reason, false, false, false, undefined);
|
|
860
|
-
task.
|
|
903
|
+
task.addProcessingDiagnostic(
|
|
861
904
|
ProcessingDiagnostic.explainingFileInclude('', reason, resolved.message, resolved.args),
|
|
862
905
|
);
|
|
863
906
|
this.rootTasks.push(task);
|
|
@@ -1031,7 +1074,7 @@ export class FileLoader {
|
|
|
1031
1074
|
}
|
|
1032
1075
|
if (!taskByFileName.startedSubTasks && loadSubTasks) {
|
|
1033
1076
|
taskByFileName.startedSubTasks = true;
|
|
1034
|
-
this.start(taskByFileName.subTasks, data.lowestDepth);
|
|
1077
|
+
if (taskByFileName.subTasks !== undefined) this.start(taskByFileName.subTasks, data.lowestDepth);
|
|
1035
1078
|
}
|
|
1036
1079
|
}
|
|
1037
1080
|
}
|
|
@@ -1073,7 +1116,7 @@ export class FileLoader {
|
|
|
1073
1116
|
if (hasExtension(task.normalizedFilePath) && this.options.allowNonTsExtensions !== true) {
|
|
1074
1117
|
const canonicalFileName = getCanonicalFileName(task.normalizedFilePath, fs.useCaseSensitiveFileNames);
|
|
1075
1118
|
if (!this.isSupportedExtension(canonicalFileName)) {
|
|
1076
|
-
task.
|
|
1119
|
+
task.addProcessingDiagnostic(
|
|
1077
1120
|
hasJSFileExtension(canonicalFileName)
|
|
1078
1121
|
? ProcessingDiagnostic.explainingFileInclude(
|
|
1079
1122
|
'',
|
|
@@ -1122,7 +1165,7 @@ export class FileLoader {
|
|
|
1122
1165
|
const reason = FileIncludeReason.reference(FileIncludeKind.LibReferenceDirective, task.path, i, undefined);
|
|
1123
1166
|
const name = getLibFileName(file.libReferenceDirectives[i].fileName);
|
|
1124
1167
|
if (name === '') {
|
|
1125
|
-
task.
|
|
1168
|
+
task.addProcessingDiagnostic(ProcessingDiagnostic.unknownReference(reason));
|
|
1126
1169
|
continue;
|
|
1127
1170
|
}
|
|
1128
1171
|
const libFile = this.pathForLibFile(name);
|
|
@@ -1140,7 +1183,7 @@ export class FileLoader {
|
|
|
1140
1183
|
this.subTasksAhead.delete(task.normalizedFilePath);
|
|
1141
1184
|
task.subTasks = ahead.subTasks;
|
|
1142
1185
|
} else task.subTasks = this.subTasksOf(loaded);
|
|
1143
|
-
for (const diagnostic of loaded.processingDiagnostics) task.
|
|
1186
|
+
for (const diagnostic of loaded.processingDiagnostics) task.addProcessingDiagnostic(diagnostic.copy());
|
|
1144
1187
|
task.resolutionsInFile = loaded.resolutionsInFile;
|
|
1145
1188
|
task.typeResolutionsInFile = loaded.typeResolutionsInFile;
|
|
1146
1189
|
task.importHelpersImportSpecifier = loaded.importHelpersImportSpecifier;
|
|
@@ -1190,7 +1233,7 @@ export class FileLoader {
|
|
|
1190
1233
|
reason,
|
|
1191
1234
|
);
|
|
1192
1235
|
if (typeof resolved !== 'string') {
|
|
1193
|
-
task.
|
|
1236
|
+
task.addProcessingDiagnostic(
|
|
1194
1237
|
ProcessingDiagnostic.explainingFileInclude('', reason, resolved.message, resolved.args),
|
|
1195
1238
|
);
|
|
1196
1239
|
return;
|
|
@@ -1216,7 +1259,7 @@ export class FileLoader {
|
|
|
1216
1259
|
containingFile,
|
|
1217
1260
|
mode,
|
|
1218
1261
|
redirect?.resolved,
|
|
1219
|
-
task.
|
|
1262
|
+
task.typeTraces(this.options.traceResolution === true),
|
|
1220
1263
|
);
|
|
1221
1264
|
resolutions.set(modeAwareKey(reference.fileName, mode), resolved);
|
|
1222
1265
|
const reason = FileIncludeReason.reference(FileIncludeKind.TypeReferenceDirective, task.path, i, undefined);
|
|
@@ -1230,7 +1273,7 @@ export class FileLoader {
|
|
|
1230
1273
|
resolved.packageId,
|
|
1231
1274
|
);
|
|
1232
1275
|
} else {
|
|
1233
|
-
task.
|
|
1276
|
+
task.addProcessingDiagnostic(ProcessingDiagnostic.unknownReference(reason));
|
|
1234
1277
|
}
|
|
1235
1278
|
}
|
|
1236
1279
|
task.typeResolutionsInFile = resolutions;
|
|
@@ -1247,7 +1290,7 @@ export class FileLoader {
|
|
|
1247
1290
|
task.normalizedFilePath,
|
|
1248
1291
|
ModuleKind.None,
|
|
1249
1292
|
undefined,
|
|
1250
|
-
task.
|
|
1293
|
+
task.typeTraces(this.options.traceResolution === true),
|
|
1251
1294
|
);
|
|
1252
1295
|
resolutions.set(modeAwareKey(name, ModuleKind.None), resolved);
|
|
1253
1296
|
if (resolved.resolvedFileName !== '') {
|
|
@@ -1260,7 +1303,7 @@ export class FileLoader {
|
|
|
1260
1303
|
resolved.packageId,
|
|
1261
1304
|
);
|
|
1262
1305
|
} else {
|
|
1263
|
-
task.
|
|
1306
|
+
task.addProcessingDiagnostic(
|
|
1264
1307
|
ProcessingDiagnostic.explainingFileInclude(
|
|
1265
1308
|
'',
|
|
1266
1309
|
FileIncludeReason.automaticTypeDirective(name, undefined),
|
|
@@ -1308,7 +1351,7 @@ export class FileLoader {
|
|
|
1308
1351
|
containingFile,
|
|
1309
1352
|
mode,
|
|
1310
1353
|
redirect?.resolved,
|
|
1311
|
-
task.
|
|
1354
|
+
task.moduleTraces(this.options.traceResolution === true),
|
|
1312
1355
|
);
|
|
1313
1356
|
resolutions.set(modeAwareKey(moduleName, mode), resolved);
|
|
1314
1357
|
const resolvedFileName = resolved.resolvedFileName;
|
|
@@ -1370,16 +1413,24 @@ export class FileLoader {
|
|
|
1370
1413
|
const packageIdToSourceFile = new Map<string, SourceFile>();
|
|
1371
1414
|
const checkCasing = this.options.forceConsistentCasingInFileNames !== false;
|
|
1372
1415
|
const seen = new Map<ParseTaskData, string>();
|
|
1373
|
-
|
|
1374
|
-
|
|
1416
|
+
// The paths each file's imports and type reference directives add (the tasks of each path), for
|
|
1417
|
+
// `ProcessedFiles.addedFiles`: recorded while collecting visits them, as their files are only known
|
|
1418
|
+
// once every file is collected.
|
|
1419
|
+
const fileData: ParseTaskData[] = [];
|
|
1420
|
+
const libData = new Map<SourceFile, ParseTaskData>();
|
|
1421
|
+
const packageIdToData = new Map<string, ParseTaskData>();
|
|
1422
|
+
|
|
1423
|
+
const collectFiles = (tasks: readonly ParseTask[], added: ParseTaskData[] | undefined): void => {
|
|
1375
1424
|
for (let task of tasks) {
|
|
1376
1425
|
const includeReason = task.includeReason;
|
|
1426
|
+
const byImport = task.byImport;
|
|
1377
1427
|
// Automatic type directive tasks are an implementation detail, not a reason.
|
|
1378
1428
|
if (task.redirectedParseTask === undefined && !task.isForAutomaticTypeDirective) {
|
|
1379
1429
|
if (task.loadedTask !== undefined) task = task.loadedTask;
|
|
1380
1430
|
if (includeReason !== undefined) addIncludeReason(includeProcessor, task, includeReason);
|
|
1381
1431
|
}
|
|
1382
1432
|
const data = this.taskDataByPath.get(task.path);
|
|
1433
|
+
if (added !== undefined && data !== undefined && byImport) added.push(data);
|
|
1383
1434
|
if (!task.loaded || data === undefined) continue;
|
|
1384
1435
|
|
|
1385
1436
|
const checkedName = seen.get(data);
|
|
@@ -1412,8 +1463,8 @@ export class FileLoader {
|
|
|
1412
1463
|
}
|
|
1413
1464
|
}
|
|
1414
1465
|
|
|
1415
|
-
for (const trace of task.typeResolutionsTrace) host.trace(trace);
|
|
1416
|
-
for (const trace of task.resolutionsTrace) host.trace(trace);
|
|
1466
|
+
for (const trace of task.typeResolutionsTrace ?? noTraces) host.trace(trace);
|
|
1467
|
+
for (const trace of task.resolutionsTrace ?? noTraces) host.trace(trace);
|
|
1417
1468
|
|
|
1418
1469
|
const file = task.file;
|
|
1419
1470
|
const packageId = data.packageId;
|
|
@@ -1434,13 +1485,18 @@ export class FileLoader {
|
|
|
1434
1485
|
),
|
|
1435
1486
|
);
|
|
1436
1487
|
filesByPath.set(task.path, packageIdFile);
|
|
1488
|
+
data.keptCopy = packageIdToData.get(key);
|
|
1437
1489
|
if (data.lowestDepth > 0) sourceFilesFoundSearchingNodeModules.add(task.path);
|
|
1438
1490
|
continue;
|
|
1439
1491
|
}
|
|
1440
|
-
if (file !== undefined)
|
|
1492
|
+
if (file !== undefined) {
|
|
1493
|
+
packageIdToSourceFile.set(key, file);
|
|
1494
|
+
packageIdToData.set(key, data);
|
|
1495
|
+
}
|
|
1441
1496
|
}
|
|
1442
1497
|
|
|
1443
|
-
|
|
1498
|
+
let own: ParseTaskData[] | undefined = undefined;
|
|
1499
|
+
if (task.subTasks !== undefined && task.subTasks.length > 0) collectFiles(task.subTasks, (own = []));
|
|
1444
1500
|
|
|
1445
1501
|
const redirected = task.redirectedParseTask;
|
|
1446
1502
|
if (redirected !== undefined) {
|
|
@@ -1449,21 +1505,26 @@ export class FileLoader {
|
|
|
1449
1505
|
}
|
|
1450
1506
|
if (task.isForAutomaticTypeDirective) {
|
|
1451
1507
|
typeResolutionsInFile.set(task.path, task.typeResolutionsInFile);
|
|
1452
|
-
for (const diagnostic of task.processingDiagnostics
|
|
1508
|
+
for (const diagnostic of task.processingDiagnostics ?? noProcessingDiagnostics)
|
|
1509
|
+
includeProcessor.addProcessingDiagnostic(diagnostic);
|
|
1453
1510
|
continue;
|
|
1454
1511
|
}
|
|
1455
1512
|
const path = task.path;
|
|
1456
|
-
for (const diagnostic of task.processingDiagnostics
|
|
1513
|
+
for (const diagnostic of task.processingDiagnostics ?? noProcessingDiagnostics)
|
|
1514
|
+
includeProcessor.addProcessingDiagnostic(diagnostic);
|
|
1457
1515
|
if (file === undefined) {
|
|
1458
1516
|
missingFiles.push(task.normalizedFilePath);
|
|
1459
1517
|
continue;
|
|
1460
1518
|
}
|
|
1461
1519
|
if (task.libFile !== undefined) {
|
|
1462
1520
|
libFiles.push(file);
|
|
1521
|
+
libData.set(file, data);
|
|
1463
1522
|
libFilesByPath.set(path, task.libFile);
|
|
1464
1523
|
} else {
|
|
1465
1524
|
files.push(file);
|
|
1525
|
+
fileData.push(data);
|
|
1466
1526
|
}
|
|
1527
|
+
if (own !== undefined) data.added = own;
|
|
1467
1528
|
filesByPath.set(path, file);
|
|
1468
1529
|
resolvedModules.set(path, task.resolutionsInFile);
|
|
1469
1530
|
typeResolutionsInFile.set(path, task.typeResolutionsInFile);
|
|
@@ -1475,13 +1536,28 @@ export class FileLoader {
|
|
|
1475
1536
|
if (data.lowestDepth > 0) sourceFilesFoundSearchingNodeModules.add(path);
|
|
1476
1537
|
}
|
|
1477
1538
|
};
|
|
1478
|
-
collectFiles(this.rootTasks);
|
|
1539
|
+
collectFiles(this.rootTasks, undefined);
|
|
1479
1540
|
|
|
1480
1541
|
const priorities = new Map<SourceFile, number>();
|
|
1481
1542
|
for (const file of libFiles) priorities.set(file, this.libFilePriority(file));
|
|
1482
1543
|
libFiles.sort((a, b) => (priorities.get(a) ?? 0) - (priorities.get(b) ?? 0));
|
|
1483
1544
|
const allFiles = [...libFiles, ...files];
|
|
1484
1545
|
for (const redirect of redirectFilesByPath.values()) redirect.index += libFiles.length;
|
|
1546
|
+
// The files a file adds, without reading its resolutions again or looking up their paths.
|
|
1547
|
+
const dataOfFiles: ParseTaskData[] = [];
|
|
1548
|
+
for (const file of libFiles) dataOfFiles.push(libData.get(file)!);
|
|
1549
|
+
for (const data of fileData) dataOfFiles.push(data);
|
|
1550
|
+
for (let i = 0; i < dataOfFiles.length; i++) dataOfFiles[i]!.index = i;
|
|
1551
|
+
const addedFiles: number[][] = [];
|
|
1552
|
+
for (let i = 0; i < dataOfFiles.length; i++) {
|
|
1553
|
+
const added: number[] = [];
|
|
1554
|
+
for (const data of dataOfFiles[i]!.added) {
|
|
1555
|
+
const kept = data.keptCopy;
|
|
1556
|
+
const k = kept !== undefined ? kept.index : data.index;
|
|
1557
|
+
if (k >= 0 && k !== i) added.push(k);
|
|
1558
|
+
}
|
|
1559
|
+
addedFiles.push(added);
|
|
1560
|
+
}
|
|
1485
1561
|
|
|
1486
1562
|
const keys = [...this.libResolutions.keys()].sort();
|
|
1487
1563
|
for (const key of keys) {
|
|
@@ -1511,6 +1587,7 @@ export class FileLoader {
|
|
|
1511
1587
|
redirectFilesByPath,
|
|
1512
1588
|
this.mapper,
|
|
1513
1589
|
this.tookPreparedResolutions ? preparedPackageJsonLookups() : noPackageJsonLookups,
|
|
1590
|
+
addedFiles,
|
|
1514
1591
|
);
|
|
1515
1592
|
}
|
|
1516
1593
|
}
|
|
@@ -1864,8 +1864,21 @@ class EmitFilesHandler {
|
|
|
1864
1864
|
const files = program.program.getSourceFiles();
|
|
1865
1865
|
const emittedOnCheckers = this.emittedOnCheckers();
|
|
1866
1866
|
const wrapped = this.wrap(writer);
|
|
1867
|
-
const
|
|
1868
|
-
|
|
1867
|
+
const ahead = this.declarationsEmittedAhead();
|
|
1868
|
+
const result = program.checked.javaScriptEmittedOnThreads
|
|
1869
|
+
? combineEmitResults(
|
|
1870
|
+
files.map((file) =>
|
|
1871
|
+
this.emitAfterEmitThreads(
|
|
1872
|
+
file,
|
|
1873
|
+
EmitOnly.All,
|
|
1874
|
+
emittedOnCheckers.get(file),
|
|
1875
|
+
ahead.get(file),
|
|
1876
|
+
writer,
|
|
1877
|
+
wrapped,
|
|
1878
|
+
),
|
|
1879
|
+
),
|
|
1880
|
+
)
|
|
1881
|
+
: emittedOnCheckers.size === 0
|
|
1869
1882
|
? program.emitter.emit(files, EmitOnly.All, wrapped)
|
|
1870
1883
|
: combineEmitResults(
|
|
1871
1884
|
files.map((file) => {
|
|
@@ -1901,20 +1914,76 @@ class EmitFilesHandler {
|
|
|
1901
1914
|
/**
|
|
1902
1915
|
* The emit results of the files checker threads emitted right after checking them (parallel-check.ts),
|
|
1903
1916
|
* which are not emitted again here. Checker threads emit every file of a program without old build
|
|
1904
|
-
* info, with the outputs its options select, as its pending emit asks.
|
|
1917
|
+
* info, with the outputs its options select, as its pending emit asks. Emit threads emit only the
|
|
1918
|
+
* JavaScript of the files (`javaScriptEmittedOnThreads`, `emitAfterEmitThreads`).
|
|
1905
1919
|
*/
|
|
1906
1920
|
private emittedOnCheckers(): Map<SourceFile, EmitResult> {
|
|
1921
|
+
return this.byFile(this.program.checked.emittedInParallel);
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
/** The declaration emit of the files the declaration thread emitted (parallel-emit.ts). */
|
|
1925
|
+
private declarationsEmittedAhead(): Map<SourceFile, EmitResult> {
|
|
1926
|
+
return this.byFile(this.program.checked.declarationsEmittedAhead);
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
/** The results of `results`, by file index, by file. */
|
|
1930
|
+
private byFile(results: readonly (EmitResult | undefined)[] | undefined): Map<SourceFile, EmitResult> {
|
|
1907
1931
|
const result = new Map<SourceFile, EmitResult>();
|
|
1908
|
-
|
|
1909
|
-
if (emitted === undefined) return result;
|
|
1932
|
+
if (results === undefined) return result;
|
|
1910
1933
|
const files = this.program.program.getSourceFiles();
|
|
1911
1934
|
for (let i = 0; i < files.length; i++) {
|
|
1912
|
-
const fileResult =
|
|
1935
|
+
const fileResult = results[i];
|
|
1913
1936
|
if (fileResult !== undefined) result.set(files[i]!, fileResult);
|
|
1914
1937
|
}
|
|
1915
1938
|
return result;
|
|
1916
1939
|
}
|
|
1917
1940
|
|
|
1941
|
+
/**
|
|
1942
|
+
* The emit of `file` with `emitOnly` where emit threads emitted the JavaScript of the program's files
|
|
1943
|
+
* while this thread checked it (`javaScriptEmittedOnThreads`, parallel-emit.ts): the outputs an emit thread
|
|
1944
|
+
* emitted of its JavaScript (`javaScript`) and the declaration thread of its declarations (`declarations`),
|
|
1945
|
+
* and the rest emitted here. A file no thread emitted is emitted here as without the threads.
|
|
1946
|
+
*/
|
|
1947
|
+
private emitAfterEmitThreads(
|
|
1948
|
+
file: SourceFile,
|
|
1949
|
+
emitOnly: EmitOnly,
|
|
1950
|
+
javaScript: EmitResult | undefined,
|
|
1951
|
+
declarations: EmitResult | undefined,
|
|
1952
|
+
writer: OutputWriter,
|
|
1953
|
+
wrapped: OutputWriter,
|
|
1954
|
+
): EmitResult {
|
|
1955
|
+
const program = this.program;
|
|
1956
|
+
if (wrapped instanceof SignatureRecordingWriter) wrapped.file = file;
|
|
1957
|
+
if (javaScript === undefined && declarations === undefined) return program.emitter.emit([file], emitOnly, wrapped);
|
|
1958
|
+
const results: EmitResult[] = [];
|
|
1959
|
+
if (emitOnly !== EmitOnly.Dts)
|
|
1960
|
+
results.push(
|
|
1961
|
+
javaScript !== undefined
|
|
1962
|
+
? this.writeThreadOutputs(file, javaScript, writer)
|
|
1963
|
+
: program.emitter.emit([file], EmitOnly.Js, writer),
|
|
1964
|
+
);
|
|
1965
|
+
if (emitOnly !== EmitOnly.Js && getEmitDeclarations(program.snapshot.options))
|
|
1966
|
+
results.push(
|
|
1967
|
+
declarations !== undefined
|
|
1968
|
+
? this.writeThreadOutputs(file, declarations, writer)
|
|
1969
|
+
: program.emitter.emit([file], EmitOnly.Dts, wrapped),
|
|
1970
|
+
);
|
|
1971
|
+
return combineEmitResults(results);
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
/**
|
|
1975
|
+
* Writes the outputs a thread emitted for `file` with `writer`, as this thread would have written them:
|
|
1976
|
+
* its declaration signatures are recorded (`recordDeclarationSignatures`), and the unchanged declaration
|
|
1977
|
+
* files of a composite program are left unwritten.
|
|
1978
|
+
*/
|
|
1979
|
+
private writeThreadOutputs(file: SourceFile, emitted: EmitResult, writer: OutputWriter): EmitResult {
|
|
1980
|
+
const skips = this.recordDeclarationSignatures(file, emitted.declarationSignatures);
|
|
1981
|
+
return writeHeldOutputs(
|
|
1982
|
+
emitted,
|
|
1983
|
+
skips === undefined ? writer : new HeldDeclarationWriter(writer, skips, this.program.host),
|
|
1984
|
+
);
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1918
1987
|
/** Records declaration signatures when declarations are emitted. */
|
|
1919
1988
|
private wrap(writer: OutputWriter): OutputWriter {
|
|
1920
1989
|
return getEmitDeclarations(this.program.snapshot.options) ? new SignatureRecordingWriter(this, writer) : writer;
|
|
@@ -1926,6 +1995,7 @@ class EmitFilesHandler {
|
|
|
1926
1995
|
collectAllAffectedFiles(program);
|
|
1927
1996
|
const wrapped = this.wrap(writer);
|
|
1928
1997
|
const emittedOnCheckers = this.emittedOnCheckers();
|
|
1998
|
+
const ahead = this.declarationsEmittedAhead();
|
|
1929
1999
|
for (const [path, emitKind] of snapshot.affectedFilesPendingEmit) {
|
|
1930
2000
|
const affectedFile = program.program.getSourceFileByPath(path);
|
|
1931
2001
|
if (affectedFile === undefined || !program.program.sourceFileMayBeEmitted(affectedFile, false)) {
|
|
@@ -1939,13 +2009,10 @@ class EmitFilesHandler {
|
|
|
1939
2009
|
if (!this.isForDtsErrors) {
|
|
1940
2010
|
const emitOnly = emitOnlyOfPendingKind(pendingKind);
|
|
1941
2011
|
const emitted = emittedOnCheckers.get(affectedFile);
|
|
1942
|
-
if (
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
skips === undefined ? writer : new HeldDeclarationWriter(writer, skips, program.host),
|
|
1947
|
-
);
|
|
1948
|
-
} else {
|
|
2012
|
+
if (program.checked.javaScriptEmittedOnThreads)
|
|
2013
|
+
result = this.emitAfterEmitThreads(affectedFile, emitOnly, emitted, ahead.get(affectedFile), writer, wrapped);
|
|
2014
|
+
else if (emitted !== undefined) result = this.writeThreadOutputs(affectedFile, emitted, writer);
|
|
2015
|
+
else {
|
|
1949
2016
|
if (wrapped instanceof SignatureRecordingWriter) wrapped.file = affectedFile;
|
|
1950
2017
|
result = program.emitter.emit([affectedFile], emitOnly, wrapped);
|
|
1951
2018
|
}
|
|
@@ -169,6 +169,38 @@ export class ClusteredIntLinkTable {
|
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
/** Ids in pages of `IdSetPaging.Ids` ids, one bit each; a page is created by the first id added to it. */
|
|
173
|
+
export class PagedIdSet {
|
|
174
|
+
readonly pages: (Int32Array | undefined)[] = [];
|
|
175
|
+
|
|
176
|
+
has(id: number): boolean {
|
|
177
|
+
const page = this.pages[id >> IdSetPaging.Bits];
|
|
178
|
+
return page !== undefined && (page[(id >> 5) & IdSetPaging.WordMask]! & (1 << (id & 31))) !== 0;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
add(id: number): void {
|
|
182
|
+
const index = id >> IdSetPaging.Bits;
|
|
183
|
+
let page = this.pages[index];
|
|
184
|
+
if (page === undefined) {
|
|
185
|
+
while (this.pages.length <= index) this.pages.push(undefined);
|
|
186
|
+
page = new Int32Array(IdSetPaging.Words);
|
|
187
|
+
this.pages[index] = page;
|
|
188
|
+
}
|
|
189
|
+
page[(id >> 5) & IdSetPaging.WordMask] |= 1 << (id & 31);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
clear(): void {
|
|
193
|
+
this.pages.length = 0;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** `PagedIdSet` pages: 8192 ids in 256 words. */
|
|
198
|
+
const enum IdSetPaging {
|
|
199
|
+
Bits = 13,
|
|
200
|
+
Words = 1 << (Bits - 5),
|
|
201
|
+
WordMask = Words - 1,
|
|
202
|
+
}
|
|
203
|
+
|
|
172
204
|
/** The number of set bits of a 32-bit value. */
|
|
173
205
|
function bitCount(x: number): number {
|
|
174
206
|
x = x - ((x >>> 1) & 0x55555555);
|