tsc-ts 0.0.6 → 0.0.8
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 +57 -18
- package/dist/api/compiler/ast.js +134 -39
- package/dist/api/compiler/binder-utilities.js +2 -2
- package/dist/api/compiler/binder.js +6 -6
- package/dist/api/compiler/checker-calls.js +4 -4
- package/dist/api/compiler/checker-contextual.js +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-emit-helpers.d.ts +2 -1
- package/dist/api/compiler/checker-emit-helpers.js +5 -4
- package/dist/api/compiler/checker-grammar.js +5 -5
- package/dist/api/compiler/checker-inference.d.ts +20 -10
- package/dist/api/compiler/checker-inference.js +48 -25
- package/dist/api/compiler/checker-members.d.ts +27 -0
- package/dist/api/compiler/checker-members.js +165 -0
- package/dist/api/compiler/checker-modules.d.ts +14 -0
- package/dist/api/compiler/checker-modules.js +73 -1
- package/dist/api/compiler/checker-symbol-types.js +5 -5
- package/dist/api/compiler/checker-symbols.js +3 -1
- package/dist/api/compiler/checker.d.ts +16 -0
- package/dist/api/compiler/checker.js +17 -0
- package/dist/api/compiler/diagnostics.js +9 -5
- package/dist/api/compiler/parallel-parse.js +3 -1
- package/dist/api/compiler/parser.d.ts +7 -0
- package/dist/api/compiler/parser.js +73 -41
- package/dist/api/compiler/printer/factory-base.js +8 -8
- package/dist/api/compiler/printer/factory.js +4 -4
- package/dist/api/compiler/printer/printer.js +6 -6
- package/dist/api/compiler/program-checker.d.ts +5 -0
- package/dist/api/compiler/program-checker.js +11 -1
- package/dist/api/compiler/relations.js +8 -3
- package/dist/api/compiler/reparser.js +13 -5
- package/dist/api/compiler/transformers/class-fields.js +3 -3
- package/dist/api/compiler/transformers/commonjs-module.js +3 -3
- package/dist/api/compiler/transformers/declarations-pseudo.js +2 -2
- package/dist/api/compiler/transformers/module.js +2 -2
- package/dist/api/compiler/transformers/optional-chain.js +3 -3
- package/dist/api/compiler/transformers/subtree-facts.js +2 -2
- package/dist/api/compiler/transformers/tagged-template.js +2 -2
- package/dist/api/compiler/transformers/type-eraser.js +2 -2
- package/dist/api/compiler/transformers/visitor-base.js +3 -3
- package/dist/api/compiler/tsconfig.js +2 -2
- package/package.json +9 -9
- package/src/compiler/ast.ts +184 -59
- package/src/compiler/binder-utilities.ts +2 -1
- package/src/compiler/binder.ts +11 -5
- package/src/compiler/checker-calls.ts +5 -3
- package/src/compiler/checker-contextual.ts +1 -1
- 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-emit-helpers.ts +5 -4
- package/src/compiler/checker-grammar.ts +5 -3
- package/src/compiler/checker-inference.ts +49 -25
- package/src/compiler/checker-members.ts +164 -0
- package/src/compiler/checker-modules.ts +92 -1
- package/src/compiler/checker-symbol-types.ts +14 -4
- package/src/compiler/checker-symbols.ts +4 -1
- package/src/compiler/checker.ts +19 -0
- package/src/compiler/decoder.ts +5 -4
- package/src/compiler/diagnostics.ts +10 -5
- package/src/compiler/encoder.ts +10 -5
- package/src/compiler/parallel-parse.ts +3 -1
- package/src/compiler/parser.ts +93 -39
- package/src/compiler/printer/factory-base.ts +14 -7
- package/src/compiler/printer/factory.ts +5 -3
- package/src/compiler/printer/printer.ts +8 -6
- package/src/compiler/program-checker.ts +10 -1
- package/src/compiler/relations.ts +10 -2
- package/src/compiler/reparser.ts +14 -4
- package/src/compiler/transformers/class-fields.ts +12 -2
- package/src/compiler/transformers/commonjs-module.ts +3 -2
- package/src/compiler/transformers/declarations-pseudo.ts +2 -1
- package/src/compiler/transformers/declarations.ts +1 -1
- package/src/compiler/transformers/module.ts +2 -1
- package/src/compiler/transformers/optional-chain.ts +5 -2
- package/src/compiler/transformers/subtree-facts.ts +2 -1
- package/src/compiler/transformers/tagged-template.ts +2 -2
- package/src/compiler/transformers/type-eraser.ts +2 -1
- package/src/compiler/transformers/visitor-base.ts +10 -5
- package/src/compiler/tsconfig.ts +2 -1
|
@@ -174,12 +174,15 @@ function threadCopyOf(file: DiagnosticFile): DiagnosticFile | undefined {
|
|
|
174
174
|
return copy;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
/** The empty value of a file's position tables until they are computed. */
|
|
178
|
+
const noNumbers: readonly number[] = [];
|
|
179
|
+
|
|
177
180
|
/** The text of a file diagnostics point into. */
|
|
178
181
|
export class DiagnosticFile {
|
|
179
182
|
readonly fileName: string;
|
|
180
183
|
readonly text: string;
|
|
181
184
|
// Computed on first use; never empty once computed.
|
|
182
|
-
private lineStarts: number[] =
|
|
185
|
+
private lineStarts: readonly number[] = noNumbers;
|
|
183
186
|
/** Whether this is a thread's copy of a possibly shared file (`threadCopyOf`). */
|
|
184
187
|
isThreadCopy = false;
|
|
185
188
|
|
|
@@ -210,8 +213,8 @@ export class DiagnosticFile {
|
|
|
210
213
|
// The non-ASCII characters, in order: their UTF-16 offsets, UTF-8 lengths, and the UTF-8 bytes
|
|
211
214
|
// beyond one per UTF-16 code unit of the text up to and including each. Unset until first used.
|
|
212
215
|
private nonASCIIStarts: number[] | undefined = undefined;
|
|
213
|
-
private nonASCIILengths: number[] =
|
|
214
|
-
private extraBytes: number[] =
|
|
216
|
+
private nonASCIILengths: readonly number[] = noNumbers;
|
|
217
|
+
private extraBytes: readonly number[] = noNumbers;
|
|
215
218
|
|
|
216
219
|
private getNonASCIIStarts(): number[] {
|
|
217
220
|
let starts = this.nonASCIIStarts;
|
|
@@ -221,8 +224,8 @@ export class DiagnosticFile {
|
|
|
221
224
|
if (Buffer.byteLength(text, 'utf8') !== text.length) {
|
|
222
225
|
// Scanning the UTF-8 encoding is faster than reading each code unit.
|
|
223
226
|
const bytes = Buffer.from(text, 'utf8');
|
|
224
|
-
const lengths =
|
|
225
|
-
const extraBytes =
|
|
227
|
+
const lengths: number[] = [];
|
|
228
|
+
const extraBytes: number[] = [];
|
|
226
229
|
let extra = 0;
|
|
227
230
|
for (let i = 0; i < bytes.length; i++) {
|
|
228
231
|
const b = bytes[i]!;
|
|
@@ -235,6 +238,8 @@ export class DiagnosticFile {
|
|
|
235
238
|
extraBytes.push(extra);
|
|
236
239
|
i += length - 1;
|
|
237
240
|
}
|
|
241
|
+
this.nonASCIILengths = lengths;
|
|
242
|
+
this.extraBytes = extraBytes;
|
|
238
243
|
}
|
|
239
244
|
this.nonASCIIStarts = starts;
|
|
240
245
|
}
|
package/src/compiler/encoder.ts
CHANGED
|
@@ -186,6 +186,11 @@ import {
|
|
|
186
186
|
YieldExpression,
|
|
187
187
|
BigIntLiteral,
|
|
188
188
|
Identifier,
|
|
189
|
+
propertyAssignmentPostfixToken,
|
|
190
|
+
propertyAssignmentType,
|
|
191
|
+
callQuestionDotToken,
|
|
192
|
+
propertyAssignmentModifiers,
|
|
193
|
+
callTypeArguments,
|
|
189
194
|
} from './ast.js';
|
|
190
195
|
import { getJSDoc } from './parser.js';
|
|
191
196
|
import { SyntaxKind } from './syntax-kind.js';
|
|
@@ -883,8 +888,8 @@ function childrenPropertyMask(node: Node): number {
|
|
|
883
888
|
case SyntaxKind.CallExpression:
|
|
884
889
|
return node instanceof CallExpression
|
|
885
890
|
? ((node as CallExpression).expression !== undefined ? 1 : 0) |
|
|
886
|
-
((node as CallExpression)
|
|
887
|
-
((node as CallExpression)
|
|
891
|
+
(callQuestionDotToken(node as CallExpression) !== undefined ? 2 : 0) |
|
|
892
|
+
(callTypeArguments(node as CallExpression) !== undefined ? 4 : 0) |
|
|
888
893
|
((node as CallExpression).arguments !== undefined ? 8 : 0)
|
|
889
894
|
: 0;
|
|
890
895
|
case SyntaxKind.NewExpression:
|
|
@@ -938,10 +943,10 @@ function childrenPropertyMask(node: Node): number {
|
|
|
938
943
|
return node instanceof SpreadAssignment ? ((node as SpreadAssignment).expression !== undefined ? 1 : 0) : 0;
|
|
939
944
|
case SyntaxKind.PropertyAssignment:
|
|
940
945
|
return node instanceof PropertyAssignment
|
|
941
|
-
? (hasModifiers((node as PropertyAssignment)
|
|
946
|
+
? (hasModifiers(propertyAssignmentModifiers(node as PropertyAssignment)) ? 1 : 0) |
|
|
942
947
|
((node as PropertyAssignment).name !== undefined ? 2 : 0) |
|
|
943
|
-
((node as PropertyAssignment)
|
|
944
|
-
((node as PropertyAssignment)
|
|
948
|
+
(propertyAssignmentPostfixToken(node as PropertyAssignment) !== undefined ? 4 : 0) |
|
|
949
|
+
(propertyAssignmentType(node as PropertyAssignment) !== undefined ? 8 : 0) |
|
|
945
950
|
((node as PropertyAssignment).initializer !== undefined ? 16 : 0)
|
|
946
951
|
: 0;
|
|
947
952
|
case SyntaxKind.ShorthandPropertyAssignment:
|
|
@@ -494,7 +494,9 @@ export class ParseSession {
|
|
|
494
494
|
}
|
|
495
495
|
|
|
496
496
|
private post(i: number, chunk: LoadMessage): void {
|
|
497
|
-
|
|
497
|
+
// Published, the chunk reaches the thread by pointer: copying its names into the message took the
|
|
498
|
+
// main thread 25-45 us per chunk, which during config read delays the matching of root files.
|
|
499
|
+
this.workers[i]!.postMessage(publish(chunk));
|
|
498
500
|
this.outstanding[i] = this.outstanding[i]! + 1;
|
|
499
501
|
if (chunk.kinds[0] === LoadKind.Library && largeLibraries.has(chunk.names[0]!)) this.blocked[i] = true;
|
|
500
502
|
this.busy++;
|
package/src/compiler/parser.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// for (const statement of file.statements.nodes) console.log(statement.kind);
|
|
7
7
|
// ```
|
|
8
8
|
import {
|
|
9
|
+
appendToList,
|
|
9
10
|
ArrayLiteralExpression,
|
|
10
11
|
ArrayTypeNode,
|
|
11
12
|
ArrowFunction,
|
|
@@ -38,6 +39,11 @@ import {
|
|
|
38
39
|
DeleteExpression,
|
|
39
40
|
DoStatement,
|
|
40
41
|
ElementAccessExpression,
|
|
42
|
+
emptyCommentDirectives,
|
|
43
|
+
emptyDiagnostics,
|
|
44
|
+
emptyFileReferences,
|
|
45
|
+
emptyNodes,
|
|
46
|
+
emptyPragmas,
|
|
41
47
|
EmptyStatement,
|
|
42
48
|
EnumDeclaration,
|
|
43
49
|
EnumMember,
|
|
@@ -193,6 +199,8 @@ import {
|
|
|
193
199
|
type Expression,
|
|
194
200
|
type Statement,
|
|
195
201
|
type TypeNode,
|
|
202
|
+
newCallExpression,
|
|
203
|
+
newPropertyAssignment,
|
|
196
204
|
} from './ast.js';
|
|
197
205
|
import {
|
|
198
206
|
OperatorPrecedence,
|
|
@@ -392,6 +400,11 @@ function appendRange(to: Node[], from: readonly Node[], start: number, end: numb
|
|
|
392
400
|
for (let i = start; i < end; i += 1) to.push(from[i]!);
|
|
393
401
|
}
|
|
394
402
|
|
|
403
|
+
// The nodes of every empty parsed list. A list's nodes are pushed into a new `[]`, which natively
|
|
404
|
+
// reserves room for its first elements (112 bytes); a parsed list never changes, so an empty one
|
|
405
|
+
// keeps this shared array instead and its builder is freed.
|
|
406
|
+
const emptyListNodes: Node[] = [];
|
|
407
|
+
|
|
395
408
|
/** Parses `text` as the file `fileName`. The script kind defaults to the one implied by the extension. */
|
|
396
409
|
export function parseSourceFile(fileName: string, text: string, options?: ParseOptions): SourceFile {
|
|
397
410
|
const path = options === undefined ? fileName : options.path;
|
|
@@ -490,6 +503,10 @@ export class Parser extends ScannerErrorReporter {
|
|
|
490
503
|
// receives reparsed nodes, and a fresh array per parsed list would be one more allocation each.
|
|
491
504
|
private readonly reparseLists: Node[][];
|
|
492
505
|
private reparseDepth: number;
|
|
506
|
+
// One scratch array per nesting depth of the lists being parsed. A list collects its elements in
|
|
507
|
+
// its depth's array and is copied out at its exact length, so the tree keeps no spare capacity.
|
|
508
|
+
private readonly listScratch: Node[][];
|
|
509
|
+
private listDepth: number;
|
|
493
510
|
reparsedClones: Node[];
|
|
494
511
|
/** Nodes with eagerly parsed JSDoc, for rewinding. */
|
|
495
512
|
jsDocInfos: Node[];
|
|
@@ -549,6 +566,8 @@ export class Parser extends ScannerErrorReporter {
|
|
|
549
566
|
this.reparseList = [];
|
|
550
567
|
this.reparseLists = [this.reparseList];
|
|
551
568
|
this.reparseDepth = 0;
|
|
569
|
+
this.listScratch = [];
|
|
570
|
+
this.listDepth = -1;
|
|
552
571
|
this.reparsedClones = [];
|
|
553
572
|
this.jsDocInfos = [];
|
|
554
573
|
this.jsDocTable = undefined;
|
|
@@ -759,11 +778,11 @@ export class Parser extends ScannerErrorReporter {
|
|
|
759
778
|
// Nodes
|
|
760
779
|
|
|
761
780
|
newNodeList(pos: number, end: number, nodes: Node[]): NodeList {
|
|
762
|
-
return new NodeList(pos, end, nodes);
|
|
781
|
+
return new NodeList(pos, end, nodes.length === 0 ? emptyListNodes : nodes);
|
|
763
782
|
}
|
|
764
783
|
|
|
765
784
|
newModifierList(pos: number, end: number, nodes: Node[]): ModifierList {
|
|
766
|
-
return new ModifierList(pos, end, nodes, modifiersToFlags(nodes));
|
|
785
|
+
return new ModifierList(pos, end, nodes.length === 0 ? emptyListNodes : nodes, modifiersToFlags(nodes));
|
|
767
786
|
}
|
|
768
787
|
|
|
769
788
|
finishNode(node: Node, pos: number): Node {
|
|
@@ -839,7 +858,8 @@ export class Parser extends ScannerErrorReporter {
|
|
|
839
858
|
}
|
|
840
859
|
|
|
841
860
|
finishSourceFile(result: SourceFile, isDeclarationFile: boolean): void {
|
|
842
|
-
|
|
861
|
+
const commentDirectives = this.scanner.getCommentDirectives();
|
|
862
|
+
result.commentDirectives = commentDirectives.length === 0 ? emptyCommentDirectives : commentDirectives;
|
|
843
863
|
result.pragmas = getCommentPragmas(this.sourceText);
|
|
844
864
|
this.processPragmasIntoFields(result);
|
|
845
865
|
result.diagnostics = attachFileToDiagnostics(this.diagnostics, result);
|
|
@@ -857,9 +877,12 @@ export class Parser extends ScannerErrorReporter {
|
|
|
857
877
|
// The table stays with the parser: when top-level await reparsing produces a second source
|
|
858
878
|
// file, it finishes with the same table, which still holds the JSDoc of retained statements.
|
|
859
879
|
result.jsDocs = this.jsDocTable;
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
880
|
+
if (this.reparsedClones.length === 0) result.reparsedClones = emptyNodes;
|
|
881
|
+
else {
|
|
882
|
+
const clones = this.reparsedClones.slice();
|
|
883
|
+
clones.sort(compareNodePositions);
|
|
884
|
+
result.reparsedClones = clones;
|
|
885
|
+
}
|
|
863
886
|
setExternalModuleIndicator(result);
|
|
864
887
|
}
|
|
865
888
|
|
|
@@ -1007,7 +1030,7 @@ export class Parser extends ScannerErrorReporter {
|
|
|
1007
1030
|
if (depth === this.reparseLists.length) this.reparseLists.push([]);
|
|
1008
1031
|
const reparseList = this.reparseLists[depth]!;
|
|
1009
1032
|
this.reparseList = reparseList;
|
|
1010
|
-
const list
|
|
1033
|
+
const list = this.openList();
|
|
1011
1034
|
while (!this.isListTerminator(kind)) {
|
|
1012
1035
|
if (this.isListElement(kind, false)) {
|
|
1013
1036
|
const elt = this.parseListElement(element, list.length);
|
|
@@ -1032,7 +1055,7 @@ export class Parser extends ScannerErrorReporter {
|
|
|
1032
1055
|
this.reparseDepth = depth - 1;
|
|
1033
1056
|
this.reparseList = outerReparseList;
|
|
1034
1057
|
this.parsingContexts = saveParsingContexts;
|
|
1035
|
-
return list;
|
|
1058
|
+
return this.closeList(list);
|
|
1036
1059
|
}
|
|
1037
1060
|
|
|
1038
1061
|
parseList(kind: ParsingContext, element: ListElement): NodeList {
|
|
@@ -1046,12 +1069,13 @@ export class Parser extends ScannerErrorReporter {
|
|
|
1046
1069
|
const pos = this.nodePos();
|
|
1047
1070
|
const saveParsingContexts = this.parsingContexts;
|
|
1048
1071
|
this.parsingContexts |= 1 << kind;
|
|
1049
|
-
const list
|
|
1072
|
+
const list = this.openList();
|
|
1050
1073
|
for (;;) {
|
|
1051
1074
|
if (this.isListElement(kind, false)) {
|
|
1052
1075
|
const startPos = this.nodePos();
|
|
1053
1076
|
const result = this.parseListElement(element, list.length);
|
|
1054
1077
|
if (result === this.noElement) {
|
|
1078
|
+
this.closeList(list);
|
|
1055
1079
|
this.parsingContexts = saveParsingContexts;
|
|
1056
1080
|
return undefined;
|
|
1057
1081
|
}
|
|
@@ -1077,7 +1101,24 @@ export class Parser extends ScannerErrorReporter {
|
|
|
1077
1101
|
if (this.abortParsingListOrMoveToNextToken(kind)) break;
|
|
1078
1102
|
}
|
|
1079
1103
|
this.parsingContexts = saveParsingContexts;
|
|
1080
|
-
return this.newNodeList(pos, this.nodePos(), list);
|
|
1104
|
+
return this.newNodeList(pos, this.nodePos(), this.closeList(list));
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
/** The scratch array for a list at the next nesting depth, empty. */
|
|
1108
|
+
private openList(): Node[] {
|
|
1109
|
+
const depth = ++this.listDepth;
|
|
1110
|
+
if (depth === this.listScratch.length) this.listScratch.push([]);
|
|
1111
|
+
return this.listScratch[depth]!;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
/** The elements collected in `list` (the scratch array from `openList`) as an array of their exact
|
|
1115
|
+
* length, or the shared empty array; empties the scratch array for the next list at its depth. */
|
|
1116
|
+
private closeList(list: Node[]): Node[] {
|
|
1117
|
+
this.listDepth--;
|
|
1118
|
+
if (list.length === 0) return emptyListNodes;
|
|
1119
|
+
const nodes = list.slice();
|
|
1120
|
+
list.length = 0;
|
|
1121
|
+
return nodes;
|
|
1081
1122
|
}
|
|
1082
1123
|
|
|
1083
1124
|
/** The list; a missing list if `opening` is absent; undefined if an element parser returned undefined. */
|
|
@@ -3106,9 +3147,10 @@ export class Parser extends ScannerErrorReporter {
|
|
|
3106
3147
|
? this.parseFunctionOrConstructorTypeToError(isUnionType)
|
|
3107
3148
|
: this.parseConstituentType(isUnionType);
|
|
3108
3149
|
if (this.token() === operator || hasLeadingOperator) {
|
|
3109
|
-
const types
|
|
3150
|
+
const types = this.openList();
|
|
3151
|
+
types.push(type);
|
|
3110
3152
|
while (this.parseOptional(operator)) types.push(this.parseFunctionOrConstructorTypeToError(isUnionType));
|
|
3111
|
-
const list = this.newNodeList(pos, this.nodePos(), types);
|
|
3153
|
+
const list = this.newNodeList(pos, this.nodePos(), this.closeList(types));
|
|
3112
3154
|
type = isUnionType ? new UnionTypeNode(list) : new IntersectionTypeNode(list);
|
|
3113
3155
|
this.finishNode(type, pos);
|
|
3114
3156
|
}
|
|
@@ -4042,13 +4084,13 @@ export class Parser extends ScannerErrorReporter {
|
|
|
4042
4084
|
|
|
4043
4085
|
parseTemplateTypeSpans(): NodeList {
|
|
4044
4086
|
const pos = this.nodePos();
|
|
4045
|
-
const list
|
|
4087
|
+
const list = this.openList();
|
|
4046
4088
|
for (;;) {
|
|
4047
4089
|
const span = this.parseTemplateTypeSpan();
|
|
4048
4090
|
list.push(span);
|
|
4049
4091
|
if (span.literal.kind !== SyntaxKind.TemplateMiddle) break;
|
|
4050
4092
|
}
|
|
4051
|
-
return this.newNodeList(pos, this.nodePos(), list);
|
|
4093
|
+
return this.newNodeList(pos, this.nodePos(), this.closeList(list));
|
|
4052
4094
|
}
|
|
4053
4095
|
|
|
4054
4096
|
parseTemplateTypeSpan(): TemplateLiteralTypeSpan {
|
|
@@ -4172,24 +4214,23 @@ export class Parser extends ScannerErrorReporter {
|
|
|
4172
4214
|
let hasTrailingModifier = false;
|
|
4173
4215
|
let hasStaticModifier = false;
|
|
4174
4216
|
const pos = this.nodePos();
|
|
4175
|
-
|
|
4217
|
+
const list = this.openList();
|
|
4176
4218
|
for (;;) {
|
|
4177
4219
|
if (allowDecorators && this.token() === SyntaxKind.AtToken && !hasTrailingModifier) {
|
|
4178
4220
|
const decorator = this.parseDecorator();
|
|
4179
|
-
if (list === undefined) list = [];
|
|
4180
4221
|
list.push(decorator);
|
|
4181
4222
|
if (hasLeadingModifier) hasTrailingDecorator = true;
|
|
4182
4223
|
} else {
|
|
4183
4224
|
const modifier = this.tryParseModifier(hasStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock);
|
|
4184
4225
|
if (modifier === undefined) break;
|
|
4185
4226
|
if (modifier.kind === SyntaxKind.StaticKeyword) hasStaticModifier = true;
|
|
4186
|
-
if (list === undefined) list = [];
|
|
4187
4227
|
list.push(modifier);
|
|
4188
4228
|
if (hasTrailingDecorator) hasTrailingModifier = true;
|
|
4189
4229
|
else hasLeadingModifier = true;
|
|
4190
4230
|
}
|
|
4191
4231
|
}
|
|
4192
|
-
|
|
4232
|
+
const nodes = this.closeList(list);
|
|
4233
|
+
return nodes.length === 0 ? undefined : this.newModifierList(pos, this.nodePos(), nodes);
|
|
4193
4234
|
}
|
|
4194
4235
|
|
|
4195
4236
|
parseDecorator(): Node {
|
|
@@ -4921,7 +4962,7 @@ export class Parser extends ScannerErrorReporter {
|
|
|
4921
4962
|
const pos = this.nodePos();
|
|
4922
4963
|
const saveParsingContexts = this.parsingContexts;
|
|
4923
4964
|
this.parsingContexts |= 1 << ParsingContext.JsxChildren;
|
|
4924
|
-
const list
|
|
4965
|
+
const list = this.openList();
|
|
4925
4966
|
for (;;) {
|
|
4926
4967
|
// Like tsgo, this leaves the parser's current token unchanged.
|
|
4927
4968
|
const currentToken = this.scanner.reScanJsxToken(true);
|
|
@@ -4941,7 +4982,7 @@ export class Parser extends ScannerErrorReporter {
|
|
|
4941
4982
|
break;
|
|
4942
4983
|
}
|
|
4943
4984
|
this.parsingContexts = saveParsingContexts;
|
|
4944
|
-
return this.newNodeList(pos, this.nodePos(), list);
|
|
4985
|
+
return this.newNodeList(pos, this.nodePos(), this.closeList(list));
|
|
4945
4986
|
}
|
|
4946
4987
|
|
|
4947
4988
|
parseJsxChild(openingTag: Node, token: SyntaxKind): Expression | undefined {
|
|
@@ -5520,12 +5561,13 @@ export class Parser extends ScannerErrorReporter {
|
|
|
5520
5561
|
const isOptionalChain = questionDotToken !== undefined || this.tryReparseOptionalChain(expression);
|
|
5521
5562
|
expression = this.checkJSSyntax(
|
|
5522
5563
|
this.finishNode(
|
|
5523
|
-
|
|
5564
|
+
newCallExpression(
|
|
5524
5565
|
expression,
|
|
5525
5566
|
questionDotToken,
|
|
5526
5567
|
typeArguments,
|
|
5527
5568
|
argumentList,
|
|
5528
5569
|
isOptionalChain ? NodeFlags.OptionalChain : NodeFlags.None,
|
|
5570
|
+
(this.contextFlags & NodeFlags.JavaScriptFile) !== 0,
|
|
5529
5571
|
),
|
|
5530
5572
|
pos,
|
|
5531
5573
|
),
|
|
@@ -5615,13 +5657,13 @@ export class Parser extends ScannerErrorReporter {
|
|
|
5615
5657
|
|
|
5616
5658
|
parseTemplateSpans(isTaggedTemplate: boolean): NodeList {
|
|
5617
5659
|
const pos = this.nodePos();
|
|
5618
|
-
const list
|
|
5660
|
+
const list = this.openList();
|
|
5619
5661
|
for (;;) {
|
|
5620
5662
|
const span = this.parseTemplateSpan(isTaggedTemplate);
|
|
5621
5663
|
list.push(span);
|
|
5622
5664
|
if (span.literal.kind !== SyntaxKind.TemplateMiddle) break;
|
|
5623
5665
|
}
|
|
5624
|
-
return this.newNodeList(pos, this.nodePos(), list);
|
|
5666
|
+
return this.newNodeList(pos, this.nodePos(), this.closeList(list));
|
|
5625
5667
|
}
|
|
5626
5668
|
|
|
5627
5669
|
parseTemplateSpan(isTaggedTemplate: boolean): TemplateSpan {
|
|
@@ -5753,7 +5795,14 @@ export class Parser extends ScannerErrorReporter {
|
|
|
5753
5795
|
} else {
|
|
5754
5796
|
this.parseExpected(SyntaxKind.ColonToken);
|
|
5755
5797
|
const initializer = this.parseAssignmentExpressionOrHigherAllowIn();
|
|
5756
|
-
node =
|
|
5798
|
+
node = newPropertyAssignment(
|
|
5799
|
+
modifiers,
|
|
5800
|
+
name,
|
|
5801
|
+
postfixToken,
|
|
5802
|
+
undefined,
|
|
5803
|
+
initializer,
|
|
5804
|
+
(this.contextFlags & NodeFlags.JavaScriptFile) !== 0,
|
|
5805
|
+
);
|
|
5757
5806
|
}
|
|
5758
5807
|
return this.finishWithJSDoc(node, pos, jsdoc);
|
|
5759
5808
|
}
|
|
@@ -6802,9 +6851,9 @@ export class Parser extends ScannerErrorReporter {
|
|
|
6802
6851
|
|
|
6803
6852
|
processPragmasIntoFields(file: SourceFile): void {
|
|
6804
6853
|
file.checkJsDirective = undefined;
|
|
6805
|
-
file.referencedFiles =
|
|
6806
|
-
file.typeReferenceDirectives =
|
|
6807
|
-
file.libReferenceDirectives =
|
|
6854
|
+
file.referencedFiles = emptyFileReferences;
|
|
6855
|
+
file.typeReferenceDirectives = emptyFileReferences;
|
|
6856
|
+
file.libReferenceDirectives = emptyFileReferences;
|
|
6808
6857
|
for (const pragma of file.pragmas) {
|
|
6809
6858
|
switch (pragma.name) {
|
|
6810
6859
|
case 'reference': {
|
|
@@ -6823,15 +6872,20 @@ export class Parser extends ScannerErrorReporter {
|
|
|
6823
6872
|
resolutionMode !== undefined
|
|
6824
6873
|
? this.parseResolutionMode(resolutionMode.value, resolutionMode.pos, resolutionMode.end)
|
|
6825
6874
|
: ModuleKind.None;
|
|
6826
|
-
file.typeReferenceDirectives
|
|
6875
|
+
file.typeReferenceDirectives = appendToList(
|
|
6876
|
+
file.typeReferenceDirectives,
|
|
6827
6877
|
new FileReference(types.pos, types.end, types.value, parsed, isPreserved),
|
|
6828
6878
|
);
|
|
6829
6879
|
} else if (lib !== undefined) {
|
|
6830
|
-
file.libReferenceDirectives
|
|
6880
|
+
file.libReferenceDirectives = appendToList(
|
|
6881
|
+
file.libReferenceDirectives,
|
|
6831
6882
|
new FileReference(lib.pos, lib.end, lib.value, ModuleKind.None, isPreserved),
|
|
6832
6883
|
);
|
|
6833
6884
|
} else if (path !== undefined) {
|
|
6834
|
-
file.referencedFiles
|
|
6885
|
+
file.referencedFiles = appendToList(
|
|
6886
|
+
file.referencedFiles,
|
|
6887
|
+
new FileReference(path.pos, path.end, path.value, ModuleKind.None, isPreserved),
|
|
6888
|
+
);
|
|
6835
6889
|
} else {
|
|
6836
6890
|
this.parseErrorAt(pragma.range.pos, pragma.range.end, Diagnostics.Invalid_reference_directive_syntax);
|
|
6837
6891
|
}
|
|
@@ -7042,8 +7096,8 @@ function typeHasBlockingError(node: TypeNode | undefined): boolean {
|
|
|
7042
7096
|
return node !== undefined && typeHasArrowFunctionBlockingParseError(node);
|
|
7043
7097
|
}
|
|
7044
7098
|
|
|
7045
|
-
function attachFileToDiagnostics(diagnostics: Diagnostic[], file: SourceFile): Diagnostic[] {
|
|
7046
|
-
if (diagnostics.length === 0) return
|
|
7099
|
+
function attachFileToDiagnostics(diagnostics: Diagnostic[], file: SourceFile): readonly Diagnostic[] {
|
|
7100
|
+
if (diagnostics.length === 0) return emptyDiagnostics;
|
|
7047
7101
|
const diagnosticFile = file.diagnosticFile();
|
|
7048
7102
|
for (const d of diagnostics) {
|
|
7049
7103
|
d.file = diagnosticFile;
|
|
@@ -7354,12 +7408,12 @@ function nextTokenIsNotColon(p: Parser): boolean {
|
|
|
7354
7408
|
|
|
7355
7409
|
// Pragmas
|
|
7356
7410
|
|
|
7357
|
-
function getCommentPragmas(sourceText: string): Pragma[] {
|
|
7358
|
-
const pragmas: Pragma[] = [];
|
|
7411
|
+
function getCommentPragmas(sourceText: string): readonly Pragma[] {
|
|
7359
7412
|
const ranges = getLeadingCommentRanges(sourceText, 0);
|
|
7360
|
-
if (ranges
|
|
7361
|
-
|
|
7362
|
-
|
|
7413
|
+
if (ranges === undefined) return emptyPragmas;
|
|
7414
|
+
const pragmas: Pragma[] = [];
|
|
7415
|
+
for (const range of ranges) extractPragmas(range, sourceText.substring(range.pos, range.end), pragmas);
|
|
7416
|
+
return pragmas.length === 0 ? emptyPragmas : pragmas;
|
|
7363
7417
|
}
|
|
7364
7418
|
|
|
7365
7419
|
function extractPragmas(range: CommentRange, text: string, pragmas: Pragma[]): void {
|
|
@@ -7528,9 +7582,9 @@ function collectModuleReferences(file: SourceFile, node: Statement, inAmbientMod
|
|
|
7528
7582
|
) {
|
|
7529
7583
|
const nameText = getText((node as ModuleDeclaration).name);
|
|
7530
7584
|
if (file.externalModuleIndicator !== undefined || (inAmbientModule && !isExternalModuleNameRelative(nameText))) {
|
|
7531
|
-
file.moduleAugmentations.
|
|
7585
|
+
file.moduleAugmentations = appendToList(file.moduleAugmentations, (node as ModuleDeclaration).name);
|
|
7532
7586
|
} else if (!inAmbientModule) {
|
|
7533
|
-
file.ambientModuleNames.
|
|
7587
|
+
file.ambientModuleNames = appendToList(file.ambientModuleNames, nameText);
|
|
7534
7588
|
const body = (node as ModuleDeclaration).body;
|
|
7535
7589
|
if (body !== undefined) {
|
|
7536
7590
|
const statements = getStatements(body);
|
|
@@ -199,6 +199,13 @@ import {
|
|
|
199
199
|
type Node,
|
|
200
200
|
type NodeList,
|
|
201
201
|
type Token,
|
|
202
|
+
propertyAssignmentPostfixToken,
|
|
203
|
+
propertyAssignmentType,
|
|
204
|
+
callQuestionDotToken,
|
|
205
|
+
propertyAssignmentModifiers,
|
|
206
|
+
callTypeArguments,
|
|
207
|
+
newCallExpression,
|
|
208
|
+
newPropertyAssignment,
|
|
202
209
|
} from '../ast.js';
|
|
203
210
|
import type { SyntaxKind } from '../syntax-kind.js';
|
|
204
211
|
|
|
@@ -359,12 +366,12 @@ export abstract class NodeFactoryBase {
|
|
|
359
366
|
): CallExpression {
|
|
360
367
|
if (
|
|
361
368
|
expression !== node.expression ||
|
|
362
|
-
questionDotToken !== node
|
|
363
|
-
typeArguments !== node
|
|
369
|
+
questionDotToken !== callQuestionDotToken(node) ||
|
|
370
|
+
typeArguments !== callTypeArguments(node) ||
|
|
364
371
|
args !== node.arguments ||
|
|
365
372
|
flags !== node.flags
|
|
366
373
|
) {
|
|
367
|
-
const updated =
|
|
374
|
+
const updated = newCallExpression(expression, questionDotToken, typeArguments, args, flags, false);
|
|
368
375
|
this.finishUpdate(updated, node);
|
|
369
376
|
return updated;
|
|
370
377
|
}
|
|
@@ -2057,13 +2064,13 @@ export abstract class NodeFactoryBase {
|
|
|
2057
2064
|
initializer: Expression,
|
|
2058
2065
|
): PropertyAssignment {
|
|
2059
2066
|
if (
|
|
2060
|
-
modifiers !== node
|
|
2067
|
+
modifiers !== propertyAssignmentModifiers(node) ||
|
|
2061
2068
|
name !== node.name ||
|
|
2062
|
-
postfixToken !== node
|
|
2063
|
-
typeNode !== node
|
|
2069
|
+
postfixToken !== propertyAssignmentPostfixToken(node) ||
|
|
2070
|
+
typeNode !== propertyAssignmentType(node) ||
|
|
2064
2071
|
initializer !== node.initializer
|
|
2065
2072
|
) {
|
|
2066
|
-
const updated =
|
|
2073
|
+
const updated = newPropertyAssignment(modifiers, name, postfixToken, typeNode, initializer, false);
|
|
2067
2074
|
this.finishUpdate(updated, node);
|
|
2068
2075
|
return updated;
|
|
2069
2076
|
}
|
|
@@ -45,6 +45,8 @@ import {
|
|
|
45
45
|
VariableDeclarationList,
|
|
46
46
|
VariableStatement,
|
|
47
47
|
VoidExpression,
|
|
48
|
+
newCallExpression,
|
|
49
|
+
newPropertyAssignment,
|
|
48
50
|
} from '../ast.js';
|
|
49
51
|
import { modifierToFlag } from '../ast-utilities.js';
|
|
50
52
|
import { getNameOfDeclaration, getNonAssignedNameOfDeclaration, hasSyntacticModifier } from '../binder-utilities.js';
|
|
@@ -166,7 +168,7 @@ export abstract class NodeFactory extends NodeFactoryBase {
|
|
|
166
168
|
|
|
167
169
|
createCallExpression(expression: Node, args: Node[]): CallExpression {
|
|
168
170
|
return this.created(
|
|
169
|
-
|
|
171
|
+
newCallExpression(expression, undefined, undefined, this.createNodeList(args), NodeFlags.None, false),
|
|
170
172
|
);
|
|
171
173
|
}
|
|
172
174
|
|
|
@@ -265,7 +267,7 @@ export abstract class NodeFactory extends NodeFactoryBase {
|
|
|
265
267
|
}
|
|
266
268
|
|
|
267
269
|
createPropertyAssignment(name: Node, initializer: Node): PropertyAssignment {
|
|
268
|
-
return this.created(
|
|
270
|
+
return this.created(newPropertyAssignment(undefined, name, undefined, undefined, initializer, false));
|
|
269
271
|
}
|
|
270
272
|
|
|
271
273
|
createParameter(name: Node): ParameterDeclaration {
|
|
@@ -546,7 +548,7 @@ export abstract class NodeFactory extends NodeFactoryBase {
|
|
|
546
548
|
createMethodCall(object: Node, method: string, args: Node[]): CallExpression {
|
|
547
549
|
const callee = this.createPropertyAccessExpression(object, this.createIdentifier(method));
|
|
548
550
|
const flags = object instanceof CallExpression ? object.flags & NodeFlags.OptionalChain : NodeFlags.None;
|
|
549
|
-
return this.created(
|
|
551
|
+
return this.created(newCallExpression(callee, undefined, undefined, this.createNodeList(args), flags, false));
|
|
550
552
|
}
|
|
551
553
|
|
|
552
554
|
/** `Global.method(...args)`, such as `Math.pow(a, b)`. */
|
|
@@ -157,6 +157,8 @@ import {
|
|
|
157
157
|
getProperties,
|
|
158
158
|
getStatements,
|
|
159
159
|
getModifiers,
|
|
160
|
+
callQuestionDotToken,
|
|
161
|
+
callTypeArguments,
|
|
160
162
|
} from '../ast.js';
|
|
161
163
|
import { OperatorPrecedence } from '../ast-utilities.js';
|
|
162
164
|
import {
|
|
@@ -2248,8 +2250,8 @@ export class Printer extends NameGeneratorHost {
|
|
|
2248
2250
|
private emitCallExpression(node: CallExpression): boolean {
|
|
2249
2251
|
const state = this.enterNode(node);
|
|
2250
2252
|
this.emitCallee(node.expression, node);
|
|
2251
|
-
this.emitOptionalToken(node
|
|
2252
|
-
this.emitTypeArguments(node, node
|
|
2253
|
+
this.emitOptionalToken(callQuestionDotToken(node));
|
|
2254
|
+
this.emitTypeArguments(node, callTypeArguments(node));
|
|
2253
2255
|
this.emitList(ListItem.Argument, node, node.arguments, ListFormat.CallExpressionArguments);
|
|
2254
2256
|
this.exitNode(node, state);
|
|
2255
2257
|
return true;
|
|
@@ -2653,8 +2655,8 @@ export class Printer extends NameGeneratorHost {
|
|
|
2653
2655
|
return factory.updateCallExpression(
|
|
2654
2656
|
node,
|
|
2655
2657
|
this.parenthesizeExpressionForNoAsi(node.expression),
|
|
2656
|
-
node
|
|
2657
|
-
node
|
|
2658
|
+
callQuestionDotToken(node),
|
|
2659
|
+
callTypeArguments(node),
|
|
2658
2660
|
node.arguments,
|
|
2659
2661
|
node.flags,
|
|
2660
2662
|
);
|
|
@@ -2921,8 +2923,8 @@ export class Printer extends NameGeneratorHost {
|
|
|
2921
2923
|
this.write1('(');
|
|
2922
2924
|
this.emitExpression(call.expression, OperatorPrecedence.Lowest);
|
|
2923
2925
|
this.write1(')');
|
|
2924
|
-
this.emitOptionalToken(call
|
|
2925
|
-
this.emitTypeArguments(call, call
|
|
2926
|
+
this.emitOptionalToken(callQuestionDotToken(call));
|
|
2927
|
+
this.emitTypeArguments(call, callTypeArguments(call));
|
|
2926
2928
|
this.emitList(ListItem.Argument, call, call.arguments, ListFormat.CallExpressionArguments);
|
|
2927
2929
|
this.exitNode(call, callState);
|
|
2928
2930
|
}
|
|
@@ -32,6 +32,11 @@ import { CommentDirectiveKind } from './types.js';
|
|
|
32
32
|
/** What the checker needs, answered by a program. */
|
|
33
33
|
export class ProgramCheckerHost extends CheckerHost {
|
|
34
34
|
private specifierHost: ProgramModuleSpecifierHost | undefined = undefined;
|
|
35
|
+
/**
|
|
36
|
+
* `getSourceFileForResolvedModule` by resolved file name (null when there is none): every import of
|
|
37
|
+
* a module asks again, and the program finds a file by its path, which it computes from the name.
|
|
38
|
+
*/
|
|
39
|
+
private readonly resolvedSourceFiles = new Map<string, SourceFile | null>();
|
|
35
40
|
|
|
36
41
|
constructor(readonly program: Program) {
|
|
37
42
|
super();
|
|
@@ -54,7 +59,11 @@ export class ProgramCheckerHost extends CheckerHost {
|
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
getSourceFileForResolvedModule(fileName: string): SourceFile | undefined {
|
|
57
|
-
|
|
62
|
+
const known = this.resolvedSourceFiles.get(fileName);
|
|
63
|
+
if (known !== undefined) return known ?? undefined;
|
|
64
|
+
const file = this.program.getSourceFileForResolvedModule(fileName);
|
|
65
|
+
this.resolvedSourceFiles.set(fileName, file ?? null);
|
|
66
|
+
return file;
|
|
58
67
|
}
|
|
59
68
|
|
|
60
69
|
getModeForUsageLocation(file: SourceFile, location: Node): ModuleKind {
|
|
@@ -129,6 +129,8 @@ import {
|
|
|
129
129
|
getResolvedMember,
|
|
130
130
|
hasResolvedProperties,
|
|
131
131
|
resolvedPropertiesAreOptional,
|
|
132
|
+
positionsOfNamesFoundInSource,
|
|
133
|
+
firstUnmatchedProperty,
|
|
132
134
|
} from './checker-members.js';
|
|
133
135
|
import {
|
|
134
136
|
getParentOfSymbol,
|
|
@@ -2822,7 +2824,13 @@ export class Relater extends TypeComparer {
|
|
|
2822
2824
|
!isObjectLiteralType(source) &&
|
|
2823
2825
|
!isEmptyArrayLiteralType(c, source) &&
|
|
2824
2826
|
!isTupleType(source);
|
|
2825
|
-
const
|
|
2827
|
+
const targetProperties = getPropertiesOfType(c, target);
|
|
2828
|
+
// Where it is known which target names the source has, nothing else is looked up by name.
|
|
2829
|
+
const found = positionsOfNamesFoundInSource(c, source, target, targetProperties);
|
|
2830
|
+
const unmatchedProperty =
|
|
2831
|
+
found !== undefined
|
|
2832
|
+
? firstUnmatchedProperty(c, targetProperties, found, requireOptionalProperties)
|
|
2833
|
+
: getUnmatchedProperty(c, source, target, requireOptionalProperties, false);
|
|
2826
2834
|
if (unmatchedProperty !== undefined) {
|
|
2827
2835
|
if (reportErrors && shouldReportUnmatchedPropertyError(c, source, target))
|
|
2828
2836
|
this.reportUnmatchedProperty(source, target, unmatchedProperty, requireOptionalProperties);
|
|
@@ -2842,7 +2850,7 @@ export class Relater extends TypeComparer {
|
|
|
2842
2850
|
}
|
|
2843
2851
|
}
|
|
2844
2852
|
const numericNamesOnly = isTupleType(source) && isTupleType(target);
|
|
2845
|
-
for (const targetProp of
|
|
2853
|
+
for (const targetProp of found !== undefined ? found.map((i) => targetProperties[i]!) : targetProperties) {
|
|
2846
2854
|
if (excludedProperties !== undefined && excludedProperties.has(targetProp.name)) continue;
|
|
2847
2855
|
const name = targetProp.name;
|
|
2848
2856
|
if (
|