tsc-ts 0.1.0 → 0.1.1
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 +9 -3
- package/dist/api/compiler/ast.js +17 -12
- package/dist/api/compiler/checker-classes.js +2 -1
- package/dist/api/compiler/checker-contextual.d.ts +20 -0
- package/dist/api/compiler/checker-contextual.js +111 -1
- package/dist/api/compiler/checker-expressions.js +14 -1
- package/dist/api/compiler/checker-jsx.js +2 -1
- package/dist/api/compiler/checker-type-factory.js +53 -12
- package/dist/api/compiler/checker.d.ts +5 -1
- package/dist/api/compiler/checker.js +10 -4
- package/dist/api/compiler/compile-program.d.ts +5 -0
- package/dist/api/compiler/compile-program.js +8 -0
- package/dist/api/compiler/expr-record.d.ts +11 -0
- package/dist/api/compiler/expr-record.js +53 -0
- package/dist/api/compiler/identifier-name.d.ts +9 -0
- package/dist/api/compiler/identifier-name.js +10 -0
- package/dist/api/compiler/jsdoc.js +4 -2
- package/dist/api/compiler/parser.d.ts +2 -1
- package/dist/api/compiler/parser.js +10 -8
- package/dist/api/compiler/printer/factory.js +3 -2
- package/dist/api/compiler/printer/printer.js +3 -2
- package/dist/api/compiler/reparser.js +4 -3
- package/dist/api/compiler/scanner.d.ts +8 -0
- package/dist/api/compiler/scanner.js +58 -42
- package/dist/api/compiler/shared-results.d.ts +376 -143
- package/dist/api/compiler/shared-results.js +1550 -773
- package/dist/api/compiler/transformers/declarations.js +2 -1
- package/package.json +9 -9
- package/src/compiler/ast.ts +19 -12
- package/src/compiler/cgroup.ts +157 -0
- package/src/compiler/checker-classes.ts +2 -1
- package/src/compiler/checker-contextual.ts +104 -0
- package/src/compiler/checker-expressions.ts +16 -1
- package/src/compiler/checker-jsx.ts +2 -1
- package/src/compiler/checker-type-factory.ts +53 -14
- package/src/compiler/checker.ts +11 -4
- package/src/compiler/compile-program.ts +8 -0
- package/src/compiler/decoder.ts +2 -1
- package/src/compiler/doctor-report.ts +133 -0
- package/src/compiler/expr-record.ts +59 -0
- package/src/compiler/identifier-name.ts +13 -0
- package/src/compiler/jsdoc.ts +4 -2
- package/src/compiler/parallel-check.ts +353 -146
- package/src/compiler/parallel-emit.ts +3 -3
- package/src/compiler/parser.ts +10 -8
- package/src/compiler/printer/factory.ts +3 -2
- package/src/compiler/printer/printer.ts +4 -2
- package/src/compiler/reparser.ts +7 -3
- package/src/compiler/run-config.ts +1383 -0
- package/src/compiler/run-record-read.ts +87 -0
- package/src/compiler/run-records.ts +575 -0
- package/src/compiler/scanner.ts +57 -41
- package/src/compiler/shared-results.ts +1626 -896
- package/src/compiler/thread-entry.ts +3 -1
- package/src/compiler/transformers/declarations.ts +2 -1
- package/src/compiler/tsc-build.ts +64 -6
- package/src/compiler/tsc-cli.ts +33 -4
- package/src/compiler/tsc-compile.ts +213 -8
- package/src/compiler/tsc-watch.ts +25 -4
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ npx tsc-ts --noEmit src/index.ts
|
|
|
33
33
|
|
|
34
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
|
-
`--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` and in the first build of `--watch`, with or without build info, 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.
|
|
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` and in the first build of `--watch`, with or without build info, 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. The checker threads share the results they compute where the run expects that to pay: at 12 or more checkers, when 40% of the program's files are declarations or come from `node_modules` and the checkers' ranges mostly resolve the same large libraries. `TSC_TS_SHARE=1` turns sharing on for any program and `TSC_TS_SHARE=0` keeps it off, and a run whose sharing stops paying stops sharing its results as it goes. A sharing run may also bound how many results it posts at a time, which costs a few percent on a project that does not gain by it and saves more on one that does: the learned choice among a project's runs, off until its record shows it faster, and `TSC_TS_SHARE_BOUNDED=1` turns it on for any program while `TSC_TS_SHARE_BOUNDED=0` keeps it off. `TSC_TS_AUTO=0` keeps the choices of a run before automatic selection (fewer checkers where the ranges resolve large libraries, no sharing), and `TSC_TS_AUTO=static` keeps the rules and the in-run switches but reads and writes no records, and `TSC_TS_AUTO=explore` adds the experimental exploration described below. Unless `--singleThreaded` is given, the files are parsed on the CPUs the process may run on, but one, whatever the checker count, and `TSC_TS_PARSE_THREADS` sets how many. `--extendedDiagnostics` prints the checker threads, the sharing and the parse threads after the statistics table, under `Suggestions:`, with where each value came from (`pinned: --checkers`, `default`, `automatic: ...`, `learned: check 14% faster over 3 runs`, `exploring`, `control`) and how to pin it; `--build` prints one section per project it builds. The section also names the run's record under `Records:`. Each run that checks a program writes what it measured to `~/.cache/tsc-ts/runs-v1/` (`TSC_TS_CACHE_DIR` sets the directory, `TSC_TS_CACHE=0` turns records off), for later runs of the same project on the same machine to read. A later run chooses from that record where the rules left a setting open: a configuration the samples show faster than the static choice — by 3% or twice the standard error of the gains each of its samples makes against the nearest run of the other arm, on three samples of each taken while the machine was not busy — is adopted, every sixteenth run (and the first after two weeks) re-measures the static choice as a control run, and an adopted configuration whose last three samples all fall behind the control runs reverts at once. A run never tries a configuration that could make itself slower: it adopts only what the samples already show faster, from `tsc-ts doctor`, from a pinned run or from a run that already used it. `TSC_TS_AUTO=explore` turns on an experimental alternative in which a run also tries a setting the signals leave uncertain: one run in eight tries three quarters of the count where the library text puts it near the cut, sharing at eight checkers near the rule's limits, or half the parse threads, and such a run is slower than the configuration it would have used. A program whose shape changed by more than 15% discards the record's samples. Watch mode, a `--build` of several projects at once, `--singleThreaded`, Node builds and `TSC_TS_AUTO=0` or `static` keep no record, and the section says why; a run with `CI` set reads and adopts but never explores. `tsc-ts doctor [-p <tsconfig>] [--runs N] [--budget SECONDS] [--emit] [--json] [--no-save]` measures these settings on this machine: it runs the project's check under the default configuration, with sharing on, with up to 16 checkers, with both, and with half the parse threads, compares the phase times by the same rule automatic selection uses, and prints what it recommends with the evidence for it. Each measured run is a child process, so it runs as a user's run would, and it writes what it measured to the file named by `TSC_TS_DOCTOR_REPORT`; runs without the variable are unaffected. Doctor stores its samples in the record with role `doctor`, unless `--no-save` is given. The command is experimental: the configurations it compares and what it recommends may change. 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
|
|
|
38
38
|
The native executable never frees syntax trees, types, signatures or symbols: it keeps them until it exits, which saves the cost of tracking them during a build. A one-shot build is unaffected, but a long-running process grows with each rebuild or project update. Native `--watch` (also with `--build`) runs in a child process, and when a change arrives while that process holds more than 2.5 times the memory it held after its first build, a new process replaces it and builds the change, reporting what the old process would have. `TSC_TS_WATCH_MEMORY` sets that limit in megabytes, and `TSC_TS_WATCH_MEMORY=0` turns the replacement off. A `--api` process grows with each project update; restart it to reclaim the memory.
|
|
39
39
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ProgramLifetime } from '@scriptc/types';
|
|
2
|
+
import { IdentifierName } from './identifier-name.js';
|
|
2
3
|
import { SyntaxKind } from './syntax-kind.js';
|
|
3
4
|
import { type CommentDirective, type CommentRange, type LanguageVariant, TokenFlags } from './types.js';
|
|
4
5
|
import { type Diagnostic, DiagnosticFile } from './diagnostics.js';
|
|
@@ -242,8 +243,9 @@ export declare class Token extends Node {
|
|
|
242
243
|
copy(): Token;
|
|
243
244
|
}
|
|
244
245
|
export declare class Identifier extends Node {
|
|
245
|
-
|
|
246
|
-
constructor(
|
|
246
|
+
readonly identifierName: IdentifierName;
|
|
247
|
+
constructor(name: IdentifierName);
|
|
248
|
+
get text(): string;
|
|
247
249
|
forEachChild(_v: NodeVisitor): boolean;
|
|
248
250
|
setParentOfChildren(): void;
|
|
249
251
|
deepClone(): Node;
|
|
@@ -256,7 +258,7 @@ export declare class Identifier extends Node {
|
|
|
256
258
|
*/
|
|
257
259
|
export declare class ReferenceIdentifier extends Identifier {
|
|
258
260
|
flowNode: FlowNode | undefined;
|
|
259
|
-
constructor(
|
|
261
|
+
constructor(name: IdentifierName);
|
|
260
262
|
copy(): Identifier;
|
|
261
263
|
}
|
|
262
264
|
export declare class PrivateIdentifier extends Node {
|
|
@@ -2346,6 +2348,10 @@ export declare class PatternAmbientModule {
|
|
|
2346
2348
|
readonly text: string;
|
|
2347
2349
|
readonly starIndex: number;
|
|
2348
2350
|
readonly symbol: Symbol;
|
|
2351
|
+
/** The part of `text` before `starIndex`, kept so a match does not copy it. */
|
|
2352
|
+
readonly prefix: string;
|
|
2353
|
+
/** The part of `text` after `starIndex`, kept so a match does not copy it. */
|
|
2354
|
+
readonly suffix: string;
|
|
2349
2355
|
constructor(text: string, starIndex: number, symbol: Symbol);
|
|
2350
2356
|
matches(candidate: string): boolean;
|
|
2351
2357
|
}
|
package/dist/api/compiler/ast.js
CHANGED
|
@@ -221,10 +221,13 @@ export class Token extends Node {
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
export class Identifier extends Node {
|
|
224
|
-
|
|
225
|
-
constructor(
|
|
224
|
+
identifierName;
|
|
225
|
+
constructor(name) {
|
|
226
226
|
super(79 /* SyntaxKind.Identifier */);
|
|
227
|
-
this.
|
|
227
|
+
this.identifierName = name;
|
|
228
|
+
}
|
|
229
|
+
get text() {
|
|
230
|
+
return this.identifierName.text;
|
|
228
231
|
}
|
|
229
232
|
forEachChild(_v) {
|
|
230
233
|
return false;
|
|
@@ -234,7 +237,7 @@ export class Identifier extends Node {
|
|
|
234
237
|
return this.copy();
|
|
235
238
|
}
|
|
236
239
|
copy() {
|
|
237
|
-
const node = new Identifier(this.
|
|
240
|
+
const node = new Identifier(this.identifierName);
|
|
238
241
|
node.flags = this.flags;
|
|
239
242
|
node.pos = this.pos;
|
|
240
243
|
node.end = this.end;
|
|
@@ -249,12 +252,12 @@ export class Identifier extends Node {
|
|
|
249
252
|
export class ReferenceIdentifier extends Identifier {
|
|
250
253
|
// Set by the binder.
|
|
251
254
|
flowNode;
|
|
252
|
-
constructor(
|
|
253
|
-
super(
|
|
255
|
+
constructor(name) {
|
|
256
|
+
super(name);
|
|
254
257
|
this.flowNode = undefined;
|
|
255
258
|
}
|
|
256
259
|
copy() {
|
|
257
|
-
const node = new ReferenceIdentifier(this.
|
|
260
|
+
const node = new ReferenceIdentifier(this.identifierName);
|
|
258
261
|
node.flags = this.flags;
|
|
259
262
|
node.pos = this.pos;
|
|
260
263
|
node.end = this.end;
|
|
@@ -6782,17 +6785,19 @@ export class PatternAmbientModule {
|
|
|
6782
6785
|
text;
|
|
6783
6786
|
starIndex;
|
|
6784
6787
|
symbol;
|
|
6788
|
+
/** The part of `text` before `starIndex`, kept so a match does not copy it. */
|
|
6789
|
+
prefix;
|
|
6790
|
+
/** The part of `text` after `starIndex`, kept so a match does not copy it. */
|
|
6791
|
+
suffix;
|
|
6785
6792
|
constructor(text, starIndex, symbol) {
|
|
6786
6793
|
this.text = text;
|
|
6787
6794
|
this.starIndex = starIndex;
|
|
6788
6795
|
this.symbol = symbol;
|
|
6796
|
+
this.prefix = text.substring(0, starIndex);
|
|
6797
|
+
this.suffix = text.substring(starIndex + 1);
|
|
6789
6798
|
}
|
|
6790
6799
|
matches(candidate) {
|
|
6791
|
-
|
|
6792
|
-
const star = this.starIndex;
|
|
6793
|
-
return (candidate.length >= text.length - 1 &&
|
|
6794
|
-
candidate.startsWith(text.substring(0, star)) &&
|
|
6795
|
-
candidate.endsWith(text.substring(star + 1)));
|
|
6800
|
+
return (candidate.length >= this.text.length - 1 && candidate.startsWith(this.prefix) && candidate.endsWith(this.suffix));
|
|
6796
6801
|
}
|
|
6797
6802
|
}
|
|
6798
6803
|
function containsNonASCII(text) {
|
|
@@ -28,6 +28,7 @@ import { checkFunctionOrConstructorSymbol, checkFunctionOrMethodSymbols } from '
|
|
|
28
28
|
import { checkClassHeritage, checkClassOrInterfaceForDuplicateIndexSignatures, checkInterfaceHeritage, } from './checker-heritage.js';
|
|
29
29
|
import { checkDecorators, getFirstTransformableStaticClassElement } from './checker-decorators.js';
|
|
30
30
|
import { getTypeOfNode } from './checker-services.js';
|
|
31
|
+
import { IdentifierName } from './identifier-name.js';
|
|
31
32
|
export function checkClassDeclaration(c, node) {
|
|
32
33
|
checkClassLikeDeclaration(c, node);
|
|
33
34
|
checkClassMembers(c, node);
|
|
@@ -464,7 +465,7 @@ function newThisPropertyReference(symbol, container, flowNode) {
|
|
|
464
465
|
if (name.startsWith('\ufffe#'))
|
|
465
466
|
accessName = new PrivateIdentifier(name.substring(name.indexOf('@') + 1));
|
|
466
467
|
else
|
|
467
|
-
accessName = new Identifier(name);
|
|
468
|
+
accessName = new Identifier(new IdentifierName(name));
|
|
468
469
|
const thisExpression = new KeywordExpression(109 /* SyntaxKind.ThisKeyword */);
|
|
469
470
|
const reference = new PropertyAccessExpression(thisExpression, undefined, accessName, 0 /* NodeFlags.None */);
|
|
470
471
|
thisExpression.parent = reference;
|
|
@@ -18,6 +18,26 @@ export declare function pushCachedContextualType(c: Checker, node: Node): void;
|
|
|
18
18
|
export declare function popContextualType(c: Checker): void;
|
|
19
19
|
/** The index of the contextual type pushed onto `node`, or -1. */
|
|
20
20
|
export declare function findContextualNode(c: Checker, node: Node, includeCaches: boolean): number;
|
|
21
|
+
/**
|
|
22
|
+
* The id of the contextual type in force for `node`, or -1 if the node's contextual type is not on
|
|
23
|
+
* the stack. A key built from -1 can't tell a check under a contextual type that was not pushed from
|
|
24
|
+
* a check with no contextual type, so callers record nothing under -1.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getContextualTypeId(c: Checker, node: Node): number;
|
|
27
|
+
/**
|
|
28
|
+
* Whether a check of `node` has no contextual type and no inference context, so its type is a
|
|
29
|
+
* function of the node and the check mode alone: the node is not on the contextual stack, no
|
|
30
|
+
* inference context contains it, and its parent gives it no contextual type. The parents answered
|
|
31
|
+
* here are the ones `getContextualTypeEx` returns `undefined` for without computing anything; a
|
|
32
|
+
* parent it computes a type for is not answered, so the result is never "yes" for a check that
|
|
33
|
+
* could have a contextual type.
|
|
34
|
+
*
|
|
35
|
+
* Types computed inside a flow loop are provisional (the checker does not cache them either), so a
|
|
36
|
+
* check in a loop is not context-free. The same holds while a reduce label is in force, as when
|
|
37
|
+
* flow analysis revisits a `finally` block with the antecedents of one outgoing path: the flow
|
|
38
|
+
* state differs from the one the earlier check of the block saw.
|
|
39
|
+
*/
|
|
40
|
+
export declare function isCheckedWithoutContextualType(c: Checker, node: Node): boolean;
|
|
21
41
|
export declare function pushInferenceContext(c: Checker, node: Node, context: InferenceContext | undefined): void;
|
|
22
42
|
export declare function popInferenceContext(c: Checker): void;
|
|
23
43
|
/** The inference context of the innermost call argument containing `node`. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Contextual typing: the type an expression's position implies, and contextual signatures.
|
|
2
2
|
import { resolvedReturnTypeOf } from './side-state.js';
|
|
3
|
-
import { getInitializer, getName, getParameters, getType, getText, getSymbol, getTypeParameters, JsxAttribute, JsxElement, } from './ast.js';
|
|
3
|
+
import { getArguments, getInitializer, getName, getParameters, getType, getText, getSymbol, getTypeParameters, JsxAttribute, JsxElement, } from './ast.js';
|
|
4
4
|
import { getImmediatelyInvokedFunctionExpression, isFunctionExpressionOrArrowFunction, isObjectLiteralMethod, isStatic, } from './binder-utilities.js';
|
|
5
5
|
import { filterType, getIntersectionType, getNumberLiteralType, getRegularTypeOfLiteralType, getUnionType, getUnionTypeEx, getWidenedLiteralType, getEndElementCount, getStringLiteralType, getTypeArguments, getTypeReferenceArity, mapType, mapTypeEx, isTupleType, tupleTargetOf, typesOf, } from './checker-type-factory.js';
|
|
6
6
|
import { combineUnionOrIntersectionMemberSignatures, compareTypeParametersIdentical, findApplicableIndexInfo, getApparentType, getBaseConstraintOrType, getIndexInfosOfStructuredType, getPropertiesOfType, getPropertyOfType, getReducedType, getSignaturesOfType, } from './checker-members.js';
|
|
@@ -68,6 +68,116 @@ export function findContextualNode(c, node, includeCaches) {
|
|
|
68
68
|
return i;
|
|
69
69
|
return -1;
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* The id of the contextual type in force for `node`, or -1 if the node's contextual type is not on
|
|
73
|
+
* the stack. A key built from -1 can't tell a check under a contextual type that was not pushed from
|
|
74
|
+
* a check with no contextual type, so callers record nothing under -1.
|
|
75
|
+
*/
|
|
76
|
+
export function getContextualTypeId(c, node) {
|
|
77
|
+
const index = findContextualNode(c, node, true);
|
|
78
|
+
if (index < 0)
|
|
79
|
+
return -1;
|
|
80
|
+
const t = c.inferenceCaches.contextualTypes[index];
|
|
81
|
+
return t === undefined ? -1 : t.id;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Whether a check of `node` has no contextual type and no inference context, so its type is a
|
|
85
|
+
* function of the node and the check mode alone: the node is not on the contextual stack, no
|
|
86
|
+
* inference context contains it, and its parent gives it no contextual type. The parents answered
|
|
87
|
+
* here are the ones `getContextualTypeEx` returns `undefined` for without computing anything; a
|
|
88
|
+
* parent it computes a type for is not answered, so the result is never "yes" for a check that
|
|
89
|
+
* could have a contextual type.
|
|
90
|
+
*
|
|
91
|
+
* Types computed inside a flow loop are provisional (the checker does not cache them either), so a
|
|
92
|
+
* check in a loop is not context-free. The same holds while a reduce label is in force, as when
|
|
93
|
+
* flow analysis revisits a `finally` block with the antecedents of one outgoing path: the flow
|
|
94
|
+
* state differs from the one the earlier check of the block saw.
|
|
95
|
+
*/
|
|
96
|
+
export function isCheckedWithoutContextualType(c, node) {
|
|
97
|
+
if (c.flowLoopStack.length !== 0)
|
|
98
|
+
return false;
|
|
99
|
+
if (c.flowReduceLabels.length !== 0)
|
|
100
|
+
return false;
|
|
101
|
+
if (findContextualNode(c, node, true) >= 0)
|
|
102
|
+
return false;
|
|
103
|
+
if (getInferenceContext(c, node) !== undefined)
|
|
104
|
+
return false;
|
|
105
|
+
const parent = node.parent;
|
|
106
|
+
if (parent === undefined)
|
|
107
|
+
return true;
|
|
108
|
+
switch (parent.kind) {
|
|
109
|
+
case 262 /* SyntaxKind.VariableDeclaration */:
|
|
110
|
+
case 171 /* SyntaxKind.Parameter */:
|
|
111
|
+
case 174 /* SyntaxKind.PropertyDeclaration */:
|
|
112
|
+
case 173 /* SyntaxKind.PropertySignature */:
|
|
113
|
+
case 210 /* SyntaxKind.BindingElement */:
|
|
114
|
+
// Only the initializer is contextually typed by the declaration.
|
|
115
|
+
return getInitializer(parent) !== node;
|
|
116
|
+
case 215 /* SyntaxKind.CallExpression */:
|
|
117
|
+
case 216 /* SyntaxKind.NewExpression */: {
|
|
118
|
+
// Only the arguments are contextually typed by the parameters; the callee is not.
|
|
119
|
+
const args = getArguments(parent);
|
|
120
|
+
if (args !== undefined) {
|
|
121
|
+
for (const arg of args.nodes)
|
|
122
|
+
if (arg === node)
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
case 212 /* SyntaxKind.ObjectLiteralExpression */:
|
|
128
|
+
// Only a method takes the property's contextual type.
|
|
129
|
+
return node.kind !== 176 /* SyntaxKind.MethodDeclaration */;
|
|
130
|
+
case 228 /* SyntaxKind.BinaryExpression */: {
|
|
131
|
+
const binary = parent;
|
|
132
|
+
if (binary.type !== undefined)
|
|
133
|
+
return false;
|
|
134
|
+
switch (binary.operatorToken.kind) {
|
|
135
|
+
case 63 /* SyntaxKind.EqualsToken */:
|
|
136
|
+
case 76 /* SyntaxKind.AmpersandAmpersandEqualsToken */:
|
|
137
|
+
case 75 /* SyntaxKind.BarBarEqualsToken */:
|
|
138
|
+
case 77 /* SyntaxKind.QuestionQuestionEqualsToken */:
|
|
139
|
+
return node !== binary.right;
|
|
140
|
+
case 56 /* SyntaxKind.BarBarToken */:
|
|
141
|
+
case 60 /* SyntaxKind.QuestionQuestionToken */:
|
|
142
|
+
case 55 /* SyntaxKind.AmpersandAmpersandToken */:
|
|
143
|
+
case 27 /* SyntaxKind.CommaToken */:
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
case 229 /* SyntaxKind.ConditionalExpression */: {
|
|
149
|
+
const conditional = parent;
|
|
150
|
+
return node !== conditional.whenTrue && node !== conditional.whenFalse;
|
|
151
|
+
}
|
|
152
|
+
case 241 /* SyntaxKind.TemplateSpan */: {
|
|
153
|
+
// Only a tagged template types its spans.
|
|
154
|
+
const template = parent.parent;
|
|
155
|
+
return template.parent === undefined || template.parent.kind !== 217 /* SyntaxKind.TaggedTemplateExpression */;
|
|
156
|
+
}
|
|
157
|
+
case 221 /* SyntaxKind.ArrowFunction */:
|
|
158
|
+
case 255 /* SyntaxKind.ReturnStatement */:
|
|
159
|
+
case 231 /* SyntaxKind.YieldExpression */:
|
|
160
|
+
case 225 /* SyntaxKind.AwaitExpression */:
|
|
161
|
+
case 172 /* SyntaxKind.Decorator */:
|
|
162
|
+
case 236 /* SyntaxKind.AsExpression */:
|
|
163
|
+
case 218 /* SyntaxKind.TypeAssertionExpression */:
|
|
164
|
+
case 240 /* SyntaxKind.SatisfiesExpression */:
|
|
165
|
+
case 279 /* SyntaxKind.ExportAssignment */:
|
|
166
|
+
case 304 /* SyntaxKind.PropertyAssignment */:
|
|
167
|
+
case 305 /* SyntaxKind.ShorthandPropertyAssignment */:
|
|
168
|
+
case 306 /* SyntaxKind.SpreadAssignment */:
|
|
169
|
+
case 211 /* SyntaxKind.ArrayLiteralExpression */:
|
|
170
|
+
case 219 /* SyntaxKind.ParenthesizedExpression */:
|
|
171
|
+
case 237 /* SyntaxKind.NonNullExpression */:
|
|
172
|
+
case 296 /* SyntaxKind.JsxExpression */:
|
|
173
|
+
case 293 /* SyntaxKind.JsxAttribute */:
|
|
174
|
+
case 295 /* SyntaxKind.JsxSpreadAttribute */:
|
|
175
|
+
case 288 /* SyntaxKind.JsxOpeningElement */:
|
|
176
|
+
case 287 /* SyntaxKind.JsxSelfClosingElement */:
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
71
181
|
export function pushInferenceContext(c, node, context) {
|
|
72
182
|
const caches = c.inferenceCaches;
|
|
73
183
|
const depth = caches.inferenceDepth;
|
|
@@ -43,7 +43,7 @@ import { isFunctionLike, isImportCall, isInJSFile, isRequireCall } from './ast-u
|
|
|
43
43
|
import { isLiteralKind } from './printer/utilities.js';
|
|
44
44
|
import { convertAutoToAny, isEvolvingArrayOperationTarget, getAssignmentTargetKind, getControlFlowContainer, isConstantVariable, isInCompoundLikeAssignment, isMutableLocalVariableDeclaration, isParameterOrMutableLocalVariable, isPastLastAssignment, isSymbolAssignedDefinitely, getFlowTypeOfReference, getNarrowedTypeOfSymbol, } from './checker-narrowing.js';
|
|
45
45
|
import { getFlowTypeOfAutoTypedProperty, getThisTypeOfAssignedFunction } from './checker-javascript.js';
|
|
46
|
-
import { checkExpressionWithContextualType, getThisTypeOfObjectLiteralMember } from './checker-contextual.js';
|
|
46
|
+
import { checkExpressionWithContextualType, getThisTypeOfObjectLiteralMember, isCheckedWithoutContextualType, } from './checker-contextual.js';
|
|
47
47
|
import { getInferenceContext, instantiateContextualType, popContextualType, pushCachedContextualType, } from './checker-contextual.js';
|
|
48
48
|
import { addIntraExpressionInferenceSite, isConstTypeVariable } from './checker-inference.js';
|
|
49
49
|
import { isContextSensitiveFunctionOrObjectLiteralMethod } from './checker-contextual.js';
|
|
@@ -56,6 +56,17 @@ export function checkExpression(c, node) {
|
|
|
56
56
|
return checkExpressionEx(c, node, 0 /* CheckMode.Normal */);
|
|
57
57
|
}
|
|
58
58
|
export function checkExpressionEx(c, node, checkMode) {
|
|
59
|
+
// A completed check of this node under this mode answers this one when the check has no
|
|
60
|
+
// contextual type and no inference context: the checker's state only grew since, so this check
|
|
61
|
+
// would produce the type the completed one produced, report the diagnostics it reported and
|
|
62
|
+
// defer the nodes it deferred. Those diagnostics are equal to ones already reported and a node
|
|
63
|
+
// is deferred at most once, so serving the completed type changes neither.
|
|
64
|
+
const recordable = isCheckedWithoutContextualType(c, node);
|
|
65
|
+
if (recordable) {
|
|
66
|
+
const recorded = c.exprCheckRecord.get(node.id, checkMode);
|
|
67
|
+
if (recorded !== undefined)
|
|
68
|
+
return recorded;
|
|
69
|
+
}
|
|
59
70
|
const saveCurrentNode = c.currentNode;
|
|
60
71
|
c.currentNode = node;
|
|
61
72
|
c.instantiationCount = 0;
|
|
@@ -63,6 +74,8 @@ export function checkExpressionEx(c, node, checkMode) {
|
|
|
63
74
|
if (isConstEnumObjectTypeLocal(t))
|
|
64
75
|
checkConstEnumAccess(c, node, t);
|
|
65
76
|
c.currentNode = saveCurrentNode;
|
|
77
|
+
if (recordable)
|
|
78
|
+
c.exprCheckRecord.set(node.id, checkMode, t);
|
|
66
79
|
return t;
|
|
67
80
|
}
|
|
68
81
|
/**
|
|
@@ -38,6 +38,7 @@ import { filterType, isTupleType } from './checker-type-factory.js';
|
|
|
38
38
|
import { createTypeFromGenericGlobalType } from './checker-type-factory.js';
|
|
39
39
|
import { isTypeAssignableTo } from './relations.js';
|
|
40
40
|
import { copyDeclarations, declarationCount, getSymbolId, } from './symbol.js';
|
|
41
|
+
import { IdentifierName } from './identifier-name.js';
|
|
41
42
|
// Names in the `JSX` namespace.
|
|
42
43
|
const jsxNamespaceName = 'JSX';
|
|
43
44
|
const jsxIntrinsicElementsName = 'IntrinsicElements';
|
|
@@ -824,7 +825,7 @@ export function createJsxAttributesTypeFromAttributesProperty(c, openingLikeElem
|
|
|
824
825
|
c.symbolTypes.set(id, createArrayType(c, getUnionType(c, childTypes)));
|
|
825
826
|
// A property signature in the attributes declares the synthetic `children` property, so it is
|
|
826
827
|
// checked as an excess property like the attributes.
|
|
827
|
-
const childrenDeclaration = new PropertySignatureDeclaration(undefined, new Identifier(jsxChildrenPropertyName), undefined, undefined, undefined);
|
|
828
|
+
const childrenDeclaration = new PropertySignatureDeclaration(undefined, new Identifier(new IdentifierName(jsxChildrenPropertyName)), undefined, undefined, undefined);
|
|
828
829
|
childrenDeclaration.parent = attributeParent;
|
|
829
830
|
childrenDeclaration.symbol = childrenPropSymbol;
|
|
830
831
|
childrenPropSymbol.valueDeclaration = childrenDeclaration;
|
|
@@ -1187,37 +1187,78 @@ export function getUnionTypeEx(c, types, unionReduction, alias, origin) {
|
|
|
1187
1187
|
return c.neverType;
|
|
1188
1188
|
if (types.length === 1)
|
|
1189
1189
|
return types[0];
|
|
1190
|
-
//
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1190
|
+
// Unioning two types is the common case, both a union with some other type, like `undefined`, and
|
|
1191
|
+
// two constituents of a list, and the same pairs recur. The union is a function of the two types,
|
|
1192
|
+
// the reduction and the alias, so the result is cached by the pair. A union that exceeded the
|
|
1193
|
+
// complexity limit was reported at the expression that needed it and comes back as the error
|
|
1194
|
+
// type: caching that would silence the report at the next expression with the same input list, so
|
|
1195
|
+
// an error result is not cached.
|
|
1196
|
+
if (types.length === 2 && origin === undefined) {
|
|
1197
|
+
const t0 = types[0];
|
|
1198
|
+
const t1 = types[1];
|
|
1199
|
+
let id1 = t0.id;
|
|
1200
|
+
let id2 = t1.id;
|
|
1196
1201
|
if (id1 > id2) {
|
|
1197
1202
|
const t = id1;
|
|
1198
1203
|
id1 = id2;
|
|
1199
1204
|
id2 = t;
|
|
1200
1205
|
}
|
|
1201
|
-
// Without an alias, both ids and the reduction pack into one
|
|
1202
|
-
|
|
1206
|
+
// Without an alias or a constrained intersection, both ids and the reduction pack into one
|
|
1207
|
+
// exact number. A constrained intersection's reduction resolves a type variable's constraint
|
|
1208
|
+
// (`addTypeToUnion`), so those pairs take the general path.
|
|
1209
|
+
if (alias === undefined &&
|
|
1210
|
+
id2 < UnionPairIdLimit &&
|
|
1211
|
+
!isConstrainedIntersection(t0) &&
|
|
1212
|
+
!isConstrainedIntersection(t1)) {
|
|
1203
1213
|
const id = (id1 * UnionPairIdLimit + id2) * 4 + unionReduction;
|
|
1204
1214
|
let result = c.unionOfUnionTypesById.get(id);
|
|
1205
1215
|
if (result === undefined) {
|
|
1206
1216
|
result = getUnionTypeWorker(c, types, unionReduction, alias, undefined);
|
|
1207
|
-
c.
|
|
1217
|
+
if (result !== c.errorType)
|
|
1218
|
+
c.unionOfUnionTypesById.set(id, result);
|
|
1208
1219
|
}
|
|
1209
1220
|
return result;
|
|
1210
1221
|
}
|
|
1211
|
-
|
|
1212
|
-
|
|
1222
|
+
if ((t0.flags & 134217728 /* TypeFlags.Union */) !== 0 || (t1.flags & 134217728 /* TypeFlags.Union */) !== 0) {
|
|
1223
|
+
const key = id1 + ',' + id2 + ',' + unionReduction + aliasKey(alias);
|
|
1224
|
+
let result = c.unionOfUnionTypes.get(key);
|
|
1225
|
+
if (result === undefined) {
|
|
1226
|
+
result = getUnionTypeWorker(c, types, unionReduction, alias, undefined);
|
|
1227
|
+
if (result !== c.errorType)
|
|
1228
|
+
c.unionOfUnionTypes.set(key, result);
|
|
1229
|
+
}
|
|
1230
|
+
return result;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
// Longer lists recur too, from nested unions and from constituents mapped in the same order.
|
|
1234
|
+
// Normalizing a list costs a sort of its constituents and the reductions, and the union is a
|
|
1235
|
+
// function of the list as given, the reduction and the alias, so the result is cached by the list.
|
|
1236
|
+
if (origin === undefined) {
|
|
1237
|
+
const hash = typeListHash(types, alias, unionReduction);
|
|
1238
|
+
let result = c.unionTypesByInputList.get(hash, types, alias, unionReduction);
|
|
1213
1239
|
if (result === undefined) {
|
|
1214
1240
|
result = getUnionTypeWorker(c, types, unionReduction, alias, undefined);
|
|
1215
|
-
c.
|
|
1241
|
+
if (result !== c.errorType && !hasConstrainedIntersection(types))
|
|
1242
|
+
c.unionTypesByInputList.set(hash, types.slice(), alias, unionReduction, result);
|
|
1216
1243
|
}
|
|
1217
1244
|
return result;
|
|
1218
1245
|
}
|
|
1219
1246
|
return getUnionTypeWorker(c, types, unionReduction, alias, origin);
|
|
1220
1247
|
}
|
|
1248
|
+
/** An intersection that `addTypeToUnion` reduces by resolving a type variable's constraint. */
|
|
1249
|
+
function isConstrainedIntersection(t) {
|
|
1250
|
+
return (t.flags & 268435456 /* TypeFlags.Intersection */) !== 0 && (t.objectFlags & 134217728 /* ObjectFlags.IsConstrainedTypeVariable */) !== 0;
|
|
1251
|
+
}
|
|
1252
|
+
/** Whether `addTypesToUnion` would set `IncludesConstrainedTypeVariable` for `types`. */
|
|
1253
|
+
function hasConstrainedIntersection(types) {
|
|
1254
|
+
for (const t of types) {
|
|
1255
|
+
if (isConstrainedIntersection(t))
|
|
1256
|
+
return true;
|
|
1257
|
+
if ((t.flags & 134217728 /* TypeFlags.Union */) !== 0 && hasConstrainedIntersection(t.types))
|
|
1258
|
+
return true;
|
|
1259
|
+
}
|
|
1260
|
+
return false;
|
|
1261
|
+
}
|
|
1221
1262
|
class TypeSet {
|
|
1222
1263
|
types = [];
|
|
1223
1264
|
includes = 0;
|
|
@@ -2,6 +2,7 @@ import type { ModuleSpecifierResult } from './node-builder-names.js';
|
|
|
2
2
|
import type { EmitHelperFileLinks } from './checker-emit-helpers.js';
|
|
3
3
|
import type { Node, PatternAmbientModule, SourceFile } from './ast.js';
|
|
4
4
|
import { CompactIntLinkTable, CompactLinkTable, IntLinkTable, LinkTable, PagedIdSet, SparseLinkTable } from './link-tables.js';
|
|
5
|
+
import { ExprCheckRecord } from './expr-record.js';
|
|
5
6
|
import { Diagnostic, type DiagnosticMessage, Diagnostics } from './diagnostics.js';
|
|
6
7
|
import { type CompilerOptions, ModuleKind, ScriptTarget } from './options.js';
|
|
7
8
|
import { CheckFlags, Symbol, SymbolFlags, type SymbolTable } from './symbol.js';
|
|
@@ -225,6 +226,8 @@ export declare class Checker implements TypeChecking {
|
|
|
225
226
|
readonly resolvedSymbols: CompactLinkTable<Symbol>;
|
|
226
227
|
/** The resolved type of a type node or expression. */
|
|
227
228
|
readonly resolvedTypes: CompactLinkTable<Type>;
|
|
229
|
+
/** The type the last completed check of each expression key produced (expr-record.ts). */
|
|
230
|
+
readonly exprCheckRecord: ExprCheckRecord;
|
|
228
231
|
/** The resolved signature of a call-like node or a signature declaration. */
|
|
229
232
|
readonly resolvedSignatures: CompactLinkTable<Signature>;
|
|
230
233
|
/** Merged symbols, indexed by the id of the symbol merged into them. */
|
|
@@ -274,6 +277,7 @@ export declare class Checker implements TypeChecking {
|
|
|
274
277
|
readonly unionOfUnionTypes: Map<string, Type>;
|
|
275
278
|
/** `unionOfUnionTypes` without an alias, by both ids and the reduction packed into one number. */
|
|
276
279
|
readonly unionOfUnionTypesById: Map<number, Type>;
|
|
280
|
+
readonly unionTypesByInputList: TypeListCache<Type>;
|
|
277
281
|
readonly intersectionTypes: TypeListCache<Type>;
|
|
278
282
|
readonly tupleTypes: Map<string, Type>;
|
|
279
283
|
readonly indexedAccessTypes: Map<string, Type>;
|
|
@@ -548,7 +552,7 @@ export declare class Checker implements TypeChecking {
|
|
|
548
552
|
/** The access flags of the key `getIndexedAccessTypeEx` keeps each indexed access type by. */
|
|
549
553
|
indexedAccessKeyFlags: Map<Type, number> | undefined;
|
|
550
554
|
/** Where results are shared between checker threads (shared-results.ts): the file of each diagnostic deferred. */
|
|
551
|
-
deferredDiagnosticFiles:
|
|
555
|
+
deferredDiagnosticFiles: number[] | undefined;
|
|
552
556
|
constructor(host: CheckerHost);
|
|
553
557
|
/** Checks `file` if needed and returns its semantic diagnostics, sorted. */
|
|
554
558
|
getDiagnostics(file: SourceFile): Diagnostic[];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { sideOf } from './side-state.js';
|
|
2
2
|
import { CompactIntLinkTable, CompactLinkTable, IntLinkTable, LinkTable, PagedIdSet, SparseLinkTable, } from './link-tables.js';
|
|
3
|
+
import { ExprCheckRecord } from './expr-record.js';
|
|
3
4
|
import { getErrorRangeForNode, getSourceFileOfNode } from './binder-utilities.js';
|
|
4
5
|
import { Diagnostic, compareDiagnostics, equalDiagnostics, } from './diagnostics.js';
|
|
5
6
|
import { ModuleKind, ScriptTarget, getEmitScriptTarget, getIsolatedModules, getStrictOptionValue, shouldPreserveConstEnums, } from './options.js';
|
|
@@ -17,7 +18,7 @@ import { InferenceCaches } from './checker-inference.js';
|
|
|
17
18
|
import { AssignmentMarker } from './checker-narrowing.js';
|
|
18
19
|
import { JsxState } from './checker-jsx.js';
|
|
19
20
|
import { SourceFileMetadata, getEmitModuleFormatOfFile } from './program-utilities.js';
|
|
20
|
-
import {
|
|
21
|
+
import { startThreadSharing } from './shared-results.js';
|
|
21
22
|
/** What the checker needs from a program. */
|
|
22
23
|
export class CheckerHost {
|
|
23
24
|
/** How a module name in `file` resolved in `mode`, if the program resolved it. */
|
|
@@ -358,6 +359,8 @@ export class Checker {
|
|
|
358
359
|
resolvedSymbols = new CompactLinkTable();
|
|
359
360
|
/** The resolved type of a type node or expression. */
|
|
360
361
|
resolvedTypes = new CompactLinkTable();
|
|
362
|
+
/** The type the last completed check of each expression key produced (expr-record.ts). */
|
|
363
|
+
exprCheckRecord = new ExprCheckRecord();
|
|
361
364
|
/** The resolved signature of a call-like node or a signature declaration. */
|
|
362
365
|
resolvedSignatures = new CompactLinkTable();
|
|
363
366
|
/** Merged symbols, indexed by the id of the symbol merged into them. */
|
|
@@ -409,6 +412,7 @@ export class Checker {
|
|
|
409
412
|
unionOfUnionTypes = new Map();
|
|
410
413
|
/** `unionOfUnionTypes` without an alias, by both ids and the reduction packed into one number. */
|
|
411
414
|
unionOfUnionTypesById = new Map();
|
|
415
|
+
unionTypesByInputList = new TypeListCache();
|
|
412
416
|
intersectionTypes = new TypeListCache();
|
|
413
417
|
tupleTypes = new Map();
|
|
414
418
|
indexedAccessTypes = new Map();
|
|
@@ -576,7 +580,7 @@ export class Checker {
|
|
|
576
580
|
deferDiagnostic(node, report) {
|
|
577
581
|
this.deferredDiagnostics.push(report);
|
|
578
582
|
if (this.deferredDiagnosticFiles !== undefined)
|
|
579
|
-
this.deferredDiagnosticFiles.push(getSourceFileOfNode(node)
|
|
583
|
+
this.deferredDiagnosticFiles.push(this.fileIndex.get(getSourceFileOfNode(node)) ?? -1);
|
|
580
584
|
}
|
|
581
585
|
/**
|
|
582
586
|
* The checked object literals of each file whose members may set deprecated properties of their contextual
|
|
@@ -886,8 +890,9 @@ export class Checker {
|
|
|
886
890
|
mergeAmbientModulesAndAugmentations(this);
|
|
887
891
|
this.modulesMerged = true;
|
|
888
892
|
this.mergeDiagnostics.push(this.diagnostics.takeLog(), this.suggestionDiagnostics.takeLog());
|
|
889
|
-
|
|
890
|
-
|
|
893
|
+
// Returns unless this thread was given sharing data (`ThreadSharingData` in its worker data): the
|
|
894
|
+
// main thread, and every thread of a run that didn't share.
|
|
895
|
+
startThreadSharing(this);
|
|
891
896
|
if (this.threadSharing !== undefined) {
|
|
892
897
|
this.distributedConditionals = new Map();
|
|
893
898
|
this.distributedByKey = new Map();
|
|
@@ -1059,6 +1064,7 @@ export function disposeChecker(c) {
|
|
|
1059
1064
|
c.unionTypes.clear();
|
|
1060
1065
|
c.unionOfUnionTypes.clear();
|
|
1061
1066
|
c.unionOfUnionTypesById.clear();
|
|
1067
|
+
c.unionTypesByInputList.clear();
|
|
1062
1068
|
c.intersectionTypes.clear();
|
|
1063
1069
|
c.tupleTypes.clear();
|
|
1064
1070
|
c.indexedAccessTypes.clear();
|
|
@@ -105,6 +105,11 @@ export declare abstract class CompilerProgram {
|
|
|
105
105
|
readonly times: CompileTimes;
|
|
106
106
|
readonly emitter: ProgramEmitter;
|
|
107
107
|
constructor(checked: CheckedProgram, times: CompileTimes);
|
|
108
|
+
/**
|
|
109
|
+
* Whether this run checked the program, which `getDiagnosticsOfProgram` sets when it checks it. A run
|
|
110
|
+
* stopped before checking, by syntax errors or `--noCheck`, keeps no record (`run-records.ts`).
|
|
111
|
+
*/
|
|
112
|
+
checkedTheProgram: boolean;
|
|
108
113
|
/**
|
|
109
114
|
* The time spent in declaration emit while checking, to count as emit time rather than check time, since
|
|
110
115
|
* the last call. Only an incremental program emits while checking, to compute signatures.
|
|
@@ -311,6 +311,11 @@ export class CompilerProgram {
|
|
|
311
311
|
this.times = times;
|
|
312
312
|
this.emitter = new ProgramEmitter(checked);
|
|
313
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* Whether this run checked the program, which `getDiagnosticsOfProgram` sets when it checks it. A run
|
|
316
|
+
* stopped before checking, by syntax errors or `--noCheck`, keeps no record (`run-records.ts`).
|
|
317
|
+
*/
|
|
318
|
+
checkedTheProgram = false;
|
|
314
319
|
/**
|
|
315
320
|
* The time spent in declaration emit while checking, to count as emit time rather than check time, since
|
|
316
321
|
* the last call. Only an incremental program emits while checking, to compute signatures.
|
|
@@ -447,6 +452,9 @@ export function getDiagnosticsOfProgram(program, withDeclarationDiagnostics, dec
|
|
|
447
452
|
for (const d of program.getGlobalDiagnostics(false))
|
|
448
453
|
result.push(d);
|
|
449
454
|
if (result.length === configCount) {
|
|
455
|
+
// With `--noCheck` the checker skips every file: the run checked nothing to sample (`run-records.ts`).
|
|
456
|
+
if (options.noCheck !== true)
|
|
457
|
+
program.checkedTheProgram = true;
|
|
450
458
|
const checkStart = performance.now();
|
|
451
459
|
const semantic = program.getSemanticDiagnostics();
|
|
452
460
|
// Declaration emit that computed signatures while checking counts as emit time, as in TypeScript 7.1.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Type } from './checker-types.js';
|
|
2
|
+
export declare class ExprCheckRecord {
|
|
3
|
+
/** The node id of the check at each entry, plus one; zero where no check is recorded. */
|
|
4
|
+
private readonly nodeIds;
|
|
5
|
+
private readonly modes;
|
|
6
|
+
private readonly types;
|
|
7
|
+
/** The type the last completed check of the node under `mode` produced, if the entry holds it. */
|
|
8
|
+
get(nodeId: number, mode: number): Type | undefined;
|
|
9
|
+
/** Records that a check of the node under `mode` produced `type`. */
|
|
10
|
+
set(nodeId: number, mode: number, type: Type): void;
|
|
11
|
+
}
|