Skip to content

Commit 8552d4e

Browse files
committed
When caching type references cache the tracked symbols so they can be emitted in the d.ts file
Fixes #51548
1 parent 2042545 commit 8552d4e

File tree

4 files changed

+26
-116
lines changed

4 files changed

+26
-116
lines changed

src/compiler/checker.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,8 @@ import {
338338
hasAccessorModifier,
339339
hasAmbientModifier,
340340
hasContextSensitiveParameters,
341-
HasDecorators,
342341
hasDecorators,
342+
HasDecorators,
343343
hasDynamicName,
344344
hasEffectiveModifier,
345345
hasEffectiveModifiers,
@@ -348,8 +348,8 @@ import {
348348
hasExtension,
349349
HasIllegalDecorators,
350350
HasIllegalModifiers,
351-
HasInitializer,
352351
hasInitializer,
352+
HasInitializer,
353353
hasJSDocNodes,
354354
hasJSDocParameterTags,
355355
hasJsonModuleEmitEnabled,
@@ -873,6 +873,7 @@ import {
873873
SatisfiesExpression,
874874
ScriptKind,
875875
ScriptTarget,
876+
SerializedTypeNodeData,
876877
SetAccessorDeclaration,
877878
setCommentRange,
878879
setEmitFlags,
@@ -6554,6 +6555,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
65546555
}
65556556
const cachedResult = links?.serializedTypes?.get(key);
65566557
if (cachedResult) {
6558+
if (context.tracker.trackSymbol) cachedResult.trackedSymbols?.forEach(([symbol, enclosingDeclaration, meaning]) => context.tracker.trackSymbol!(symbol, enclosingDeclaration, meaning));
65576559
if (cachedResult.truncating) {
65586560
context.truncating = true;
65596561
}
@@ -6570,15 +6572,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
65706572
context.symbolDepth!.set(id, depth + 1);
65716573
}
65726574
context.visitedTypes.add(typeId);
6575+
const existingTracked = context.tracker.trackSymbol?.bind(context.tracker);
6576+
let trackedSymbols: [symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags][] | undefined;
6577+
context.tracker.trackSymbol = existingTracked ? (symbol, enclosingDeclaration, meaning) => {
6578+
(trackedSymbols ??= []).push([symbol, enclosingDeclaration, meaning]);
6579+
return existingTracked?.(symbol, enclosingDeclaration, meaning);
6580+
} : existingTracked;
65736581
const startLength = context.approximateLength;
6574-
const result = transform(type);
6582+
const result = transform(type) as unknown as SerializedTypeNodeData;
65756583
const addedLength = context.approximateLength - startLength;
65766584
if (!context.reportedDiagnostic && !context.encounteredError) {
65776585
if (context.truncating) {
6578-
(result as any).truncating = true;
6586+
result.truncating = true;
65796587
}
6580-
(result as any).addedLength = addedLength;
6581-
links?.serializedTypes?.set(key, result as TypeNode as TypeNode & {truncating?: boolean, addedLength: number});
6588+
result.addedLength = addedLength;
6589+
if (trackedSymbols) result.trackedSymbols = trackedSymbols;
6590+
links?.serializedTypes?.set(key, result);
65826591
}
65836592
context.visitedTypes.delete(typeId);
65846593
if (id) {

src/compiler/types.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5660,6 +5660,13 @@ export const enum NodeCheckFlags {
56605660
InCheckIdentifier = 1 << 24,
56615661
}
56625662

5663+
/**@internal*/
5664+
export interface SerializedTypeNodeData extends TypeNode {
5665+
truncating?: boolean;
5666+
addedLength: number;
5667+
trackedSymbols: readonly [symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags][] | undefined;
5668+
}
5669+
56635670
/** @internal */
56645671
export interface NodeLinks {
56655672
flags: NodeCheckFlags; // Set of flags specific to Node
@@ -5687,7 +5694,7 @@ export interface NodeLinks {
56875694
isExhaustive?: boolean | 0; // Is node an exhaustive switch statement (0 indicates in-process resolution)
56885695
skipDirectInference?: true; // Flag set by the API `getContextualType` call on a node when `Completions` is passed to force the checker to skip making inferences to a node's type
56895696
declarationRequiresScopeChange?: boolean; // Set by `useOuterVariableScopeInParameter` in checker when downlevel emit would change the name resolution scope inside of a parameter.
5690-
serializedTypes?: Map<string, TypeNode & {truncating?: boolean, addedLength: number}>; // Collection of types serialized at this location
5697+
serializedTypes?: Map<string, SerializedTypeNodeData>; // Collection of types serialized at this location
56915698
}
56925699

56935700
export const enum TypeFlags {

tests/baselines/reference/tsc/incremental/generates-typerefs-correctly-discrepancies.js

Lines changed: 0 additions & 101 deletions
This file was deleted.

tests/baselines/reference/tsc/incremental/generates-typerefs-correctly.js

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ export const bug: W.Wrap<{
226226
n: B.Box<number>;
227227
}>;
228228
export const something: 1;
229+
import * as B from "./box.js";
229230
import * as W from "./wrap.js";
230231

231232

@@ -255,7 +256,7 @@ exports.something = 1;
255256

256257

257258
//// [/src/project/outDir/tsconfig.tsbuildinfo]
258-
{"program":{"fileNames":["../../../lib/lib.d.ts","../src/box.ts","../src/wrap.ts","../src/bug.js"],"fileInfos":[{"version":"3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"-14267342128-export interface Box<T> {\n unbox(): T\n}\n","signature":"-3708762094-export interface Box<T> {\r\n unbox(): T;\r\n}\r\n"},{"version":"-7208318765-export type Wrap<C> = {\n [K in keyof C]: { wrapped: C[K] }\n}\n","signature":"-1963209831-export type Wrap<C> = {\r\n [K in keyof C]: {\r\n wrapped: C[K];\r\n };\r\n};\r\n"},{"version":"-25729561895-import * as B from \"./box.js\"\nimport * as W from \"./wrap.js\"\n\n/**\n * @template {object} C\n * @param {C} source\n * @returns {W.Wrap<C>}\n */\nconst wrap = source => {\nthrow source\n}\n\n/**\n * @returns {B.Box<number>}\n */\nconst box = (n = 0) => ({ unbox: () => n })\n\nexport const bug = wrap({ n: box(1) });\nexport const something = 1;","signature":"-18323848036-export const bug: W.Wrap<{\r\n n: B.Box<number>;\r\n}>;\r\nexport const something: 1;\r\nimport * as B from \"./box.js\";\r\nimport * as W from \"./wrap.js\";\r\n"}],"options":{"composite":true,"outDir":"./"},"fileIdsList":[[2,3]],"referencedMap":[[4,1]],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,2,4,3],"emitSignatures":[[4,"-5518966042-export const bug: W.Wrap<{\r\n n: B.Box<number>;\r\n}>;\r\nexport const something: 1;\r\nimport * as W from \"./wrap.js\";\r\n"]],"latestChangedDtsFile":"./src/bug.d.ts"},"version":"FakeTSVersion"}
259+
{"program":{"fileNames":["../../../lib/lib.d.ts","../src/box.ts","../src/wrap.ts","../src/bug.js"],"fileInfos":[{"version":"3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"-14267342128-export interface Box<T> {\n unbox(): T\n}\n","signature":"-3708762094-export interface Box<T> {\r\n unbox(): T;\r\n}\r\n"},{"version":"-7208318765-export type Wrap<C> = {\n [K in keyof C]: { wrapped: C[K] }\n}\n","signature":"-1963209831-export type Wrap<C> = {\r\n [K in keyof C]: {\r\n wrapped: C[K];\r\n };\r\n};\r\n"},{"version":"-25729561895-import * as B from \"./box.js\"\nimport * as W from \"./wrap.js\"\n\n/**\n * @template {object} C\n * @param {C} source\n * @returns {W.Wrap<C>}\n */\nconst wrap = source => {\nthrow source\n}\n\n/**\n * @returns {B.Box<number>}\n */\nconst box = (n = 0) => ({ unbox: () => n })\n\nexport const bug = wrap({ n: box(1) });\nexport const something = 1;","signature":"-18323848036-export const bug: W.Wrap<{\r\n n: B.Box<number>;\r\n}>;\r\nexport const something: 1;\r\nimport * as B from \"./box.js\";\r\nimport * as W from \"./wrap.js\";\r\n"}],"options":{"composite":true,"outDir":"./"},"fileIdsList":[[2,3]],"referencedMap":[[4,1]],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,2,4,3],"latestChangedDtsFile":"./src/bug.d.ts"},"version":"FakeTSVersion"}
259260

260261
//// [/src/project/outDir/tsconfig.tsbuildinfo.readable.baseline.txt]
261262
{
@@ -324,15 +325,9 @@ exports.something = 1;
324325
"../src/bug.js",
325326
"../src/wrap.ts"
326327
],
327-
"emitSignatures": [
328-
[
329-
"../src/bug.js",
330-
"-5518966042-export const bug: W.Wrap<{\r\n n: B.Box<number>;\r\n}>;\r\nexport const something: 1;\r\nimport * as W from \"./wrap.js\";\r\n"
331-
]
332-
],
333328
"latestChangedDtsFile": "./src/bug.d.ts"
334329
},
335330
"version": "FakeTSVersion",
336-
"size": 1918
331+
"size": 1751
337332
}
338333

0 commit comments

Comments
 (0)