Skip to content

Commit 6ff28d1

Browse files
authored
Node builder reuses type predicate nodes, more often reuses return position nodes (#57990)
1 parent 12402f2 commit 6ff28d1

File tree

191 files changed

+1194
-1375
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

191 files changed

+1194
-1375
lines changed

src/compiler/checker.ts

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,7 @@ import {
855855
ModuleKind,
856856
ModuleResolutionKind,
857857
ModuleSpecifierResolutionHost,
858+
Mutable,
858859
NamedDeclaration,
859860
NamedExports,
860861
NamedImportsOrExports,
@@ -6469,6 +6470,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
64696470
typePredicateToTypePredicateNode: (typePredicate: TypePredicate, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typePredicateToTypePredicateNodeHelper(typePredicate, context)),
64706471
expressionOrTypeToTypeNode: (expr: Expression | JsxAttributeValue | undefined, type: Type, addUndefined?: boolean, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => expressionOrTypeToTypeNode(context, expr, type, addUndefined)),
64716472
serializeTypeForDeclaration: (type: Type, symbol: Symbol, addUndefined?: boolean, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => serializeTypeForDeclaration(context, type, symbol, enclosingDeclaration, /*includePrivateSymbol*/ undefined, /*bundled*/ undefined, addUndefined)),
6473+
serializeReturnTypeForSignature: (signature: Signature, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => serializeReturnTypeForSignature(context, signature)),
64726474
indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => indexInfoToIndexSignatureDeclarationHelper(indexInfo, context, /*typeNode*/ undefined)),
64736475
signatureToSignatureDeclaration: (signature: Signature, kind: SignatureDeclaration["kind"], enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => signatureToSignatureDeclarationHelper(signature, kind, context)),
64746476
symbolToEntityName: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToName(symbol, context, meaning, /*expectsIdentifier*/ false)),
@@ -7649,8 +7651,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
76497651
}
76507652

76517653
function signatureToSignatureDeclarationHelper(signature: Signature, kind: SignatureDeclaration["kind"], context: NodeBuilderContext, options?: SignatureToSignatureDeclarationOptions): SignatureDeclaration {
7652-
const suppressAny = context.flags & NodeBuilderFlags.SuppressAnyReturnType;
7653-
if (suppressAny) context.flags &= ~NodeBuilderFlags.SuppressAnyReturnType; // suppress only toplevel `any`s
7654+
const flags = context.flags;
7655+
context.flags &= ~NodeBuilderFlags.SuppressAnyReturnType; // SuppressAnyReturnType should only apply to the signature `return` position
76547656
context.approximateLength += 3; // Usually a signature contributes a few more characters than this, but 3 is the minimum
76557657
let typeParameters: TypeParameterDeclaration[] | undefined;
76567658
let typeArguments: TypeNode[] | undefined;
@@ -7780,21 +7782,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
77807782
if (thisParameter) {
77817783
parameters.unshift(thisParameter);
77827784
}
7785+
context.flags = flags;
7786+
7787+
const returnTypeNode = serializeReturnTypeForSignature(context, signature, options?.privateSymbolVisitor, options?.bundledImports);
77837788

7784-
let returnTypeNode: TypeNode | undefined;
7785-
const typePredicate = getTypePredicateOfSignature(signature);
7786-
if (typePredicate) {
7787-
returnTypeNode = typePredicateToTypePredicateNodeHelper(typePredicate, context);
7788-
}
7789-
else {
7790-
const returnType = getReturnTypeOfSignature(signature);
7791-
if (returnType && !(suppressAny && isTypeAny(returnType))) {
7792-
returnTypeNode = serializeReturnTypeForSignature(context, returnType, signature, options?.privateSymbolVisitor, options?.bundledImports);
7793-
}
7794-
else if (!suppressAny) {
7795-
returnTypeNode = factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
7796-
}
7797-
}
77987789
let modifiers = options?.modifiers;
77997790
if ((kind === SyntaxKind.ConstructorType) && signature.flags & SignatureFlags.Abstract) {
78007791
const flags = modifiersToFlags(modifiers);
@@ -8572,7 +8563,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
85728563
return false;
85738564
}
85748565

8575-
function serializeReturnTypeForSignature(context: NodeBuilderContext, type: Type, signature: Signature, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) {
8566+
function serializeReturnTypeForSignature(context: NodeBuilderContext, signature: Signature, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) {
8567+
const suppressAny = context.flags & NodeBuilderFlags.SuppressAnyReturnType;
8568+
const flags = context.flags;
8569+
if (suppressAny) context.flags &= ~NodeBuilderFlags.SuppressAnyReturnType; // suppress only toplevel `any`s
8570+
let returnTypeNode: TypeNode | undefined;
8571+
const returnType = getReturnTypeOfSignature(signature);
8572+
if (returnType && !(suppressAny && isTypeAny(returnType))) {
8573+
returnTypeNode = serializeReturnTypeForSignatureWorker(context, signature, includePrivateSymbol, bundled);
8574+
}
8575+
else if (!suppressAny) {
8576+
returnTypeNode = factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
8577+
}
8578+
context.flags = flags;
8579+
return returnTypeNode;
8580+
}
8581+
8582+
function serializeReturnTypeForSignatureWorker(context: NodeBuilderContext, signature: Signature, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) {
8583+
const typePredicate = getTypePredicateOfSignature(signature);
8584+
const type = getReturnTypeOfSignature(signature);
85768585
if (!isErrorType(type) && context.enclosingDeclaration) {
85778586
const annotation = signature.declaration && getEffectiveReturnTypeNode(signature.declaration);
85788587
const enclosingDeclarationIgnoringFakeScope = getEnclosingDeclarationIgnoringFakeScope(context.enclosingDeclaration);
@@ -8585,7 +8594,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
85858594
}
85868595
}
85878596
}
8588-
return typeToTypeNodeHelper(type, context);
8597+
if (typePredicate) {
8598+
return typePredicateToTypePredicateNodeHelper(typePredicate, context);
8599+
}
8600+
const expr = signature.declaration && getPossibleTypeNodeReuseExpression(signature.declaration);
8601+
return expressionOrTypeToTypeNode(context, expr, type);
85898602
}
85908603

85918604
function trackExistingEntityName<T extends EntityNameOrEntityNameExpression>(node: T, context: NodeBuilderContext, includePrivateSymbol?: (s: Symbol) => void) {
@@ -8633,7 +8646,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
86338646
}
86348647
return transformed === existing ? setTextRange(factory.cloneNode(existing), existing) : transformed;
86358648

8636-
function visitExistingNodeTreeSymbols(node: Node): Node {
8649+
function visitExistingNodeTreeSymbols(node: Node): Node | undefined {
86378650
// We don't _actually_ support jsdoc namepath types, emit `any` instead
86388651
if (isJSDocAllType(node) || node.kind === SyntaxKind.JSDocNamepathType) {
86398652
return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
@@ -8642,16 +8655,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
86428655
return factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword);
86438656
}
86448657
if (isJSDocNullableType(node)) {
8645-
return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode), factory.createLiteralTypeNode(factory.createNull())]);
8658+
return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode)!, factory.createLiteralTypeNode(factory.createNull())]);
86468659
}
86478660
if (isJSDocOptionalType(node)) {
8648-
return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode), factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]);
8661+
return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode)!, factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]);
86498662
}
86508663
if (isJSDocNonNullableType(node)) {
86518664
return visitNode(node.type, visitExistingNodeTreeSymbols);
86528665
}
86538666
if (isJSDocVariadicType(node)) {
8654-
return factory.createArrayTypeNode(visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode));
8667+
return factory.createArrayTypeNode(visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode)!);
86558668
}
86568669
if (isJSDocTypeLiteral(node)) {
86578670
return factory.createTypeLiteralNode(map(node.jsDocPropertyTags, t => {
@@ -8743,15 +8756,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
87438756
node.isTypeOf,
87448757
);
87458758
}
8746-
if (isParameter(node)) {
8747-
if (!node.type && !node.initializer) {
8748-
return factory.updateParameterDeclaration(node, /*modifiers*/ undefined, node.dotDotDotToken, visitEachChild(node.name, visitExistingNodeTreeSymbols, /*context*/ undefined), node.questionToken, factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), /*initializer*/ undefined);
8749-
}
8759+
if (isNamedDeclaration(node) && node.name.kind === SyntaxKind.ComputedPropertyName && !isLateBindableName(node.name)) {
8760+
return undefined;
87508761
}
8751-
if (isPropertySignature(node)) {
8752-
if (!node.type && !node.initializer) {
8753-
return factory.updatePropertySignature(node, node.modifiers, node.name, node.questionToken, factory.createKeywordTypeNode(SyntaxKind.AnyKeyword));
8762+
if (
8763+
(isFunctionLike(node) && !node.type)
8764+
|| (isPropertyDeclaration(node) && !node.type && !node.initializer)
8765+
|| (isPropertySignature(node) && !node.type && !node.initializer)
8766+
|| (isParameter(node) && !node.type && !node.initializer)
8767+
) {
8768+
let visited = visitEachChild(node, visitExistingNodeTreeSymbols, /*context*/ undefined);
8769+
if (visited === node) {
8770+
visited = setTextRange(factory.cloneNode(node), node);
87548771
}
8772+
(visited as Mutable<typeof visited>).type = factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
8773+
if (isParameter(node)) {
8774+
(visited as Mutable<ParameterDeclaration>).modifiers = undefined;
8775+
}
8776+
return visited;
87558777
}
87568778

87578779
if (isEntityName(node) || isEntityNameExpression(node)) {
@@ -48664,6 +48686,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4866448686

4866548687
type DeclarationWithPotentialInnerNodeReuse =
4866648688
| SignatureDeclaration
48689+
| JSDocSignature
4866748690
| AccessorDeclaration
4866848691
| VariableLikeDeclaration
4866948692
| PropertyAccessExpression
@@ -48712,13 +48735,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4871248735
if (!signatureDeclaration) {
4871348736
return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode;
4871448737
}
48715-
const signature = getSignatureFromDeclaration(signatureDeclaration);
48716-
const typePredicate = getTypePredicateOfSignature(signature);
48717-
if (typePredicate) {
48718-
// Inferred type predicates
48719-
return nodeBuilder.typePredicateToTypePredicateNode(typePredicate, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker);
48720-
}
48721-
return nodeBuilder.expressionOrTypeToTypeNode(getPossibleTypeNodeReuseExpression(signatureDeclaration), getReturnTypeOfSignature(signature), /*addUndefined*/ undefined, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker);
48738+
return nodeBuilder.serializeReturnTypeForSignature(getSignatureFromDeclaration(signatureDeclaration), enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker);
4872248739
}
4872348740

4872448741
function createTypeOfExpression(exprIn: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) {

tests/baselines/reference/arrayEvery.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ const foo: (number | string)[] = ['aaa'];
1111

1212
const isString = (x: unknown): x is string => typeof x === 'string';
1313
>isString : (x: unknown) => x is string
14-
> : ^^^^ ^^^^^^^^^^^^^^^^
14+
> : ^^^^ ^^^^^
1515
>(x: unknown): x is string => typeof x === 'string' : (x: unknown) => x is string
16-
> : ^^^^ ^^^^^^^^^^^^^^^^
16+
> : ^^^^ ^^^^^
1717
>x : unknown
1818
> : ^^^^^^^
1919
>typeof x === 'string' : boolean

tests/baselines/reference/arrayFind.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// test fix for #18112, type guard predicates should narrow returned element
55
function isNumber(x: any): x is number {
66
>isNumber : (x: any) => x is number
7-
> : ^^^^ ^^^^^^^^^^^^^^^^
7+
> : ^^^^ ^^^^^
88
>x : any
99

1010
return typeof x === "number";

tests/baselines/reference/arrowFunctionWithObjectLiteralBody1.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
=== arrowFunctionWithObjectLiteralBody1.ts ===
44
var v = a => <any>{}
55
>v : (a: any) => any
6-
> : ^^^^^^^^^^^^^^^
6+
> : ^^^^^^^^^^^^
77
>a => <any>{} : (a: any) => any
8-
> : ^^^^^^^^^^^^^^^
8+
> : ^^^^^^^^^^^^
99
>a : any
1010
><any>{} : any
1111
>{} : {}

tests/baselines/reference/arrowFunctionWithObjectLiteralBody2.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
=== arrowFunctionWithObjectLiteralBody2.ts ===
44
var v = a => <any><any>{}
55
>v : (a: any) => any
6-
> : ^^^^^^^^^^^^^^^
6+
> : ^^^^^^^^^^^^
77
>a => <any><any>{} : (a: any) => any
8-
> : ^^^^^^^^^^^^^^^
8+
> : ^^^^^^^^^^^^
99
>a : any
1010
><any><any>{} : any
1111
><any>{} : any

tests/baselines/reference/arrowFunctionWithObjectLiteralBody3.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
=== arrowFunctionWithObjectLiteralBody3.ts ===
44
var v = a => <any>{}
55
>v : (a: any) => any
6-
> : ^^^^^^^^^^^^^^^
6+
> : ^^^^^^^^^^^^
77
>a => <any>{} : (a: any) => any
8-
> : ^^^^^^^^^^^^^^^
8+
> : ^^^^^^^^^^^^
99
>a : any
1010
><any>{} : any
1111
>{} : {}

tests/baselines/reference/arrowFunctionWithObjectLiteralBody4.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
=== arrowFunctionWithObjectLiteralBody4.ts ===
44
var v = a => <any><any>{}
55
>v : (a: any) => any
6-
> : ^^^^^^^^^^^^^^^
6+
> : ^^^^^^^^^^^^
77
>a => <any><any>{} : (a: any) => any
8-
> : ^^^^^^^^^^^^^^^
8+
> : ^^^^^^^^^^^^
99
>a : any
1010
><any><any>{} : any
1111
><any>{} : any

tests/baselines/reference/arrowFunctionWithObjectLiteralBody5.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
=== arrowFunctionWithObjectLiteralBody5.ts ===
44
var a = () => <Error>{ name: "foo", message: "bar" };
55
>a : () => Error
6-
> : ^^^^^^^^^^^
6+
> : ^^^^^^
77
>() => <Error>{ name: "foo", message: "bar" } : () => Error
8-
> : ^^^^^^^^^^^
8+
> : ^^^^^^
99
><Error>{ name: "foo", message: "bar" } : Error
1010
> : ^^^^^
1111
>{ name: "foo", message: "bar" } : { name: string; message: string; }

tests/baselines/reference/arrowFunctionWithObjectLiteralBody6.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
=== arrowFunctionWithObjectLiteralBody6.ts ===
44
var a = () => <Error>{ name: "foo", message: "bar" };
55
>a : () => Error
6-
> : ^^^^^^^^^^^
6+
> : ^^^^^^
77
>() => <Error>{ name: "foo", message: "bar" } : () => Error
8-
> : ^^^^^^^^^^^
8+
> : ^^^^^^
99
><Error>{ name: "foo", message: "bar" } : Error
1010
> : ^^^^^
1111
>{ name: "foo", message: "bar" } : { name: string; message: string; }

tests/baselines/reference/assertionFunctionWildcardImport1.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export { Debug };
1212
=== src/core/debug.ts ===
1313
export declare function assert(expression: unknown): asserts expression;
1414
>assert : (expression: unknown) => asserts expression
15-
> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
15+
> : ^^^^^^^^^^^^^ ^^^^^
1616
>expression : unknown
1717
> : ^^^^^^^
1818

tests/baselines/reference/assertionFunctionWildcardImport2.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
=== asserts.ts ===
44
function isNonNullable<T>(obj: T): asserts obj is NonNullable<T> {
55
>isNonNullable : <T>(obj: T) => asserts obj is NonNullable<T>
6-
> : ^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
> : ^ ^^^^^^^ ^^^^^
77
>obj : T
88
> : ^
99

tests/baselines/reference/assertionFunctionsCanNarrowByDiscriminant.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type Animal = Cat | Dog;
3131

3232
declare function assertEqual<T>(value: any, type: T): asserts value is T;
3333
>assertEqual : <T>(value: any, type: T) => asserts value is T
34-
> : ^ ^^^^^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
34+
> : ^ ^^^^^^^^^ ^^^^^^^^ ^^^^^
3535
>value : any
3636
>type : T
3737
> : ^

0 commit comments

Comments
 (0)