fix(core): renderer-to-renderer2 migration not migrating methods (#33571)

The `renderer-to-renderer2` migration currently does not work
properly in v9 because the migration relies on the type checker
for detecting references to `Renderer` from `@angular/core`.

This is contradictory since the `Renderer` is no longer
exported in v9 `@angular/core`. In order to make sure that
the migration still works in v9, and that we can rely on the
type checker for the best possible detection, we take advantage
of module augmentation and in-memory add the `Renderer` export
to the `@angular/core` module.

PR Close #33571
This commit is contained in:
Paul Gschwendtner 2019-11-05 20:25:46 +01:00 committed by atscott
parent 974005b064
commit d751ca7596
3 changed files with 24 additions and 8 deletions

View File

@ -18,18 +18,17 @@ import {HelperFunction, getHelper} from './helpers';
import {migrateExpression, replaceImport} from './migration';
import {findCoreImport, findRendererReferences} from './util';
const MODULE_AUGMENTATION_FILENAME = 'ɵɵRENDERER_MIGRATION_CORE_AUGMENTATION.d.ts';
/**
* Migration that switches from `Renderer` to `Renderer2`. More information on how it works:
* https://hackmd.angular.io/UTzUZTnPRA-cSa_4mHyfYw
*/
export default function(): Rule {
return (tree: Tree, context: SchematicContext) => {
return (tree: Tree) => {
const {buildPaths, testPaths} = getProjectTsConfigPaths(tree);
const basePath = process.cwd();
const allPaths = [...buildPaths, ...testPaths];
const logger = context.logger;
if (!allPaths.length) {
throw new SchematicsException(
@ -44,8 +43,23 @@ export default function(): Rule {
function runRendererToRenderer2Migration(tree: Tree, tsconfigPath: string, basePath: string) {
const parsed = parseTsconfigFile(tsconfigPath, dirname(tsconfigPath));
const host = createMigrationCompilerHost(tree, parsed.options, basePath);
const program = ts.createProgram(parsed.fileNames, parsed.options, host);
const host = createMigrationCompilerHost(tree, parsed.options, basePath, fileName => {
// In case the module augmentation file has been requested, we return a source file that
// augments "@angular/core" to include a named export called "Renderer". This ensures that
// we can rely on the type checker for this migration in v9 where "Renderer" has been removed.
if (fileName === MODULE_AUGMENTATION_FILENAME) {
return `
import '@angular/core';
declare module "@angular/core" {
class Renderer {}
}
`;
}
return null;
});
const program =
ts.createProgram(parsed.fileNames.concat(MODULE_AUGMENTATION_FILENAME), parsed.options, host);
const typeChecker = program.getTypeChecker();
const printer = ts.createPrinter();
const sourceFiles = program.getSourceFiles().filter(

View File

@ -35,7 +35,6 @@ describe('Renderer to Renderer2 migration', () => {
}));
// We need to declare the Angular symbols we're testing for, otherwise type checking won't work.
writeFile('/node_modules/@angular/core/index.d.ts', `
export declare abstract class Renderer {}
export declare function forwardRef(fn: () => any): any {}
`);

View File

@ -10,7 +10,8 @@ import {relative} from 'path';
import * as ts from 'typescript';
export function createMigrationCompilerHost(
tree: Tree, options: ts.CompilerOptions, basePath: string): ts.CompilerHost {
tree: Tree, options: ts.CompilerOptions, basePath: string,
fakeRead?: (fileName: string) => string | null): ts.CompilerHost {
const host = ts.createCompilerHost(options, true);
// We need to overwrite the host "readFile" method, as we want the TypeScript
@ -18,7 +19,9 @@ export function createMigrationCompilerHost(
// if we run multiple migrations we might have intersecting changes and
// source files.
host.readFile = fileName => {
const buffer = tree.read(relative(basePath, fileName));
const treeRelativePath = relative(basePath, fileName);
const fakeOutput = fakeRead ? fakeRead(treeRelativePath) : null;
const buffer = fakeOutput === null ? tree.read(treeRelativePath) : fakeOutput;
// Strip BOM as otherwise TSC methods (Ex: getWidth) will return an offset which
// which breaks the CLI UpdateRecorder.
// See: https://github.com/angular/angular/pull/30719