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 35b6c764ae..4c0f09cb51 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 @@ -6,13 +6,13 @@ * found in the LICENSE file at https://angular.io/license */ -import {AotCompiler, CompileStylesheetMetadata} from '@angular/compiler'; -import {createProgram, readConfiguration} from '@angular/compiler-cli'; +import {AotCompiler} from '@angular/compiler'; +import {CompilerHost, createProgram, readConfiguration} from '@angular/compiler-cli'; import * as ts from 'typescript'; /** Creates an NGC program that can be used to read and parse metadata for files. */ export function createNgcProgram( - createHost: (options: ts.CompilerOptions) => ts.CompilerHost, tsconfigPath: string) { + createHost: (options: ts.CompilerOptions) => CompilerHost, tsconfigPath: string) { const {rootNames, options} = readConfiguration(tsconfigPath); // https://github.com/angular/angular/commit/ec4381dd401f03bded652665b047b6b90f2b425f made Ivy @@ -21,24 +21,21 @@ export function createNgcProgram( options.enableIvy = false; const host = createHost(options); + + // For this migration, we never need to read resources and can just return + // an empty string for requested resources. We need to handle requested resources + // because our created NGC compiler program does not know about special resolutions + // which are set up by the Angular CLI. i.e. resolving stylesheets through "tilde". + host.readResource = () => ''; + host.resourceNameToFileName = () => '$fake-file$'; + const ngcProgram = createProgram({rootNames, options, host}); - const program = ngcProgram.getTsProgram(); // The "AngularCompilerProgram" does not expose the "AotCompiler" instance, nor does it // expose the logic that is necessary to analyze the determined modules. We work around // this by just accessing the necessary private properties using the bracket notation. const compiler: AotCompiler = (ngcProgram as any)['compiler']; - const metadataResolver = compiler['_metadataResolver']; - // Modify the "DirectiveNormalizer" to not normalize any referenced external stylesheets. - // This is necessary because in CLI projects preprocessor files are commonly referenced - // and we don't want to parse them in order to extract relative style references. This - // breaks the analysis of the project because we instantiate a standalone AOT compiler - // program which does not contain the custom logic by the Angular CLI Webpack compiler plugin. - const directiveNormalizer = metadataResolver !['_directiveNormalizer']; - directiveNormalizer['_normalizeStylesheet'] = function(metadata: CompileStylesheetMetadata) { - return new CompileStylesheetMetadata( - {styles: metadata.styles, styleUrls: [], moduleUrl: metadata.moduleUrl !}); - }; + const program = ngcProgram.getTsProgram(); return {host, ngcProgram, program, compiler}; } 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 5ec019d950..06dfbb231d 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 @@ -1457,5 +1457,27 @@ describe('Undecorated classes with DI migration', () => { expect(errorOutput.length).toBe(1); expect(errorOutput[0]).toMatch(/error TS1005: 'from' expected/); }); + + it('should not throw if resources could not be read', async() => { + writeFile('/index.ts', ` + import {Component, NgModule} from '@angular/core'; + + @Component({ + templateUrl: './my-template.pug', + styleUrls: ["./test.scss", "./some-special-file.custom"], + }) + export class TestComp {} + + @NgModule({declarations: [TestComp]}) + export class MyModule {} + `); + + writeFile('/test.scss', `@import '~theme.scss';`); + + await runMigration(); + + expect(warnOutput.length).toBe(0); + expect(errorOutput.length).toBe(0); + }); }); });