angular-cn/packages/language-service/ivy/compiler_factory.ts

92 lines
3.4 KiB
TypeScript
Raw Normal View History

/**
* @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 {NgCompiler} from '@angular/compiler-cli/src/ngtsc/core';
import {NgCompilerOptions} from '@angular/compiler-cli/src/ngtsc/core/api';
import {TrackedIncrementalBuildStrategy} from '@angular/compiler-cli/src/ngtsc/incremental';
import {TypeCheckingProgramStrategy} from '@angular/compiler-cli/src/ngtsc/typecheck/api';
import * as ts from 'typescript/lib/tsserverlibrary';
import {LanguageServiceAdapter} from './language_service_adapter';
import {isExternalTemplate} from './utils';
test(language-service): introduce new virtual testing environment (#39594) This commit adds new language service testing infrastructure which allows for in-memory testing. It solves a number of issues with the previous testing infrastructure that relied on a single integration project across all of the tests, and also provides for much faster builds by using the compiler-cli's mock versions of @angular/core and @angular/common. A new `LanguageServiceTestEnvironment` class (conceptually mirroring the compiler-cli `NgtscTestEnvironment`) controls setup and execution of tests. The `FileSystem` abstraction is used to drive a `ts.server.ServerHost`, which backs the language service infrastructure. Since many language service tests revolve around the template, the API is currently optimized to spin up a "skeleton" project and then override its template for each test. The existing Quick Info tests (quick_info_spec.ts) were ported to the new infrastructure for validation. The tests were cleaned up a bit to remove unnecessary initializations as well as correct legitimate template errors which did not affect the test outcome, but caused additional validation of test correctness to fail. They still utilize a shared project with all fields required for each individual unit test, which is an anti-pattern, but new tests can now easily be written independently without relying on the shared project, which was extremely difficult previously. Future cleanup work might refactor these tests to be more independent. PR Close #39594
2020-11-04 15:28:59 -05:00
/**
* Manages the `NgCompiler` instance which backs the language service, updating or replacing it as
* needed to produce an up-to-date understanding of the current program.
*
* TODO(alxhub): currently the options used for the compiler are specified at `CompilerFactory`
* construction, and are not changable. In a real project, users can update `tsconfig.json`. We need
* to properly handle a change in the compiler options, either by having an API to update the
* `CompilerFactory` to use new options, or by replacing it entirely.
*/
export class CompilerFactory {
private readonly incrementalStrategy = new TrackedIncrementalBuildStrategy();
private compiler: NgCompiler|null = null;
private lastKnownProgram: ts.Program|null = null;
constructor(
private readonly adapter: LanguageServiceAdapter,
private readonly programStrategy: TypeCheckingProgramStrategy,
test(language-service): introduce new virtual testing environment (#39594) This commit adds new language service testing infrastructure which allows for in-memory testing. It solves a number of issues with the previous testing infrastructure that relied on a single integration project across all of the tests, and also provides for much faster builds by using the compiler-cli's mock versions of @angular/core and @angular/common. A new `LanguageServiceTestEnvironment` class (conceptually mirroring the compiler-cli `NgtscTestEnvironment`) controls setup and execution of tests. The `FileSystem` abstraction is used to drive a `ts.server.ServerHost`, which backs the language service infrastructure. Since many language service tests revolve around the template, the API is currently optimized to spin up a "skeleton" project and then override its template for each test. The existing Quick Info tests (quick_info_spec.ts) were ported to the new infrastructure for validation. The tests were cleaned up a bit to remove unnecessary initializations as well as correct legitimate template errors which did not affect the test outcome, but caused additional validation of test correctness to fail. They still utilize a shared project with all fields required for each individual unit test, which is an anti-pattern, but new tests can now easily be written independently without relying on the shared project, which was extremely difficult previously. Future cleanup work might refactor these tests to be more independent. PR Close #39594
2020-11-04 15:28:59 -05:00
private readonly options: NgCompilerOptions,
) {}
test(language-service): introduce new virtual testing environment (#39594) This commit adds new language service testing infrastructure which allows for in-memory testing. It solves a number of issues with the previous testing infrastructure that relied on a single integration project across all of the tests, and also provides for much faster builds by using the compiler-cli's mock versions of @angular/core and @angular/common. A new `LanguageServiceTestEnvironment` class (conceptually mirroring the compiler-cli `NgtscTestEnvironment`) controls setup and execution of tests. The `FileSystem` abstraction is used to drive a `ts.server.ServerHost`, which backs the language service infrastructure. Since many language service tests revolve around the template, the API is currently optimized to spin up a "skeleton" project and then override its template for each test. The existing Quick Info tests (quick_info_spec.ts) were ported to the new infrastructure for validation. The tests were cleaned up a bit to remove unnecessary initializations as well as correct legitimate template errors which did not affect the test outcome, but caused additional validation of test correctness to fail. They still utilize a shared project with all fields required for each individual unit test, which is an anti-pattern, but new tests can now easily be written independently without relying on the shared project, which was extremely difficult previously. Future cleanup work might refactor these tests to be more independent. PR Close #39594
2020-11-04 15:28:59 -05:00
getOrCreate(): NgCompiler {
const program = this.programStrategy.getProgram();
test(language-service): introduce new virtual testing environment (#39594) This commit adds new language service testing infrastructure which allows for in-memory testing. It solves a number of issues with the previous testing infrastructure that relied on a single integration project across all of the tests, and also provides for much faster builds by using the compiler-cli's mock versions of @angular/core and @angular/common. A new `LanguageServiceTestEnvironment` class (conceptually mirroring the compiler-cli `NgtscTestEnvironment`) controls setup and execution of tests. The `FileSystem` abstraction is used to drive a `ts.server.ServerHost`, which backs the language service infrastructure. Since many language service tests revolve around the template, the API is currently optimized to spin up a "skeleton" project and then override its template for each test. The existing Quick Info tests (quick_info_spec.ts) were ported to the new infrastructure for validation. The tests were cleaned up a bit to remove unnecessary initializations as well as correct legitimate template errors which did not affect the test outcome, but caused additional validation of test correctness to fail. They still utilize a shared project with all fields required for each individual unit test, which is an anti-pattern, but new tests can now easily be written independently without relying on the shared project, which was extremely difficult previously. Future cleanup work might refactor these tests to be more independent. PR Close #39594
2020-11-04 15:28:59 -05:00
if (this.compiler === null || program !== this.lastKnownProgram) {
this.compiler = new NgCompiler(
this.adapter, // like compiler host
test(language-service): introduce new virtual testing environment (#39594) This commit adds new language service testing infrastructure which allows for in-memory testing. It solves a number of issues with the previous testing infrastructure that relied on a single integration project across all of the tests, and also provides for much faster builds by using the compiler-cli's mock versions of @angular/core and @angular/common. A new `LanguageServiceTestEnvironment` class (conceptually mirroring the compiler-cli `NgtscTestEnvironment`) controls setup and execution of tests. The `FileSystem` abstraction is used to drive a `ts.server.ServerHost`, which backs the language service infrastructure. Since many language service tests revolve around the template, the API is currently optimized to spin up a "skeleton" project and then override its template for each test. The existing Quick Info tests (quick_info_spec.ts) were ported to the new infrastructure for validation. The tests were cleaned up a bit to remove unnecessary initializations as well as correct legitimate template errors which did not affect the test outcome, but caused additional validation of test correctness to fail. They still utilize a shared project with all fields required for each individual unit test, which is an anti-pattern, but new tests can now easily be written independently without relying on the shared project, which was extremely difficult previously. Future cleanup work might refactor these tests to be more independent. PR Close #39594
2020-11-04 15:28:59 -05:00
this.options, // angular compiler options
program,
this.programStrategy,
this.incrementalStrategy,
true, // enableTemplateTypeChecker
this.lastKnownProgram,
undefined, // perfRecorder (use default)
);
this.lastKnownProgram = program;
}
test(language-service): introduce new virtual testing environment (#39594) This commit adds new language service testing infrastructure which allows for in-memory testing. It solves a number of issues with the previous testing infrastructure that relied on a single integration project across all of the tests, and also provides for much faster builds by using the compiler-cli's mock versions of @angular/core and @angular/common. A new `LanguageServiceTestEnvironment` class (conceptually mirroring the compiler-cli `NgtscTestEnvironment`) controls setup and execution of tests. The `FileSystem` abstraction is used to drive a `ts.server.ServerHost`, which backs the language service infrastructure. Since many language service tests revolve around the template, the API is currently optimized to spin up a "skeleton" project and then override its template for each test. The existing Quick Info tests (quick_info_spec.ts) were ported to the new infrastructure for validation. The tests were cleaned up a bit to remove unnecessary initializations as well as correct legitimate template errors which did not affect the test outcome, but caused additional validation of test correctness to fail. They still utilize a shared project with all fields required for each individual unit test, which is an anti-pattern, but new tests can now easily be written independently without relying on the shared project, which was extremely difficult previously. Future cleanup work might refactor these tests to be more independent. PR Close #39594
2020-11-04 15:28:59 -05:00
return this.compiler;
}
/**
* Create a new instance of the Ivy compiler if the program has changed since
* the last time the compiler was instantiated. If the program has not changed,
* return the existing instance.
* @param fileName override the template if this is an external template file
* @param options angular compiler options
*/
getOrCreateWithChangedFile(fileName: string): NgCompiler {
const compiler = this.getOrCreate();
if (isExternalTemplate(fileName)) {
test(language-service): introduce new virtual testing environment (#39594) This commit adds new language service testing infrastructure which allows for in-memory testing. It solves a number of issues with the previous testing infrastructure that relied on a single integration project across all of the tests, and also provides for much faster builds by using the compiler-cli's mock versions of @angular/core and @angular/common. A new `LanguageServiceTestEnvironment` class (conceptually mirroring the compiler-cli `NgtscTestEnvironment`) controls setup and execution of tests. The `FileSystem` abstraction is used to drive a `ts.server.ServerHost`, which backs the language service infrastructure. Since many language service tests revolve around the template, the API is currently optimized to spin up a "skeleton" project and then override its template for each test. The existing Quick Info tests (quick_info_spec.ts) were ported to the new infrastructure for validation. The tests were cleaned up a bit to remove unnecessary initializations as well as correct legitimate template errors which did not affect the test outcome, but caused additional validation of test correctness to fail. They still utilize a shared project with all fields required for each individual unit test, which is an anti-pattern, but new tests can now easily be written independently without relying on the shared project, which was extremely difficult previously. Future cleanup work might refactor these tests to be more independent. PR Close #39594
2020-11-04 15:28:59 -05:00
this.overrideTemplate(fileName, compiler);
}
test(language-service): introduce new virtual testing environment (#39594) This commit adds new language service testing infrastructure which allows for in-memory testing. It solves a number of issues with the previous testing infrastructure that relied on a single integration project across all of the tests, and also provides for much faster builds by using the compiler-cli's mock versions of @angular/core and @angular/common. A new `LanguageServiceTestEnvironment` class (conceptually mirroring the compiler-cli `NgtscTestEnvironment`) controls setup and execution of tests. The `FileSystem` abstraction is used to drive a `ts.server.ServerHost`, which backs the language service infrastructure. Since many language service tests revolve around the template, the API is currently optimized to spin up a "skeleton" project and then override its template for each test. The existing Quick Info tests (quick_info_spec.ts) were ported to the new infrastructure for validation. The tests were cleaned up a bit to remove unnecessary initializations as well as correct legitimate template errors which did not affect the test outcome, but caused additional validation of test correctness to fail. They still utilize a shared project with all fields required for each individual unit test, which is an anti-pattern, but new tests can now easily be written independently without relying on the shared project, which was extremely difficult previously. Future cleanup work might refactor these tests to be more independent. PR Close #39594
2020-11-04 15:28:59 -05:00
return compiler;
}
private overrideTemplate(fileName: string, compiler: NgCompiler) {
if (!this.adapter.isTemplateDirty(fileName)) {
return;
}
// 1. Get the latest snapshot
const latestTemplate = this.adapter.readResource(fileName);
// 2. Find all components that use the template
const ttc = compiler.getTemplateTypeChecker();
const components = compiler.getComponentsWithTemplateFile(fileName);
// 3. Update component template
for (const component of components) {
if (ts.isClassDeclaration(component)) {
ttc.overrideComponentTemplate(component, latestTemplate);
}
}
}
registerLastKnownProgram() {
this.lastKnownProgram = this.programStrategy.getProgram();
}
}