perf(ivy): template type-check the entire program in 1 file if possible (#29698)

The template type-checking engine previously would assemble a type-checking
program by inserting Type Check Blocks (TCBs) into existing user files. This
approach proved expensive, as TypeScript has to re-parse and re-type-check
those files when processing the type-checking program.

Instead, a far more performant approach is to augment the program with a
single type-checking file, into which all TCBs are generated. Additionally,
type constructors are also inlined into this file.

This is not always possible - both TCBs and type constructors can sometimes
require inlining into user code, particularly if bound generic type
parameters are present, so the approach taken is actually a hybrid. These
operations are inlined if necessary, but are otherwise generated in a single
file.

It is critically important that the original program also include an empty
version of the type-checking file, otherwise the shape of the two programs
will be different and TypeScript will throw away all the old program
information. This leads to a painfully slow type checking pass, on the same
order as the original program creation. A shim to generate this file in the
original program is therefore added.

Testing strategy: this commit is largely a refactor with no externally
observable behavioral differences, and thus no tests are needed.

PR Close #29698
This commit is contained in:
Alex Rickabaugh
2019-04-02 11:25:33 -07:00
committed by Ben Lesh
parent f4c536ae36
commit 98f86de8da
17 changed files with 753 additions and 317 deletions

View File

@ -11,3 +11,4 @@
export {FactoryGenerator, FactoryInfo, generatedFactoryTransform} from './src/factory_generator';
export {GeneratedShimsHostWrapper, ShimGenerator} from './src/host';
export {SummaryGenerator} from './src/summary_generator';
export {TypeCheckShimGenerator} from './src/typecheck_shim';

View File

@ -0,0 +1,33 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import * as ts from 'typescript';
import {AbsoluteFsPath} from '../../path';
import {ShimGenerator} from './host';
/**
* A `ShimGenerator` which adds a type-checking file to the `ts.Program`.
*
* This is a requirement for performant template type-checking, as TypeScript will only reuse
* information in the main program when creating the type-checking program if the set of files in
* each are exactly the same. Thus, the main program also needs the synthetic type-checking file.
*/
export class TypeCheckShimGenerator implements ShimGenerator {
constructor(private typeCheckFile: AbsoluteFsPath) {}
recognize(fileName: AbsoluteFsPath): boolean { return fileName === this.typeCheckFile; }
generate(genFileName: AbsoluteFsPath, readFile: (fileName: string) => ts.SourceFile | null):
ts.SourceFile|null {
return ts.createSourceFile(
genFileName, 'export const USED_FOR_NG_TYPE_CHECKING = true;', ts.ScriptTarget.Latest, true,
ts.ScriptKind.TS);
}
}