tsc-ts 0.0.7 → 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.
- package/README.md +1 -1
- package/dist/api/compiler/checker-declaration-order.js +3 -2
- package/dist/api/compiler/checker-declared-types.js +6 -3
- package/dist/api/compiler/checker-deprecation.js +14 -13
- package/dist/api/compiler/checker-destructuring.js +3 -2
- package/dist/api/compiler/checker-members.js +6 -2
- 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-symbol-types.js +5 -5
- package/dist/api/compiler/checker-symbols.js +5 -2
- package/dist/api/compiler/checker.d.ts +6 -1
- package/dist/api/compiler/checker.js +9 -1
- package/dist/api/compiler/file-loader.d.ts +2 -2
- package/dist/api/compiler/file-loader.js +43 -23
- package/dist/api/compiler/link-tables.d.ts +7 -0
- package/dist/api/compiler/link-tables.js +22 -0
- package/dist/api/compiler/parser.d.ts +7 -0
- package/dist/api/compiler/parser.js +55 -32
- package/dist/api/compiler/program-checker.d.ts +18 -0
- package/dist/api/compiler/program-checker.js +35 -2
- 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/checker-declaration-order.ts +3 -2
- package/src/compiler/checker-declared-types.ts +6 -3
- package/src/compiler/checker-deprecation.ts +13 -11
- package/src/compiler/checker-destructuring.ts +11 -2
- package/src/compiler/checker-members.ts +6 -2
- package/src/compiler/checker-source-file.ts +34 -0
- package/src/compiler/checker-symbol-types.ts +14 -4
- package/src/compiler/checker-symbols.ts +6 -2
- package/src/compiler/checker.ts +8 -1
- package/src/compiler/file-loader.ts +49 -24
- package/src/compiler/link-tables.ts +32 -0
- package/src/compiler/parallel-check.ts +199 -20
- package/src/compiler/parser.ts +55 -32
- package/src/compiler/program-checker.ts +36 -2
- package/src/compiler/thread-entry.ts +16 -1
- 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`.
|
|
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`.
|
|
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
|
|
|
@@ -12,7 +12,7 @@ import { getExportSymbolOfValueSymbolIfExported } from './checker-symbols.js';
|
|
|
12
12
|
import { getBaseTypes, getDeclaredTypeOfSymbol } from './checker-declared-types.js';
|
|
13
13
|
import { getPropertyOfType } from './checker-members.js';
|
|
14
14
|
import { getFunctionFlags } from './checker-utilities.js';
|
|
15
|
-
import {
|
|
15
|
+
import { declarationAt, declarationCount } from './symbol.js';
|
|
16
16
|
/** Reports a block-scoped variable, class or enum resolved at `errorLocation` before its declaration. */
|
|
17
17
|
export function checkResolvedBlockScopedVariable(c, resolved, errorLocation) {
|
|
18
18
|
const result = getExportSymbolOfValueSymbolIfExported(c, resolved);
|
|
@@ -23,7 +23,8 @@ export function checkResolvedBlockScopedVariable(c, resolved, errorLocation) {
|
|
|
23
23
|
(result.flags & 32 /* SymbolFlags.Class */) !== 0)
|
|
24
24
|
return;
|
|
25
25
|
let declaration;
|
|
26
|
-
for (
|
|
26
|
+
for (let i = 0; i < declarationCount(result); i++) {
|
|
27
|
+
const d = declarationAt(result, i);
|
|
27
28
|
if (isBlockOrCatchScoped(d) || isClassLike(d) || d.kind === 267 /* SyntaxKind.EnumDeclaration */) {
|
|
28
29
|
declaration = d;
|
|
29
30
|
break;
|
|
@@ -20,7 +20,7 @@ import { getIndexedAccessType, isGenericMappedType } from './checker-type-operat
|
|
|
20
20
|
import { getSignatureInstantiation } from './checker-signatures.js';
|
|
21
21
|
import { evaluateEnumMember } from './checker-evaluator.js';
|
|
22
22
|
import { checkTypeAssignableTo, isTypeIdenticalTo } from './relations.js';
|
|
23
|
-
import { getDeclarations } from './symbol.js';
|
|
23
|
+
import { declarationAt, declarationCount, getDeclarations } from './symbol.js';
|
|
24
24
|
export { getParentOfSymbol };
|
|
25
25
|
export function getDeclaredTypeOfSymbol(c, symbol) {
|
|
26
26
|
return tryGetDeclaredTypeOfSymbol(c, symbol) ?? c.errorType;
|
|
@@ -752,11 +752,14 @@ export function getMinTypeArgumentCount(c, typeParameters) {
|
|
|
752
752
|
}
|
|
753
753
|
/** Whether a type parameter is declared with a default, without resolving it. */
|
|
754
754
|
function hasTypeParameterDefault(t) {
|
|
755
|
-
|
|
755
|
+
const symbol = t.symbol;
|
|
756
|
+
if (symbol === undefined)
|
|
756
757
|
return false;
|
|
757
|
-
for (
|
|
758
|
+
for (let i = 0; i < declarationCount(symbol); i++) {
|
|
759
|
+
const d = declarationAt(symbol, i);
|
|
758
760
|
if (d.kind === 169 /* SyntaxKind.TypeParameter */ && d.defaultType !== undefined)
|
|
759
761
|
return true;
|
|
762
|
+
}
|
|
760
763
|
return false;
|
|
761
764
|
}
|
|
762
765
|
export function fillMissingTypeArguments(c, typeArguments, typeParameters, minTypeArgumentCount, isJavaScriptImplicitAny) {
|
|
@@ -12,7 +12,7 @@ import { entityNameToString } from './checker-expressions.js';
|
|
|
12
12
|
import { isErrorType } from './checker-type-factory.js';
|
|
13
13
|
import { getPropertyOfType } from './checker-members.js';
|
|
14
14
|
import { signatureToString } from './type-printer.js';
|
|
15
|
-
import { declarationCount, getDeclarations } from './symbol.js';
|
|
15
|
+
import { declarationAt, declarationCount, getDeclarations } from './symbol.js';
|
|
16
16
|
/** Whether `declaration`, or the statement it belongs to, has a `@deprecated` JSDoc tag. */
|
|
17
17
|
export function isDeprecatedDeclaration(declaration) {
|
|
18
18
|
if ((getCombinedNodeFlags(declaration) & 67108864 /* NodeFlags.PossiblyContainsDeprecatedTag */) === 0)
|
|
@@ -38,24 +38,24 @@ function getJSDocDeprecatedTag(node) {
|
|
|
38
38
|
* members when all are.
|
|
39
39
|
*/
|
|
40
40
|
export function isDeprecatedSymbol(c, symbol) {
|
|
41
|
-
const
|
|
41
|
+
const count = declarationCount(symbol);
|
|
42
42
|
const parentSymbol = getParentOfSymbol(c, symbol);
|
|
43
|
-
if (parentSymbol !== undefined &&
|
|
43
|
+
if (parentSymbol !== undefined && count > 1)
|
|
44
44
|
return (parentSymbol.flags & 64 /* SymbolFlags.Interface */) !== 0
|
|
45
|
-
? someDeprecatedDeclaration(
|
|
46
|
-
: everyDeprecatedDeclaration(
|
|
45
|
+
? someDeprecatedDeclaration(symbol)
|
|
46
|
+
: everyDeprecatedDeclaration(symbol);
|
|
47
47
|
return ((symbol.valueDeclaration !== undefined && isDeprecatedDeclaration(symbol.valueDeclaration)) ||
|
|
48
|
-
(
|
|
48
|
+
(count !== 0 && everyDeprecatedDeclaration(symbol)));
|
|
49
49
|
}
|
|
50
|
-
function someDeprecatedDeclaration(
|
|
51
|
-
for (
|
|
52
|
-
if (isDeprecatedDeclaration(
|
|
50
|
+
function someDeprecatedDeclaration(symbol) {
|
|
51
|
+
for (let i = 0; i < declarationCount(symbol); i++)
|
|
52
|
+
if (isDeprecatedDeclaration(declarationAt(symbol, i)))
|
|
53
53
|
return true;
|
|
54
54
|
return false;
|
|
55
55
|
}
|
|
56
|
-
function everyDeprecatedDeclaration(
|
|
57
|
-
for (
|
|
58
|
-
if (!isDeprecatedDeclaration(
|
|
56
|
+
function everyDeprecatedDeclaration(symbol) {
|
|
57
|
+
for (let i = 0; i < declarationCount(symbol); i++)
|
|
58
|
+
if (!isDeprecatedDeclaration(declarationAt(symbol, i)))
|
|
59
59
|
return false;
|
|
60
60
|
return true;
|
|
61
61
|
}
|
|
@@ -290,7 +290,8 @@ export function checkDeprecatedTypeReference(c, node, type) {
|
|
|
290
290
|
const symbol = c.resolvedSymbols.get(node.id);
|
|
291
291
|
if (symbol === undefined)
|
|
292
292
|
return;
|
|
293
|
-
for (
|
|
293
|
+
for (let i = 0; i < declarationCount(symbol); i++) {
|
|
294
|
+
const d = declarationAt(symbol, i);
|
|
294
295
|
if (isTypeDeclaration(d) && isDeprecatedDeclaration(d)) {
|
|
295
296
|
addDeprecatedSuggestion(c, getDeprecatedSuggestionNode(node), getDeclarations(symbol), symbol.name);
|
|
296
297
|
return;
|
|
@@ -22,7 +22,7 @@ import { getNonNullableType, getTypeWithFacts, hasTypeFacts } from './checker-fl
|
|
|
22
22
|
import { sliceTupleType } from './checker-signatures.js';
|
|
23
23
|
import { getPropertyNameFromType, isTypeUsableAsPropertyName, maybeTypeOfKind } from './checker-utilities.js';
|
|
24
24
|
import { checkPropertyAccessibility } from './checker-property-access.js';
|
|
25
|
-
import { copyDeclarations,
|
|
25
|
+
import { copyDeclarations, declarationAt, declarationCount, getSymbolId, } from './symbol.js';
|
|
26
26
|
function isBindingPatternNode(node) {
|
|
27
27
|
return (node !== undefined &&
|
|
28
28
|
(node.kind === 207 /* SyntaxKind.ObjectBindingPattern */ || node.kind === 208 /* SyntaxKind.ArrayBindingPattern */));
|
|
@@ -548,7 +548,8 @@ export function isSpreadableProperty(prop) {
|
|
|
548
548
|
const notMethodOrAccessor = (prop.flags & (8192 /* SymbolFlags.Method */ | 32768 /* SymbolFlags.GetAccessor */ | 65536 /* SymbolFlags.SetAccessor */)) === 0;
|
|
549
549
|
let hasPrivateName = false;
|
|
550
550
|
let inClass = false;
|
|
551
|
-
for (
|
|
551
|
+
for (let i = 0; i < declarationCount(prop); i++) {
|
|
552
|
+
const d = declarationAt(prop, i);
|
|
552
553
|
if (isPrivateIdentifierClassElementDeclaration(d))
|
|
553
554
|
hasPrivateName = true;
|
|
554
555
|
if (d.parent !== undefined && isClassLike(d.parent))
|
|
@@ -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;
|
|
@@ -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)
|
|
@@ -26,7 +26,7 @@ import { getTypeForBindingElement, getTypeFromBindingPattern } from './checker-d
|
|
|
26
26
|
import { checkRightHandSideOfForOf } from './checker-statements.js';
|
|
27
27
|
import { getTypeWithFacts, hasTypeFacts, getNonNullableType } from './checker-flow.js';
|
|
28
28
|
import { getTypeOfModuleExportsSymbol, getWidenedTypeForAssignmentDeclaration } from './checker-javascript.js';
|
|
29
|
-
import { copyDeclarations, getDeclarations, getSymbolId } from './symbol.js';
|
|
29
|
+
import { copyDeclarations, declarationAt, declarationCount, getDeclarations, getSymbolId, } from './symbol.js';
|
|
30
30
|
export function getTypeOfSymbol(c, symbol) {
|
|
31
31
|
const checkFlags = symbol.checkFlags;
|
|
32
32
|
if ((checkFlags & 65536 /* CheckFlags.DeferredType */) !== 0)
|
|
@@ -748,11 +748,11 @@ export function isReadonlySymbol(c, symbol) {
|
|
|
748
748
|
(getDeclarationNodeFlagsFromSymbol(symbol) & 6 /* NodeFlags.Constant */) !== 0) ||
|
|
749
749
|
((symbol.flags & 98304 /* SymbolFlags.Accessor */) !== 0 && (symbol.flags & 65536 /* SymbolFlags.SetAccessor */) === 0) ||
|
|
750
750
|
(symbol.flags & 8 /* SymbolFlags.EnumMember */) !== 0 ||
|
|
751
|
-
someReadonlyAssignmentDeclaration(c,
|
|
751
|
+
someReadonlyAssignmentDeclaration(c, symbol));
|
|
752
752
|
}
|
|
753
|
-
function someReadonlyAssignmentDeclaration(c,
|
|
754
|
-
for (
|
|
755
|
-
if (isReadonlyAssignmentDeclaration(c,
|
|
753
|
+
function someReadonlyAssignmentDeclaration(c, symbol) {
|
|
754
|
+
for (let i = 0; i < declarationCount(symbol); i++)
|
|
755
|
+
if (isReadonlyAssignmentDeclaration(c, declarationAt(symbol, i)))
|
|
756
756
|
return true;
|
|
757
757
|
return false;
|
|
758
758
|
}
|
|
@@ -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;
|
|
@@ -1459,9 +1460,11 @@ export function symbolIsValue(c, symbol) {
|
|
|
1459
1460
|
function isDeclarationContainedBy(symbol, container) {
|
|
1460
1461
|
const declaration = symbol.valueDeclaration;
|
|
1461
1462
|
if (declaration !== undefined)
|
|
1462
|
-
for (
|
|
1463
|
+
for (let i = 0; i < declarationCount(container); i++) {
|
|
1464
|
+
const d = declarationAt(container, i);
|
|
1463
1465
|
if (declaration.pos >= d.pos && declaration.end <= d.end)
|
|
1464
1466
|
return true;
|
|
1467
|
+
}
|
|
1465
1468
|
return false;
|
|
1466
1469
|
}
|
|
1467
1470
|
/** Value members other than signatures and index signatures, declared ones first, each part ordered by declaration. */
|
|
@@ -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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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);
|
|
@@ -135,6 +135,8 @@ export declare class Parser extends ScannerErrorReporter {
|
|
|
135
135
|
reparseList: Node[];
|
|
136
136
|
private readonly reparseLists;
|
|
137
137
|
private reparseDepth;
|
|
138
|
+
private readonly listScratch;
|
|
139
|
+
private listDepth;
|
|
138
140
|
reparsedClones: Node[];
|
|
139
141
|
/** Nodes with eagerly parsed JSDoc, for rewinding. */
|
|
140
142
|
jsDocInfos: Node[];
|
|
@@ -209,6 +211,11 @@ export declare class Parser extends ScannerErrorReporter {
|
|
|
209
211
|
parseList(kind: ParsingContext, element: ListElement): NodeList;
|
|
210
212
|
/** The list, or undefined if an element parser returned undefined. */
|
|
211
213
|
parseDelimitedList(kind: ParsingContext, element: ListElement): NodeList | undefined;
|
|
214
|
+
/** The scratch array for a list at the next nesting depth, empty. */
|
|
215
|
+
private openList;
|
|
216
|
+
/** The elements collected in `list` (the scratch array from `openList`) as an array of their exact
|
|
217
|
+
* length, or the shared empty array; empties the scratch array for the next list at its depth. */
|
|
218
|
+
private closeList;
|
|
212
219
|
/** The list; a missing list if `opening` is absent; undefined if an element parser returned undefined. */
|
|
213
220
|
parseBracketedList(kind: ParsingContext, element: ListElement, opening: SyntaxKind, closing: SyntaxKind): NodeList | undefined;
|
|
214
221
|
parseEmptyNodeList(): NodeList;
|