Skip to content

Commit 2e794fe

Browse files
committed
Report the most expensive statements as diagnostics
1 parent 5c5e149 commit 2e794fe

File tree

5 files changed

+39
-15
lines changed

5 files changed

+39
-15
lines changed

src/compiler/checker.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -333,12 +333,6 @@ namespace ts {
333333
const keyofStringsOnly = !!compilerOptions.keyofStringsOnly;
334334
const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : ObjectFlags.FreshLiteral;
335335

336-
interface ExpensiveStatement {
337-
node: Node;
338-
typeDelta: number;
339-
symbolDelta: number;
340-
}
341-
342336
let ignoreExpensiveStatement = true;
343337
const maxExpensiveStatementCount = compilerOptions.expensiveStatements ?? 0;
344338
const expensiveStatements: ExpensiveStatement[] = [];
@@ -378,6 +372,7 @@ namespace ts {
378372
subtype: subtypeRelation.size,
379373
strictSubtype: strictSubtypeRelation.size,
380374
}),
375+
getExpensiveStatements: () => expensiveStatements,
381376
isUndefinedSymbol: symbol => symbol === undefinedSymbol,
382377
isArgumentsSymbol: symbol => symbol === argumentsSymbol,
383378
isUnknownSymbol: symbol => symbol === unknownSymbol,

src/compiler/program.ts

+1
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,7 @@ namespace ts {
954954
getTypeCount: () => getDiagnosticsProducingTypeChecker().getTypeCount(),
955955
getInstantiationCount: () => getDiagnosticsProducingTypeChecker().getInstantiationCount(),
956956
getRelationCacheSizes: () => getDiagnosticsProducingTypeChecker().getRelationCacheSizes(),
957+
getExpensiveStatements: () => getDiagnosticsProducingTypeChecker().getExpensiveStatements(),
957958
getFileProcessingDiagnostics: () => fileProcessingDiagnostics,
958959
getResolvedTypeReferenceDirectives: () => resolvedTypeReferenceDirectives,
959960
isSourceFileFromExternalLibrary,

src/compiler/types.ts

+9
Original file line numberDiff line numberDiff line change
@@ -3737,6 +3737,7 @@ namespace ts {
37373737
getTypeCount(): number;
37383738
getInstantiationCount(): number;
37393739
getRelationCacheSizes(): { assignable: number, identity: number, subtype: number, strictSubtype: number };
3740+
/* @internal */ getExpensiveStatements(): readonly ExpensiveStatement[];
37403741

37413742
/* @internal */ getFileProcessingDiagnostics(): DiagnosticCollection;
37423743
/* @internal */ getResolvedTypeReferenceDirectives(): ESMap<string, ResolvedTypeReferenceDirective | undefined>;
@@ -4070,6 +4071,7 @@ namespace ts {
40704071
/* @internal */ getTypeCount(): number;
40714072
/* @internal */ getInstantiationCount(): number;
40724073
/* @internal */ getRelationCacheSizes(): { assignable: number, identity: number, subtype: number, strictSubtype: number };
4074+
/* @internal */ getExpensiveStatements(): readonly ExpensiveStatement[];
40734075

40744076
/* @internal */ isArrayType(type: Type): boolean;
40754077
/* @internal */ isTupleType(type: Type): boolean;
@@ -8067,4 +8069,11 @@ namespace ts {
80678069
negative: boolean;
80688070
base10Value: string;
80698071
}
8072+
8073+
/* @internal */
8074+
export interface ExpensiveStatement {
8075+
node: Node;
8076+
typeDelta: number;
8077+
symbolDelta: number;
8078+
}
80708079
}

src/executeCommandLine/executeCommandLine.ts

+23-9
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ namespace ts {
440440
createBuilderStatusReporter(sys, shouldBePretty(sys, buildOptions)),
441441
createWatchStatusReporter(sys, buildOptions)
442442
);
443-
updateSolutionBuilderHost(sys, cb, buildHost);
443+
updateSolutionBuilderHost(sys, reportDiagnostic, cb, buildHost);
444444
const builder = createSolutionBuilderWithWatch(buildHost, projects, buildOptions, watchOptions);
445445
builder.build();
446446
return builder;
@@ -453,7 +453,7 @@ namespace ts {
453453
createBuilderStatusReporter(sys, shouldBePretty(sys, buildOptions)),
454454
createReportErrorSummary(sys, buildOptions)
455455
);
456-
updateSolutionBuilderHost(sys, cb, buildHost);
456+
updateSolutionBuilderHost(sys, reportDiagnostic, cb, buildHost);
457457
const builder = createSolutionBuilder(buildHost, projects, buildOptions);
458458
const exitStatus = buildOptions.clean ? builder.clean() : builder.build();
459459
return sys.exit(exitStatus);
@@ -492,7 +492,7 @@ namespace ts {
492492
s => sys.write(s + sys.newLine),
493493
createReportErrorSummary(sys, options)
494494
);
495-
reportStatistics(sys, program);
495+
reportStatistics(sys, program, reportDiagnostic);
496496
cb(program);
497497
return sys.exit(exitStatus);
498498
}
@@ -516,7 +516,7 @@ namespace ts {
516516
reportDiagnostic,
517517
reportErrorSummary: createReportErrorSummary(sys, options),
518518
afterProgramEmitAndDiagnostics: builderProgram => {
519-
reportStatistics(sys, builderProgram.getProgram());
519+
reportStatistics(sys, builderProgram.getProgram(), reportDiagnostic);
520520
cb(builderProgram);
521521
}
522522
});
@@ -525,12 +525,13 @@ namespace ts {
525525

526526
function updateSolutionBuilderHost(
527527
sys: System,
528+
reportDiagnostic: DiagnosticReporter,
528529
cb: ExecuteCommandLineCallbacks,
529530
buildHost: SolutionBuilderHostBase<EmitAndSemanticDiagnosticsBuilderProgram>
530531
) {
531532
updateCreateProgram(sys, buildHost);
532533
buildHost.afterProgramEmitAndDiagnostics = program => {
533-
reportStatistics(sys, program.getProgram());
534+
reportStatistics(sys, program.getProgram(), reportDiagnostic);
534535
cb(program);
535536
};
536537
buildHost.afterEmitBundle = cb;
@@ -549,14 +550,15 @@ namespace ts {
549550

550551
function updateWatchCompilationHost(
551552
sys: System,
553+
reportDiagnostic: DiagnosticReporter,
552554
cb: ExecuteCommandLineCallbacks,
553555
watchCompilerHost: WatchCompilerHost<EmitAndSemanticDiagnosticsBuilderProgram>,
554556
) {
555557
updateCreateProgram(sys, watchCompilerHost);
556558
const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate!; // TODO: GH#18217
557559
watchCompilerHost.afterProgramCreate = builderProgram => {
558560
emitFilesUsingBuilder(builderProgram);
559-
reportStatistics(sys, builderProgram.getProgram());
561+
reportStatistics(sys, builderProgram.getProgram(), reportDiagnostic);
560562
cb(builderProgram);
561563
};
562564
}
@@ -581,7 +583,7 @@ namespace ts {
581583
reportDiagnostic,
582584
reportWatchStatus: createWatchStatusReporter(system, configParseResult.options)
583585
});
584-
updateWatchCompilationHost(system, cb, watchCompilerHost);
586+
updateWatchCompilationHost(system, reportDiagnostic, cb, watchCompilerHost);
585587
watchCompilerHost.configFileParsingResult = configParseResult;
586588
return createWatchProgram(watchCompilerHost);
587589
}
@@ -602,7 +604,7 @@ namespace ts {
602604
reportDiagnostic,
603605
reportWatchStatus: createWatchStatusReporter(system, options)
604606
});
605-
updateWatchCompilationHost(system, cb, watchCompilerHost);
607+
updateWatchCompilationHost(system, reportDiagnostic, cb, watchCompilerHost);
606608
return createWatchProgram(watchCompilerHost);
607609
}
608610

@@ -616,9 +618,21 @@ namespace ts {
616618
}
617619
}
618620

619-
function reportStatistics(sys: System, program: Program) {
621+
function reportStatistics(sys: System, program: Program, reportDiagnostic: DiagnosticReporter) {
620622
let statistics: Statistic[];
621623
const compilerOptions = program.getCompilerOptions();
624+
625+
if (compilerOptions.expensiveStatements) {
626+
for (const expensiveStatement of program.getExpensiveStatements()) {
627+
reportDiagnostic(
628+
createDiagnosticForNode(
629+
expensiveStatement.node,
630+
Diagnostics.Checking_this_statement_may_result_in_the_creation_of_as_many_as_0_types_and_1_symbols,
631+
expensiveStatement.typeDelta,
632+
expensiveStatement.symbolDelta));
633+
}
634+
}
635+
622636
if (canReportDiagnostics(sys, compilerOptions)) {
623637
statistics = [];
624638
const memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"compilerOptions": {
3+
"expensiveStatements": 0
4+
}
5+
}

0 commit comments

Comments
 (0)