Skip to content

Commit 1592629

Browse files
sheetalkamatpull[bot]
authored andcommitted
When caching type references cache the tracked symbols so they can be emitted in the d.ts file (#51721)
1 parent efe22a2 commit 1592629

File tree

4 files changed

+449
-1
lines changed

4 files changed

+449
-1
lines changed

src/compiler/checker.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,7 @@ import {
10101010
tokenToString,
10111011
tracing,
10121012
TracingNode,
1013+
TrackedSymbol,
10131014
TransientSymbol,
10141015
TransientSymbolLinks,
10151016
tryAddToSet,
@@ -6424,6 +6425,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
64246425
symbolDepth: undefined,
64256426
inferTypeParameters: undefined,
64266427
approximateLength: 0,
6428+
trackedSymbols: undefined,
64276429
};
64286430
context.tracker = new SymbolTrackerImpl(context, tracker, moduleResolverHost);
64296431
const resultingNode = cb(context);
@@ -6922,6 +6924,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
69226924
}
69236925
const cachedResult = links?.serializedTypes?.get(key);
69246926
if (cachedResult) {
6927+
// TODO:: check if we instead store late painted statements associated with this?
6928+
cachedResult.trackedSymbols?.forEach(
6929+
([symbol, enclosingDeclaration, meaning]) =>
6930+
context.tracker.trackSymbol(
6931+
symbol,
6932+
enclosingDeclaration,
6933+
meaning,
6934+
),
6935+
);
69256936
if (cachedResult.truncating) {
69266937
context.truncating = true;
69276938
}
@@ -6942,7 +6953,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
69426953
const result = transform(type);
69436954
const addedLength = context.approximateLength - startLength;
69446955
if (!context.reportedDiagnostic && !context.encounteredError) {
6945-
links?.serializedTypes?.set(key, { node: result, truncating: context.truncating, addedLength });
6956+
links?.serializedTypes?.set(key, {
6957+
node: result,
6958+
truncating: context.truncating,
6959+
addedLength,
6960+
trackedSymbols: context.trackedSymbols,
6961+
});
69466962
}
69476963
context.visitedTypes.delete(typeId);
69486964
if (id) {
@@ -8860,6 +8876,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
88608876
if (context.reportedDiagnostic) {
88618877
oldcontext.reportedDiagnostic = context.reportedDiagnostic; // hoist diagnostic result into outer context
88628878
}
8879+
if (context.trackedSymbols) {
8880+
if (!oldContext.trackedSymbols) oldContext.trackedSymbols = context.trackedSymbols;
8881+
else Debug.assert(context.trackedSymbols === oldContext.trackedSymbols);
8882+
}
88638883
context = oldContext;
88648884
}
88658885
}
@@ -50378,6 +50398,7 @@ interface NodeBuilderContext {
5037850398
// State
5037950399
encounteredError: boolean;
5038050400
reportedDiagnostic: boolean;
50401+
trackedSymbols: TrackedSymbol[] | undefined;
5038150402
visitedTypes: Set<number> | undefined;
5038250403
symbolDepth: Map<string, number> | undefined;
5038350404
inferTypeParameters: TypeParameter[] | undefined;
@@ -50418,6 +50439,8 @@ class SymbolTrackerImpl implements SymbolTracker {
5041850439
this.onDiagnosticReported();
5041950440
return true;
5042050441
}
50442+
// Skip recording type parameters as they dont contribute to late painted statements
50443+
if (!(symbol.flags & SymbolFlags.TypeParameter)) (this.context.trackedSymbols ??= []).push([symbol, enclosingDeclaration, meaning]);
5042150444
}
5042250445
return false;
5042350446
}

src/compiler/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6031,11 +6031,14 @@ export interface NodeLinks {
60316031
assertionExpressionType?: Type; // Cached type of the expression of a type assertion
60326032
}
60336033

6034+
/** @internal */
6035+
export type TrackedSymbol = [symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags];
60346036
/** @internal */
60356037
export interface SerializedTypeEntry {
60366038
node: TypeNode;
60376039
truncating?: boolean;
60386040
addedLength: number;
6041+
trackedSymbols: readonly TrackedSymbol[] | undefined;
60396042
}
60406043

60416044
// dprint-ignore

src/testRunner/unittests/tsc/incremental.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,4 +908,55 @@ console.log(a);`,
908908
}],
909909
baselinePrograms: true,
910910
});
911+
912+
verifyTsc({
913+
scenario: "incremental",
914+
subScenario: "generates typerefs correctly",
915+
commandLineArgs: ["-p", `/src/project`],
916+
fs: () =>
917+
loadProjectFromFiles({
918+
"/src/project/tsconfig.json": jsonToReadableText({
919+
compilerOptions: {
920+
composite: true,
921+
outDir: "outDir",
922+
checkJs: true,
923+
},
924+
include: ["src"],
925+
}),
926+
"/src/project/src/box.ts": Utils.dedent`
927+
export interface Box<T> {
928+
unbox(): T
929+
}
930+
`,
931+
"/src/project/src/bug.js": Utils.dedent`
932+
import * as B from "./box.js"
933+
import * as W from "./wrap.js"
934+
935+
/**
936+
* @template {object} C
937+
* @param {C} source
938+
* @returns {W.Wrap<C>}
939+
*/
940+
const wrap = source => {
941+
throw source
942+
}
943+
944+
/**
945+
* @returns {B.Box<number>}
946+
*/
947+
const box = (n = 0) => ({ unbox: () => n })
948+
949+
export const bug = wrap({ n: box(1) });
950+
`,
951+
"/src/project/src/wrap.ts": Utils.dedent`
952+
export type Wrap<C> = {
953+
[K in keyof C]: { wrapped: C[K] }
954+
}
955+
`,
956+
}),
957+
edits: [{
958+
caption: "modify js file",
959+
edit: fs => appendText(fs, "/src/project/src/bug.js", `export const something = 1;`),
960+
}],
961+
});
911962
});

0 commit comments

Comments
 (0)