tsc-ts 0.1.1 → 0.1.3
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 +7 -1
- package/dist/api/compiler/ast.d.ts +6 -0
- package/dist/api/compiler/ast.js +19 -3
- package/dist/api/compiler/checker-functions.js +5 -1
- package/dist/api/compiler/checker-grammar.d.ts +39 -4
- package/dist/api/compiler/checker-grammar.js +239 -75
- package/dist/api/compiler/checker-heritage.js +20 -14
- package/dist/api/compiler/checker-modules.js +4 -2
- package/dist/api/compiler/checker-narrowing.d.ts +7 -0
- package/dist/api/compiler/checker-narrowing.js +31 -4
- package/dist/api/compiler/checker-source-file.js +16 -1
- package/dist/api/compiler/checker-statements.js +11 -2
- package/dist/api/compiler/checker-type-factory.js +17 -7
- package/dist/api/compiler/checker-type-nodes.d.ts +1 -1
- package/dist/api/compiler/checker-type-nodes.js +5 -5
- package/dist/api/compiler/checker-unused.js +15 -10
- package/dist/api/compiler/checker.d.ts +4 -0
- package/dist/api/compiler/checker.js +6 -0
- package/dist/api/compiler/file-loader.d.ts +5 -0
- package/dist/api/compiler/file-loader.js +7 -0
- package/dist/api/compiler/program-checker.d.ts +18 -0
- package/dist/api/compiler/program-checker.js +27 -0
- package/package.json +14 -9
- package/src/compiler/ast.ts +20 -3
- package/src/compiler/checker-functions.ts +5 -0
- package/src/compiler/checker-grammar.ts +247 -88
- package/src/compiler/checker-heritage.ts +31 -17
- package/src/compiler/checker-modules.ts +4 -2
- package/src/compiler/checker-narrowing.ts +30 -4
- package/src/compiler/checker-source-file.ts +16 -1
- package/src/compiler/checker-statements.ts +10 -2
- package/src/compiler/checker-type-factory.ts +14 -7
- package/src/compiler/checker-type-nodes.ts +5 -5
- package/src/compiler/checker-unused.ts +13 -8
- package/src/compiler/checker.ts +6 -0
- package/src/compiler/file-loader.ts +8 -0
- package/src/compiler/parallel-check.ts +13 -1
- package/src/compiler/parse-thread.ts +24 -2
- package/src/compiler/program-checker.ts +28 -0
- package/src/compiler/run-records.ts +12 -5
- package/src/compiler/tsc-compile.ts +10 -1
|
@@ -668,17 +668,18 @@ function areTypeParametersIdentical(c, lists, targetParameters) {
|
|
|
668
668
|
* (with `checkPrivateNames`) private names shared by static and instance members.
|
|
669
669
|
*/
|
|
670
670
|
export function checkObjectTypeForDuplicateDeclarations(c, node, checkPrivateNames) {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
671
|
+
// Only a symbol with several declarations can be a duplicate, so the maps are created for the first one.
|
|
672
|
+
let instanceNames;
|
|
673
|
+
let staticNames;
|
|
674
|
+
let privateNames;
|
|
674
675
|
const nodeInAmbientContext = (node.flags & 8388608 /* NodeFlags.Ambient */) !== 0;
|
|
675
676
|
for (const member of getMembers(node).nodes) {
|
|
676
677
|
if (member.kind === 178 /* SyntaxKind.Constructor */) {
|
|
677
678
|
for (const param of getParameters(member).nodes)
|
|
678
679
|
if (isParameterPropertyDeclaration(param, member) && !isBindingPattern(getName(param))) {
|
|
679
680
|
const symbol = getSymbolOfDeclaration(c, param);
|
|
680
|
-
if (symbol !== undefined)
|
|
681
|
-
checkPropertyOrAccessor(c, node, instanceNames, symbol, 1 /* MemberKind.Property */, false);
|
|
681
|
+
if (symbol !== undefined && declarationCount(symbol) > 1)
|
|
682
|
+
checkPropertyOrAccessor(c, node, (instanceNames ??= new Map()), symbol, 1 /* MemberKind.Property */, false);
|
|
682
683
|
}
|
|
683
684
|
continue;
|
|
684
685
|
}
|
|
@@ -688,17 +689,22 @@ export function checkObjectTypeForDuplicateDeclarations(c, node, checkPrivateNam
|
|
|
688
689
|
const memberIsStatic = hasStaticModifier(member);
|
|
689
690
|
if (!nodeInAmbientContext && memberIsStatic && symbol.name === 'prototype')
|
|
690
691
|
c.error(getName(member), 838 /* Diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1 */, symbol.name, symbolToString(c, getSymbolOfDeclaration(c, node)));
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
692
|
+
if (declarationCount(symbol) > 1) {
|
|
693
|
+
const names = memberIsStatic
|
|
694
|
+
? (staticNames ??= new Map())
|
|
695
|
+
: (instanceNames ??= new Map());
|
|
696
|
+
const hasAccessorModifier = hasSyntacticModifier(member, 512 /* ModifierFlags.Accessor */);
|
|
697
|
+
if ((member.kind === 174 /* SyntaxKind.PropertyDeclaration */ && !hasAccessorModifier) ||
|
|
698
|
+
member.kind === 173 /* SyntaxKind.PropertySignature */)
|
|
699
|
+
checkPropertyOrAccessor(c, node, names, symbol, 1 /* MemberKind.Property */, memberIsStatic);
|
|
700
|
+
else if (member.kind === 179 /* SyntaxKind.GetAccessor */ ||
|
|
701
|
+
member.kind === 180 /* SyntaxKind.SetAccessor */ ||
|
|
702
|
+
(member.kind === 174 /* SyntaxKind.PropertyDeclaration */ && hasAccessorModifier))
|
|
703
|
+
checkPropertyOrAccessor(c, node, names, symbol, 2 /* MemberKind.Accessor */, memberIsStatic);
|
|
704
|
+
}
|
|
700
705
|
const name = getName(member);
|
|
701
706
|
if (checkPrivateNames && name !== undefined && name.kind === 80 /* SyntaxKind.PrivateIdentifier */) {
|
|
707
|
+
privateNames ??= new Map();
|
|
702
708
|
let flags = privateNames.get(symbol.name) ?? 0;
|
|
703
709
|
if (flags === 3)
|
|
704
710
|
continue;
|
|
@@ -1525,7 +1525,8 @@ function getSymbolFlagsExcludingTypeOnly(c, symbol) {
|
|
|
1525
1525
|
}
|
|
1526
1526
|
/** `getSymbolFlags`, optionally stopping at type-only aliases or leaving out the symbol's own flags. */
|
|
1527
1527
|
function getSymbolFlagsEx(c, symbol, excludeTypeOnlyMeanings, excludeLocalMeanings) {
|
|
1528
|
-
|
|
1528
|
+
// Only a chain of aliases needs the set, so most calls never create it.
|
|
1529
|
+
let seen;
|
|
1529
1530
|
let flags = excludeLocalMeanings ? 0 /* SymbolFlags.None */ : symbol.flags;
|
|
1530
1531
|
while ((symbol.flags & 2097152 /* SymbolFlags.Alias */) !== 0) {
|
|
1531
1532
|
if (excludeTypeOnlyMeanings && getTypeOnlyAliasDeclaration(c, symbol) !== undefined)
|
|
@@ -1534,8 +1535,9 @@ function getSymbolFlagsEx(c, symbol, excludeTypeOnlyMeanings, excludeLocalMeanin
|
|
|
1534
1535
|
if (target === c.unknownSymbol)
|
|
1535
1536
|
return 1073741823 /* SymbolFlags.All */;
|
|
1536
1537
|
if ((target.flags & 2097152 /* SymbolFlags.Alias */) !== 0) {
|
|
1537
|
-
if (target === symbol || seen
|
|
1538
|
+
if (target === symbol || seen?.has(target))
|
|
1538
1539
|
break;
|
|
1540
|
+
seen ??= new Set();
|
|
1539
1541
|
seen.add(symbol);
|
|
1540
1542
|
seen.add(target);
|
|
1541
1543
|
}
|
|
@@ -112,6 +112,13 @@ export declare function getEvolvingArrayType(c: Checker, elementType: Type): Typ
|
|
|
112
112
|
export declare function isEvolvingArrayOperationTarget(c: Checker, node: Node): boolean;
|
|
113
113
|
/** The array type an evolving array settles on; `any[]` while it has no elements. */
|
|
114
114
|
export declare function finalizeEvolvingArrayType(c: Checker, t: Type): Type;
|
|
115
|
+
/**
|
|
116
|
+
* Ends the narrowing stopped in `body`, whose checks have finished: what follows the body starts over.
|
|
117
|
+
* A walk that stopped in another body keeps its body's narrowing stopped.
|
|
118
|
+
*/
|
|
119
|
+
export declare function endFlowAnalysisStop(c: Checker, body: Node): void;
|
|
120
|
+
/** Whether `node` is the body of a function or a module, where flow analysis starts over (flowAnalysisDisabled). */
|
|
121
|
+
export declare function isFunctionOrModuleBlock(node: Node): boolean;
|
|
115
122
|
/**
|
|
116
123
|
* The type of `symbol` at `location`. A destructured variable of a const declaration or unassigned
|
|
117
124
|
* parameter is narrowed by checks of its siblings: in `const { kind, payload } = action`, testing
|
|
@@ -182,7 +182,7 @@ export function getFlowTypeOfReference(c, reference, declaredType, initialType,
|
|
|
182
182
|
}
|
|
183
183
|
/** `getFlowTypeOfReference` at `flowNode`, for pseudo-references such as binding patterns. */
|
|
184
184
|
export function getFlowTypeOfReferenceAt(c, reference, declaredType, initialType, flowContainer, flowNode) {
|
|
185
|
-
if (c.flowAnalysisDisabled)
|
|
185
|
+
if (c.flowAnalysisDisabled && isInFlowAnalysisStop(c, reference))
|
|
186
186
|
return c.errorType;
|
|
187
187
|
if (flowNode === undefined)
|
|
188
188
|
return declaredType;
|
|
@@ -211,7 +211,7 @@ export function getFlowTypeOfReferenceAt(c, reference, declaredType, initialType
|
|
|
211
211
|
f.steps >= minFlowWalkSteps &&
|
|
212
212
|
!f.incomplete &&
|
|
213
213
|
!f.positional &&
|
|
214
|
-
!c.flowAnalysisDisabled &&
|
|
214
|
+
!(c.flowAnalysisDisabled && isInFlowAnalysisStop(c, reference)) &&
|
|
215
215
|
c.resolutionCycleCount === cycles) {
|
|
216
216
|
const walk = f.walk;
|
|
217
217
|
if (walk !== undefined) {
|
|
@@ -248,6 +248,7 @@ function complete(f, t) {
|
|
|
248
248
|
export function getTypeAtFlowNode(c, f, start) {
|
|
249
249
|
if (f.depth === 2000) {
|
|
250
250
|
c.flowAnalysisDisabled = true;
|
|
251
|
+
c.flowAnalysisDisabledBody = getContainingFlowBody(f.reference);
|
|
251
252
|
reportFlowControlError(c, f.reference);
|
|
252
253
|
return complete(f, c.errorType);
|
|
253
254
|
}
|
|
@@ -2759,17 +2760,43 @@ function getContextFreeTypeOfExpression(c, node) {
|
|
|
2759
2760
|
links.contextFreeType = t;
|
|
2760
2761
|
return t;
|
|
2761
2762
|
}
|
|
2762
|
-
|
|
2763
|
+
/** The body whose walk reached the flow limit, or undefined when no body is stopped. */
|
|
2764
|
+
function getContainingFlowBody(node) {
|
|
2763
2765
|
let block = node;
|
|
2764
2766
|
while (block !== undefined && !isFunctionOrModuleBlock(block))
|
|
2765
2767
|
block = block.parent;
|
|
2768
|
+
return block;
|
|
2769
|
+
}
|
|
2770
|
+
/** Whether `node` is in the body whose walk reached the flow limit, or in a body it contains. */
|
|
2771
|
+
function isInFlowAnalysisStop(c, node) {
|
|
2772
|
+
const stop = c.flowAnalysisDisabledBody;
|
|
2773
|
+
if (stop === undefined)
|
|
2774
|
+
return false;
|
|
2775
|
+
for (let n = node; n !== undefined; n = n.parent)
|
|
2776
|
+
if (n === stop)
|
|
2777
|
+
return true;
|
|
2778
|
+
return false;
|
|
2779
|
+
}
|
|
2780
|
+
/**
|
|
2781
|
+
* Ends the narrowing stopped in `body`, whose checks have finished: what follows the body starts over.
|
|
2782
|
+
* A walk that stopped in another body keeps its body's narrowing stopped.
|
|
2783
|
+
*/
|
|
2784
|
+
export function endFlowAnalysisStop(c, body) {
|
|
2785
|
+
if (c.flowAnalysisDisabledBody !== body)
|
|
2786
|
+
return;
|
|
2787
|
+
c.flowAnalysisDisabled = false;
|
|
2788
|
+
c.flowAnalysisDisabledBody = undefined;
|
|
2789
|
+
}
|
|
2790
|
+
function reportFlowControlError(c, node) {
|
|
2791
|
+
const block = getContainingFlowBody(node);
|
|
2766
2792
|
if (block === undefined)
|
|
2767
2793
|
return;
|
|
2768
2794
|
const file = getSourceFileOfNode(node);
|
|
2769
2795
|
const span = getRangeOfTokenAtPosition(file, getStatements(block).pos);
|
|
2770
2796
|
c.addDiagnostic(new Diagnostic(file.diagnosticFile(), span.pos, span.end, 724 /* Diagnostics.The_containing_function_or_module_body_is_too_large_for_control_flow_analysis */, []));
|
|
2771
2797
|
}
|
|
2772
|
-
function
|
|
2798
|
+
/** Whether `node` is the body of a function or a module, where flow analysis starts over (flowAnalysisDisabled). */
|
|
2799
|
+
export function isFunctionOrModuleBlock(node) {
|
|
2773
2800
|
return (node.kind === 308 /* SyntaxKind.SourceFile */ ||
|
|
2774
2801
|
node.kind === 270 /* SyntaxKind.ModuleBlock */ ||
|
|
2775
2802
|
(node.kind === 243 /* SyntaxKind.Block */ && node.parent !== undefined && isFunctionLike(node.parent)));
|
|
@@ -43,6 +43,11 @@ import { checkContextualDeprecations, checkDeprecatedTypeReference } from './che
|
|
|
43
43
|
* identifiers, which need the whole file checked first.
|
|
44
44
|
*/
|
|
45
45
|
export function checkSourceFile(c, file, checkUnused = false) {
|
|
46
|
+
// A source file is a module body: narrowing stopped by a body too large for control flow analysis
|
|
47
|
+
// (flowAnalysisDisabled, checker-narrowing.ts) starts over in the next check. A checker checks many files
|
|
48
|
+
// (parallel-check.ts), so its diagnostics of a file must not depend on the files it checked before it.
|
|
49
|
+
c.flowAnalysisDisabled = false;
|
|
50
|
+
c.flowAnalysisDisabledBody = undefined;
|
|
46
51
|
const links = c.nodeLinks(file);
|
|
47
52
|
if ((links.flags & 1 /* NodeCheckFlags.TypeChecked */) === 0) {
|
|
48
53
|
links.flags |= 1 /* NodeCheckFlags.TypeChecked */;
|
|
@@ -52,6 +57,9 @@ export function checkSourceFile(c, file, checkUnused = false) {
|
|
|
52
57
|
links.flags |= 2 /* NodeCheckFlags.UnusedChecked */;
|
|
53
58
|
checkUnusedIdentifiers(c, file);
|
|
54
59
|
}
|
|
60
|
+
// Every body of the file has finished its checks; a stop recorded for one of them ends with the file.
|
|
61
|
+
c.flowAnalysisDisabled = false;
|
|
62
|
+
c.flowAnalysisDisabledBody = undefined;
|
|
55
63
|
}
|
|
56
64
|
function checkSourceFileWorker(c, file) {
|
|
57
65
|
c.fileBeingChecked = file;
|
|
@@ -89,6 +97,10 @@ function checkSourceFileWorker(c, file) {
|
|
|
89
97
|
*/
|
|
90
98
|
export function checkSourceFileRange(c, file, start, end) {
|
|
91
99
|
const statements = getStatements(file).nodes;
|
|
100
|
+
// A range of a file's statements is part of its module body: narrowing stopped by a body too large for
|
|
101
|
+
// control flow analysis (flowAnalysisDisabled, checker-narrowing.ts) starts over in the next range.
|
|
102
|
+
c.flowAnalysisDisabled = false;
|
|
103
|
+
c.flowAnalysisDisabledBody = undefined;
|
|
92
104
|
c.fileBeingChecked = file;
|
|
93
105
|
for (let i = start; i < end; i++)
|
|
94
106
|
checkSourceElement(c, statements[i]);
|
|
@@ -106,6 +118,9 @@ export function checkSourceFileRange(c, file, start, end) {
|
|
|
106
118
|
produceDeferredDiagnostics(c);
|
|
107
119
|
// Deferred nodes of a later range are queued again (checkNodeDeferred).
|
|
108
120
|
c.nodeLinks(file).deferredNodes = undefined;
|
|
121
|
+
// The range's bodies have finished their checks; a stop recorded for one of them ends with the range.
|
|
122
|
+
c.flowAnalysisDisabled = false;
|
|
123
|
+
c.flowAnalysisDisabledBody = undefined;
|
|
109
124
|
return c.diagnostics.forFile(file.fileName).length > 0;
|
|
110
125
|
}
|
|
111
126
|
/**
|
|
@@ -520,7 +535,7 @@ function checkTypeMemberAccessor(c, node) {
|
|
|
520
535
|
/** Variadic tuple elements must be array-like. */
|
|
521
536
|
function checkTupleRestElements(c, node) {
|
|
522
537
|
for (const e of node.elements.nodes) {
|
|
523
|
-
if ((getTupleElementFlags(
|
|
538
|
+
if ((getTupleElementFlags(e) & 8 /* ElementFlags.Variadic */) === 0)
|
|
524
539
|
continue;
|
|
525
540
|
if (!isArrayLikeType(c, getTypeFromTypeNode(c, getType(e)))) {
|
|
526
541
|
c.error(e, 732 /* Diagnostics.A_rest_element_type_must_be_an_array_type */);
|
|
@@ -7,7 +7,7 @@ import { checkIteratedTypeOrElementType } from './checker-iteration.js';
|
|
|
7
7
|
import { checkDestructuringAssignment } from './checker-destructuring.js';
|
|
8
8
|
import { checkReferenceExpression, checkTestingKnownTruthyType, checkTruthinessExpression, isTypeEqualityComparableTo, } from './checker-operators.js';
|
|
9
9
|
import { checkTypeComparableTo, isTypeAssignableTo } from './relations.js';
|
|
10
|
-
import { isReachableFlowNode } from './checker-narrowing.js';
|
|
10
|
+
import { endFlowAnalysisStop, isFunctionOrModuleBlock, isReachableFlowNode } from './checker-narrowing.js';
|
|
11
11
|
import { getIndexType, isTypeAssignableToKindEx as isTypeAssignableToKind } from './checker-type-operators.js';
|
|
12
12
|
import { getExtractStringType } from './checker-symbol-types.js';
|
|
13
13
|
import { checkSourceElement } from './checker-source-file.js';
|
|
@@ -21,8 +21,17 @@ import { checkExternalEmitHelpers } from './checker-emit-helpers.js';
|
|
|
21
21
|
import { typeToString } from './type-printer.js';
|
|
22
22
|
import { getNonNullableType, hasTypeFacts } from './checker-flow.js';
|
|
23
23
|
export function checkBlock(c, node) {
|
|
24
|
-
|
|
24
|
+
const statements = getStatements(node).nodes;
|
|
25
|
+
if (!isFunctionOrModuleBlock(node)) {
|
|
26
|
+
for (const s of statements)
|
|
27
|
+
checkSourceElement(c, s);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// A body too large for control flow analysis stops narrowing in the rest of that body only
|
|
31
|
+
// (flowAnalysisDisabled, checker-narrowing.ts); what follows the body starts over.
|
|
32
|
+
for (const s of statements)
|
|
25
33
|
checkSourceElement(c, s);
|
|
34
|
+
endFlowAnalysisStop(c, node);
|
|
26
35
|
}
|
|
27
36
|
export function checkExpressionStatement(c, node) {
|
|
28
37
|
checkExpression(c, getExpression(node));
|
|
@@ -1749,18 +1749,27 @@ export function intersectTypes(c, type1, type2) {
|
|
|
1749
1749
|
export function getIntersectionType(c, types) {
|
|
1750
1750
|
return getIntersectionTypeEx(c, types, 0 /* IntersectionFlags.None */, undefined);
|
|
1751
1751
|
}
|
|
1752
|
+
/**
|
|
1753
|
+
* The distinct types of an intersection, in the order they were added. Most intersections have a few
|
|
1754
|
+
* types, which a scan of `values` finds faster than a `Set` costs to build, so the set is created only
|
|
1755
|
+
* once the list grows past `INDEX_AFTER`.
|
|
1756
|
+
*/
|
|
1752
1757
|
class OrderedTypeSet {
|
|
1758
|
+
static INDEX_AFTER = 8;
|
|
1753
1759
|
values = [];
|
|
1754
|
-
|
|
1760
|
+
index;
|
|
1755
1761
|
includes = 0;
|
|
1756
1762
|
has(t) {
|
|
1757
|
-
return this.
|
|
1763
|
+
return this.index !== undefined ? this.index.has(t) : this.values.includes(t);
|
|
1758
1764
|
}
|
|
1759
1765
|
add(t) {
|
|
1760
|
-
if (
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1766
|
+
if (this.has(t))
|
|
1767
|
+
return;
|
|
1768
|
+
this.values.push(t);
|
|
1769
|
+
if (this.index !== undefined)
|
|
1770
|
+
this.index.add(t);
|
|
1771
|
+
else if (this.values.length > OrderedTypeSet.INDEX_AFTER)
|
|
1772
|
+
this.index = new Set(this.values);
|
|
1764
1773
|
}
|
|
1765
1774
|
}
|
|
1766
1775
|
function addTypesToIntersection(c, set, types) {
|
|
@@ -2126,7 +2135,8 @@ function getCrossProductIntersections(c, types, flags) {
|
|
|
2126
2135
|
*/
|
|
2127
2136
|
function addCrossProductIntersections(c, types, flags, constituents, index, unit, intersections) {
|
|
2128
2137
|
if (index === types.length) {
|
|
2129
|
-
|
|
2138
|
+
// getIntersectionTypeEx copies the types it keeps, so the buffer is reused for the next combination.
|
|
2139
|
+
const t = getIntersectionTypeEx(c, constituents, flags, undefined);
|
|
2130
2140
|
if ((t.flags & 262144 /* TypeFlags.Never */) === 0)
|
|
2131
2141
|
intersections.push(t);
|
|
2132
2142
|
return;
|
|
@@ -20,7 +20,7 @@ export declare function isTypeAlias(node: Node): boolean;
|
|
|
20
20
|
export declare function getAliasForTypeNode(c: Checker, node: Node): TypeAlias | undefined;
|
|
21
21
|
export declare function getAliasSymbolForTypeNode(c: Checker, node: Node): Symbol | undefined;
|
|
22
22
|
export declare function getTypeAliasInstantiation(c: Checker, symbol: Symbol, typeArguments: Type[], alias: TypeAlias | undefined): Type;
|
|
23
|
-
export declare function getTupleElementFlags(
|
|
23
|
+
export declare function getTupleElementFlags(node: Node): ElementFlags;
|
|
24
24
|
/** Type arguments of a deferred reference from its node. */
|
|
25
25
|
export declare function getTypeArgumentsOfDeferredReference(c: Checker, node: Node, target: InterfaceType): Type[];
|
|
26
26
|
/** The symbol an identifier resolves to, cached on the identifier. */
|
|
@@ -711,7 +711,7 @@ function getTypeFromTypeQueryNode(c, node) {
|
|
|
711
711
|
}
|
|
712
712
|
return type;
|
|
713
713
|
}
|
|
714
|
-
export function getTupleElementFlags(
|
|
714
|
+
export function getTupleElementFlags(node) {
|
|
715
715
|
switch (node.kind) {
|
|
716
716
|
case 192 /* SyntaxKind.OptionalType */:
|
|
717
717
|
return 2 /* ElementFlags.Optional */;
|
|
@@ -730,8 +730,8 @@ export function getTupleElementFlags(c, node) {
|
|
|
730
730
|
}
|
|
731
731
|
return 1 /* ElementFlags.Required */;
|
|
732
732
|
}
|
|
733
|
-
function getTupleElementInfo(
|
|
734
|
-
return new TupleElementInfo(getTupleElementFlags(
|
|
733
|
+
function getTupleElementInfo(node) {
|
|
734
|
+
return new TupleElementInfo(getTupleElementFlags(node), node.kind === 204 /* SyntaxKind.NamedTupleMember */ || node.kind === 171 /* SyntaxKind.Parameter */ ? node : undefined);
|
|
735
735
|
}
|
|
736
736
|
function getArrayElementTypeNode(node) {
|
|
737
737
|
switch (node.kind) {
|
|
@@ -760,7 +760,7 @@ function getArrayOrTupleTargetType(c, node) {
|
|
|
760
760
|
return readonly ? c.globalReadonlyArrayType : c.globalArrayType;
|
|
761
761
|
const elementInfos = [];
|
|
762
762
|
for (const e of node.elements.nodes)
|
|
763
|
-
elementInfos.push(getTupleElementInfo(
|
|
763
|
+
elementInfos.push(getTupleElementInfo(e));
|
|
764
764
|
return getTupleTargetType(c, elementInfos, readonly);
|
|
765
765
|
}
|
|
766
766
|
function getTypeFromArrayOrTupleTypeNode(c, node) {
|
|
@@ -787,7 +787,7 @@ function getTypeFromArrayOrTupleTypeNode(c, node) {
|
|
|
787
787
|
}
|
|
788
788
|
function hasVariadicTupleElement(c, node) {
|
|
789
789
|
for (const e of node.elements.nodes)
|
|
790
|
-
if ((getTupleElementFlags(
|
|
790
|
+
if ((getTupleElementFlags(e) & 8 /* ElementFlags.Variadic */) !== 0)
|
|
791
791
|
return true;
|
|
792
792
|
return false;
|
|
793
793
|
}
|
|
@@ -326,8 +326,9 @@ function checkUnusedLocalsAndParameters(c, node) {
|
|
|
326
326
|
const locals = getLocals(node);
|
|
327
327
|
if (locals === undefined)
|
|
328
328
|
return;
|
|
329
|
-
|
|
330
|
-
|
|
329
|
+
// Created on the first unused declaration: most scopes have none.
|
|
330
|
+
let variableParents;
|
|
331
|
+
let importClauses;
|
|
331
332
|
for (const local of locals.values()) {
|
|
332
333
|
const referenceKinds = c.symbolReferenceKinds.get(getSymbolId(local));
|
|
333
334
|
if ((local.flags & 262144 /* SymbolFlags.TypeParameter */) !== 0) {
|
|
@@ -343,6 +344,7 @@ function checkUnusedLocalsAndParameters(c, node) {
|
|
|
343
344
|
case 262 /* SyntaxKind.VariableDeclaration */:
|
|
344
345
|
case 171 /* SyntaxKind.Parameter */:
|
|
345
346
|
case 210 /* SyntaxKind.BindingElement */:
|
|
347
|
+
variableParents ??= new Set();
|
|
346
348
|
variableParents.add(getRootDeclaration(declaration).parent);
|
|
347
349
|
break;
|
|
348
350
|
case 275 /* SyntaxKind.ImportClause */:
|
|
@@ -350,6 +352,7 @@ function checkUnusedLocalsAndParameters(c, node) {
|
|
|
350
352
|
case 276 /* SyntaxKind.NamespaceImport */:
|
|
351
353
|
if (!isIdentifierThatStartsWithUnderscore(getName(declaration))) {
|
|
352
354
|
const importClause = importClauseFromImported(declaration);
|
|
355
|
+
importClauses ??= new Map();
|
|
353
356
|
const unuseds = importClauses.get(importClause);
|
|
354
357
|
if (unuseds === undefined)
|
|
355
358
|
importClauses.set(importClause, [declaration]);
|
|
@@ -363,14 +366,16 @@ function checkUnusedLocalsAndParameters(c, node) {
|
|
|
363
366
|
}
|
|
364
367
|
}
|
|
365
368
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
369
|
+
if (variableParents !== undefined)
|
|
370
|
+
for (const declaration of variableParents) {
|
|
371
|
+
if (declaration.kind === 263 /* SyntaxKind.VariableDeclarationList */)
|
|
372
|
+
reportUnusedVariables(c, declaration, declaration.declarations.nodes);
|
|
373
|
+
else
|
|
374
|
+
reportUnusedVariableDeclarations(c, getParameters(declaration).nodes);
|
|
375
|
+
}
|
|
376
|
+
if (importClauses !== undefined)
|
|
377
|
+
for (const [declaration, unuseds] of importClauses)
|
|
378
|
+
reportUnusedImports(c, declaration, unuseds);
|
|
374
379
|
}
|
|
375
380
|
function reportUnusedLocal(c, node, name) {
|
|
376
381
|
const message = isTypeDeclaration(node)
|
|
@@ -155,6 +155,8 @@ export declare class Checker implements TypeChecking {
|
|
|
155
155
|
readonly noUncheckedIndexedAccess: boolean;
|
|
156
156
|
typeCount: number;
|
|
157
157
|
signatureCount: number;
|
|
158
|
+
/** Transient symbols the checker created (statistics), as tsgo's `Checker.SymbolCount`. */
|
|
159
|
+
symbolCount: number;
|
|
158
160
|
/** Positions of members by name in the tables and lists that lazily instantiated members come from. */
|
|
159
161
|
readonly memberPositionsInLists: Map<Symbol[], Map<string, number>>;
|
|
160
162
|
/** The property names of the last instantiation of each such list whose table is built on demand. */
|
|
@@ -464,6 +466,8 @@ export declare class Checker implements TypeChecking {
|
|
|
464
466
|
/** `{ meta: ImportMeta }`, the type of `import.meta` for symbol queries. */
|
|
465
467
|
importMetaExpressionType: Type | undefined;
|
|
466
468
|
flowAnalysisDisabled: boolean;
|
|
469
|
+
/** The body whose walk reached the flow limit (flowAnalysisDisabled), until its checks finish. */
|
|
470
|
+
flowAnalysisDisabledBody: Node | undefined;
|
|
467
471
|
inlineLevel: number;
|
|
468
472
|
/**
|
|
469
473
|
* Shared flow nodes cached by the walks in progress, with their types: the first
|
|
@@ -282,6 +282,8 @@ export class Checker {
|
|
|
282
282
|
// Counters for type and signature ids.
|
|
283
283
|
typeCount = 0;
|
|
284
284
|
signatureCount = 0;
|
|
285
|
+
/** Transient symbols the checker created (statistics), as tsgo's `Checker.SymbolCount`. */
|
|
286
|
+
symbolCount = 0;
|
|
285
287
|
/** Positions of members by name in the tables and lists that lazily instantiated members come from. */
|
|
286
288
|
memberPositionsInLists = new Map();
|
|
287
289
|
/** The property names of the last instantiation of each such list whose table is built on demand. */
|
|
@@ -610,6 +612,8 @@ export class Checker {
|
|
|
610
612
|
importMetaExpressionType = undefined;
|
|
611
613
|
// Control flow analysis
|
|
612
614
|
flowAnalysisDisabled = false;
|
|
615
|
+
/** The body whose walk reached the flow limit (flowAnalysisDisabled), until its checks finish. */
|
|
616
|
+
flowAnalysisDisabledBody = undefined;
|
|
613
617
|
inlineLevel = 0;
|
|
614
618
|
/**
|
|
615
619
|
* Shared flow nodes cached by the walks in progress, with their types: the first
|
|
@@ -982,10 +986,12 @@ export class Checker {
|
|
|
982
986
|
return new TypeParameter(this.nextTypeId(), symbol);
|
|
983
987
|
}
|
|
984
988
|
newSymbol(flags, name) {
|
|
989
|
+
this.symbolCount++;
|
|
985
990
|
const symbol = new Symbol(flags | 33554432 /* SymbolFlags.Transient */, name);
|
|
986
991
|
return symbol;
|
|
987
992
|
}
|
|
988
993
|
newSymbolWithCheckFlags(flags, name, checkFlags) {
|
|
994
|
+
this.symbolCount++;
|
|
989
995
|
const symbol = new Symbol(flags | 33554432 /* SymbolFlags.Transient */, name);
|
|
990
996
|
symbol.checkFlags = checkFlags;
|
|
991
997
|
return symbol;
|
|
@@ -29,6 +29,11 @@ export declare class CompilerHost extends ModuleResolutionHost {
|
|
|
29
29
|
readFile(path: string): string | undefined;
|
|
30
30
|
realpath(path: string): string;
|
|
31
31
|
getDirectories(path: string): readonly string[];
|
|
32
|
+
/**
|
|
33
|
+
* The metadata of the file `FileLoader` is parsing, which it computes from the file's package scope
|
|
34
|
+
* before it parses it; a host that walks the grammar of the parsed file reads it (parse-thread.ts).
|
|
35
|
+
*/
|
|
36
|
+
loadingSourceFileMetadata: SourceFileMetadata | undefined;
|
|
32
37
|
/** Parses a file, or returns `undefined` if it can't be read. */
|
|
33
38
|
getSourceFile(fileName: string, path: string, externalModuleIndicatorOptions: ExternalModuleIndicatorOptions): SourceFile | undefined;
|
|
34
39
|
/** The config of a referenced project, or `undefined` if it can't be read. */
|
|
@@ -51,6 +51,11 @@ export class CompilerHost extends ModuleResolutionHost {
|
|
|
51
51
|
getDirectories(path) {
|
|
52
52
|
return this.fs.getAccessibleEntries(path).directories;
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* The metadata of the file `FileLoader` is parsing, which it computes from the file's package scope
|
|
56
|
+
* before it parses it; a host that walks the grammar of the parsed file reads it (parse-thread.ts).
|
|
57
|
+
*/
|
|
58
|
+
loadingSourceFileMetadata = undefined;
|
|
54
59
|
/** Parses a file, or returns `undefined` if it can't be read. */
|
|
55
60
|
getSourceFile(fileName, path, externalModuleIndicatorOptions) {
|
|
56
61
|
// A file that parse threads prepared (parallel-parse.ts).
|
|
@@ -1054,6 +1059,8 @@ export class FileLoader {
|
|
|
1054
1059
|
? libFileMetadata
|
|
1055
1060
|
: (loaded?.metadata ?? this.loadSourceFileMetadata(task.normalizedFilePath));
|
|
1056
1061
|
const options = this.mapper.getCompilerOptionsForFile(task.path, task.normalizedFilePath);
|
|
1062
|
+
// For the host that walks the grammar of the file as it parses it (parse-thread.ts).
|
|
1063
|
+
this.host.loadingSourceFileMetadata = task.metadata;
|
|
1057
1064
|
const file = this.host.getSourceFile(task.normalizedFilePath, task.path, getExternalModuleIndicatorOptions(task.normalizedFilePath, options, task.metadata));
|
|
1058
1065
|
if (file === undefined)
|
|
1059
1066
|
return;
|
|
@@ -88,6 +88,18 @@ export declare class CheckedProgram {
|
|
|
88
88
|
createChecker(): Checker;
|
|
89
89
|
/** Frees the checker that reports the program's diagnostics (`disposeChecker`). */
|
|
90
90
|
disposeCheckers(): void;
|
|
91
|
+
/** Adds the counts a checker thread sent (`CheckerResult.counts`): types, instantiations, symbols. */
|
|
92
|
+
addCheckerCounts(counts: readonly number[]): void;
|
|
93
|
+
/**
|
|
94
|
+
* The types, instantiations and transient symbols of every checker of the program: this thread's and
|
|
95
|
+
* the checker threads', as tsgo's `Program.TypeCount`, `InstantiationCount` and `SymbolCount` add them up.
|
|
96
|
+
* Reading them doesn't create this thread's checker.
|
|
97
|
+
*/
|
|
98
|
+
checkerCounts(): {
|
|
99
|
+
types: number;
|
|
100
|
+
instantiations: number;
|
|
101
|
+
symbols: number;
|
|
102
|
+
};
|
|
91
103
|
getBindDiagnostics(file: SourceFile | undefined): Diagnostic[];
|
|
92
104
|
/**
|
|
93
105
|
* Diagnostics of checker threads (parallel-check.ts): the semantic diagnostics of each file by file
|
|
@@ -109,6 +121,12 @@ export declare class CheckedProgram {
|
|
|
109
121
|
*/
|
|
110
122
|
referenceThreads: number;
|
|
111
123
|
readonly parallelGlobalDiagnostics: Diagnostic[];
|
|
124
|
+
/** The types checker threads created (`CheckerResult.counts`), which `--diagnostics` adds to `checker`'s. */
|
|
125
|
+
threadTypeCount: number;
|
|
126
|
+
/** The instantiations checker threads made. */
|
|
127
|
+
threadInstantiations: number;
|
|
128
|
+
/** The transient symbols checker threads created. */
|
|
129
|
+
threadSymbolCount: number;
|
|
112
130
|
/**
|
|
113
131
|
* Whether the semantic diagnostics of a file include the global diagnostics its checker found while
|
|
114
132
|
* checking it, as an incremental program caches them (IncrementalProgram). Such a program doesn't report
|
|
@@ -176,6 +176,27 @@ export class CheckedProgram {
|
|
|
176
176
|
disposeChecker(this.reportingChecker);
|
|
177
177
|
this.reportingChecker = undefined;
|
|
178
178
|
}
|
|
179
|
+
/** Adds the counts a checker thread sent (`CheckerResult.counts`): types, instantiations, symbols. */
|
|
180
|
+
addCheckerCounts(counts) {
|
|
181
|
+
if (counts.length < 3)
|
|
182
|
+
return;
|
|
183
|
+
this.threadTypeCount += counts[0];
|
|
184
|
+
this.threadInstantiations += counts[1];
|
|
185
|
+
this.threadSymbolCount += counts[2];
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* The types, instantiations and transient symbols of every checker of the program: this thread's and
|
|
189
|
+
* the checker threads', as tsgo's `Program.TypeCount`, `InstantiationCount` and `SymbolCount` add them up.
|
|
190
|
+
* Reading them doesn't create this thread's checker.
|
|
191
|
+
*/
|
|
192
|
+
checkerCounts() {
|
|
193
|
+
const own = this.reportingChecker;
|
|
194
|
+
return {
|
|
195
|
+
types: (own === undefined ? 0 : own.typeCount) + this.threadTypeCount,
|
|
196
|
+
instantiations: (own === undefined ? 0 : own.totalInstantiations) + this.threadInstantiations,
|
|
197
|
+
symbols: (own === undefined ? 0 : own.symbolCount) + this.threadSymbolCount,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
179
200
|
getBindDiagnostics(file) {
|
|
180
201
|
return this.collect(file, (f) => f.bindDiagnostics);
|
|
181
202
|
}
|
|
@@ -199,6 +220,12 @@ export class CheckedProgram {
|
|
|
199
220
|
*/
|
|
200
221
|
referenceThreads = 1;
|
|
201
222
|
parallelGlobalDiagnostics = [];
|
|
223
|
+
/** The types checker threads created (`CheckerResult.counts`), which `--diagnostics` adds to `checker`'s. */
|
|
224
|
+
threadTypeCount = 0;
|
|
225
|
+
/** The instantiations checker threads made. */
|
|
226
|
+
threadInstantiations = 0;
|
|
227
|
+
/** The transient symbols checker threads created. */
|
|
228
|
+
threadSymbolCount = 0;
|
|
202
229
|
/**
|
|
203
230
|
* Whether the semantic diagnostics of a file include the global diagnostics its checker found while
|
|
204
231
|
* checking it, as an incremental program caches them (IncrementalProgram). Such a program doesn't report
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsc-ts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "The TypeScript 7 compiler, ported to TypeScript and compiled to a native executable.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -28,19 +28,24 @@
|
|
|
28
28
|
},
|
|
29
29
|
"./package.json": "./package.json"
|
|
30
30
|
},
|
|
31
|
-
"
|
|
31
|
+
"peerDependencies": {
|
|
32
32
|
"@scriptc/threads": "0.4.8"
|
|
33
33
|
},
|
|
34
|
+
"peerDependenciesMeta": {
|
|
35
|
+
"@scriptc/threads": {
|
|
36
|
+
"optional": true
|
|
37
|
+
}
|
|
38
|
+
},
|
|
34
39
|
"engines": {
|
|
35
40
|
"node": ">=20"
|
|
36
41
|
},
|
|
37
42
|
"optionalDependencies": {
|
|
38
|
-
"@tsc-ts/darwin-arm64": "0.1.
|
|
39
|
-
"@tsc-ts/darwin-x64": "0.1.
|
|
40
|
-
"@tsc-ts/linux-arm64-gnu": "0.1.
|
|
41
|
-
"@tsc-ts/linux-arm64-musl": "0.1.
|
|
42
|
-
"@tsc-ts/linux-x64-gnu": "0.1.
|
|
43
|
-
"@tsc-ts/linux-x64-musl": "0.1.
|
|
44
|
-
"@tsc-ts/win32-x64-msvc": "0.1.
|
|
43
|
+
"@tsc-ts/darwin-arm64": "0.1.3",
|
|
44
|
+
"@tsc-ts/darwin-x64": "0.1.3",
|
|
45
|
+
"@tsc-ts/linux-arm64-gnu": "0.1.3",
|
|
46
|
+
"@tsc-ts/linux-arm64-musl": "0.1.3",
|
|
47
|
+
"@tsc-ts/linux-x64-gnu": "0.1.3",
|
|
48
|
+
"@tsc-ts/linux-x64-musl": "0.1.3",
|
|
49
|
+
"@tsc-ts/win32-x64-msvc": "0.1.3"
|
|
45
50
|
}
|
|
46
51
|
}
|
package/src/compiler/ast.ts
CHANGED
|
@@ -209,9 +209,14 @@ export abstract class NodeVisitor {
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
// Native builds store `pos`, `end` and `id` as 32-bit integers when every write provably stores
|
|
213
|
-
// int32, so writes of values the compiler can't bound (parameters, the id counter) are
|
|
214
|
-
// with `| 0`; the values are always int32.
|
|
212
|
+
// Native builds store `pos`, `end` and `id` as 32-bit integers when every write provably stores
|
|
213
|
+
// an int32, so writes of values the compiler can't bound (parameters, the id counter) are
|
|
214
|
+
// coerced with `| 0`; the values are always int32.
|
|
215
|
+
//
|
|
216
|
+
// The fields of a node that the public API's node types declare are stored fields, not values
|
|
217
|
+
// computed from or packed into another field: a native build copies the stored fields of a node
|
|
218
|
+
// into a record when API code narrows one (`node as StringLiteralLike`), and a field behind an
|
|
219
|
+
// accessor is not copied.
|
|
215
220
|
export abstract class Node implements ProgramLifetime {
|
|
216
221
|
readonly kind: SyntaxKind;
|
|
217
222
|
flags: NodeFlags;
|
|
@@ -8244,6 +8249,7 @@ export const emptyCommentDirectives: readonly CommentDirective[] = [];
|
|
|
8244
8249
|
export const emptyPragmas: readonly Pragma[] = [];
|
|
8245
8250
|
export const emptyFileReferences: readonly FileReference[] = [];
|
|
8246
8251
|
export const emptyPatternAmbientModules: readonly PatternAmbientModule[] = [];
|
|
8252
|
+
const emptyNumbers: readonly number[] = [];
|
|
8247
8253
|
|
|
8248
8254
|
/** `list` with `item` appended: a new array when `list` is empty (it may be shared), else `list` itself. */
|
|
8249
8255
|
export function appendToList<T>(list: readonly T[], item: T): readonly T[] {
|
|
@@ -8320,6 +8326,14 @@ export class SourceFile extends Node {
|
|
|
8320
8326
|
/** UMD exports from `export as namespace N`. */
|
|
8321
8327
|
globalExports: SymbolTable | undefined;
|
|
8322
8328
|
|
|
8329
|
+
// Set by the grammar checks of a parse thread (checker-grammar.ts).
|
|
8330
|
+
/** The diagnostics the parse thread's grammar walk reported for this file. */
|
|
8331
|
+
grammarDiagnostics: Diagnostic[] | undefined;
|
|
8332
|
+
/** The nodes of this file whose grammar check needs the checker, in tree order. */
|
|
8333
|
+
grammarResidualNodes: Node[] | undefined;
|
|
8334
|
+
/** The blocks and statements that reported a statement in an ambient context. */
|
|
8335
|
+
grammarAmbientReports: readonly number[];
|
|
8336
|
+
|
|
8323
8337
|
constructor(
|
|
8324
8338
|
fileName: string,
|
|
8325
8339
|
path: string,
|
|
@@ -8373,6 +8387,9 @@ export class SourceFile extends Node {
|
|
|
8373
8387
|
this.symbolCount = 0;
|
|
8374
8388
|
this.patternAmbientModules = emptyPatternAmbientModules;
|
|
8375
8389
|
this.globalExports = undefined;
|
|
8390
|
+
this.grammarDiagnostics = undefined;
|
|
8391
|
+
this.grammarResidualNodes = undefined;
|
|
8392
|
+
this.grammarAmbientReports = emptyNumbers;
|
|
8376
8393
|
}
|
|
8377
8394
|
|
|
8378
8395
|
forEachChild(v: NodeVisitor): boolean {
|