tsc-ts 0.0.8 → 0.0.9

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.
@@ -702,8 +702,12 @@ export function resolveDeclaredMembers(c, t) {
702
702
  const members = getMembersOfSymbol(c, t.symbol);
703
703
  declared.declaredMembersResolved = true;
704
704
  declared.declaredMembers = members;
705
- declared.declaredCallSignatures = getSignaturesOfSymbol(c, members.get("\uFFFEcall" /* InternalSymbolName.Call */));
706
- declared.declaredConstructSignatures = getSignaturesOfSymbol(c, members.get("\uFFFEnew" /* InternalSymbolName.New */));
705
+ // Most interfaces declare neither, and share one empty list.
706
+ const call = members.get("\uFFFEcall" /* InternalSymbolName.Call */);
707
+ const construct = members.get("\uFFFEnew" /* InternalSymbolName.New */);
708
+ declared.declaredCallSignatures = call !== undefined ? getSignaturesOfSymbol(c, call) : emptySignatures;
709
+ declared.declaredConstructSignatures =
710
+ construct !== undefined ? getSignaturesOfSymbol(c, construct) : emptySignatures;
707
711
  declared.declaredIndexInfos = getIndexInfosOfSymbol(c, t.symbol);
708
712
  }
709
713
  return declared;
@@ -5,6 +5,18 @@ import type { Checker } from './checker.js';
5
5
  * identifiers, which need the whole file checked first.
6
6
  */
7
7
  export declare function checkSourceFile(c: Checker, file: SourceFile, checkUnused?: boolean): void;
8
+ /**
9
+ * Checks the statements `start` to `end` of the declaration file `file`, one of the ranges that several
10
+ * checkers check it in (parallel-check.ts), and returns whether the checker then has diagnostics in the
11
+ * file. The range ending the file also runs the checks of the whole file. The file is not marked checked.
12
+ *
13
+ * When no range finds a diagnostic in the file, checking it whole would find none either: each statement
14
+ * is checked by the checker of its range. Otherwise the file is checked whole (`startParallelCheck`): the
15
+ * diagnostics of the ranges can differ from the file's, where they depend on the order the file's
16
+ * declarations are resolved in. A union type prints its members in the order the checker created them,
17
+ * and a check that a symbol's first declaration runs reports on all its declarations.
18
+ */
19
+ export declare function checkSourceFileRange(c: Checker, file: SourceFile, start: number, end: number): boolean;
8
20
  /** Checks a statement, declaration, class member or type node. */
9
21
  export declare function checkSourceElement(c: Checker, node: Node | undefined): void;
10
22
  /** Resolves the `@link` names of a node's JSDoc, which marks what they name referenced. */
@@ -81,6 +81,41 @@ function checkSourceFileWorker(c, file) {
81
81
  links.typeChecked = true;
82
82
  links.deferredNodes = undefined;
83
83
  }
84
+ /**
85
+ * Checks the statements `start` to `end` of the declaration file `file`, one of the ranges that several
86
+ * checkers check it in (parallel-check.ts), and returns whether the checker then has diagnostics in the
87
+ * file. The range ending the file also runs the checks of the whole file. The file is not marked checked.
88
+ *
89
+ * When no range finds a diagnostic in the file, checking it whole would find none either: each statement
90
+ * is checked by the checker of its range. Otherwise the file is checked whole (`startParallelCheck`): the
91
+ * diagnostics of the ranges can differ from the file's, where they depend on the order the file's
92
+ * declarations are resolved in. A union type prints its members in the order the checker created them,
93
+ * and a check that a symbol's first declaration runs reports on all its declarations.
94
+ */
95
+ export function checkSourceFileRange(c, file, start, end) {
96
+ const statements = getStatements(file).nodes;
97
+ c.fileBeingChecked = file;
98
+ c.saveDeferredDiagnostics = true;
99
+ for (let i = start; i < end; i++)
100
+ checkSourceElement(c, statements[i]);
101
+ checkDeferredNodes(c, file);
102
+ const whole = end === statements.length;
103
+ if (whole && isExternalOrCommonJSModule(file))
104
+ checkExternalModuleExports(c, file);
105
+ c.renamedBindingElementsInTypes.length = 0;
106
+ if (whole) {
107
+ checkGrammarSourceFile(c, file);
108
+ checkDeferredNodes(c, file);
109
+ checkPendingExternalEmitHelpers(c, file);
110
+ }
111
+ c.fileBeingChecked = undefined;
112
+ c.saveDeferredDiagnostics = false;
113
+ produceDeferredIterationErrors(c);
114
+ produceDeferredCollisionChecks(c);
115
+ // Deferred nodes of a later range are queued again (checkNodeDeferred).
116
+ c.nodeLinks(file).deferredNodes = undefined;
117
+ return c.diagnostics.forFile(file.fileName).length > 0;
118
+ }
84
119
  /** Checks a statement, declaration, class member or type node. */
85
120
  export function checkSourceElement(c, node) {
86
121
  if (node === undefined)
@@ -697,6 +697,7 @@ function setMergedSymbol(c, id, target) {
697
697
  c.mergedSymbolChanges.set(c.mergedSymbols, id, target);
698
698
  else
699
699
  c.mergedSymbols.set(id, target);
700
+ c.mergedSymbolIds.add(id);
700
701
  }
701
702
  /** Merges script locals into globals; ambient modules and augmentations wait for global types. */
702
703
  export function initializeGlobals(c) {
@@ -1033,7 +1034,7 @@ function recordMergedSymbol(c, target, source) {
1033
1034
  }
1034
1035
  export function getMergedSymbol(c, symbol) {
1035
1036
  const id = symbol.id;
1036
- if (id !== 0) {
1037
+ if (id !== 0 && c.mergedSymbolIds.has(id)) {
1037
1038
  const merged = c.mergedSymbols.get(id);
1038
1039
  if (merged !== undefined)
1039
1040
  return merged;
@@ -1,7 +1,7 @@
1
1
  import type { DeferredCollisionCheck } from './checker-generated-code.js';
2
2
  import type { EmitHelperFileLinks } from './checker-emit-helpers.js';
3
3
  import type { Node, PatternAmbientModule, SourceFile } from './ast.js';
4
- import { CompactSymbolLinkTable, IntLinkTable, LinkTable, SparseLinkTable } from './link-tables.js';
4
+ import { CompactSymbolLinkTable, IntLinkTable, LinkTable, PagedIdSet, SparseLinkTable } from './link-tables.js';
5
5
  import { Diagnostic, type DiagnosticMessage, Diagnostics } from './diagnostics.js';
6
6
  import { type CompilerOptions, ModuleKind, ScriptTarget } from './options.js';
7
7
  import { CheckFlags, Symbol, SymbolFlags, type SymbolTable } from './symbol.js';
@@ -204,6 +204,11 @@ export declare class Checker implements TypeChecking {
204
204
  readonly resolvedSignatures: SparseLinkTable<Signature>;
205
205
  /** Merged symbols, indexed by the id of the symbol merged into them. */
206
206
  readonly mergedSymbols: Map<number, Symbol>;
207
+ /**
208
+ * The ids that `mergedSymbols` has, or had: most symbols are merged into none, and `getMergedSymbol`
209
+ * finds that here without probing the map.
210
+ */
211
+ readonly mergedSymbolIds: PagedIdSet;
207
212
  /** Globals merged from the default libraries, shared with other checkers. */
208
213
  libGlobals: LibGlobals | undefined;
209
214
  /** The program's globals and module augmentations as another checker merged them, shared with it. */
@@ -1,5 +1,5 @@
1
1
  import { sideOf } from './side-state.js';
2
- import { CompactSymbolLinkTable, IntLinkTable, LinkTable, SparseLinkTable } from './link-tables.js';
2
+ import { CompactSymbolLinkTable, IntLinkTable, LinkTable, PagedIdSet, SparseLinkTable } from './link-tables.js';
3
3
  import { getErrorRangeForNode, getSourceFileOfNode } from './binder-utilities.js';
4
4
  import { Diagnostic, compareDiagnostics } from './diagnostics.js';
5
5
  import { ModuleKind, ScriptTarget, getEmitScriptTarget, getIsolatedModules, getStrictOptionValue, shouldPreserveConstEnums, } from './options.js';
@@ -284,6 +284,11 @@ export class Checker {
284
284
  resolvedSignatures = new SparseLinkTable();
285
285
  /** Merged symbols, indexed by the id of the symbol merged into them. */
286
286
  mergedSymbols;
287
+ /**
288
+ * The ids that `mergedSymbols` has, or had: most symbols are merged into none, and `getMergedSymbol`
289
+ * finds that here without probing the map.
290
+ */
291
+ mergedSymbolIds = new PagedIdSet();
287
292
  /** Globals merged from the default libraries, shared with other checkers. */
288
293
  libGlobals;
289
294
  /** The program's globals and module augmentations as another checker merged them, shared with it. */
@@ -616,6 +621,8 @@ export class Checker {
616
621
  this.globals = libs.copyGlobals();
617
622
  this.mergedSymbols = libs.copyMergedSymbols();
618
623
  }
624
+ for (const id of this.mergedSymbols.keys())
625
+ this.mergedSymbolIds.add(id);
619
626
  this.globalThisSymbol = this.newSymbol(1536 /* SymbolFlags.Module */, 'globalThis');
620
627
  this.globalThisSymbol.checkFlags = 8 /* CheckFlags.Readonly */;
621
628
  this.globalThisSymbol.exports = this.globals;
@@ -890,6 +897,7 @@ export function disposeChecker(c) {
890
897
  c.mergedSymbols.clear();
891
898
  c.globals.clear();
892
899
  }
900
+ c.mergedSymbolIds.clear();
893
901
  c.sharedSymbolCopies.clear();
894
902
  c.memberPositionsInLists.clear();
895
903
  c.memberNamesOfLists.clear();
@@ -95,10 +95,10 @@ export declare class LoadedFile {
95
95
  readonly references: LoadedReference[];
96
96
  readonly resolutionsInFile: ModeAwareCache<ResolvedModule> | undefined;
97
97
  readonly typeResolutionsInFile: ModeAwareCache<ResolvedTypeReferenceDirective> | undefined;
98
- readonly processingDiagnostics: ProcessingDiagnostic[];
98
+ readonly processingDiagnostics: readonly ProcessingDiagnostic[];
99
99
  readonly importHelpersImportSpecifier: StringLiteral | undefined;
100
100
  readonly jsxRuntimeImport: JsxRuntimeImport | undefined;
101
- constructor(file: SourceFile, isLibFile: boolean, metadata: SourceFileMetadata, references: LoadedReference[], resolutionsInFile: ModeAwareCache<ResolvedModule> | undefined, typeResolutionsInFile: ModeAwareCache<ResolvedTypeReferenceDirective> | undefined, processingDiagnostics: ProcessingDiagnostic[], importHelpersImportSpecifier: StringLiteral | undefined, jsxRuntimeImport: JsxRuntimeImport | undefined);
101
+ constructor(file: SourceFile, isLibFile: boolean, metadata: SourceFileMetadata, references: LoadedReference[], resolutionsInFile: ModeAwareCache<ResolvedModule> | undefined, typeResolutionsInFile: ModeAwareCache<ResolvedTypeReferenceDirective> | undefined, processingDiagnostics: readonly ProcessingDiagnostic[], importHelpersImportSpecifier: StringLiteral | undefined, jsxRuntimeImport: JsxRuntimeImport | undefined);
102
102
  }
103
103
  /** Referenced projects, and how their sources map to declaration outputs. */
104
104
  export declare class ProjectReferenceMapper {
@@ -165,6 +165,14 @@ class SubTasksAhead {
165
165
  this.subTasks = subTasks;
166
166
  }
167
167
  }
168
+ /** Read in place of a task's lists it has not created. */
169
+ const noParseTasks = [];
170
+ const noTraces = [];
171
+ const noProcessingDiagnostics = [];
172
+ /**
173
+ * A file to load. Its lists are created on first use: most tasks never get sub-tasks, traces or processing
174
+ * diagnostics, and large programs create hundreds of thousands of tasks.
175
+ */
168
176
  class ParseTask {
169
177
  normalizedFilePath;
170
178
  libFile;
@@ -176,15 +184,15 @@ class ParseTask {
176
184
  path = '';
177
185
  file = undefined;
178
186
  redirectedParseTask = undefined;
179
- subTasks = [];
187
+ subTasks = undefined;
180
188
  loaded = false;
181
189
  startedSubTasks = false;
182
190
  metadata = libFileMetadata;
183
191
  resolutionsInFile = undefined;
184
- resolutionsTrace = [];
192
+ resolutionsTrace = undefined;
185
193
  typeResolutionsInFile = undefined;
186
- typeResolutionsTrace = [];
187
- processingDiagnostics = [];
194
+ typeResolutionsTrace = undefined;
195
+ processingDiagnostics = undefined;
188
196
  importHelpersImportSpecifier = undefined;
189
197
  jsxRuntimeImport = undefined;
190
198
  /** The task of the same file name that was loaded instead of this one. */
@@ -201,7 +209,18 @@ class ParseTask {
201
209
  this.packageId = packageId;
202
210
  }
203
211
  addSubTask(fileName, libFile, reason, increaseDepth, elideOnDepth, packageId) {
204
- this.subTasks.push(new ParseTask(normalizePath(fileName), libFile, reason, false, increaseDepth, elideOnDepth, packageId));
212
+ (this.subTasks ??= []).push(new ParseTask(normalizePath(fileName), libFile, reason, false, increaseDepth, elideOnDepth, packageId));
213
+ }
214
+ addProcessingDiagnostic(diagnostic) {
215
+ (this.processingDiagnostics ??= []).push(diagnostic);
216
+ }
217
+ /** Where module resolution traces go under `--traceResolution`; undefined without it. */
218
+ moduleTraces(trace) {
219
+ return trace ? (this.resolutionsTrace ??= []) : undefined;
220
+ }
221
+ /** Where type reference resolution traces go under `--traceResolution`; undefined without it. */
222
+ typeTraces(trace) {
223
+ return trace ? (this.typeResolutionsTrace ??= []) : undefined;
205
224
  }
206
225
  }
207
226
  /** The tasks of one path, by file name casing. */
@@ -640,7 +659,7 @@ export class FileLoader {
640
659
  return undefined;
641
660
  }
642
661
  const references = [];
643
- for (const sub of task.subTasks) {
662
+ for (const sub of task.subTasks ?? noParseTasks) {
644
663
  references.push(new LoadedReference(sub.normalizedFilePath, sub.libFile !== undefined ? sub.libFile.name : '', sub.includeReason, sub.increaseDepth, sub.elideOnDepth, sub.packageId));
645
664
  const subDepth = sub.increaseDepth ? depth + 1 : depth;
646
665
  // `run` skips these.
@@ -655,7 +674,7 @@ export class FileLoader {
655
674
  // Traces are reported in the program's order: such programs resolve on their own.
656
675
  if (file === undefined || this.options.traceResolution === true)
657
676
  return undefined;
658
- return new LoadedFile(file, task.libFile !== undefined, task.metadata, references, task.resolutionsInFile, task.typeResolutionsInFile, task.processingDiagnostics, task.importHelpersImportSpecifier, task.jsxRuntimeImport);
677
+ return new LoadedFile(file, task.libFile !== undefined, task.metadata, references, task.resolutionsInFile, task.typeResolutionsInFile, task.processingDiagnostics ?? noProcessingDiagnostics, task.importHelpersImportSpecifier, task.jsxRuntimeImport);
659
678
  }
660
679
  // ---- Project references
661
680
  loadProjectReferences() {
@@ -737,7 +756,7 @@ export class FileLoader {
737
756
  return;
738
757
  }
739
758
  const task = new ParseTask(absolute, undefined, reason, false, false, false, undefined);
740
- task.processingDiagnostics.push(ProcessingDiagnostic.explainingFileInclude('', reason, resolved.message, resolved.args));
759
+ task.addProcessingDiagnostic(ProcessingDiagnostic.explainingFileInclude('', reason, resolved.message, resolved.args));
741
760
  this.rootTasks.push(task);
742
761
  }
743
762
  isSupportedExtension(canonicalFileName) {
@@ -888,7 +907,8 @@ export class FileLoader {
888
907
  }
889
908
  if (!taskByFileName.startedSubTasks && loadSubTasks) {
890
909
  taskByFileName.startedSubTasks = true;
891
- this.start(taskByFileName.subTasks, data.lowestDepth);
910
+ if (taskByFileName.subTasks !== undefined)
911
+ this.start(taskByFileName.subTasks, data.lowestDepth);
892
912
  }
893
913
  }
894
914
  }
@@ -921,7 +941,7 @@ export class FileLoader {
921
941
  if (hasExtension(task.normalizedFilePath) && this.options.allowNonTsExtensions !== true) {
922
942
  const canonicalFileName = getCanonicalFileName(task.normalizedFilePath, fs.useCaseSensitiveFileNames);
923
943
  if (!this.isSupportedExtension(canonicalFileName)) {
924
- task.processingDiagnostics.push(hasJSFileExtension(canonicalFileName)
944
+ task.addProcessingDiagnostic(hasJSFileExtension(canonicalFileName)
925
945
  ? ProcessingDiagnostic.explainingFileInclude('', task.includeReason, 1519 /* Diagnostics.File_0_is_a_JavaScript_file_Did_you_mean_to_enable_the_allowJs_option */, [task.normalizedFilePath])
926
946
  : ProcessingDiagnostic.explainingFileInclude('', task.includeReason, 1230 /* Diagnostics.File_0_has_an_unsupported_extension_The_only_supported_extensions_are_1 */, [task.normalizedFilePath, this.supportedExtensionsList()]));
927
947
  return;
@@ -955,7 +975,7 @@ export class FileLoader {
955
975
  const reason = FileIncludeReason.reference(3 /* FileIncludeKind.LibReferenceDirective */, task.path, i, undefined);
956
976
  const name = getLibFileName(file.libReferenceDirectives[i].fileName);
957
977
  if (name === '') {
958
- task.processingDiagnostics.push(ProcessingDiagnostic.unknownReference(reason));
978
+ task.addProcessingDiagnostic(ProcessingDiagnostic.unknownReference(reason));
959
979
  continue;
960
980
  }
961
981
  const libFile = this.pathForLibFile(name);
@@ -975,7 +995,7 @@ export class FileLoader {
975
995
  else
976
996
  task.subTasks = this.subTasksOf(loaded);
977
997
  for (const diagnostic of loaded.processingDiagnostics)
978
- task.processingDiagnostics.push(diagnostic.copy());
998
+ task.addProcessingDiagnostic(diagnostic.copy());
979
999
  task.resolutionsInFile = loaded.resolutionsInFile;
980
1000
  task.typeResolutionsInFile = loaded.typeResolutionsInFile;
981
1001
  task.importHelpersImportSpecifier = loaded.importHelpersImportSpecifier;
@@ -1002,7 +1022,7 @@ export class FileLoader {
1002
1022
  const reason = FileIncludeReason.reference(1 /* FileIncludeKind.ReferenceFile */, this.toPath(containingFile), index, undefined);
1003
1023
  const resolved = this.getSourceFileFromReference(normalizePath(referencedFileName), moduleName, containingFile, reason);
1004
1024
  if (typeof resolved !== 'string') {
1005
- task.processingDiagnostics.push(ProcessingDiagnostic.explainingFileInclude('', reason, resolved.message, resolved.args));
1025
+ task.addProcessingDiagnostic(ProcessingDiagnostic.explainingFileInclude('', reason, resolved.message, resolved.args));
1006
1026
  return;
1007
1027
  }
1008
1028
  task.addSubTask(resolved, undefined, reason, false, false, undefined);
@@ -1020,14 +1040,14 @@ export class FileLoader {
1020
1040
  const mode = reference.resolutionMode !== ModuleKind.None
1021
1041
  ? reference.resolutionMode
1022
1042
  : getDefaultResolutionModeForFile(file.fileName, task.metadata, options);
1023
- const resolved = this.resolver.resolveTypeReferenceDirective(reference.fileName, containingFile, mode, redirect?.resolved, task.typeResolutionsTrace);
1043
+ const resolved = this.resolver.resolveTypeReferenceDirective(reference.fileName, containingFile, mode, redirect?.resolved, task.typeTraces(this.options.traceResolution === true));
1024
1044
  resolutions.set(modeAwareKey(reference.fileName, mode), resolved);
1025
1045
  const reason = FileIncludeReason.reference(2 /* FileIncludeKind.TypeReferenceDirective */, task.path, i, undefined);
1026
1046
  if (resolved.resolvedFileName !== '') {
1027
1047
  task.addSubTask(resolved.resolvedFileName, undefined, reason, resolved.isExternalLibraryImport, false, resolved.packageId);
1028
1048
  }
1029
1049
  else {
1030
- task.processingDiagnostics.push(ProcessingDiagnostic.unknownReference(reason));
1050
+ task.addProcessingDiagnostic(ProcessingDiagnostic.unknownReference(reason));
1031
1051
  }
1032
1052
  }
1033
1053
  task.typeResolutionsInFile = resolutions;
@@ -1039,13 +1059,13 @@ export class FileLoader {
1039
1059
  const resolutions = new Map();
1040
1060
  for (const name of names) {
1041
1061
  // Resolved without a mode: CommonJS under node16/nodenext, `import` conditions under bundler.
1042
- const resolved = this.resolver.resolveTypeReferenceDirective(name, task.normalizedFilePath, ModuleKind.None, undefined, task.typeResolutionsTrace);
1062
+ const resolved = this.resolver.resolveTypeReferenceDirective(name, task.normalizedFilePath, ModuleKind.None, undefined, task.typeTraces(this.options.traceResolution === true));
1043
1063
  resolutions.set(modeAwareKey(name, ModuleKind.None), resolved);
1044
1064
  if (resolved.resolvedFileName !== '') {
1045
1065
  task.addSubTask(resolved.resolvedFileName, undefined, FileIncludeReason.automaticTypeDirective(name, resolved.packageId), resolved.isExternalLibraryImport, false, resolved.packageId);
1046
1066
  }
1047
1067
  else {
1048
- task.processingDiagnostics.push(ProcessingDiagnostic.explainingFileInclude('', FileIncludeReason.automaticTypeDirective(name, undefined), 821 /* Diagnostics.Cannot_find_type_definition_file_for_0 */, [name]));
1068
+ task.addProcessingDiagnostic(ProcessingDiagnostic.explainingFileInclude('', FileIncludeReason.automaticTypeDirective(name, undefined), 821 /* Diagnostics.Cannot_find_type_definition_file_for_0 */, [name]));
1049
1069
  }
1050
1070
  }
1051
1071
  task.typeResolutionsInFile = resolutions;
@@ -1083,7 +1103,7 @@ export class FileLoader {
1083
1103
  if (moduleName === '')
1084
1104
  continue;
1085
1105
  const mode = getModeForUsageLocation(file.fileName, task.metadata, entry, options);
1086
- const resolved = this.resolver.resolveModuleName(moduleName, containingFile, mode, redirect?.resolved, task.resolutionsTrace);
1106
+ const resolved = this.resolver.resolveModuleName(moduleName, containingFile, mode, redirect?.resolved, task.moduleTraces(this.options.traceResolution === true));
1087
1107
  resolutions.set(modeAwareKey(moduleName, mode), resolved);
1088
1108
  const resolvedFileName = resolved.resolvedFileName;
1089
1109
  if (resolvedFileName === '')
@@ -1169,9 +1189,9 @@ export class FileLoader {
1169
1189
  tasksSeenByNameIgnoreCase.set(lowerCasePath, task);
1170
1190
  }
1171
1191
  }
1172
- for (const trace of task.typeResolutionsTrace)
1192
+ for (const trace of task.typeResolutionsTrace ?? noTraces)
1173
1193
  host.trace(trace);
1174
- for (const trace of task.resolutionsTrace)
1194
+ for (const trace of task.resolutionsTrace ?? noTraces)
1175
1195
  host.trace(trace);
1176
1196
  const file = task.file;
1177
1197
  const packageId = data.packageId;
@@ -1193,7 +1213,7 @@ export class FileLoader {
1193
1213
  if (file !== undefined)
1194
1214
  packageIdToSourceFile.set(key, file);
1195
1215
  }
1196
- if (task.subTasks.length > 0)
1216
+ if (task.subTasks !== undefined && task.subTasks.length > 0)
1197
1217
  collectFiles(task.subTasks);
1198
1218
  const redirected = task.redirectedParseTask;
1199
1219
  if (redirected !== undefined) {
@@ -1202,12 +1222,12 @@ export class FileLoader {
1202
1222
  }
1203
1223
  if (task.isForAutomaticTypeDirective) {
1204
1224
  typeResolutionsInFile.set(task.path, task.typeResolutionsInFile);
1205
- for (const diagnostic of task.processingDiagnostics)
1225
+ for (const diagnostic of task.processingDiagnostics ?? noProcessingDiagnostics)
1206
1226
  includeProcessor.addProcessingDiagnostic(diagnostic);
1207
1227
  continue;
1208
1228
  }
1209
1229
  const path = task.path;
1210
- for (const diagnostic of task.processingDiagnostics)
1230
+ for (const diagnostic of task.processingDiagnostics ?? noProcessingDiagnostics)
1211
1231
  includeProcessor.addProcessingDiagnostic(diagnostic);
1212
1232
  if (file === undefined) {
1213
1233
  missingFiles.push(task.normalizedFilePath);
@@ -58,6 +58,13 @@ export declare class ClusteredIntLinkTable {
58
58
  set(id: number, value: number): void;
59
59
  private pageOf;
60
60
  }
61
+ /** Ids in pages of `IdSetPaging.Ids` ids, one bit each; a page is created by the first id added to it. */
62
+ export declare class PagedIdSet {
63
+ readonly pages: (Int32Array | undefined)[];
64
+ has(id: number): boolean;
65
+ add(id: number): void;
66
+ clear(): void;
67
+ }
61
68
  /**
62
69
  * A page of a `CompactSymbolLinkTable`: one bit per id of the page in eight 32-id words, the number
63
70
  * of symbols stored before each word, and the symbols in id order. The words are fields, so a
@@ -146,6 +146,28 @@ export class ClusteredIntLinkTable {
146
146
  return this.lastPage;
147
147
  }
148
148
  }
149
+ /** Ids in pages of `IdSetPaging.Ids` ids, one bit each; a page is created by the first id added to it. */
150
+ export class PagedIdSet {
151
+ pages = [];
152
+ has(id) {
153
+ const page = this.pages[id >> 13 /* IdSetPaging.Bits */];
154
+ return page !== undefined && (page[(id >> 5) & 255 /* IdSetPaging.WordMask */] & (1 << (id & 31))) !== 0;
155
+ }
156
+ add(id) {
157
+ const index = id >> 13 /* IdSetPaging.Bits */;
158
+ let page = this.pages[index];
159
+ if (page === undefined) {
160
+ while (this.pages.length <= index)
161
+ this.pages.push(undefined);
162
+ page = new Int32Array(256 /* IdSetPaging.Words */);
163
+ this.pages[index] = page;
164
+ }
165
+ page[(id >> 5) & 255 /* IdSetPaging.WordMask */] |= 1 << (id & 31);
166
+ }
167
+ clear() {
168
+ this.pages.length = 0;
169
+ }
170
+ }
149
171
  /** The number of set bits of a 32-bit value. */
150
172
  function bitCount(x) {
151
173
  x = x - ((x >>> 1) & 0x55555555);
@@ -3010,17 +3010,12 @@ export class Parser extends ScannerErrorReporter {
3010
3010
  return false;
3011
3011
  }
3012
3012
  parseTypeOrTypePredicate() {
3013
- if (this.isIdentifier()) {
3014
- const state = this.beginSpeculation();
3013
+ // `x is T`: the identifier is parsed only once `is` is known to follow it.
3014
+ if (this.isIdentifier() && this.lookAhead(nextTokenIsIsKeywordOnSameLine)) {
3015
3015
  const pos = this.nodePos();
3016
3016
  const id = this.parseIdentifier(1 /* IdentifierUse.Name */);
3017
- if (this.token() === 142 /* SyntaxKind.IsKeyword */ && !this.hasPrecedingLineBreak()) {
3018
- this.endSpeculation(state);
3019
- this.nextToken();
3020
- return this.finishNode(new TypePredicateNode(undefined, id, this.parseType()), pos);
3021
- }
3022
- this.rewind(state);
3023
- this.endSpeculation(state);
3017
+ this.nextToken();
3018
+ return this.finishNode(new TypePredicateNode(undefined, id, this.parseType()), pos);
3024
3019
  }
3025
3020
  return this.parseType();
3026
3021
  }
@@ -5982,6 +5977,9 @@ function nextTokenCanFollowExportModifier(p) {
5982
5977
  function nextTokenIsClassKeywordOnSameLine(p) {
5983
5978
  return p.nextToken() === 85 /* SyntaxKind.ClassKeyword */ && !p.hasPrecedingLineBreak();
5984
5979
  }
5980
+ function nextTokenIsIsKeywordOnSameLine(p) {
5981
+ return p.nextToken() === 142 /* SyntaxKind.IsKeyword */ && !p.hasPrecedingLineBreak();
5982
+ }
5985
5983
  function nextTokenIsFunctionKeywordOnSameLine(p) {
5986
5984
  return p.nextToken() === 99 /* SyntaxKind.FunctionKeyword */ && !p.hasPrecedingLineBreak();
5987
5985
  }
@@ -6034,11 +6032,14 @@ function nextIsUnParenthesizedAsyncArrowFunction(p) {
6034
6032
  // `async =>` is a simple arrow function with a parameter named `async`.
6035
6033
  if (p.hasPrecedingLineBreak() || p.token() === 38 /* SyntaxKind.EqualsGreaterThanToken */)
6036
6034
  return false;
6037
- const expr = p.parseBinaryExpressionOrHigher(0 /* OperatorPrecedence.Lowest */);
6038
- if (!p.hasPrecedingLineBreak() &&
6039
- expr.kind === 79 /* SyntaxKind.Identifier */ &&
6040
- p.token() === 38 /* SyntaxKind.EqualsGreaterThanToken */)
6041
- return true;
6035
+ // The binary expression after `async` is a lone identifier followed by `=>` only when an identifier
6036
+ // token is followed by `=>`. Any other first token starts another kind of expression or none, and any
6037
+ // other token after the identifier continues the expression or ends it before `=>`. Checking the
6038
+ // tokens gives the same answer as parsing the expression, whose nodes would be discarded.
6039
+ if (!p.isIdentifier())
6040
+ return false;
6041
+ p.nextToken();
6042
+ return !p.hasPrecedingLineBreak() && p.token() === 38 /* SyntaxKind.EqualsGreaterThanToken */;
6042
6043
  }
6043
6044
  return false;
6044
6045
  }
@@ -134,6 +134,23 @@ export declare class CheckedProgram {
134
134
  * incremental program keeps them unfiltered under `noEmit` too.
135
135
  */
136
136
  unfilteredDiagnosticsOfFile(file: SourceFile): Diagnostic[];
137
+ /**
138
+ * Checks the statements `start` to `end` of the declaration file `file` with this checker, one of the
139
+ * ranges that several checkers check it in (`checkSourceFileRange`, parallel-check.ts), and returns
140
+ * whether the checker then has diagnostics in the file.
141
+ */
142
+ checkRange(file: SourceFile, start: number, end: number): boolean;
143
+ /**
144
+ * The diagnostics of `file`, as `unfilteredDiagnosticsOfFile` gives them, where checkers checked it in
145
+ * ranges and found no diagnostics in it (`checkRange`).
146
+ */
147
+ unfilteredDiagnosticsOfCleanRanges(file: SourceFile): Diagnostic[];
148
+ /**
149
+ * The diagnostics of `file`, as `unfilteredDiagnosticsOfFile` gives them, from a new checker that checks it
150
+ * whole: for a file checked in ranges that found diagnostics in it (parallel-check.ts), part of which this
151
+ * thread's checker may have checked.
152
+ */
153
+ unfilteredDiagnosticsOfFileOnNewChecker(file: SourceFile): Diagnostic[];
137
154
  /**
138
155
  * The bind and check diagnostics of `file` before `noEmit` filtering and without include errors.
139
156
  * Once checker threads checked the program, they come from the threads' diagnostics of the file,
@@ -156,6 +173,7 @@ export declare class CheckedProgram {
156
173
  skipTypeChecking(file: SourceFile): boolean;
157
174
  private collect;
158
175
  private collectChecked;
176
+ /** `checks` are the checker's diagnostics of `file`. */
159
177
  private getBindAndCheckDiagnostics;
160
178
  getIncludeProcessorDiagnostics(file: SourceFile): Diagnostic[];
161
179
  }
@@ -4,6 +4,7 @@ import { ModuleSpecifierHost } from './module-specifiers.js';
4
4
  import { sortAndDeduplicateDiagnostics } from './program.js';
5
5
  import { getEmitModuleFormatOfFile, getEmitSyntaxForUsageLocation, isCheckJsEnabledForFile, } from './program-utilities.js';
6
6
  import { bindSourceFile } from './binder.js';
7
+ import { checkSourceFileRange } from './checker-source-file.js';
7
8
  import { computeLineOfPosition } from './scanner.js';
8
9
  /** What the checker needs, answered by a program. */
9
10
  export class ProgramCheckerHost extends CheckerHost {
@@ -250,6 +251,37 @@ export class CheckedProgram {
250
251
  result.push(d);
251
252
  return result;
252
253
  }
254
+ /**
255
+ * Checks the statements `start` to `end` of the declaration file `file` with this checker, one of the
256
+ * ranges that several checkers check it in (`checkSourceFileRange`, parallel-check.ts), and returns
257
+ * whether the checker then has diagnostics in the file.
258
+ */
259
+ checkRange(file, start, end) {
260
+ return checkSourceFileRange(this.checker, file, start, end);
261
+ }
262
+ /**
263
+ * The diagnostics of `file`, as `unfilteredDiagnosticsOfFile` gives them, where checkers checked it in
264
+ * ranges and found no diagnostics in it (`checkRange`).
265
+ */
266
+ unfilteredDiagnosticsOfCleanRanges(file) {
267
+ const result = this.getBindAndCheckDiagnostics(file, []);
268
+ for (const d of this.getIncludeProcessorDiagnostics(file))
269
+ result.push(d);
270
+ return result;
271
+ }
272
+ /**
273
+ * The diagnostics of `file`, as `unfilteredDiagnosticsOfFile` gives them, from a new checker that checks it
274
+ * whole: for a file checked in ranges that found diagnostics in it (parallel-check.ts), part of which this
275
+ * thread's checker may have checked.
276
+ */
277
+ unfilteredDiagnosticsOfFileOnNewChecker(file) {
278
+ const checker = this.createChecker();
279
+ const result = this.getBindAndCheckDiagnostics(file, checker.getDiagnostics(file));
280
+ disposeChecker(checker);
281
+ for (const d of this.getIncludeProcessorDiagnostics(file))
282
+ result.push(d);
283
+ return result;
284
+ }
253
285
  /**
254
286
  * The bind and check diagnostics of `file` before `noEmit` filtering and without include errors.
255
287
  * Once checker threads checked the program, they come from the threads' diagnostics of the file,
@@ -331,10 +363,11 @@ export class CheckedProgram {
331
363
  }
332
364
  return sortAndDeduplicateDiagnostics(result);
333
365
  }
334
- getBindAndCheckDiagnostics(file) {
366
+ /** `checks` are the checker's diagnostics of `file`. */
367
+ getBindAndCheckDiagnostics(file, checks) {
335
368
  const options = this.program.options;
336
369
  const diagnostics = file.bindDiagnostics.slice();
337
- for (const d of this.checker.getDiagnostics(file))
370
+ for (const d of checks ?? this.checker.getDiagnostics(file))
338
371
  diagnostics.push(d);
339
372
  if (isPlainJSFile(file, options)) {
340
373
  const result = [];
@@ -11,3 +11,13 @@ export declare function diagnosticOf(d: CompilerDiagnostic): Diagnostic;
11
11
  * them. Declaration diagnostics are empty, as tsgo's API returns them.
12
12
  */
13
13
  export declare function programDiagnostics(checked: CheckedProgram, kind: DiagnosticKind, file: SourceFile | undefined): readonly CompilerDiagnostic[];
14
+ /**
15
+ * What `semantic` answers for each of `files` and what `global` answers, after checking `files` and
16
+ * no other file. Checking one file can add diagnostics located in another, so every file is checked
17
+ * before any file's diagnostics are collected. With every file of the program listed, the answers are
18
+ * those of the full check.
19
+ */
20
+ export declare function checkedFileDiagnostics(checked: CheckedProgram, files: readonly SourceFile[]): {
21
+ files: (readonly CompilerDiagnostic[])[];
22
+ global: readonly CompilerDiagnostic[];
23
+ };
@@ -48,3 +48,23 @@ export function programDiagnostics(checked, kind, file) {
48
48
  return [];
49
49
  }
50
50
  }
51
+ /**
52
+ * What `semantic` answers for each of `files` and what `global` answers, after checking `files` and
53
+ * no other file. Checking one file can add diagnostics located in another, so every file is checked
54
+ * before any file's diagnostics are collected. With every file of the program listed, the answers are
55
+ * those of the full check.
56
+ */
57
+ export function checkedFileDiagnostics(checked, files) {
58
+ for (const file of files)
59
+ checked.getSemanticDiagnostics(file);
60
+ const program = checked.program;
61
+ const global = [
62
+ ...program.getConfigFileParsingDiagnostics(),
63
+ ...program.getProgramDiagnostics(),
64
+ ...checked.getGlobalDiagnostics(),
65
+ ];
66
+ return {
67
+ files: files.map((file) => checked.getSemanticDiagnostics(file)),
68
+ global: sortAndDeduplicateDiagnostics(global).filter((d) => d.file === undefined),
69
+ };
70
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsc-ts",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "The TypeScript 7 compiler, ported to TypeScript and compiled to a native executable.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -35,12 +35,12 @@
35
35
  "node": ">=20"
36
36
  },
37
37
  "optionalDependencies": {
38
- "@tsc-ts/darwin-arm64": "0.0.8",
39
- "@tsc-ts/darwin-x64": "0.0.8",
40
- "@tsc-ts/linux-arm64-gnu": "0.0.8",
41
- "@tsc-ts/linux-arm64-musl": "0.0.8",
42
- "@tsc-ts/linux-x64-gnu": "0.0.8",
43
- "@tsc-ts/linux-x64-musl": "0.0.8",
44
- "@tsc-ts/win32-x64-msvc": "0.0.8"
38
+ "@tsc-ts/darwin-arm64": "0.0.9",
39
+ "@tsc-ts/darwin-x64": "0.0.9",
40
+ "@tsc-ts/linux-arm64-gnu": "0.0.9",
41
+ "@tsc-ts/linux-arm64-musl": "0.0.9",
42
+ "@tsc-ts/linux-x64-gnu": "0.0.9",
43
+ "@tsc-ts/linux-x64-musl": "0.0.9",
44
+ "@tsc-ts/win32-x64-msvc": "0.0.9"
45
45
  }
46
46
  }
@@ -923,8 +923,12 @@ export function resolveDeclaredMembers(c: Checker, t: InterfaceType): InterfaceT
923
923
  const members = getMembersOfSymbol(c, t.symbol!);
924
924
  declared.declaredMembersResolved = true;
925
925
  declared.declaredMembers = members;
926
- declared.declaredCallSignatures = getSignaturesOfSymbol(c, members.get(InternalSymbolName.Call));
927
- declared.declaredConstructSignatures = getSignaturesOfSymbol(c, members.get(InternalSymbolName.New));
926
+ // Most interfaces declare neither, and share one empty list.
927
+ const call = members.get(InternalSymbolName.Call);
928
+ const construct = members.get(InternalSymbolName.New);
929
+ declared.declaredCallSignatures = call !== undefined ? getSignaturesOfSymbol(c, call) : emptySignatures;
930
+ declared.declaredConstructSignatures =
931
+ construct !== undefined ? getSignaturesOfSymbol(c, construct) : emptySignatures;
928
932
  declared.declaredIndexInfos = getIndexInfosOfSymbol(c, t.symbol!);
929
933
  }
930
934
  return declared;