refactor(compiler-cli): make IncrementalBuild strategy configurable (#37339)
Commit 24b2f1da2b introduced an `NgCompiler` which operates on a `ts.Program` independently of the `NgtscProgram`. The NgCompiler got its `IncrementalDriver` (for incremental reuse of Angular compilation results) by looking at a monkey-patched property on the `ts.Program`. This monkey-patching operation causes problems with the Angular indexer (specifically, it seems to cause the indexer to retain too much of prior programs, resulting in OOM issues). To work around this, `IncrementalDriver` reuse is now handled by a dedicated `IncrementalBuildStrategy`. One implementation of this interface is used by the `NgtscProgram` to perform the old-style reuse, relying on the previous instance of `NgtscProgram` instead of monkey-patching. Only for `NgTscPlugin` is the monkey-patching strategy used, as the plugin sits behind an interface which only provides access to the `ts.Program`, not a prior instance of the plugin. PR Close #37339
This commit is contained in:
parent
a7faa6bb65
commit
300c2fec9c
@ -27,6 +27,7 @@ ts_library(
|
|||||||
"//packages/compiler-cli/src/ngtsc/core:api",
|
"//packages/compiler-cli/src/ngtsc/core:api",
|
||||||
"//packages/compiler-cli/src/ngtsc/diagnostics",
|
"//packages/compiler-cli/src/ngtsc/diagnostics",
|
||||||
"//packages/compiler-cli/src/ngtsc/file_system",
|
"//packages/compiler-cli/src/ngtsc/file_system",
|
||||||
|
"//packages/compiler-cli/src/ngtsc/incremental",
|
||||||
"//packages/compiler-cli/src/ngtsc/indexer",
|
"//packages/compiler-cli/src/ngtsc/indexer",
|
||||||
"//packages/compiler-cli/src/ngtsc/perf",
|
"//packages/compiler-cli/src/ngtsc/perf",
|
||||||
"//packages/compiler-cli/src/ngtsc/reflection",
|
"//packages/compiler-cli/src/ngtsc/reflection",
|
||||||
|
@ -15,7 +15,7 @@ import {ErrorCode, ngErrorCode} from '../../diagnostics';
|
|||||||
import {checkForPrivateExports, ReferenceGraph} from '../../entry_point';
|
import {checkForPrivateExports, ReferenceGraph} from '../../entry_point';
|
||||||
import {getSourceFileOrError, LogicalFileSystem} from '../../file_system';
|
import {getSourceFileOrError, LogicalFileSystem} from '../../file_system';
|
||||||
import {AbsoluteModuleStrategy, AliasingHost, AliasStrategy, DefaultImportTracker, ImportRewriter, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, NoopImportRewriter, PrivateExportAliasingHost, R3SymbolsImportRewriter, Reference, ReferenceEmitStrategy, ReferenceEmitter, RelativePathStrategy, UnifiedModulesAliasingHost, UnifiedModulesStrategy} from '../../imports';
|
import {AbsoluteModuleStrategy, AliasingHost, AliasStrategy, DefaultImportTracker, ImportRewriter, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, NoopImportRewriter, PrivateExportAliasingHost, R3SymbolsImportRewriter, Reference, ReferenceEmitStrategy, ReferenceEmitter, RelativePathStrategy, UnifiedModulesAliasingHost, UnifiedModulesStrategy} from '../../imports';
|
||||||
import {IncrementalDriver} from '../../incremental';
|
import {IncrementalBuildStrategy, IncrementalDriver} from '../../incremental';
|
||||||
import {generateAnalysis, IndexedComponent, IndexingContext} from '../../indexer';
|
import {generateAnalysis, IndexedComponent, IndexingContext} from '../../indexer';
|
||||||
import {CompoundMetadataReader, CompoundMetadataRegistry, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry, MetadataReader} from '../../metadata';
|
import {CompoundMetadataReader, CompoundMetadataRegistry, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry, MetadataReader} from '../../metadata';
|
||||||
import {ModuleWithProvidersScanner} from '../../modulewithproviders';
|
import {ModuleWithProvidersScanner} from '../../modulewithproviders';
|
||||||
@ -100,7 +100,8 @@ export class NgCompiler {
|
|||||||
private adapter: NgCompilerAdapter, private options: NgCompilerOptions,
|
private adapter: NgCompilerAdapter, private options: NgCompilerOptions,
|
||||||
private tsProgram: ts.Program,
|
private tsProgram: ts.Program,
|
||||||
private typeCheckingProgramStrategy: TypeCheckingProgramStrategy,
|
private typeCheckingProgramStrategy: TypeCheckingProgramStrategy,
|
||||||
oldProgram: ts.Program|null = null, private perfRecorder: PerfRecorder = NOOP_PERF_RECORDER) {
|
private incrementalStrategy: IncrementalBuildStrategy, oldProgram: ts.Program|null = null,
|
||||||
|
private perfRecorder: PerfRecorder = NOOP_PERF_RECORDER) {
|
||||||
this.constructionDiagnostics.push(...this.adapter.constructionDiagnostics);
|
this.constructionDiagnostics.push(...this.adapter.constructionDiagnostics);
|
||||||
const incompatibleTypeCheckOptionsDiagnostic = verifyCompatibleTypeCheckOptions(this.options);
|
const incompatibleTypeCheckOptionsDiagnostic = verifyCompatibleTypeCheckOptions(this.options);
|
||||||
if (incompatibleTypeCheckOptionsDiagnostic !== null) {
|
if (incompatibleTypeCheckOptionsDiagnostic !== null) {
|
||||||
@ -129,7 +130,7 @@ export class NgCompiler {
|
|||||||
if (oldProgram === null) {
|
if (oldProgram === null) {
|
||||||
this.incrementalDriver = IncrementalDriver.fresh(tsProgram);
|
this.incrementalDriver = IncrementalDriver.fresh(tsProgram);
|
||||||
} else {
|
} else {
|
||||||
const oldDriver = getIncrementalDriver(oldProgram);
|
const oldDriver = this.incrementalStrategy.getIncrementalDriver(oldProgram);
|
||||||
if (oldDriver !== null) {
|
if (oldDriver !== null) {
|
||||||
this.incrementalDriver =
|
this.incrementalDriver =
|
||||||
IncrementalDriver.reconcile(oldProgram, oldDriver, tsProgram, modifiedResourceFiles);
|
IncrementalDriver.reconcile(oldProgram, oldDriver, tsProgram, modifiedResourceFiles);
|
||||||
@ -140,7 +141,7 @@ export class NgCompiler {
|
|||||||
this.incrementalDriver = IncrementalDriver.fresh(tsProgram);
|
this.incrementalDriver = IncrementalDriver.fresh(tsProgram);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setIncrementalDriver(tsProgram, this.incrementalDriver);
|
this.incrementalStrategy.setIncrementalDriver(this.incrementalDriver, tsProgram);
|
||||||
|
|
||||||
this.ignoreForDiagnostics =
|
this.ignoreForDiagnostics =
|
||||||
new Set(tsProgram.getSourceFiles().filter(sf => this.adapter.isShim(sf)));
|
new Set(tsProgram.getSourceFiles().filter(sf => this.adapter.isShim(sf)));
|
||||||
@ -506,7 +507,7 @@ export class NgCompiler {
|
|||||||
|
|
||||||
const program = this.typeCheckingProgramStrategy.getProgram();
|
const program = this.typeCheckingProgramStrategy.getProgram();
|
||||||
this.perfRecorder.stop(typeCheckSpan);
|
this.perfRecorder.stop(typeCheckSpan);
|
||||||
setIncrementalDriver(program, this.incrementalDriver);
|
this.incrementalStrategy.setIncrementalDriver(this.incrementalDriver, program);
|
||||||
this.nextProgram = program;
|
this.nextProgram = program;
|
||||||
|
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
@ -793,44 +794,6 @@ function getR3SymbolsFile(program: ts.Program): ts.SourceFile|null {
|
|||||||
return program.getSourceFiles().find(file => file.fileName.indexOf('r3_symbols.ts') >= 0) || null;
|
return program.getSourceFiles().find(file => file.fileName.indexOf('r3_symbols.ts') >= 0) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Symbol under which the `IncrementalDriver` is stored on a `ts.Program`.
|
|
||||||
*
|
|
||||||
* The TS model of incremental compilation is based around reuse of a previous `ts.Program` in the
|
|
||||||
* construction of a new one. The `NgCompiler` follows this abstraction - passing in a previous
|
|
||||||
* `ts.Program` is sufficient to trigger incremental compilation. This previous `ts.Program` need
|
|
||||||
* not be from an Angular compilation (that is, it need not have been created from `NgCompiler`).
|
|
||||||
*
|
|
||||||
* If it is, though, Angular can benefit from reusing previous analysis work. This reuse is managed
|
|
||||||
* by the `IncrementalDriver`, which is inherited from the old program to the new program. To
|
|
||||||
* support this behind the API of passing an old `ts.Program`, the `IncrementalDriver` is stored on
|
|
||||||
* the `ts.Program` under this symbol.
|
|
||||||
*/
|
|
||||||
const SYM_INCREMENTAL_DRIVER = Symbol('NgIncrementalDriver');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an `IncrementalDriver` from the given `ts.Program` if one is present.
|
|
||||||
*
|
|
||||||
* See `SYM_INCREMENTAL_DRIVER` for more details.
|
|
||||||
*/
|
|
||||||
function getIncrementalDriver(program: ts.Program): IncrementalDriver|null {
|
|
||||||
const driver = (program as any)[SYM_INCREMENTAL_DRIVER];
|
|
||||||
if (driver === undefined || !(driver instanceof IncrementalDriver)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return driver;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save the given `IncrementalDriver` onto the given `ts.Program`, for retrieval in a subsequent
|
|
||||||
* incremental compilation.
|
|
||||||
*
|
|
||||||
* See `SYM_INCREMENTAL_DRIVER` for more details.
|
|
||||||
*/
|
|
||||||
function setIncrementalDriver(program: ts.Program, driver: IncrementalDriver): void {
|
|
||||||
(program as any)[SYM_INCREMENTAL_DRIVER] = driver;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Since "strictTemplates" is a true superset of type checking capabilities compared to
|
* Since "strictTemplates" is a true superset of type checking capabilities compared to
|
||||||
* "strictTemplateTypeCheck", it is required that the latter is not explicitly disabled if the
|
* "strictTemplateTypeCheck", it is required that the latter is not explicitly disabled if the
|
||||||
|
@ -14,6 +14,7 @@ ts_library(
|
|||||||
"//packages/compiler-cli/src/ngtsc/core:api",
|
"//packages/compiler-cli/src/ngtsc/core:api",
|
||||||
"//packages/compiler-cli/src/ngtsc/file_system",
|
"//packages/compiler-cli/src/ngtsc/file_system",
|
||||||
"//packages/compiler-cli/src/ngtsc/file_system/testing",
|
"//packages/compiler-cli/src/ngtsc/file_system/testing",
|
||||||
|
"//packages/compiler-cli/src/ngtsc/incremental",
|
||||||
"//packages/compiler-cli/src/ngtsc/typecheck",
|
"//packages/compiler-cli/src/ngtsc/typecheck",
|
||||||
"@npm//typescript",
|
"@npm//typescript",
|
||||||
],
|
],
|
||||||
|
@ -10,6 +10,7 @@ import * as ts from 'typescript';
|
|||||||
|
|
||||||
import {absoluteFrom as _, FileSystem, getFileSystem, getSourceFileOrError, NgtscCompilerHost, setFileSystem} from '../../file_system';
|
import {absoluteFrom as _, FileSystem, getFileSystem, getSourceFileOrError, NgtscCompilerHost, setFileSystem} from '../../file_system';
|
||||||
import {runInEachFileSystem} from '../../file_system/testing';
|
import {runInEachFileSystem} from '../../file_system/testing';
|
||||||
|
import {NoopIncrementalBuildStrategy} from '../../incremental';
|
||||||
import {ReusedProgramStrategy} from '../../typecheck/src/augmented_program';
|
import {ReusedProgramStrategy} from '../../typecheck/src/augmented_program';
|
||||||
import {NgCompilerOptions} from '../api';
|
import {NgCompilerOptions} from '../api';
|
||||||
import {NgCompiler} from '../src/compiler';
|
import {NgCompiler} from '../src/compiler';
|
||||||
@ -47,7 +48,8 @@ runInEachFileSystem(() => {
|
|||||||
const host = NgCompilerHost.wrap(baseHost, [COMPONENT], options, /* oldProgram */ null);
|
const host = NgCompilerHost.wrap(baseHost, [COMPONENT], options, /* oldProgram */ null);
|
||||||
const program = ts.createProgram({host, options, rootNames: host.inputFiles});
|
const program = ts.createProgram({host, options, rootNames: host.inputFiles});
|
||||||
const compiler = new NgCompiler(
|
const compiler = new NgCompiler(
|
||||||
host, options, program, new ReusedProgramStrategy(program, host, options, []));
|
host, options, program, new ReusedProgramStrategy(program, host, options, []),
|
||||||
|
new NoopIncrementalBuildStrategy());
|
||||||
|
|
||||||
const diags = compiler.getDiagnostics(getSourceFileOrError(program, COMPONENT));
|
const diags = compiler.getDiagnostics(getSourceFileOrError(program, COMPONENT));
|
||||||
expect(diags.length).toBe(1);
|
expect(diags.length).toBe(1);
|
||||||
|
@ -8,3 +8,4 @@
|
|||||||
|
|
||||||
export {NOOP_INCREMENTAL_BUILD} from './src/noop';
|
export {NOOP_INCREMENTAL_BUILD} from './src/noop';
|
||||||
export {IncrementalDriver} from './src/state';
|
export {IncrementalDriver} from './src/state';
|
||||||
|
export * from './src/strategy';
|
||||||
|
95
packages/compiler-cli/src/ngtsc/incremental/src/strategy.ts
Normal file
95
packages/compiler-cli/src/ngtsc/incremental/src/strategy.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google LLC 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 {IncrementalDriver} from './state';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strategy used to manage the association between a `ts.Program` and the `IncrementalDriver` which
|
||||||
|
* represents the reusable Angular part of its compilation.
|
||||||
|
*/
|
||||||
|
export interface IncrementalBuildStrategy {
|
||||||
|
/**
|
||||||
|
* Determine the Angular `IncrementalDriver` for the given `ts.Program`, if one is available.
|
||||||
|
*/
|
||||||
|
getIncrementalDriver(program: ts.Program): IncrementalDriver|null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate the given `IncrementalDriver` with the given `ts.Program` and make it available to
|
||||||
|
* future compilations.
|
||||||
|
*/
|
||||||
|
setIncrementalDriver(driver: IncrementalDriver, program: ts.Program): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A noop implementation of `IncrementalBuildStrategy` which neither returns nor tracks any
|
||||||
|
* incremental data.
|
||||||
|
*/
|
||||||
|
export class NoopIncrementalBuildStrategy implements IncrementalBuildStrategy {
|
||||||
|
getIncrementalDriver(): null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIncrementalDriver(): void {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks an `IncrementalDriver` within the strategy itself.
|
||||||
|
*/
|
||||||
|
export class TrackedIncrementalBuildStrategy implements IncrementalBuildStrategy {
|
||||||
|
private previous: IncrementalDriver|null = null;
|
||||||
|
private next: IncrementalDriver|null = null;
|
||||||
|
|
||||||
|
getIncrementalDriver(): IncrementalDriver|null {
|
||||||
|
return this.next !== null ? this.next : this.previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIncrementalDriver(driver: IncrementalDriver): void {
|
||||||
|
this.next = driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
toNextBuildStrategy(): TrackedIncrementalBuildStrategy {
|
||||||
|
const strategy = new TrackedIncrementalBuildStrategy();
|
||||||
|
strategy.previous = this.next;
|
||||||
|
return strategy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the `IncrementalDriver` associated with a `ts.Program` by monkey-patching it onto the
|
||||||
|
* program under `SYM_INCREMENTAL_DRIVER`.
|
||||||
|
*/
|
||||||
|
export class PatchedProgramIncrementalBuildStrategy implements IncrementalBuildStrategy {
|
||||||
|
getIncrementalDriver(program: ts.Program): IncrementalDriver|null {
|
||||||
|
const driver = (program as any)[SYM_INCREMENTAL_DRIVER];
|
||||||
|
if (driver === undefined || !(driver instanceof IncrementalDriver)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIncrementalDriver(driver: IncrementalDriver, program: ts.Program): void {
|
||||||
|
(program as any)[SYM_INCREMENTAL_DRIVER] = driver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Symbol under which the `IncrementalDriver` is stored on a `ts.Program`.
|
||||||
|
*
|
||||||
|
* The TS model of incremental compilation is based around reuse of a previous `ts.Program` in the
|
||||||
|
* construction of a new one. The `NgCompiler` follows this abstraction - passing in a previous
|
||||||
|
* `ts.Program` is sufficient to trigger incremental compilation. This previous `ts.Program` need
|
||||||
|
* not be from an Angular compilation (that is, it need not have been created from `NgCompiler`).
|
||||||
|
*
|
||||||
|
* If it is, though, Angular can benefit from reusing previous analysis work. This reuse is managed
|
||||||
|
* by the `IncrementalDriver`, which is inherited from the old program to the new program. To
|
||||||
|
* support this behind the API of passing an old `ts.Program`, the `IncrementalDriver` is stored on
|
||||||
|
* the `ts.Program` under this symbol.
|
||||||
|
*/
|
||||||
|
const SYM_INCREMENTAL_DRIVER = Symbol('NgIncrementalDriver');
|
@ -14,6 +14,7 @@ import {verifySupportedTypeScriptVersion} from '../typescript_support';
|
|||||||
|
|
||||||
import {NgCompiler, NgCompilerHost} from './core';
|
import {NgCompiler, NgCompilerHost} from './core';
|
||||||
import {NgCompilerOptions} from './core/api';
|
import {NgCompilerOptions} from './core/api';
|
||||||
|
import {TrackedIncrementalBuildStrategy} from './incremental';
|
||||||
import {IndexedComponent} from './indexer';
|
import {IndexedComponent} from './indexer';
|
||||||
import {NOOP_PERF_RECORDER, PerfRecorder, PerfTracker} from './perf';
|
import {NOOP_PERF_RECORDER, PerfRecorder, PerfTracker} from './perf';
|
||||||
import {ReusedProgramStrategy} from './typecheck';
|
import {ReusedProgramStrategy} from './typecheck';
|
||||||
@ -51,6 +52,7 @@ export class NgtscProgram implements api.Program {
|
|||||||
private host: NgCompilerHost;
|
private host: NgCompilerHost;
|
||||||
private perfRecorder: PerfRecorder = NOOP_PERF_RECORDER;
|
private perfRecorder: PerfRecorder = NOOP_PERF_RECORDER;
|
||||||
private perfTracker: PerfTracker|null = null;
|
private perfTracker: PerfTracker|null = null;
|
||||||
|
private incrementalStrategy: TrackedIncrementalBuildStrategy;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
rootNames: ReadonlyArray<string>, private options: NgCompilerOptions,
|
rootNames: ReadonlyArray<string>, private options: NgCompilerOptions,
|
||||||
@ -77,9 +79,14 @@ export class NgtscProgram implements api.Program {
|
|||||||
const reusedProgramStrategy = new ReusedProgramStrategy(
|
const reusedProgramStrategy = new ReusedProgramStrategy(
|
||||||
this.tsProgram, this.host, this.options, this.host.shimExtensionPrefixes);
|
this.tsProgram, this.host, this.options, this.host.shimExtensionPrefixes);
|
||||||
|
|
||||||
|
this.incrementalStrategy = oldProgram !== undefined ?
|
||||||
|
oldProgram.incrementalStrategy.toNextBuildStrategy() :
|
||||||
|
new TrackedIncrementalBuildStrategy();
|
||||||
|
|
||||||
// Create the NgCompiler which will drive the rest of the compilation.
|
// Create the NgCompiler which will drive the rest of the compilation.
|
||||||
this.compiler = new NgCompiler(
|
this.compiler = new NgCompiler(
|
||||||
this.host, options, this.tsProgram, reusedProgramStrategy, reuseProgram, this.perfRecorder);
|
this.host, options, this.tsProgram, reusedProgramStrategy, this.incrementalStrategy,
|
||||||
|
reuseProgram, this.perfRecorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTsProgram(): ts.Program {
|
getTsProgram(): ts.Program {
|
||||||
|
@ -11,6 +11,7 @@ import * as ts from 'typescript';
|
|||||||
import {NgCompiler, NgCompilerHost} from './core';
|
import {NgCompiler, NgCompilerHost} from './core';
|
||||||
import {NgCompilerOptions, UnifiedModulesHost} from './core/api';
|
import {NgCompilerOptions, UnifiedModulesHost} from './core/api';
|
||||||
import {NodeJSFileSystem, setFileSystem} from './file_system';
|
import {NodeJSFileSystem, setFileSystem} from './file_system';
|
||||||
|
import {PatchedProgramIncrementalBuildStrategy} from './incremental';
|
||||||
import {NOOP_PERF_RECORDER} from './perf';
|
import {NOOP_PERF_RECORDER} from './perf';
|
||||||
import {ReusedProgramStrategy} from './typecheck/src/augmented_program';
|
import {ReusedProgramStrategy} from './typecheck/src/augmented_program';
|
||||||
|
|
||||||
@ -94,7 +95,8 @@ export class NgTscPlugin implements TscPlugin {
|
|||||||
const typeCheckStrategy = new ReusedProgramStrategy(
|
const typeCheckStrategy = new ReusedProgramStrategy(
|
||||||
program, this.host, this.options, this.host.shimExtensionPrefixes);
|
program, this.host, this.options, this.host.shimExtensionPrefixes);
|
||||||
this._compiler = new NgCompiler(
|
this._compiler = new NgCompiler(
|
||||||
this.host, this.options, program, typeCheckStrategy, oldProgram, NOOP_PERF_RECORDER);
|
this.host, this.options, program, typeCheckStrategy,
|
||||||
|
new PatchedProgramIncrementalBuildStrategy(), oldProgram, NOOP_PERF_RECORDER);
|
||||||
return {
|
return {
|
||||||
ignoreForDiagnostics: this._compiler.ignoreForDiagnostics,
|
ignoreForDiagnostics: this._compiler.ignoreForDiagnostics,
|
||||||
ignoreForEmit: this._compiler.ignoreForEmit,
|
ignoreForEmit: this._compiler.ignoreForEmit,
|
||||||
|
@ -9,6 +9,7 @@ ts_library(
|
|||||||
"//packages/compiler-cli",
|
"//packages/compiler-cli",
|
||||||
"//packages/compiler-cli/src/ngtsc/core",
|
"//packages/compiler-cli/src/ngtsc/core",
|
||||||
"//packages/compiler-cli/src/ngtsc/file_system",
|
"//packages/compiler-cli/src/ngtsc/file_system",
|
||||||
|
"//packages/compiler-cli/src/ngtsc/incremental",
|
||||||
"//packages/compiler-cli/src/ngtsc/typecheck",
|
"//packages/compiler-cli/src/ngtsc/typecheck",
|
||||||
"@npm//typescript",
|
"@npm//typescript",
|
||||||
],
|
],
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
import {CompilerOptions} from '@angular/compiler-cli';
|
import {CompilerOptions} from '@angular/compiler-cli';
|
||||||
import {NgCompiler, NgCompilerHost} from '@angular/compiler-cli/src/ngtsc/core';
|
import {NgCompiler, NgCompilerHost} from '@angular/compiler-cli/src/ngtsc/core';
|
||||||
import {AbsoluteFsPath} from '@angular/compiler-cli/src/ngtsc/file_system';
|
import {AbsoluteFsPath} from '@angular/compiler-cli/src/ngtsc/file_system';
|
||||||
|
import {PatchedProgramIncrementalBuildStrategy} from '@angular/compiler-cli/src/ngtsc/incremental';
|
||||||
import {TypeCheckingProgramStrategy, UpdateMode} from '@angular/compiler-cli/src/ngtsc/typecheck';
|
import {TypeCheckingProgramStrategy, UpdateMode} from '@angular/compiler-cli/src/ngtsc/typecheck';
|
||||||
import * as ts from 'typescript/lib/tsserverlibrary';
|
import * as ts from 'typescript/lib/tsserverlibrary';
|
||||||
|
|
||||||
@ -31,7 +32,9 @@ export class Compiler {
|
|||||||
);
|
);
|
||||||
this.strategy = createTypeCheckingProgramStrategy(project);
|
this.strategy = createTypeCheckingProgramStrategy(project);
|
||||||
this.lastKnownProgram = this.strategy.getProgram();
|
this.lastKnownProgram = this.strategy.getProgram();
|
||||||
this.compiler = new NgCompiler(ngCompilerHost, options, this.lastKnownProgram, this.strategy);
|
this.compiler = new NgCompiler(
|
||||||
|
ngCompilerHost, options, this.lastKnownProgram, this.strategy,
|
||||||
|
new PatchedProgramIncrementalBuildStrategy());
|
||||||
}
|
}
|
||||||
|
|
||||||
setCompilerOptions(options: CompilerOptions) {
|
setCompilerOptions(options: CompilerOptions) {
|
||||||
@ -43,8 +46,9 @@ export class Compiler {
|
|||||||
const ngCompilerHost =
|
const ngCompilerHost =
|
||||||
NgCompilerHost.wrap(this.tsCompilerHost, inputFiles, this.options, this.lastKnownProgram);
|
NgCompilerHost.wrap(this.tsCompilerHost, inputFiles, this.options, this.lastKnownProgram);
|
||||||
const program = this.strategy.getProgram();
|
const program = this.strategy.getProgram();
|
||||||
this.compiler =
|
this.compiler = new NgCompiler(
|
||||||
new NgCompiler(ngCompilerHost, this.options, program, this.strategy, this.lastKnownProgram);
|
ngCompilerHost, this.options, program, this.strategy,
|
||||||
|
new PatchedProgramIncrementalBuildStrategy(), this.lastKnownProgram);
|
||||||
try {
|
try {
|
||||||
// This is the only way to force the compiler to update the typecheck file
|
// This is the only way to force the compiler to update the typecheck file
|
||||||
// in the program. We have to do try-catch because the compiler immediately
|
// in the program. We have to do try-catch because the compiler immediately
|
||||||
|
Loading…
x
Reference in New Issue
Block a user