From 59607dc4954a50fb90f760d9add9b659747ec8cf Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Tue, 3 Mar 2020 12:17:55 +0100 Subject: [PATCH] fix(core): undecorated-classes-with-di migration should handle libraries generated with CLI versions past v6.2.0 (#35824) The options for `flatModuleId` and `flatModuleOutFile` had been removed in the CLI from generated libraries with https://github.com/angular/angular-cli/commit/718ee15b9a1d7b9d7ad520f25c67b8659059a33a. This has been done because `ng-packagr` (which is used to build the libraries) automatically set these options in-memory when it compiles the library. No migration has been created for this because there was no actual need to get rid of this. Keeping the options in the library `tsconfig` does not cause any problems unless the `tsconfig` is used outside of `ng-packagr`. This was not anticipated, but is now commonly done in `ng update` migrations. The `ng update` migrations try to create an instance of the `AngularCompilerProgram` by simply parsing the `tsconfig`. The migrations make the valid assumption that `tsconfig` files are not incomplete/invalid. They _definitely_ are in the file system though. It just works for libraries because `ng-packagr` in-memory completes the invalid `tsconfig` files, so that they can be passed to the `@angular/compiler-cli`. We can't have this logic in the `ng update` migrations because it's out-of-scope for individual migrations to distinguish between libraries and applications. Also it would be out-of-scope to parse the `ng-packagr` configuration and handle the tsconfig in-memory completion. As a workaround though, we can remove the flat-module bundle options in-memory when creating the compiler program. This is acceptable since we don't emit the program and the flat module bundles are not needed. Fixes #34985. PR Close #35824 --- .../create_ngc_program.ts | 13 +++++++ ...ecorated_classes_with_di_migration_spec.ts | 34 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/packages/core/schematics/migrations/undecorated-classes-with-di/create_ngc_program.ts b/packages/core/schematics/migrations/undecorated-classes-with-di/create_ngc_program.ts index 4c0f09cb51..a25fc52c0b 100644 --- a/packages/core/schematics/migrations/undecorated-classes-with-di/create_ngc_program.ts +++ b/packages/core/schematics/migrations/undecorated-classes-with-di/create_ngc_program.ts @@ -20,6 +20,19 @@ export function createNgcProgram( // NGC program. In order to ensure that the migration runs properly, we set "enableIvy" to false. options.enableIvy = false; + // Libraries which have been generated with CLI versions past v6.2.0, explicitly set the + // flat-module options in their tsconfig files. This is problematic because by default, + // those tsconfig files do not specify explicit source files which can be considered as + // entry point for the flat-module bundle. Therefore the `@angular/compiler-cli` is unable + // to determine the flat module entry point and throws a compile error. This is not an issue + // for the libraries built with `ng-packagr`, because the tsconfig files are modified in-memory + // to specify an explicit flat module entry-point. Our migrations don't distinguish between + // libraries and applications, and also don't run `ng-packagr`. To ensure that such libraries + // can be successfully migrated, we remove the flat-module options to eliminate the flat module + // entry-point requirement. More context: https://github.com/angular/angular/issues/34985. + options.flatModuleId = undefined; + options.flatModuleOutFile = undefined; + const host = createHost(options); // For this migration, we never need to read resources and can just return diff --git a/packages/core/schematics/test/undecorated_classes_with_di_migration_spec.ts b/packages/core/schematics/test/undecorated_classes_with_di_migration_spec.ts index b39a8ae74a..997dca5b52 100644 --- a/packages/core/schematics/test/undecorated_classes_with_di_migration_spec.ts +++ b/packages/core/schematics/test/undecorated_classes_with_di_migration_spec.ts @@ -1473,6 +1473,40 @@ describe('Undecorated classes with DI migration', () => { 'TypeScript program failures'); }); + // Regression test for: https://github.com/angular/angular/issues/34985. + it('should be able to migrate libraries with multiple source files and flat-module ' + + 'options set', + async() => { + writeFile('/tsconfig.json', JSON.stringify({ + compilerOptions: { + lib: ['es2015'], + }, + angularCompilerOptions: + {flatModuleId: 'AUTOGENERATED', flatModuleOutFile: 'AUTOGENERATED'} + })); + + writeFile('/second.ts', ``); + writeFile('/test.ts', ` + import {Injectable, NgModule, NgZone} from '@angular/core'; + + export class BaseClass { + constructor(zone: NgZone) {} + } + + @Injectable({template: ''}) + export class MyService extends BaseClass {} + + @NgModule({providers: [MyService]}) + export class AppModule {} + `); + + await runMigration(); + + expect(errorOutput.length).toBe(0); + expect(warnOutput.length).toBe(0); + expect(tree.readContent('/test.ts')).toMatch(/@Injectable\(\)\nexport class BaseClass {/); + }); + it('should not throw if resources could not be read', async() => { writeFile('/index.ts', ` import {Component, NgModule} from '@angular/core';