From f6ada20d4dc16444df87c540946ba67b219f1325 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 3 Apr 2020 18:04:28 -0700 Subject: [PATCH] Report the most expensive statements as diagnostics --- src/compiler/checker.ts | 7 +---- src/compiler/program.ts | 1 + src/compiler/types.ts | 9 ++++++ src/executeCommandLine/executeCommandLine.ts | 32 ++++++++++++++------ 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 25e959311b255..99ab70e556f80 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -328,12 +328,6 @@ namespace ts { const keyofStringsOnly = !!compilerOptions.keyofStringsOnly; const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : ObjectFlags.FreshLiteral; - interface ExpensiveStatement { - node: Node; - typeDelta: number; - symbolDelta: number; - } - let ignoreExpensiveStatement = true; const maxExpensiveStatementCount = compilerOptions.expensiveStatements ?? 0; const expensiveStatements: ExpensiveStatement[] = []; @@ -373,6 +367,7 @@ namespace ts { subtype: subtypeRelation.size, strictSubtype: strictSubtypeRelation.size, }), + getExpensiveStatements: () => expensiveStatements, isUndefinedSymbol: symbol => symbol === undefinedSymbol, isArgumentsSymbol: symbol => symbol === argumentsSymbol, isUnknownSymbol: symbol => symbol === unknownSymbol, diff --git a/src/compiler/program.ts b/src/compiler/program.ts index d06ee2cd0205a..01e118e152876 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -950,6 +950,7 @@ namespace ts { getTypeCount: () => getDiagnosticsProducingTypeChecker().getTypeCount(), getInstantiationCount: () => getDiagnosticsProducingTypeChecker().getInstantiationCount(), getRelationCacheSizes: () => getDiagnosticsProducingTypeChecker().getRelationCacheSizes(), + getExpensiveStatements: () => getDiagnosticsProducingTypeChecker().getExpensiveStatements(), getFileProcessingDiagnostics: () => fileProcessingDiagnostics, getResolvedTypeReferenceDirectives: () => resolvedTypeReferenceDirectives, isSourceFileFromExternalLibrary, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9f399bdabf1b5..d338106f28085 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3261,6 +3261,7 @@ namespace ts { getTypeCount(): number; getInstantiationCount(): number; getRelationCacheSizes(): { assignable: number, identity: number, subtype: number, strictSubtype: number }; + getExpensiveStatements(): readonly ExpensiveStatement[]; /* @internal */ getFileProcessingDiagnostics(): DiagnosticCollection; /* @internal */ getResolvedTypeReferenceDirectives(): Map; @@ -3592,6 +3593,7 @@ namespace ts { /* @internal */ getTypeCount(): number; /* @internal */ getInstantiationCount(): number; /* @internal */ getRelationCacheSizes(): { assignable: number, identity: number, subtype: number, strictSubtype: number }; + /* @internal */ getExpensiveStatements(): readonly ExpensiveStatement[]; /* @internal */ isArrayType(type: Type): boolean; /* @internal */ isTupleType(type: Type): boolean; @@ -6737,4 +6739,11 @@ namespace ts { negative: boolean; base10Value: string; } + + /* @internal */ + export interface ExpensiveStatement { + node: Node; + typeDelta: number; + symbolDelta: number; + } } diff --git a/src/executeCommandLine/executeCommandLine.ts b/src/executeCommandLine/executeCommandLine.ts index 96cf7e5f04452..93c0b2ed65acb 100644 --- a/src/executeCommandLine/executeCommandLine.ts +++ b/src/executeCommandLine/executeCommandLine.ts @@ -440,7 +440,7 @@ namespace ts { createBuilderStatusReporter(sys, shouldBePretty(sys, buildOptions)), createWatchStatusReporter(sys, buildOptions) ); - updateSolutionBuilderHost(sys, cb, buildHost); + updateSolutionBuilderHost(sys, reportDiagnostic, cb, buildHost); const builder = createSolutionBuilderWithWatch(buildHost, projects, buildOptions, watchOptions); builder.build(); return builder; @@ -453,7 +453,7 @@ namespace ts { createBuilderStatusReporter(sys, shouldBePretty(sys, buildOptions)), createReportErrorSummary(sys, buildOptions) ); - updateSolutionBuilderHost(sys, cb, buildHost); + updateSolutionBuilderHost(sys, reportDiagnostic, cb, buildHost); const builder = createSolutionBuilder(buildHost, projects, buildOptions); const exitStatus = buildOptions.clean ? builder.clean() : builder.build(); return sys.exit(exitStatus); @@ -492,7 +492,7 @@ namespace ts { s => sys.write(s + sys.newLine), createReportErrorSummary(sys, options) ); - reportStatistics(sys, program); + reportStatistics(sys, program, reportDiagnostic); cb(program); return sys.exit(exitStatus); } @@ -516,7 +516,7 @@ namespace ts { reportDiagnostic, reportErrorSummary: createReportErrorSummary(sys, options), afterProgramEmitAndDiagnostics: builderProgram => { - reportStatistics(sys, builderProgram.getProgram()); + reportStatistics(sys, builderProgram.getProgram(), reportDiagnostic); cb(builderProgram); } }); @@ -525,12 +525,13 @@ namespace ts { function updateSolutionBuilderHost( sys: System, + reportDiagnostic: DiagnosticReporter, cb: ExecuteCommandLineCallbacks, buildHost: SolutionBuilderHostBase ) { updateCreateProgram(sys, buildHost); buildHost.afterProgramEmitAndDiagnostics = program => { - reportStatistics(sys, program.getProgram()); + reportStatistics(sys, program.getProgram(), reportDiagnostic); cb(program); }; buildHost.afterEmitBundle = cb; @@ -549,6 +550,7 @@ namespace ts { function updateWatchCompilationHost( sys: System, + reportDiagnostic: DiagnosticReporter, cb: ExecuteCommandLineCallbacks, watchCompilerHost: WatchCompilerHost, ) { @@ -556,7 +558,7 @@ namespace ts { const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate!; // TODO: GH#18217 watchCompilerHost.afterProgramCreate = builderProgram => { emitFilesUsingBuilder(builderProgram); - reportStatistics(sys, builderProgram.getProgram()); + reportStatistics(sys, builderProgram.getProgram(), reportDiagnostic); cb(builderProgram); }; } @@ -581,7 +583,7 @@ namespace ts { reportDiagnostic, reportWatchStatus: createWatchStatusReporter(system, configParseResult.options) }); - updateWatchCompilationHost(system, cb, watchCompilerHost); + updateWatchCompilationHost(system, reportDiagnostic, cb, watchCompilerHost); watchCompilerHost.configFileParsingResult = configParseResult; return createWatchProgram(watchCompilerHost); } @@ -602,7 +604,7 @@ namespace ts { reportDiagnostic, reportWatchStatus: createWatchStatusReporter(system, options) }); - updateWatchCompilationHost(system, cb, watchCompilerHost); + updateWatchCompilationHost(system, reportDiagnostic, cb, watchCompilerHost); return createWatchProgram(watchCompilerHost); } @@ -616,9 +618,21 @@ namespace ts { } } - function reportStatistics(sys: System, program: Program) { + function reportStatistics(sys: System, program: Program, reportDiagnostic: DiagnosticReporter) { let statistics: Statistic[]; const compilerOptions = program.getCompilerOptions(); + + if (compilerOptions.expensiveStatements) { + for (const expensiveStatement of program.getExpensiveStatements()) { + reportDiagnostic( + createDiagnosticForNode( + expensiveStatement.node, + Diagnostics.Checking_this_statement_may_result_in_the_creation_of_as_many_as_0_types_and_1_symbols, + expensiveStatement.typeDelta, + expensiveStatement.symbolDelta)); + } + } + if (canReportDiagnostics(sys, compilerOptions)) { statistics = []; const memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;