Skip to content

Commit

Permalink
Report the most expensive statements as diagnostics
Browse files Browse the repository at this point in the history
  • Loading branch information
amcasey committed Apr 4, 2020
1 parent 0da8143 commit f6ada20
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 15 deletions.
7 changes: 1 addition & 6 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = [];
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,7 @@ namespace ts {
getTypeCount: () => getDiagnosticsProducingTypeChecker().getTypeCount(),
getInstantiationCount: () => getDiagnosticsProducingTypeChecker().getInstantiationCount(),
getRelationCacheSizes: () => getDiagnosticsProducingTypeChecker().getRelationCacheSizes(),
getExpensiveStatements: () => getDiagnosticsProducingTypeChecker().getExpensiveStatements(),
getFileProcessingDiagnostics: () => fileProcessingDiagnostics,
getResolvedTypeReferenceDirectives: () => resolvedTypeReferenceDirectives,
isSourceFileFromExternalLibrary,
Expand Down
9 changes: 9 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<ResolvedTypeReferenceDirective | undefined>;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -6737,4 +6739,11 @@ namespace ts {
negative: boolean;
base10Value: string;
}

/* @internal */
export interface ExpensiveStatement {
node: Node;
typeDelta: number;
symbolDelta: number;
}
}
32 changes: 23 additions & 9 deletions src/executeCommandLine/executeCommandLine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
Expand All @@ -516,7 +516,7 @@ namespace ts {
reportDiagnostic,
reportErrorSummary: createReportErrorSummary(sys, options),
afterProgramEmitAndDiagnostics: builderProgram => {
reportStatistics(sys, builderProgram.getProgram());
reportStatistics(sys, builderProgram.getProgram(), reportDiagnostic);
cb(builderProgram);
}
});
Expand All @@ -525,12 +525,13 @@ namespace ts {

function updateSolutionBuilderHost(
sys: System,
reportDiagnostic: DiagnosticReporter,
cb: ExecuteCommandLineCallbacks,
buildHost: SolutionBuilderHostBase<EmitAndSemanticDiagnosticsBuilderProgram>
) {
updateCreateProgram(sys, buildHost);
buildHost.afterProgramEmitAndDiagnostics = program => {
reportStatistics(sys, program.getProgram());
reportStatistics(sys, program.getProgram(), reportDiagnostic);
cb(program);
};
buildHost.afterEmitBundle = cb;
Expand All @@ -549,14 +550,15 @@ namespace ts {

function updateWatchCompilationHost(
sys: System,
reportDiagnostic: DiagnosticReporter,
cb: ExecuteCommandLineCallbacks,
watchCompilerHost: WatchCompilerHost<EmitAndSemanticDiagnosticsBuilderProgram>,
) {
updateCreateProgram(sys, watchCompilerHost);
const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate!; // TODO: GH#18217
watchCompilerHost.afterProgramCreate = builderProgram => {
emitFilesUsingBuilder(builderProgram);
reportStatistics(sys, builderProgram.getProgram());
reportStatistics(sys, builderProgram.getProgram(), reportDiagnostic);
cb(builderProgram);
};
}
Expand All @@ -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);
}
Expand All @@ -602,7 +604,7 @@ namespace ts {
reportDiagnostic,
reportWatchStatus: createWatchStatusReporter(system, options)
});
updateWatchCompilationHost(system, cb, watchCompilerHost);
updateWatchCompilationHost(system, reportDiagnostic, cb, watchCompilerHost);
return createWatchProgram(watchCompilerHost);
}

Expand All @@ -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;
Expand Down

0 comments on commit f6ada20

Please sign in to comment.