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
|
@@ -57,7 +57,8 @@ class PendingHelperCheck {
|
|
|
57
57
|
export class EmitHelperFileLinks {
|
|
58
58
|
helpersModule: Symbol | undefined = undefined;
|
|
59
59
|
requestedHelpers: number = ExternalEmitHelpers.None;
|
|
60
|
-
|
|
60
|
+
/** Created on the first check; most files have none. */
|
|
61
|
+
pending: PendingHelperCheck[] | undefined = undefined;
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
function fileLinks(c: Checker, file: SourceFile): EmitHelperFileLinks {
|
|
@@ -86,7 +87,7 @@ export function checkExternalEmitHelpers(c: Checker, location: Node, helpers: Ex
|
|
|
86
87
|
const fileIndex = c.fileIndex.get(file);
|
|
87
88
|
const checkingIndex = c.fileIndex.get(checking);
|
|
88
89
|
if (fileIndex !== undefined && checkingIndex !== undefined && fileIndex < checkingIndex) {
|
|
89
|
-
fileLinks(c, file).pending.push(new PendingHelperCheck(location, helpers));
|
|
90
|
+
(fileLinks(c, file).pending ??= []).push(new PendingHelperCheck(location, helpers));
|
|
90
91
|
return;
|
|
91
92
|
}
|
|
92
93
|
}
|
|
@@ -141,9 +142,9 @@ export function checkExternalEmitHelpers(c: Checker, location: Node, helpers: Ex
|
|
|
141
142
|
/** Runs the helper checks for nodes of `file` that were reached while checking later files. */
|
|
142
143
|
export function checkPendingExternalEmitHelpers(c: Checker, file: SourceFile): void {
|
|
143
144
|
const links = c.emitHelperFileLinks.get(file);
|
|
144
|
-
if (links === undefined
|
|
145
|
+
if (links?.pending === undefined) return;
|
|
145
146
|
const pending = links.pending;
|
|
146
|
-
links.pending =
|
|
147
|
+
links.pending = undefined;
|
|
147
148
|
for (const check of pending) checkExternalEmitHelpers(c, check.location, check.helpers);
|
|
148
149
|
}
|
|
149
150
|
|
|
@@ -80,6 +80,8 @@ import {
|
|
|
80
80
|
getTypeArguments,
|
|
81
81
|
getTypeParameters,
|
|
82
82
|
isDeclarationNode,
|
|
83
|
+
callQuestionDotToken,
|
|
84
|
+
callTypeArguments,
|
|
83
85
|
} from './ast.js';
|
|
84
86
|
import {
|
|
85
87
|
canHaveDecorators,
|
|
@@ -1297,7 +1299,7 @@ function checkGrammarDecorator(g: GrammarChecker, decorator: Decorator): boolean
|
|
|
1297
1299
|
const call = node as CallExpression;
|
|
1298
1300
|
if (!canHaveCallExpression) errorNode = node;
|
|
1299
1301
|
// A `?.` token comes first, so it wins over an earlier error node.
|
|
1300
|
-
if (call
|
|
1302
|
+
if (callQuestionDotToken(call) !== undefined) errorNode = callQuestionDotToken(call);
|
|
1301
1303
|
node = call.expression;
|
|
1302
1304
|
canHaveCallExpression = false;
|
|
1303
1305
|
continue;
|
|
@@ -3305,7 +3307,7 @@ function checkGrammarCallExpression(g: GrammarChecker, node: CallExpression): vo
|
|
|
3305
3307
|
(callee as MetaProperty).keywordToken === SyntaxKind.ImportKeyword &&
|
|
3306
3308
|
(callee as MetaProperty).name.text === 'defer');
|
|
3307
3309
|
if (isImportCall) checkGrammarImportCallExpression(g, node);
|
|
3308
|
-
else checkGrammarTypeArguments(g, node
|
|
3310
|
+
else checkGrammarTypeArguments(g, callTypeArguments(node));
|
|
3309
3311
|
}
|
|
3310
3312
|
|
|
3311
3313
|
function checkGrammarImportCallExpression(g: GrammarChecker, node: CallExpression): boolean {
|
|
@@ -3331,7 +3333,7 @@ function checkGrammarImportCallExpression(g: GrammarChecker, node: CallExpressio
|
|
|
3331
3333
|
node,
|
|
3332
3334
|
Diagnostics.Dynamic_imports_are_only_supported_when_the_module_flag_is_set_to_es2020_es2022_esnext_commonjs_amd_system_umd_node16_node18_node20_or_nodenext,
|
|
3333
3335
|
);
|
|
3334
|
-
if (node
|
|
3336
|
+
if (callTypeArguments(node) !== undefined)
|
|
3335
3337
|
return grammarErrorOnNode(
|
|
3336
3338
|
g,
|
|
3337
3339
|
node,
|
|
@@ -293,20 +293,27 @@ export class IntraExpressionInferenceSite {
|
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
-
|
|
296
|
+
/**
|
|
297
|
+
* The inferences for a set of type parameters. The context is its own fixing mapper (`mapper`), and
|
|
298
|
+
* each read of `nonFixingMapper` returns a new mapper that reads the context: no mapper the context
|
|
299
|
+
* holds refers back to it, so a context whose inference is done is freed by reference counting
|
|
300
|
+
* rather than by the cycle collector.
|
|
301
|
+
*/
|
|
302
|
+
export class InferenceContext extends TypeMapper {
|
|
303
|
+
readonly c: Checker;
|
|
297
304
|
inferences: InferenceInfo[];
|
|
298
305
|
/** The generic signature inferences are made for, if any. */
|
|
299
306
|
readonly signature: Signature | undefined;
|
|
300
307
|
flags: InferenceFlags;
|
|
301
308
|
readonly compareTypes: TypeComparer;
|
|
302
|
-
/**
|
|
303
|
-
|
|
304
|
-
nonFixingMapper: TypeMapper;
|
|
309
|
+
/** Combined after the non-fixing mapper (conditional types' `infer` constraints), if any. */
|
|
310
|
+
nonFixingOuter: TypeMapper | undefined = undefined;
|
|
305
311
|
/** Maps to inferences from the return type, if any. */
|
|
306
312
|
returnMapper: TypeMapper | undefined = undefined;
|
|
307
313
|
outerReturnMapper: TypeMapper | undefined = undefined;
|
|
308
314
|
inferredTypeParameters: Type[] | undefined = undefined;
|
|
309
|
-
|
|
315
|
+
/** Created on the first site; most contexts get none. */
|
|
316
|
+
intraExpressionInferenceSites: IntraExpressionInferenceSite[] | undefined = undefined;
|
|
310
317
|
|
|
311
318
|
constructor(
|
|
312
319
|
c: Checker,
|
|
@@ -315,45 +322,61 @@ export class InferenceContext {
|
|
|
315
322
|
flags: InferenceFlags,
|
|
316
323
|
compareTypes: TypeComparer,
|
|
317
324
|
) {
|
|
325
|
+
super();
|
|
326
|
+
this.c = c;
|
|
318
327
|
this.inferences = inferences;
|
|
319
328
|
this.signature = signature;
|
|
320
329
|
this.flags = flags;
|
|
321
330
|
this.compareTypes = compareTypes;
|
|
322
|
-
this.mapper = new InferenceTypeMapper(c, this, true);
|
|
323
|
-
this.nonFixingMapper = new InferenceTypeMapper(c, this, false);
|
|
324
331
|
}
|
|
325
|
-
}
|
|
326
332
|
|
|
327
|
-
/**
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
readonly fixing: boolean;
|
|
333
|
+
/** Fixes inferences. */
|
|
334
|
+
get mapper(): TypeMapper {
|
|
335
|
+
return this;
|
|
336
|
+
}
|
|
332
337
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
this.
|
|
338
|
+
/** Maps to the current inferences without fixing them. */
|
|
339
|
+
get nonFixingMapper(): TypeMapper {
|
|
340
|
+
const mapper = new NonFixingInferenceMapper(this);
|
|
341
|
+
const outer = this.nonFixingOuter;
|
|
342
|
+
return outer !== undefined ? combineTypeMappers(this.c, mapper, outer) : mapper;
|
|
338
343
|
}
|
|
339
344
|
|
|
340
345
|
map(type: Type): Type {
|
|
341
|
-
const inferences = this.
|
|
346
|
+
const inferences = this.inferences;
|
|
342
347
|
for (let i = 0; i < inferences.length; i++) {
|
|
343
348
|
const inference = inferences[i]!;
|
|
344
349
|
if (type !== inference.typeParameter) continue;
|
|
345
|
-
if (
|
|
350
|
+
if (!inference.isFixed) {
|
|
346
351
|
// Infer from intra-expression sites before committing to an inference.
|
|
347
|
-
inferFromIntraExpressionSites(this.c, this
|
|
352
|
+
inferFromIntraExpressionSites(this.c, this);
|
|
348
353
|
clearCachedInferences(inferences);
|
|
349
354
|
inference.isFixed = true;
|
|
350
355
|
}
|
|
351
|
-
return getInferredType(this.c, this
|
|
356
|
+
return getInferredType(this.c, this, i);
|
|
352
357
|
}
|
|
353
358
|
return type;
|
|
354
359
|
}
|
|
355
360
|
}
|
|
356
361
|
|
|
362
|
+
/** Maps a context's type parameters to their inferred types without fixing them. */
|
|
363
|
+
export class NonFixingInferenceMapper extends TypeMapper {
|
|
364
|
+
readonly context: InferenceContext;
|
|
365
|
+
|
|
366
|
+
constructor(context: InferenceContext) {
|
|
367
|
+
super();
|
|
368
|
+
this.context = context;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
map(type: Type): Type {
|
|
372
|
+
const context = this.context;
|
|
373
|
+
const inferences = context.inferences;
|
|
374
|
+
for (let i = 0; i < inferences.length; i++)
|
|
375
|
+
if (type === inferences[i]!.typeParameter) return getInferredType(context.c, context, i);
|
|
376
|
+
return type;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
357
380
|
export function createInferenceContext(
|
|
358
381
|
c: Checker,
|
|
359
382
|
typeParameters: readonly Type[],
|
|
@@ -402,7 +425,7 @@ export function createOuterReturnMapper(c: Checker, context: InferenceContext):
|
|
|
402
425
|
}
|
|
403
426
|
|
|
404
427
|
export function addIntraExpressionInferenceSite(context: InferenceContext, node: Node, type: Type): void {
|
|
405
|
-
context.intraExpressionInferenceSites.push(new IntraExpressionInferenceSite(node, type));
|
|
428
|
+
(context.intraExpressionInferenceSites ??= []).push(new IntraExpressionInferenceSite(node, type));
|
|
406
429
|
}
|
|
407
430
|
|
|
408
431
|
export function clearCachedInferences(inferences: InferenceInfo[]): void {
|
|
@@ -2126,7 +2149,8 @@ export function instantiateReverseMappedType(c: Checker, t: ReverseMappedType, m
|
|
|
2126
2149
|
/** Infers early from intra-expression sites (context-sensitive elements of object and array literals). */
|
|
2127
2150
|
export function inferFromIntraExpressionSites(c: Checker, context: InferenceContext): void {
|
|
2128
2151
|
const sites = context.intraExpressionInferenceSites;
|
|
2129
|
-
|
|
2152
|
+
if (sites === undefined) return;
|
|
2153
|
+
context.intraExpressionInferenceSites = undefined;
|
|
2130
2154
|
for (const site of sites) {
|
|
2131
2155
|
const contextualType = getContextualTypeForInference(c, site.node);
|
|
2132
2156
|
if (contextualType !== undefined)
|
|
@@ -2402,7 +2426,7 @@ export function inferTypesForConditional(
|
|
|
2402
2426
|
// The constraints of `infer` type parameters may refer to other roots or to what `mapper` maps,
|
|
2403
2427
|
// so the non-fixing mapper combines with `mapper`.
|
|
2404
2428
|
const context = createInferenceContext(c, root.inferTypeParameters, undefined, InferenceFlags.None, undefined);
|
|
2405
|
-
if (mapper !== undefined) context.
|
|
2429
|
+
if (mapper !== undefined) context.nonFixingOuter = mapper;
|
|
2406
2430
|
// Inferences from constraints could eagerly resolve what should defer; contravariance is always strict.
|
|
2407
2431
|
if (!checkTypeDeferred)
|
|
2408
2432
|
inferTypes(
|
|
@@ -1611,6 +1611,170 @@ export function getPropertyOfTypeEx(
|
|
|
1611
1611
|
return undefined;
|
|
1612
1612
|
}
|
|
1613
1613
|
|
|
1614
|
+
/**
|
|
1615
|
+
* A long property list that `propertiesRelatedTo` walks: the position of each name, and the positions of
|
|
1616
|
+
* the static private properties, which `getUnmatchedProperty` never reports, and of the required ones.
|
|
1617
|
+
*/
|
|
1618
|
+
export class PropertyListIndex {
|
|
1619
|
+
readonly positions: Map<string, number>;
|
|
1620
|
+
readonly staticPrivate: number[];
|
|
1621
|
+
readonly required: number[];
|
|
1622
|
+
|
|
1623
|
+
constructor(positions: Map<string, number>, staticPrivate: number[], required: number[]) {
|
|
1624
|
+
this.positions = positions;
|
|
1625
|
+
this.staticPrivate = staticPrivate;
|
|
1626
|
+
this.required = required;
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
/** The uses of a long property list after which `propertyListIndex` indexes it by a table of its own. */
|
|
1631
|
+
const propertyListUsesBeforeIndex = 3;
|
|
1632
|
+
|
|
1633
|
+
/**
|
|
1634
|
+
* The index of `properties`, the properties of `target`. Where the members of `target` are properties
|
|
1635
|
+
* with shared names (`PropertyMembers` with `MemberNames`), the index reads the positions of those names.
|
|
1636
|
+
* Other lists get a positions table of their own on the use after the first `propertyListUsesBeforeIndex`:
|
|
1637
|
+
* most long lists are related only a few times, and the lists related many times hold most of the lookups
|
|
1638
|
+
* the index saves. Undefined before that, and where the list repeats a name.
|
|
1639
|
+
*/
|
|
1640
|
+
function propertyListIndex(c: Checker, target: Type, properties: Symbol[]): PropertyListIndex | undefined {
|
|
1641
|
+
const known = c.propertyListIndexes.get(properties);
|
|
1642
|
+
if (known instanceof PropertyListIndex) return known;
|
|
1643
|
+
if (known === null) return undefined;
|
|
1644
|
+
let positions: Map<string, number> | undefined;
|
|
1645
|
+
const pending = (target.flags & TypeFlags.Object) !== 0 ? membersHolder(c, target).pendingMembers : undefined;
|
|
1646
|
+
if (
|
|
1647
|
+
pending instanceof PropertyMembers &&
|
|
1648
|
+
pending.materializedProperties === properties &&
|
|
1649
|
+
pending.names !== undefined
|
|
1650
|
+
) {
|
|
1651
|
+
// The names are the names of the properties, in order (hasMemberNames).
|
|
1652
|
+
positions = pending.names.positions;
|
|
1653
|
+
if (positions.size !== properties.length) {
|
|
1654
|
+
c.propertyListIndexes.set(properties, null);
|
|
1655
|
+
return undefined;
|
|
1656
|
+
}
|
|
1657
|
+
} else {
|
|
1658
|
+
const uses = known ?? 0;
|
|
1659
|
+
if (uses < propertyListUsesBeforeIndex) {
|
|
1660
|
+
c.propertyListIndexes.set(properties, uses + 1);
|
|
1661
|
+
return undefined;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
const own = positions === undefined ? new Map<string, number>() : undefined;
|
|
1665
|
+
const staticPrivate: number[] = [];
|
|
1666
|
+
const required: number[] = [];
|
|
1667
|
+
for (let i = 0; i < properties.length; i++) {
|
|
1668
|
+
const p = properties[i]!;
|
|
1669
|
+
if (own !== undefined) {
|
|
1670
|
+
if (own.has(p.name)) {
|
|
1671
|
+
c.propertyListIndexes.set(properties, null);
|
|
1672
|
+
return undefined;
|
|
1673
|
+
}
|
|
1674
|
+
own.set(p.name, i);
|
|
1675
|
+
}
|
|
1676
|
+
if (isStaticPrivateIdentifierProperty(p)) staticPrivate.push(i);
|
|
1677
|
+
else if ((p.flags & SymbolFlags.Optional) === 0 && (p.checkFlags & CheckFlags.Partial) === 0) required.push(i);
|
|
1678
|
+
}
|
|
1679
|
+
const index = new PropertyListIndex((positions ?? own)!, staticPrivate, required);
|
|
1680
|
+
c.propertyListIndexes.set(properties, index);
|
|
1681
|
+
return index;
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
/**
|
|
1685
|
+
* `getUnmatchedProperty(c, source, target, requireOptionalProperties, false)` where `targetProperties` are
|
|
1686
|
+
* the target's properties and `found` the positions of the names the source has
|
|
1687
|
+
* (`positionsOfNamesFoundInSource`): the first property that is not static private, and is required unless
|
|
1688
|
+
* `requireOptionalProperties`, at a position not in `found`.
|
|
1689
|
+
*/
|
|
1690
|
+
export function firstUnmatchedProperty(
|
|
1691
|
+
c: Checker,
|
|
1692
|
+
targetProperties: Symbol[],
|
|
1693
|
+
found: number[],
|
|
1694
|
+
requireOptionalProperties: boolean,
|
|
1695
|
+
): Symbol | undefined {
|
|
1696
|
+
const index = c.propertyListIndexes.get(targetProperties) as PropertyListIndex;
|
|
1697
|
+
let next = 0;
|
|
1698
|
+
if (!requireOptionalProperties) {
|
|
1699
|
+
for (const position of index.required) {
|
|
1700
|
+
while (next < found.length && found[next]! < position) next++;
|
|
1701
|
+
if (next === found.length || found[next] !== position) return targetProperties[position];
|
|
1702
|
+
}
|
|
1703
|
+
return undefined;
|
|
1704
|
+
}
|
|
1705
|
+
const staticPrivate = index.staticPrivate;
|
|
1706
|
+
let nextPrivate = 0;
|
|
1707
|
+
for (let position = 0; position < targetProperties.length; position++) {
|
|
1708
|
+
// A position can be both found and static private: both lists move past it.
|
|
1709
|
+
const isFound = next < found.length && found[next] === position;
|
|
1710
|
+
if (isFound) next++;
|
|
1711
|
+
const isStaticPrivate = nextPrivate < staticPrivate.length && staticPrivate[nextPrivate] === position;
|
|
1712
|
+
if (isStaticPrivate) nextPrivate++;
|
|
1713
|
+
if (!isFound && !isStaticPrivate) return targetProperties[position];
|
|
1714
|
+
}
|
|
1715
|
+
return undefined;
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
/** The shortest target property list that `positionsOfNamesFoundInSource` indexes. */
|
|
1719
|
+
const indexedTargetPropertiesMinimum = 32;
|
|
1720
|
+
|
|
1721
|
+
/** The properties of `t` where its members are resolved and instantiated, else undefined. */
|
|
1722
|
+
function resolvedPropertiesIfAny(c: Checker, t: Type): Symbol[] | undefined {
|
|
1723
|
+
const holder = (t.objectFlags & ObjectFlags.MembersResolved) !== 0 ? (t as StructuredType) : membersHolder(c, t);
|
|
1724
|
+
if ((holder.objectFlags & ObjectFlags.MembersResolved) === 0) return undefined;
|
|
1725
|
+
const pending = holder.pendingMembers;
|
|
1726
|
+
return pending === undefined || pending.materializedProperties !== undefined ? holder.properties : undefined;
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
/**
|
|
1730
|
+
* The positions in `targetProperties`, the properties of `target`, ascending, of the names
|
|
1731
|
+
* `getPropertyOfType(c, source, name)` finds: the names of the source's properties and of the Function and
|
|
1732
|
+
* Object members its lookups fall back to. `getPropertyOfType` answers undefined for the names at every
|
|
1733
|
+
* other position. Undefined where the answer cannot be read from resolved property lists without resolving
|
|
1734
|
+
* anything (not an object type, an apparent type, members not resolved or not instantiated yet, a module),
|
|
1735
|
+
* where the target list is too short or the source list too long to save lookups, and where the target
|
|
1736
|
+
* list has no index (yet: `propertyListIndex`).
|
|
1737
|
+
*/
|
|
1738
|
+
export function positionsOfNamesFoundInSource(
|
|
1739
|
+
c: Checker,
|
|
1740
|
+
source: Type,
|
|
1741
|
+
target: Type,
|
|
1742
|
+
targetProperties: Symbol[],
|
|
1743
|
+
): number[] | undefined {
|
|
1744
|
+
if (targetProperties.length < indexedTargetPropertiesMinimum) return undefined;
|
|
1745
|
+
if ((source.flags & TypeFlags.Object) === 0 || !isOwnReducedApparentType(source)) return undefined;
|
|
1746
|
+
// A module's member that only an `export type *` declaration exports is not found.
|
|
1747
|
+
if (source.symbol !== undefined && (source.symbol.flags & SymbolFlags.ValueModule) !== 0) return undefined;
|
|
1748
|
+
const sourceProperties = resolvedPropertiesIfAny(c, source);
|
|
1749
|
+
if (sourceProperties === undefined) return undefined;
|
|
1750
|
+
const resolved = membersHolder(c, source);
|
|
1751
|
+
let functionType: Type | undefined;
|
|
1752
|
+
if (source === c.anyFunctionType) functionType = c.globalFunctionType;
|
|
1753
|
+
else if (resolved.callSignatures.length !== 0) functionType = c.globalCallableFunctionType;
|
|
1754
|
+
else if (resolved.constructSignatures.length !== 0) functionType = c.globalNewableFunctionType;
|
|
1755
|
+
let functionProperties = emptySymbols;
|
|
1756
|
+
if (functionType !== undefined && (functionType.flags & TypeFlags.Object) !== 0) {
|
|
1757
|
+
const properties = resolvedPropertiesIfAny(c, functionType);
|
|
1758
|
+
if (properties === undefined) return undefined;
|
|
1759
|
+
functionProperties = properties;
|
|
1760
|
+
}
|
|
1761
|
+
const objectProperties =
|
|
1762
|
+
(c.globalObjectType.flags & TypeFlags.Object) !== 0 ? resolvedPropertiesIfAny(c, c.globalObjectType) : emptySymbols;
|
|
1763
|
+
if (objectProperties === undefined) return undefined;
|
|
1764
|
+
if ((sourceProperties.length + functionProperties.length + objectProperties.length) * 4 > targetProperties.length)
|
|
1765
|
+
return undefined;
|
|
1766
|
+
const index = propertyListIndex(c, target, targetProperties);
|
|
1767
|
+
if (index === undefined) return undefined;
|
|
1768
|
+
const positions = index.positions;
|
|
1769
|
+
const found: number[] = [];
|
|
1770
|
+
for (const list of [sourceProperties, functionProperties, objectProperties])
|
|
1771
|
+
for (const p of list) {
|
|
1772
|
+
const position = positions.get(p.name);
|
|
1773
|
+
if (position !== undefined && !found.includes(position)) found.push(position);
|
|
1774
|
+
}
|
|
1775
|
+
return found.sort((a, b) => a - b);
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1614
1778
|
export function getPropertyOfObjectType(c: Checker, t: Type, name: string): Symbol | undefined {
|
|
1615
1779
|
if ((t.flags & TypeFlags.Object) === 0) return undefined;
|
|
1616
1780
|
const symbol = getResolvedMember(resolveStructuredTypeMembers(c, t), name);
|
|
@@ -226,6 +226,22 @@ export function resolveExternalModuleNameWorker(
|
|
|
226
226
|
);
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
/** A `resolveExternalModule` result that reported nothing, and the arguments it was computed for. */
|
|
230
|
+
export class ModuleResolution {
|
|
231
|
+
constructor(
|
|
232
|
+
readonly moduleReference: string,
|
|
233
|
+
readonly moduleNotFoundError: DiagnosticMessage | undefined,
|
|
234
|
+
readonly isForAugmentation: boolean,
|
|
235
|
+
readonly symbol: Symbol | undefined,
|
|
236
|
+
) {}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* The module symbol `moduleReference` resolves to from `location`, reporting resolution errors at
|
|
241
|
+
* `errorNode`. Each name an import or export declaration lists resolves its module specifier again,
|
|
242
|
+
* with the same result and the same diagnostics: a result that reported nothing is kept for the
|
|
243
|
+
* specifier and returned to later calls from the same declaration (`sharesSpecifierContext`).
|
|
244
|
+
*/
|
|
229
245
|
export function resolveExternalModule(
|
|
230
246
|
c: Checker,
|
|
231
247
|
location: Node,
|
|
@@ -233,6 +249,80 @@ export function resolveExternalModule(
|
|
|
233
249
|
moduleNotFoundError: DiagnosticMessage | undefined,
|
|
234
250
|
errorNode: Node | undefined,
|
|
235
251
|
isForAugmentation: boolean,
|
|
252
|
+
): Symbol | undefined {
|
|
253
|
+
// An augmentation merged later can give the resolved module a new merged symbol, so results are
|
|
254
|
+
// kept only once every augmentation is merged.
|
|
255
|
+
const shared = c.modulesMerged && errorNode !== undefined && sharesSpecifierContext(location, errorNode);
|
|
256
|
+
if (shared) {
|
|
257
|
+
const known = c.moduleResolutions.get(errorNode);
|
|
258
|
+
if (
|
|
259
|
+
known !== undefined &&
|
|
260
|
+
known.moduleReference === moduleReference &&
|
|
261
|
+
known.moduleNotFoundError === moduleNotFoundError &&
|
|
262
|
+
known.isForAugmentation === isForAugmentation
|
|
263
|
+
)
|
|
264
|
+
return known.symbol;
|
|
265
|
+
}
|
|
266
|
+
const reports = c.reports;
|
|
267
|
+
const symbol = resolveExternalModuleWorker(
|
|
268
|
+
c,
|
|
269
|
+
location,
|
|
270
|
+
moduleReference,
|
|
271
|
+
moduleNotFoundError,
|
|
272
|
+
errorNode,
|
|
273
|
+
isForAugmentation,
|
|
274
|
+
);
|
|
275
|
+
if (shared && c.reports === reports)
|
|
276
|
+
c.moduleResolutions.set(
|
|
277
|
+
errorNode,
|
|
278
|
+
new ModuleResolution(moduleReference, moduleNotFoundError, isForAugmentation, symbol),
|
|
279
|
+
);
|
|
280
|
+
return symbol;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Whether a resolution from `location` with errors at `errorNode` depends on `location` only through
|
|
285
|
+
* the declaration that `errorNode` is the module specifier of: `location` is that declaration, a
|
|
286
|
+
* clause or specifier inside it, or the specifier itself. The resolution mode, the emittability of
|
|
287
|
+
* the import and its resolution-mode attributes then all come from that declaration.
|
|
288
|
+
*/
|
|
289
|
+
function sharesSpecifierContext(location: Node, errorNode: Node): boolean {
|
|
290
|
+
const declaration = errorNode.parent;
|
|
291
|
+
if (
|
|
292
|
+
declaration === undefined ||
|
|
293
|
+
(declaration.kind !== SyntaxKind.ImportDeclaration &&
|
|
294
|
+
declaration.kind !== SyntaxKind.JSImportDeclaration &&
|
|
295
|
+
declaration.kind !== SyntaxKind.ExportDeclaration) ||
|
|
296
|
+
getModuleSpecifier(declaration) !== errorNode
|
|
297
|
+
)
|
|
298
|
+
return false;
|
|
299
|
+
for (let current: Node | undefined = location; current !== undefined; current = current.parent)
|
|
300
|
+
switch (current.kind) {
|
|
301
|
+
case SyntaxKind.ImportDeclaration:
|
|
302
|
+
case SyntaxKind.JSImportDeclaration:
|
|
303
|
+
case SyntaxKind.ExportDeclaration:
|
|
304
|
+
return current === declaration;
|
|
305
|
+
case SyntaxKind.ImportClause:
|
|
306
|
+
case SyntaxKind.NamedImports:
|
|
307
|
+
case SyntaxKind.NamespaceImport:
|
|
308
|
+
case SyntaxKind.ImportSpecifier:
|
|
309
|
+
case SyntaxKind.NamedExports:
|
|
310
|
+
case SyntaxKind.NamespaceExport:
|
|
311
|
+
case SyntaxKind.ExportSpecifier:
|
|
312
|
+
break;
|
|
313
|
+
default:
|
|
314
|
+
if (current !== errorNode) return false;
|
|
315
|
+
}
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function resolveExternalModuleWorker(
|
|
320
|
+
c: Checker,
|
|
321
|
+
location: Node,
|
|
322
|
+
moduleReference: string,
|
|
323
|
+
moduleNotFoundError: DiagnosticMessage | undefined,
|
|
324
|
+
errorNode: Node | undefined,
|
|
325
|
+
isForAugmentation: boolean,
|
|
236
326
|
): Symbol | undefined {
|
|
237
327
|
if (errorNode !== undefined && moduleReference.startsWith('@types/'))
|
|
238
328
|
c.error(
|
|
@@ -789,7 +879,8 @@ function isOnlyImportableAsDefault(c: Checker, usage: Node, resolvedModule: Symb
|
|
|
789
879
|
const targetFile = moduleSymbol !== undefined ? getSourceFileOfModuleSymbol(moduleSymbol) : undefined;
|
|
790
880
|
return (
|
|
791
881
|
targetFile !== undefined &&
|
|
792
|
-
(isJsonSourceFile(targetFile) ||
|
|
882
|
+
(isJsonSourceFile(targetFile) ||
|
|
883
|
+
(targetFile.fileName.endsWith('.d.json.ts') && getDeclarationFileExtension(targetFile.fileName) === '.d.json.ts'))
|
|
793
884
|
);
|
|
794
885
|
}
|
|
795
886
|
|
|
@@ -129,7 +129,16 @@ import { getTypeForBindingElement, getTypeFromBindingPattern } from './checker-d
|
|
|
129
129
|
import { checkRightHandSideOfForOf } from './checker-statements.js';
|
|
130
130
|
import { getTypeWithFacts, TypeFacts, hasTypeFacts, getNonNullableType } from './checker-flow.js';
|
|
131
131
|
import { getTypeOfModuleExportsSymbol, getWidenedTypeForAssignmentDeclaration } from './checker-javascript.js';
|
|
132
|
-
import {
|
|
132
|
+
import {
|
|
133
|
+
CheckFlags,
|
|
134
|
+
copyDeclarations,
|
|
135
|
+
declarationAt,
|
|
136
|
+
declarationCount,
|
|
137
|
+
getDeclarations,
|
|
138
|
+
getSymbolId,
|
|
139
|
+
type Symbol,
|
|
140
|
+
SymbolFlags,
|
|
141
|
+
} from './symbol.js';
|
|
133
142
|
|
|
134
143
|
export function getTypeOfSymbol(c: Checker, symbol: Symbol): Type {
|
|
135
144
|
const checkFlags = symbol.checkFlags;
|
|
@@ -932,12 +941,13 @@ export function isReadonlySymbol(c: Checker, symbol: Symbol): boolean {
|
|
|
932
941
|
(getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Constant) !== 0) ||
|
|
933
942
|
((symbol.flags & SymbolFlags.Accessor) !== 0 && (symbol.flags & SymbolFlags.SetAccessor) === 0) ||
|
|
934
943
|
(symbol.flags & SymbolFlags.EnumMember) !== 0 ||
|
|
935
|
-
someReadonlyAssignmentDeclaration(c,
|
|
944
|
+
someReadonlyAssignmentDeclaration(c, symbol)
|
|
936
945
|
);
|
|
937
946
|
}
|
|
938
947
|
|
|
939
|
-
function someReadonlyAssignmentDeclaration(c: Checker,
|
|
940
|
-
for (
|
|
948
|
+
function someReadonlyAssignmentDeclaration(c: Checker, symbol: Symbol): boolean {
|
|
949
|
+
for (let i = 0; i < declarationCount(symbol); i++)
|
|
950
|
+
if (isReadonlyAssignmentDeclaration(c, declarationAt(symbol, i))) return true;
|
|
941
951
|
return false;
|
|
942
952
|
}
|
|
943
953
|
|
|
@@ -1761,7 +1761,10 @@ export function symbolIsValue(c: Checker, symbol: Symbol): boolean {
|
|
|
1761
1761
|
function isDeclarationContainedBy(symbol: Symbol, container: Symbol): boolean {
|
|
1762
1762
|
const declaration = symbol.valueDeclaration;
|
|
1763
1763
|
if (declaration !== undefined)
|
|
1764
|
-
for (
|
|
1764
|
+
for (let i = 0; i < declarationCount(container); i++) {
|
|
1765
|
+
const d = declarationAt(container, i);
|
|
1766
|
+
if (declaration.pos >= d.pos && declaration.end <= d.end) return true;
|
|
1767
|
+
}
|
|
1765
1768
|
return false;
|
|
1766
1769
|
}
|
|
1767
1770
|
|
package/src/compiler/checker.ts
CHANGED
|
@@ -72,6 +72,7 @@ import {
|
|
|
72
72
|
type TypeChecking,
|
|
73
73
|
} from './checker-types.js';
|
|
74
74
|
import { getBaseTypes } from './checker-declared-types.js';
|
|
75
|
+
import type { ModuleResolution } from './checker-modules.js';
|
|
75
76
|
import { getFalseTypeFromConditionalType, getTrueTypeFromConditionalType } from './checker-type-operators.js';
|
|
76
77
|
import {
|
|
77
78
|
createArrayType,
|
|
@@ -112,6 +113,7 @@ import { SourceFileMetadata, getEmitModuleFormatOfFile } from './program-utiliti
|
|
|
112
113
|
import type { GrammarChecker } from './checker-grammar.js';
|
|
113
114
|
import type { ResolvedModule } from './module-resolution-types.js';
|
|
114
115
|
import type { ModuleSpecifierHost } from './module-specifiers.js';
|
|
116
|
+
import type { PropertyListIndex } from './checker-members.js';
|
|
115
117
|
|
|
116
118
|
/** What the checker needs from a program. */
|
|
117
119
|
export abstract class CheckerHost {
|
|
@@ -345,6 +347,15 @@ export class Checker implements TypeChecking {
|
|
|
345
347
|
|
|
346
348
|
readonly diagnostics = new DiagnosticCollection();
|
|
347
349
|
readonly suggestionDiagnostics = new DiagnosticCollection();
|
|
350
|
+
/** Diagnostics and suggestions reported so far, whether kept or not (`resolveExternalModule`'s cache). */
|
|
351
|
+
reports = 0;
|
|
352
|
+
/** `resolveExternalModule` results that reported nothing, by module specifier (checker-modules.ts). */
|
|
353
|
+
readonly moduleResolutions = new Map<Node, ModuleResolution>();
|
|
354
|
+
/**
|
|
355
|
+
* Whether ambient modules and module augmentations are merged. Merging can give a module a new
|
|
356
|
+
* merged symbol, so `resolveExternalModule` keeps results only from then on.
|
|
357
|
+
*/
|
|
358
|
+
modulesMerged = false;
|
|
348
359
|
/** Module specifiers of `import("…")` types, by module symbol id, importing file path and resolution mode. */
|
|
349
360
|
readonly moduleSpecifiers = new Map<string, string>();
|
|
350
361
|
/** Specifier generation for hosts without a program. */
|
|
@@ -359,6 +370,11 @@ export class Checker implements TypeChecking {
|
|
|
359
370
|
readonly sideHolders = new LinkTable<Type>();
|
|
360
371
|
/** The same for signatures with side state (`signatureSideOf`), by signature id. */
|
|
361
372
|
readonly signatureSideHolders = new LinkTable<Signature>();
|
|
373
|
+
/**
|
|
374
|
+
* The indexes of long property lists that `propertiesRelatedTo` walks; before a list is indexed, its uses
|
|
375
|
+
* so far; null where a list repeats a name.
|
|
376
|
+
*/
|
|
377
|
+
readonly propertyListIndexes = new Map<Symbol[], PropertyListIndex | number | null>();
|
|
362
378
|
/** The type of a value symbol. */
|
|
363
379
|
readonly symbolTypes = new LinkTable<Type>();
|
|
364
380
|
/** For instantiated and synthetic symbols, the symbol they come from. */
|
|
@@ -894,6 +910,7 @@ export class Checker implements TypeChecking {
|
|
|
894
910
|
this.diagnostics.startLog();
|
|
895
911
|
this.suggestionDiagnostics.startLog();
|
|
896
912
|
mergeAmbientModulesAndAugmentations(this);
|
|
913
|
+
this.modulesMerged = true;
|
|
897
914
|
this.mergeDiagnostics.push(this.diagnostics.takeLog(), this.suggestionDiagnostics.takeLog());
|
|
898
915
|
}
|
|
899
916
|
|
|
@@ -1026,11 +1043,13 @@ export class Checker implements TypeChecking {
|
|
|
1026
1043
|
}
|
|
1027
1044
|
|
|
1028
1045
|
addDiagnostic(diagnostic: Diagnostic): void {
|
|
1046
|
+
this.reports++;
|
|
1029
1047
|
// Discard diagnostics created while at the maximum number of nested typeToString calls.
|
|
1030
1048
|
if (this.serializationLevel < maxSerializationLevel) this.diagnostics.add(diagnostic);
|
|
1031
1049
|
}
|
|
1032
1050
|
|
|
1033
1051
|
addSuggestion(diagnostic: Diagnostic): void {
|
|
1052
|
+
this.reports++;
|
|
1034
1053
|
this.suggestionDiagnostics.add(diagnostic);
|
|
1035
1054
|
}
|
|
1036
1055
|
|
package/src/compiler/decoder.ts
CHANGED
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
BindingPattern,
|
|
14
14
|
Block,
|
|
15
15
|
BreakStatement,
|
|
16
|
-
CallExpression,
|
|
17
16
|
CallSignatureDeclaration,
|
|
18
17
|
CaseBlock,
|
|
19
18
|
CaseOrDefaultClause,
|
|
@@ -149,7 +148,6 @@ import {
|
|
|
149
148
|
PrefixUnaryExpression,
|
|
150
149
|
PrivateIdentifier,
|
|
151
150
|
PropertyAccessExpression,
|
|
152
|
-
PropertyAssignment,
|
|
153
151
|
PropertyDeclaration,
|
|
154
152
|
PropertySignatureDeclaration,
|
|
155
153
|
QualifiedName,
|
|
@@ -197,6 +195,8 @@ import {
|
|
|
197
195
|
WhileStatement,
|
|
198
196
|
WithStatement,
|
|
199
197
|
YieldExpression,
|
|
198
|
+
newCallExpression,
|
|
199
|
+
newPropertyAssignment,
|
|
200
200
|
} from './ast.js';
|
|
201
201
|
import { modifiersToFlags } from './ast-utilities.js';
|
|
202
202
|
import { protocolVersion } from './encoder.js';
|
|
@@ -883,7 +883,7 @@ class Decoder {
|
|
|
883
883
|
case SyntaxKind.ElementAccessExpression:
|
|
884
884
|
return new ElementAccessExpression(this.required(0), this.token(1), this.required(2), 0);
|
|
885
885
|
case SyntaxKind.CallExpression:
|
|
886
|
-
return
|
|
886
|
+
return newCallExpression(this.required(0), this.token(1), this.list(2), this.requiredList(3), 0, false);
|
|
887
887
|
case SyntaxKind.NewExpression:
|
|
888
888
|
return new NewExpression(this.required(0), this.list(1), this.list(2));
|
|
889
889
|
case SyntaxKind.MetaProperty:
|
|
@@ -910,12 +910,13 @@ class Decoder {
|
|
|
910
910
|
case SyntaxKind.SpreadAssignment:
|
|
911
911
|
return new SpreadAssignment(this.required(0));
|
|
912
912
|
case SyntaxKind.PropertyAssignment:
|
|
913
|
-
return
|
|
913
|
+
return newPropertyAssignment(
|
|
914
914
|
this.modifiers(0),
|
|
915
915
|
this.required(1),
|
|
916
916
|
this.token(2),
|
|
917
917
|
this.node(3),
|
|
918
918
|
this.required(4),
|
|
919
|
+
false,
|
|
919
920
|
);
|
|
920
921
|
case SyntaxKind.ShorthandPropertyAssignment:
|
|
921
922
|
return new ShorthandPropertyAssignment(
|