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
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ npx tsc-ts -p tsconfig.json
|
|
|
31
31
|
npx tsc-ts --noEmit src/index.ts
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
`tsc-ts --api` serves the TypeScript API over stdin and stdout, like `tsc --api`. On Windows, `--api --pipe \\.\pipe\<name>` serves it over a named pipe it creates, as `tsc --api --pipe` does, for clients that connect to the pipe (such as scriptc under Node.js); only the native executable supports `--pipe`.
|
|
34
|
+
`tsc-ts --api` serves the TypeScript API over stdin and stdout, like `tsc --api`. On Windows, `--api --pipe \\.\pipe\<name>` serves it over a named pipe it creates, as `tsc --api --pipe` does, for clients that connect to the pipe (such as scriptc under Node.js); only the native executable supports `--pipe`. On macOS and Linux, `--api --listen <path>` serves it on a Unix socket it creates, with mode 0600, to one client of the same user at a time, each until the client closes its end. Each client gets the answers a new `tsc-ts --api` process would give, except that symbol ids continue from earlier clients, and the server reads every file through the client again, but it keeps parsed files between clients and reuses those whose text is unchanged, along with the encoding `getSourceFile` sends for each, so a client that opens the same project again loads it faster. The server exits when no client connects for 60 seconds (`--idle-exit <seconds>` sets the time), or after a client when its resident memory is above 2.5 times what it held after its first client (`TSC_TS_LISTEN_MEMORY` sets the limit in megabytes). To stop, it removes the socket file, serves the clients that had connected, and exits. It replaces a socket file that no server answers on, such as one left by a server that was killed. Only the native executable supports `--listen`. With `--default-libraries-from-disk`, the server reads the files in its default library directory (`TSC_TS_LIB_DIR`, or the executable's directory) from the disk itself, even when the client handles file system calls (`--callbacks`), which saves a round trip to the client for each library file.
|
|
35
35
|
|
|
36
36
|
`--checkers N` checks the program on N threads. Unless `--checkers` or `--singleThreaded` is given, the native executable uses one checker per CPU it may run on (up to 16), and at least tsgo's four; it uses fewer than the CPUs, but never fewer than four, when the estimated peak memory of more checkers would not fit 85% of the machine's memory (`TSC_TS_CHECKERS=fixed` keeps tsgo's four), and checkers beyond the fourth stop taking files, one at a time, when the process's memory reaches that share; it shares one program between its threads and also parses and binds the program's files on them. Unless `--singleThreaded` is given, the program's files are parsed and bound on threads also with `--checkers 1`, as tsgo does. Files that share costly declarations, such as a large generated schema and the few files importing it, are checked together on one checker. Under Node.js, where every thread builds its own copy of the program, tsc-ts checks on one thread unless `--checkers` is given. `--incremental`, `--watch` and `--build` always check on one thread. The diagnostics are the same as with one checker.
|
|
37
37
|
|
|
@@ -2281,6 +2281,8 @@ export declare class SourceFile extends Node {
|
|
|
2281
2281
|
identifierCount: number;
|
|
2282
2282
|
nodeCount: number;
|
|
2283
2283
|
textCount: number;
|
|
2284
|
+
/** The API's binary encoding of this file, when an API server keeps it (`keptEncodingOf`). */
|
|
2285
|
+
apiEncoding: Uint8Array | undefined;
|
|
2284
2286
|
/** Module specifiers of imports, exports, `require` calls and `import()` types, in source order. */
|
|
2285
2287
|
imports: Node[];
|
|
2286
2288
|
/** Names of `declare module "x"` augmentations and `declare global` blocks in modules. */
|
package/dist/api/compiler/ast.js
CHANGED
|
@@ -6641,6 +6641,8 @@ export class SourceFile extends Node {
|
|
|
6641
6641
|
identifierCount;
|
|
6642
6642
|
nodeCount;
|
|
6643
6643
|
textCount;
|
|
6644
|
+
/** The API's binary encoding of this file, when an API server keeps it (`keptEncodingOf`). */
|
|
6645
|
+
apiEncoding;
|
|
6644
6646
|
/** Module specifiers of imports, exports, `require` calls and `import()` types, in source order. */
|
|
6645
6647
|
imports;
|
|
6646
6648
|
/** Names of `declare module "x"` augmentations and `declare global` blocks in modules. */
|
|
@@ -6699,6 +6701,7 @@ export class SourceFile extends Node {
|
|
|
6699
6701
|
this.identifierCount = 0;
|
|
6700
6702
|
this.nodeCount = 0;
|
|
6701
6703
|
this.textCount = 0;
|
|
6704
|
+
this.apiEncoding = undefined;
|
|
6702
6705
|
this.imports = [];
|
|
6703
6706
|
this.moduleAugmentations = emptyNodes;
|
|
6704
6707
|
this.ambientModuleNames = emptyStrings;
|
|
@@ -709,7 +709,11 @@ export function reorderCandidates(c, signatures, callChainFlags) {
|
|
|
709
709
|
spliceIndex = index;
|
|
710
710
|
if (callChainFlags !== 0)
|
|
711
711
|
signature = getOptionalCallSignature(c, signature, callChainFlags);
|
|
712
|
-
|
|
712
|
+
// Most signatures go at the end, where a push is cheaper than an inserting splice.
|
|
713
|
+
if (spliceIndex === result.length)
|
|
714
|
+
result.push(signature);
|
|
715
|
+
else
|
|
716
|
+
result.splice(spliceIndex, 0, signature);
|
|
713
717
|
}
|
|
714
718
|
return result;
|
|
715
719
|
}
|
|
@@ -2255,7 +2255,8 @@ function getEmitSyntaxOfImportOrExport(g) {
|
|
|
2255
2255
|
return ModuleKind.None;
|
|
2256
2256
|
}
|
|
2257
2257
|
function checkGrammarObjectLiteralExpression(g, node, inDestructuring) {
|
|
2258
|
-
|
|
2258
|
+
// An object literal with one property can't repeat a name, so it needs no table of names.
|
|
2259
|
+
const seen = node.properties.nodes.length > 1 ? new Map() : undefined;
|
|
2259
2260
|
for (const property of node.properties.nodes) {
|
|
2260
2261
|
if (property.kind === 305 /* SyntaxKind.SpreadAssignment */) {
|
|
2261
2262
|
if (inDestructuring) {
|
|
@@ -2313,7 +2314,7 @@ function checkGrammarObjectLiteralExpression(g, node, inDestructuring) {
|
|
|
2313
2314
|
if (inDestructuring)
|
|
2314
2315
|
continue;
|
|
2315
2316
|
const effectiveName = getEffectivePropertyNameForPropertyNameNode(g.c, name);
|
|
2316
|
-
if (effectiveName === undefined)
|
|
2317
|
+
if (effectiveName === undefined || seen === undefined)
|
|
2317
2318
|
continue;
|
|
2318
2319
|
const existingKind = seen.get(effectiveName);
|
|
2319
2320
|
if (existingKind === undefined) {
|
|
@@ -450,8 +450,14 @@ class InferenceState {
|
|
|
450
450
|
index = 0;
|
|
451
451
|
while (index < inference.candidateDepths.length && inference.candidateDepths[index] >= this.depth)
|
|
452
452
|
index++;
|
|
453
|
-
inference.candidates.
|
|
454
|
-
|
|
453
|
+
if (index === inference.candidates.length) {
|
|
454
|
+
inference.candidates.push(candidate);
|
|
455
|
+
inference.candidateDepths.push(this.depth);
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
inference.candidates.splice(index, 0, candidate);
|
|
459
|
+
inference.candidateDepths.splice(index, 0, this.depth);
|
|
460
|
+
}
|
|
455
461
|
clearCachedInferences(this.inferences);
|
|
456
462
|
}
|
|
457
463
|
}
|
|
@@ -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
|
-
|
|
706
|
-
|
|
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;
|
|
@@ -1264,7 +1268,8 @@ export function getPropertyOfTypeEx(c, t, name, skipObjectFunctionPropertyAugmen
|
|
|
1264
1268
|
if (!isOwnReducedApparentType(t))
|
|
1265
1269
|
t = getReducedApparentTypeWorker(c, t);
|
|
1266
1270
|
if ((t.flags & 1048576 /* TypeFlags.Object */) !== 0) {
|
|
1267
|
-
|
|
1271
|
+
// The first test of resolveStructuredTypeMembers, here where most lookups find the members resolved.
|
|
1272
|
+
const resolved = (t.objectFlags & 2097152 /* ObjectFlags.MembersResolved */) !== 0 ? t : resolveStructuredTypeMembers(c, t);
|
|
1268
1273
|
const symbol = getResolvedMember(resolved, name);
|
|
1269
1274
|
if (symbol !== undefined && includeTypeOnlyMembers)
|
|
1270
1275
|
return symbol;
|
|
@@ -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;
|
|
@@ -989,7 +989,10 @@ export function insertType(c, types, t) {
|
|
|
989
989
|
const index = binarySearchTypes(c, types, t);
|
|
990
990
|
if (index >= 0)
|
|
991
991
|
return false;
|
|
992
|
-
|
|
992
|
+
if (~index === types.length)
|
|
993
|
+
types.push(t);
|
|
994
|
+
else
|
|
995
|
+
types.splice(~index, 0, t);
|
|
993
996
|
return true;
|
|
994
997
|
}
|
|
995
998
|
// ---- Iterating unions
|
|
@@ -1198,7 +1201,10 @@ function insertTypeNearLast(c, set, t) {
|
|
|
1198
1201
|
else
|
|
1199
1202
|
high = middle - 1;
|
|
1200
1203
|
}
|
|
1201
|
-
|
|
1204
|
+
if (low === types.length)
|
|
1205
|
+
types.push(t);
|
|
1206
|
+
else
|
|
1207
|
+
types.splice(low, 0, t);
|
|
1202
1208
|
set.last = low;
|
|
1203
1209
|
}
|
|
1204
1210
|
function getUnionTypeWorker(c, types, unionReduction, alias, origin) {
|
|
@@ -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';
|
|
@@ -71,6 +71,10 @@ declare class DiagnosticCollection {
|
|
|
71
71
|
/** An already reported diagnostic equal to `diagnostic`, if any. */
|
|
72
72
|
lookup(diagnostic: Diagnostic): Diagnostic | undefined;
|
|
73
73
|
globals(): Diagnostic[];
|
|
74
|
+
/** The global diagnostics `withoutNewGlobals` removed. */
|
|
75
|
+
removedGlobals: number;
|
|
76
|
+
/** Runs `run`, then removes the global diagnostics it added. */
|
|
77
|
+
withoutNewGlobals<T>(run: () => T): T;
|
|
74
78
|
/** Records the diagnostics added from now on. */
|
|
75
79
|
startLog(): void;
|
|
76
80
|
/** The diagnostics added since `startLog`, in order; stops recording. */
|
|
@@ -204,6 +208,11 @@ export declare class Checker implements TypeChecking {
|
|
|
204
208
|
readonly resolvedSignatures: SparseLinkTable<Signature>;
|
|
205
209
|
/** Merged symbols, indexed by the id of the symbol merged into them. */
|
|
206
210
|
readonly mergedSymbols: Map<number, Symbol>;
|
|
211
|
+
/**
|
|
212
|
+
* The ids that `mergedSymbols` has, or had: most symbols are merged into none, and `getMergedSymbol`
|
|
213
|
+
* finds that here without probing the map.
|
|
214
|
+
*/
|
|
215
|
+
readonly mergedSymbolIds: PagedIdSet;
|
|
207
216
|
/** Globals merged from the default libraries, shared with other checkers. */
|
|
208
217
|
libGlobals: LibGlobals | undefined;
|
|
209
218
|
/** The program's globals and module augmentations as another checker merged them, shared with it. */
|
|
@@ -486,6 +495,13 @@ export declare class Checker implements TypeChecking {
|
|
|
486
495
|
getSuggestionDiagnostics(file: SourceFile): Diagnostic[];
|
|
487
496
|
/** Diagnostics without a file, such as missing global types. */
|
|
488
497
|
getGlobalDiagnostics(): Diagnostic[];
|
|
498
|
+
/**
|
|
499
|
+
* Runs `run` (such as emitting declarations), then forgets the global diagnostics it reported:
|
|
500
|
+
* the program collects global diagnostics before it emits.
|
|
501
|
+
*/
|
|
502
|
+
withoutGlobalDiagnostics<T>(run: () => T): T;
|
|
503
|
+
/** The global diagnostics `withoutGlobalDiagnostics` forgot so far. */
|
|
504
|
+
forgottenGlobalDiagnostics(): number;
|
|
489
505
|
/** The rarely used links of `symbol`, created on first use. */
|
|
490
506
|
symbolLinks(symbol: Symbol): SymbolLinks;
|
|
491
507
|
/** The links of `symbol` if it has any, without creating them. */
|
|
@@ -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';
|
|
@@ -137,6 +137,35 @@ class DiagnosticCollection {
|
|
|
137
137
|
}
|
|
138
138
|
return this.global.slice();
|
|
139
139
|
}
|
|
140
|
+
/** The global diagnostics `withoutNewGlobals` removed. */
|
|
141
|
+
removedGlobals = 0;
|
|
142
|
+
/** Runs `run`, then removes the global diagnostics it added. */
|
|
143
|
+
withoutNewGlobals(run) {
|
|
144
|
+
const outer = this.log;
|
|
145
|
+
const added = [];
|
|
146
|
+
this.log = added;
|
|
147
|
+
try {
|
|
148
|
+
return run();
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
this.log = outer;
|
|
152
|
+
if (outer !== undefined)
|
|
153
|
+
for (const d of added)
|
|
154
|
+
outer.push(d);
|
|
155
|
+
const globals = new Set();
|
|
156
|
+
for (const d of added)
|
|
157
|
+
if (d.file === undefined)
|
|
158
|
+
globals.add(d);
|
|
159
|
+
if (globals.size > 0) {
|
|
160
|
+
this.removedGlobals += globals.size;
|
|
161
|
+
let kept = 0;
|
|
162
|
+
for (const d of this.global)
|
|
163
|
+
if (!globals.has(d))
|
|
164
|
+
this.global[kept++] = d;
|
|
165
|
+
this.global.length = kept;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
140
169
|
/** Records the diagnostics added from now on. */
|
|
141
170
|
startLog() {
|
|
142
171
|
this.log = [];
|
|
@@ -284,6 +313,11 @@ export class Checker {
|
|
|
284
313
|
resolvedSignatures = new SparseLinkTable();
|
|
285
314
|
/** Merged symbols, indexed by the id of the symbol merged into them. */
|
|
286
315
|
mergedSymbols;
|
|
316
|
+
/**
|
|
317
|
+
* The ids that `mergedSymbols` has, or had: most symbols are merged into none, and `getMergedSymbol`
|
|
318
|
+
* finds that here without probing the map.
|
|
319
|
+
*/
|
|
320
|
+
mergedSymbolIds = new PagedIdSet();
|
|
287
321
|
/** Globals merged from the default libraries, shared with other checkers. */
|
|
288
322
|
libGlobals;
|
|
289
323
|
/** The program's globals and module augmentations as another checker merged them, shared with it. */
|
|
@@ -616,6 +650,8 @@ export class Checker {
|
|
|
616
650
|
this.globals = libs.copyGlobals();
|
|
617
651
|
this.mergedSymbols = libs.copyMergedSymbols();
|
|
618
652
|
}
|
|
653
|
+
for (const id of this.mergedSymbols.keys())
|
|
654
|
+
this.mergedSymbolIds.add(id);
|
|
619
655
|
this.globalThisSymbol = this.newSymbol(1536 /* SymbolFlags.Module */, 'globalThis');
|
|
620
656
|
this.globalThisSymbol.checkFlags = 8 /* CheckFlags.Readonly */;
|
|
621
657
|
this.globalThisSymbol.exports = this.globals;
|
|
@@ -773,6 +809,17 @@ export class Checker {
|
|
|
773
809
|
getGlobalDiagnostics() {
|
|
774
810
|
return this.diagnostics.globals();
|
|
775
811
|
}
|
|
812
|
+
/**
|
|
813
|
+
* Runs `run` (such as emitting declarations), then forgets the global diagnostics it reported:
|
|
814
|
+
* the program collects global diagnostics before it emits.
|
|
815
|
+
*/
|
|
816
|
+
withoutGlobalDiagnostics(run) {
|
|
817
|
+
return this.diagnostics.withoutNewGlobals(run);
|
|
818
|
+
}
|
|
819
|
+
/** The global diagnostics `withoutGlobalDiagnostics` forgot so far. */
|
|
820
|
+
forgottenGlobalDiagnostics() {
|
|
821
|
+
return this.diagnostics.removedGlobals;
|
|
822
|
+
}
|
|
776
823
|
// ---- Links
|
|
777
824
|
/** The rarely used links of `symbol`, created on first use. */
|
|
778
825
|
symbolLinks(symbol) {
|
|
@@ -890,6 +937,7 @@ export function disposeChecker(c) {
|
|
|
890
937
|
c.mergedSymbols.clear();
|
|
891
938
|
c.globals.clear();
|
|
892
939
|
}
|
|
940
|
+
c.mergedSymbolIds.clear();
|
|
893
941
|
c.sharedSymbolCopies.clear();
|
|
894
942
|
c.memberPositionsInLists.clear();
|
|
895
943
|
c.memberNamesOfLists.clear();
|
|
@@ -61,6 +61,28 @@ export declare class EmitIndexes {
|
|
|
61
61
|
readonly declarations: DeclarationGlobals | undefined;
|
|
62
62
|
constructor(program: Program);
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* The JavaScript emit of a program's files without a checker, for emit threads (parallel-emit.ts).
|
|
66
|
+
* JavaScript emit asks the checker only how decorator metadata serializes a type
|
|
67
|
+
* (`CheckerEmitResolver`): with `kinds`, the answers the main thread's checker gave
|
|
68
|
+
* (`recordMetadataKinds`), else files with decorator metadata are emitted by a `ProgramEmitter`.
|
|
69
|
+
*/
|
|
70
|
+
export declare class JavaScriptEmitter {
|
|
71
|
+
private readonly host;
|
|
72
|
+
private readonly recorded;
|
|
73
|
+
constructor(program: Program, kinds?: readonly number[]);
|
|
74
|
+
/**
|
|
75
|
+
* Emits `file`, or returns undefined if its decorator metadata asked for a kind that wasn't recorded: what
|
|
76
|
+
* was written is then not the file's emit, and it must be emitted with the checker.
|
|
77
|
+
*/
|
|
78
|
+
emit(file: SourceFile, writer: OutputWriter): EmitResult | undefined;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The serialization kinds of decorator metadata that the checker of `checked` gives the type references of
|
|
82
|
+
* `files`, in the order JavaScript emit asks for them: the type name's node id, the location's node id (-1 for
|
|
83
|
+
* none) and the kind, for each. Only the decorator metadata transform runs, as the first transform of emit.
|
|
84
|
+
*/
|
|
85
|
+
export declare function recordMetadataKinds(checked: CheckedProgram, files: readonly SourceFile[]): number[];
|
|
64
86
|
/** A checked program and the emit of its files. */
|
|
65
87
|
export declare class ProgramEmitter {
|
|
66
88
|
readonly checked: CheckedProgram;
|
|
@@ -110,9 +132,11 @@ export declare class PlainProgram extends CompilerProgram {
|
|
|
110
132
|
export declare function handleNoEmitOnError(program: CompilerProgram): EmitResult | undefined;
|
|
111
133
|
/**
|
|
112
134
|
* Config and syntax errors; without syntax errors, program, global and semantic errors too, and
|
|
113
|
-
* declaration errors under `noEmit` (or `withDeclarationDiagnostics`).
|
|
135
|
+
* declaration errors under `noEmit` (or `withDeclarationDiagnostics`). With `declarationsLater`, the
|
|
136
|
+
* declaration errors are left to `program.emit`, which reports them under `noEmit` (without
|
|
137
|
+
* `noEmitOnError`) whether or not other errors were found.
|
|
114
138
|
*/
|
|
115
|
-
export declare function getDiagnosticsOfProgram(program: CompilerProgram, withDeclarationDiagnostics: boolean): Diagnostic[];
|
|
139
|
+
export declare function getDiagnosticsOfProgram(program: CompilerProgram, withDeclarationDiagnostics: boolean, declarationsLater?: boolean): Diagnostic[];
|
|
116
140
|
/** Combines emit results in order. */
|
|
117
141
|
export declare function combineEmitResults(results: readonly EmitResult[]): EmitResult;
|
|
118
142
|
export { CheckedProgram };
|
|
@@ -6,6 +6,10 @@ import { CheckerDeclarationEmitResolver, CheckerEmitResolver } from './checker-e
|
|
|
6
6
|
import { getEmitModuleFormatOfFile } from './program-utilities.js';
|
|
7
7
|
import { DeclarationGlobals, SyntacticDeclarationEmitResolver } from './transformers/declarations-syntactic.js';
|
|
8
8
|
import { mark } from './timeline.js';
|
|
9
|
+
import { DecoratorMetadata } from './transformers/decorator-metadata.js';
|
|
10
|
+
import { SyntaxFacts } from './transformers/syntax-facts.js';
|
|
11
|
+
import { EmitContext } from './printer/emit-context.js';
|
|
12
|
+
import { SyntacticEmitResolver } from './transformers/emit-resolver.js';
|
|
9
13
|
import { ModuleFormatHost } from './transformers/module.js';
|
|
10
14
|
import { ModuleLookup, ReferenceResolver } from './transformers/reference-resolver.js';
|
|
11
15
|
/** Where emit writes files. */
|
|
@@ -165,6 +169,82 @@ export class EmitIndexes {
|
|
|
165
169
|
: undefined;
|
|
166
170
|
}
|
|
167
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* The JavaScript emit of a program's files without a checker, for emit threads (parallel-emit.ts).
|
|
174
|
+
* JavaScript emit asks the checker only how decorator metadata serializes a type
|
|
175
|
+
* (`CheckerEmitResolver`): with `kinds`, the answers the main thread's checker gave
|
|
176
|
+
* (`recordMetadataKinds`), else files with decorator metadata are emitted by a `ProgramEmitter`.
|
|
177
|
+
*/
|
|
178
|
+
export class JavaScriptEmitter {
|
|
179
|
+
host;
|
|
180
|
+
recorded;
|
|
181
|
+
constructor(program, kinds = []) {
|
|
182
|
+
const options = program.options;
|
|
183
|
+
const indexes = program.emitIndexes;
|
|
184
|
+
const references = new ReferenceResolver(options, program.getSourceFiles(), new ProgramModules(program), indexes !== undefined ? indexes.globals : undefined);
|
|
185
|
+
this.recorded = kinds.length > 0 ? new RecordedKindsEmitResolver(options, references, kinds) : undefined;
|
|
186
|
+
this.host = new ProgramEmitHost(program, this.recorded ?? new SyntacticEmitResolver(options, references));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Emits `file`, or returns undefined if its decorator metadata asked for a kind that wasn't recorded: what
|
|
190
|
+
* was written is then not the file's emit, and it must be emitted with the checker.
|
|
191
|
+
*/
|
|
192
|
+
emit(file, writer) {
|
|
193
|
+
const host = this.host;
|
|
194
|
+
const recorded = this.recorded;
|
|
195
|
+
if (recorded !== undefined)
|
|
196
|
+
recorded.missed = false;
|
|
197
|
+
host.writer = writer;
|
|
198
|
+
const result = emitFiles(host, [file], 1 /* EmitOnly.Js */);
|
|
199
|
+
host.writer = undefined;
|
|
200
|
+
return recorded !== undefined && recorded.missed ? undefined : result;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* The serialization kinds of decorator metadata that the checker of `checked` gives the type references of
|
|
205
|
+
* `files`, in the order JavaScript emit asks for them: the type name's node id, the location's node id (-1 for
|
|
206
|
+
* none) and the kind, for each. Only the decorator metadata transform runs, as the first transform of emit.
|
|
207
|
+
*/
|
|
208
|
+
export function recordMetadataKinds(checked, files) {
|
|
209
|
+
const program = checked.program;
|
|
210
|
+
const options = program.options;
|
|
211
|
+
const indexes = program.emitIndexes;
|
|
212
|
+
const references = new ReferenceResolver(options, program.getSourceFiles(), new ProgramModules(program), indexes !== undefined ? indexes.globals : undefined);
|
|
213
|
+
const resolver = new RecordingEmitResolver(options, references, checked.checker);
|
|
214
|
+
for (const file of files)
|
|
215
|
+
new DecoratorMetadata(new EmitContext(), options, resolver, new SyntaxFacts()).transformSourceFile(file);
|
|
216
|
+
return resolver.kinds;
|
|
217
|
+
}
|
|
218
|
+
/** A `CheckerEmitResolver` that records the serialization kinds it gives (`recordMetadataKinds`). */
|
|
219
|
+
class RecordingEmitResolver extends CheckerEmitResolver {
|
|
220
|
+
kinds = [];
|
|
221
|
+
getTypeReferenceSerializationKind(typeName, location) {
|
|
222
|
+
const kind = super.getTypeReferenceSerializationKind(typeName, location);
|
|
223
|
+
this.kinds.push(typeName.id, location === undefined ? -1 : location.id, kind);
|
|
224
|
+
return kind;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/** Answers serialization kinds from those recorded on the main thread; `missed` once one wasn't. */
|
|
228
|
+
class RecordedKindsEmitResolver extends SyntacticEmitResolver {
|
|
229
|
+
kinds;
|
|
230
|
+
/** The kind and location of each type name, by the type name's node id. */
|
|
231
|
+
byName = new Map();
|
|
232
|
+
missed = false;
|
|
233
|
+
constructor(options, referenceResolver, kinds) {
|
|
234
|
+
super(options, referenceResolver);
|
|
235
|
+
this.kinds = kinds;
|
|
236
|
+
for (let i = 0; i < kinds.length; i += 3)
|
|
237
|
+
if (!this.byName.has(kinds[i]))
|
|
238
|
+
this.byName.set(kinds[i], i);
|
|
239
|
+
}
|
|
240
|
+
getTypeReferenceSerializationKind(typeName, location) {
|
|
241
|
+
const at = this.byName.get(typeName.id);
|
|
242
|
+
if (at !== undefined && this.kinds[at + 1] === (location === undefined ? -1 : location.id))
|
|
243
|
+
return this.kinds[at + 2];
|
|
244
|
+
this.missed = true;
|
|
245
|
+
return super.getTypeReferenceSerializationKind(typeName, location);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
168
248
|
/** A checked program and the emit of its files. */
|
|
169
249
|
export class ProgramEmitter {
|
|
170
250
|
checked;
|
|
@@ -291,14 +371,24 @@ export class PlainProgram extends CompilerProgram {
|
|
|
291
371
|
const program = this.program;
|
|
292
372
|
const files = program.getSourceFiles();
|
|
293
373
|
const parallel = this.checked.emittedInParallel;
|
|
294
|
-
// Checker threads emitted the files they checked (parallel-check.ts)
|
|
374
|
+
// Checker threads emitted the files they checked (parallel-check.ts), or emit threads their JavaScript
|
|
375
|
+
// (parallel-emit.ts); the rest is emitted here, in order.
|
|
295
376
|
const result = parallel === undefined
|
|
296
377
|
? this.emitter.emit(files, 0 /* EmitOnly.All */, writer)
|
|
297
378
|
: combineEmitResults(files.map((file, i) => {
|
|
298
379
|
const emitted = parallel[i];
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
380
|
+
// The declaration thread emitted the declarations of the files it could (parallel-emit.ts).
|
|
381
|
+
const ahead = this.checked.declarationsEmittedAhead;
|
|
382
|
+
const declarations = () => ahead?.[i] ?? this.emitter.emit([file], 2 /* EmitOnly.Dts */, writer);
|
|
383
|
+
if (emitted === undefined)
|
|
384
|
+
return ahead !== undefined
|
|
385
|
+
? combineEmitResults([this.emitter.emit([file], 1 /* EmitOnly.Js */, writer), declarations()])
|
|
386
|
+
: this.emitter.emit([file], 0 /* EmitOnly.All */, writer);
|
|
387
|
+
const written = writeHeldOutputs(emitted, writer);
|
|
388
|
+
// Emit threads emit JavaScript only.
|
|
389
|
+
if (!this.checked.javaScriptEmittedOnThreads || !getEmitDeclarations(options))
|
|
390
|
+
return written;
|
|
391
|
+
return combineEmitResults([written, declarations()]);
|
|
302
392
|
}));
|
|
303
393
|
if (options.noEmit === true) {
|
|
304
394
|
// Emit is skipped only for files that would have been emitted.
|
|
@@ -326,9 +416,11 @@ export function handleNoEmitOnError(program) {
|
|
|
326
416
|
}
|
|
327
417
|
/**
|
|
328
418
|
* Config and syntax errors; without syntax errors, program, global and semantic errors too, and
|
|
329
|
-
* declaration errors under `noEmit` (or `withDeclarationDiagnostics`).
|
|
419
|
+
* declaration errors under `noEmit` (or `withDeclarationDiagnostics`). With `declarationsLater`, the
|
|
420
|
+
* declaration errors are left to `program.emit`, which reports them under `noEmit` (without
|
|
421
|
+
* `noEmitOnError`) whether or not other errors were found.
|
|
330
422
|
*/
|
|
331
|
-
export function getDiagnosticsOfProgram(program, withDeclarationDiagnostics) {
|
|
423
|
+
export function getDiagnosticsOfProgram(program, withDeclarationDiagnostics, declarationsLater = false) {
|
|
332
424
|
const result = [...program.getConfigFileParsingDiagnostics()];
|
|
333
425
|
const configCount = result.length;
|
|
334
426
|
for (const d of program.getSyntacticDiagnostics())
|
|
@@ -356,7 +448,8 @@ export function getDiagnosticsOfProgram(program, withDeclarationDiagnostics) {
|
|
|
356
448
|
result.push(d);
|
|
357
449
|
mark('semantic diagnostics');
|
|
358
450
|
}
|
|
359
|
-
if (
|
|
451
|
+
if (!declarationsLater &&
|
|
452
|
+
(withDeclarationDiagnostics || options.noEmit === true) &&
|
|
360
453
|
getEmitDeclarations(options) &&
|
|
361
454
|
result.length === configCount) {
|
|
362
455
|
for (const d of program.getDeclarationDiagnostics())
|
|
@@ -109,6 +109,11 @@ export declare class Diagnostic {
|
|
|
109
109
|
readonly reportsDeprecated: boolean;
|
|
110
110
|
skippedOnNoEmit: boolean;
|
|
111
111
|
repopulateInfo: RepopulateInfo | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* What `formatDiagnostic` gives for this diagnostic in `formattedReports.format`, where the checker
|
|
114
|
+
* thread that found it formatted it (`packResult`); `''` otherwise.
|
|
115
|
+
*/
|
|
116
|
+
formatted: string;
|
|
112
117
|
constructor(file: DiagnosticFile | undefined, pos: number, end: number, message: DiagnosticMessage, args?: readonly string[]);
|
|
113
118
|
localize(locale: Locale): string;
|
|
114
119
|
addMessageChain(chain: Diagnostic | undefined): Diagnostic;
|
|
@@ -132,6 +137,14 @@ export declare function chainDiagnostic(chain: Diagnostic | undefined, message:
|
|
|
132
137
|
export declare function compareCodePoints(a: string, b: string): number;
|
|
133
138
|
/** The order tsc reports diagnostics in: by file, position, code, arguments, then elaboration. */
|
|
134
139
|
export declare function compareDiagnostics(a: Diagnostic, b: Diagnostic): number;
|
|
140
|
+
/**
|
|
141
|
+
* `diagnostics` in the order of `compareDiagnostics`, equal ones in their order in `diagnostics`. File
|
|
142
|
+
* names are compared once per pair of files rather than once per pair of diagnostics: the distinct
|
|
143
|
+
* files are sorted by name, and each diagnostic sorts by its file's place in that order, then by the
|
|
144
|
+
* rest of `compareDiagnostics`. A program's diagnostics come a file at a time, so the files are found
|
|
145
|
+
* from the runs of one file.
|
|
146
|
+
*/
|
|
147
|
+
export declare function sortDiagnostics(diagnostics: readonly Diagnostic[]): Diagnostic[];
|
|
135
148
|
/** Whether two diagnostics report the same thing, ignoring related information. */
|
|
136
149
|
export declare function equalDiagnosticsNoRelatedInfo(a: Diagnostic, b: Diagnostic): boolean;
|
|
137
150
|
export declare function equalDiagnostics(a: Diagnostic, b: Diagnostic): boolean;
|
|
@@ -145,6 +158,15 @@ export interface DiagnosticFormatOptions {
|
|
|
145
158
|
export declare function flattenDiagnosticMessage(diagnostic: Diagnostic, newLine: string, locale: Locale): string;
|
|
146
159
|
/** `file(line,col): error TS1005: message`, as tsc prints without `--pretty`. */
|
|
147
160
|
export declare function formatDiagnostic(diagnostic: Diagnostic, options: DiagnosticFormatOptions): string;
|
|
161
|
+
/**
|
|
162
|
+
* The plain format the main thread reports a compilation's diagnostics in (`DiagnosticReporter.plainFormat`),
|
|
163
|
+
* which its checker threads receive a copy of and format the diagnostics they send back in
|
|
164
|
+
* (`Diagnostic.formatted`). Unset where diagnostics are reported with color and context, or not at all.
|
|
165
|
+
*/
|
|
166
|
+
export declare class FormattedReports {
|
|
167
|
+
format: DiagnosticFormatOptions | undefined;
|
|
168
|
+
}
|
|
169
|
+
export declare const formattedReports: FormattedReports;
|
|
148
170
|
/** `formatDiagnostic` of each diagnostic. */
|
|
149
171
|
export declare function formatDiagnostics(diagnostics: readonly Diagnostic[], options: DiagnosticFormatOptions): string;
|
|
150
172
|
/** The colored form with source snippets, as tsc prints with `--pretty`. */
|