refactor(ivy): ngcc - move typings rendering to `Renderer` (#26403)

The rendering of typings is not specific to the package
format, so it doesn't make sense to put it in a specific
renderer.

As a result there is no real difference between esm5 and esm2015
renderers, so there is no point in having separate classes.

PR Close #26403
This commit is contained in:
Pete Bacon Darwin 2018-10-10 17:52:55 +01:00 committed by Kara Erickson
parent e804143183
commit dff10085e8
9 changed files with 45 additions and 100 deletions

View File

@ -16,9 +16,7 @@ import {DtsMapper} from '../host/dts_mapper';
import {Esm2015ReflectionHost} from '../host/esm2015_host';
import {Esm5ReflectionHost} from '../host/esm5_host';
import {NgccReflectionHost} from '../host/ngcc_host';
import {Esm2015Renderer} from '../rendering/esm2015_renderer';
import {Esm5Renderer} from '../rendering/esm5_renderer';
import {Fesm2015Renderer} from '../rendering/fesm2015_renderer';
import {EsmRenderer} from '../rendering/esm_renderer';
import {FileInfo, Renderer} from '../rendering/renderer';
import {checkMarkerFile, writeMarkerFile} from './build_marker';
@ -122,18 +120,13 @@ export class Transformer {
getRenderer(
format: string, program: ts.Program, host: NgccReflectionHost, isCore: boolean,
rewriteCoreImportsTo: ts.SourceFile|null, dtsMapper: DtsMapper): Renderer {
rewriteCoreImportsTo: ts.SourceFile|null, dtsMapper: DtsMapper|null): Renderer {
switch (format) {
case 'esm2015':
return new Esm2015Renderer(
host, isCore, rewriteCoreImportsTo, this.sourcePath, this.targetPath, dtsMapper);
case 'fesm2015':
return new Fesm2015Renderer(
host, isCore, rewriteCoreImportsTo, this.sourcePath, this.targetPath);
case 'esm5':
case 'fesm2015':
case 'fesm5':
return new Esm5Renderer(
host, isCore, rewriteCoreImportsTo, this.sourcePath, this.targetPath);
return new EsmRenderer(host, isCore, rewriteCoreImportsTo, this.sourcePath, this.targetPath, dtsMapper);
default:
throw new Error(`Renderer for "${format}" not yet implemented.`);
}

View File

@ -1,63 +0,0 @@
/**
* @license
* Copyright Google Inc. 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 {relative, resolve} from 'canonical-path';
import {readFileSync} from 'fs';
import * as ts from 'typescript';
import {DtsFileTransformer} from '../../../ngtsc/transform';
import {DecorationAnalysis} from '../analysis/decoration_analyzer';
import {SwitchMarkerAnalysis} from '../analysis/switch_marker_analyzer';
import {IMPORT_PREFIX} from '../constants';
import {DtsMapper} from '../host/dts_mapper';
import {NgccReflectionHost} from '../host/ngcc_host';
import {Fesm2015Renderer} from './fesm2015_renderer';
import {FileInfo} from './renderer';
export class Esm2015Renderer extends Fesm2015Renderer {
constructor(
protected host: NgccReflectionHost, protected isCore: boolean,
protected rewriteCoreImportsTo: ts.SourceFile|null, protected sourcePath: string,
protected targetPath: string, protected dtsMapper: DtsMapper) {
super(host, isCore, rewriteCoreImportsTo, sourcePath, targetPath);
}
renderFile(
sourceFile: ts.SourceFile, decorationAnalysis: DecorationAnalysis|undefined,
switchMarkerAnalysis: SwitchMarkerAnalysis|undefined, targetPath: string): FileInfo[] {
const renderedFiles =
super.renderFile(sourceFile, decorationAnalysis, switchMarkerAnalysis, targetPath);
// Transform the `.d.ts` files.
// TODO(gkalpak): What about `.d.ts` source maps? (See
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html#new---declarationmap.)
if (decorationAnalysis) {
// Create a `DtsFileTransformer` for the source file and record the generated fields, which
// will allow the corresponding `.d.ts` file to be transformed later.
const dtsTransformer = new DtsFileTransformer(this.rewriteCoreImportsTo, IMPORT_PREFIX);
decorationAnalysis.analyzedClasses.forEach(
analyzedClass =>
dtsTransformer.recordStaticField(analyzedClass.name, analyzedClass.compilation));
// Find the corresponding `.d.ts` file.
const sourceFileName = sourceFile.fileName;
const originalDtsFileName = this.dtsMapper.getDtsFileNameFor(sourceFileName);
const originalDtsContents = readFileSync(originalDtsFileName, 'utf8');
// Transform the `.d.ts` file based on the recorded source file changes.
const transformedDtsFileName =
resolve(this.targetPath, relative(this.sourcePath, originalDtsFileName));
const transformedDtsContents = dtsTransformer.transform(originalDtsContents, sourceFileName);
// Add the transformed `.d.ts` file to the list of output files.
renderedFiles.push({path: transformedDtsFileName, contents: transformedDtsContents});
}
return renderedFiles;
}
}

View File

@ -1,10 +0,0 @@
/**
* @license
* Copyright Google Inc. 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 {Fesm2015Renderer} from './fesm2015_renderer';
export class Esm5Renderer extends Fesm2015Renderer {}

View File

@ -7,16 +7,17 @@
*/
import * as ts from 'typescript';
import MagicString from 'magic-string';
import {DtsMapper} from '../host/dts_mapper';
import {NgccReflectionHost, POST_R3_MARKER, PRE_R3_MARKER, SwitchableVariableDeclaration} from '../host/ngcc_host';
import {AnalyzedClass} from '../analysis/decoration_analyzer';
import {Renderer} from './renderer';
export class Fesm2015Renderer extends Renderer {
export class EsmRenderer extends Renderer {
constructor(
protected host: NgccReflectionHost, protected isCore: boolean,
protected rewriteCoreImportsTo: ts.SourceFile|null, protected sourcePath: string,
protected targetPath: string) {
super(host, isCore, rewriteCoreImportsTo, sourcePath, targetPath);
protected targetPath: string, dtsMapper: DtsMapper|null) {
super(host, isCore, rewriteCoreImportsTo, sourcePath, targetPath, dtsMapper);
}
/**

View File

@ -14,11 +14,13 @@ import {SourceMapConsumer, SourceMapGenerator, RawSourceMap} from 'source-map';
import * as ts from 'typescript';
import {Decorator} from '../../../ngtsc/host';
import {DtsFileTransformer} from '../../../ngtsc/transform';
import {translateStatement} from '../../../ngtsc/translator';
import {NgccImportManager} from './ngcc_import_manager';
import {AnalyzedClass, DecorationAnalysis, DecorationAnalyses} from '../analysis/decoration_analyzer';
import {SwitchMarkerAnalyses, SwitchMarkerAnalysis} from '../analysis/switch_marker_analyzer';
import {IMPORT_PREFIX} from '../constants';
import {DtsMapper} from '../host/dts_mapper';
import {NgccReflectionHost, SwitchableVariableDeclaration} from '../host/ngcc_host';
interface SourceMapInfo {
@ -65,23 +67,27 @@ export abstract class Renderer {
constructor(
protected host: NgccReflectionHost, protected isCore: boolean,
protected rewriteCoreImportsTo: ts.SourceFile|null, protected sourcePath: string,
protected targetPath: string) {}
protected targetPath: string, protected dtsMapper: DtsMapper|null) {}
renderProgram(
program: ts.Program, decorationAnalyses: DecorationAnalyses,
switchMarkerAnalyses: SwitchMarkerAnalyses): FileInfo[] {
const renderedFiles: FileInfo[] = [];
// Transform the source files and source maps.
// Transform the source files, source maps and typings files.
program.getSourceFiles().map(sourceFile => {
const decorationAnalysis = decorationAnalyses.get(sourceFile);
const switchMarkerAnalysis = switchMarkerAnalyses.get(sourceFile);
// Transform the source files and source maps.
if (decorationAnalysis || switchMarkerAnalysis) {
const targetPath = resolve(this.targetPath, relative(this.sourcePath, sourceFile.fileName));
renderedFiles.push(
...this.renderFile(sourceFile, decorationAnalysis, switchMarkerAnalysis, targetPath));
}
if (decorationAnalyses) {
renderedFiles.push(...this.renderTypings(decorationAnalyses));
}
});
return renderedFiles;
}
@ -244,6 +250,27 @@ export abstract class Renderer {
};
}
}
// TODO(gkalpak): What about `.d.ts` source maps? (See
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html#new---declarationmap.)
renderTypings(decorationAnalyses: DecorationAnalyses): FileInfo[] {
const renderedFiles: FileInfo[] = [];
if (this.dtsMapper) {
const dtsTransformer = new DtsFileTransformer(this.rewriteCoreImportsTo, IMPORT_PREFIX);
decorationAnalyses.forEach((analysis, sourceFile) => {
const sourceFileName = sourceFile.fileName;
const dtsFileName = this.dtsMapper !.getDtsFileNameFor(sourceFileName);
const dtsContents = readFileSync(dtsFileName, 'utf8');
analysis.analyzedClasses.forEach(analyzedClass => dtsTransformer.recordStaticField(analyzedClass.name, analyzedClass.compilation));
const newDtsFileName = resolve(this.targetPath, relative(this.sourcePath, dtsFileName));
const newDtsContents = dtsTransformer.transform(dtsContents, sourceFileName);
renderedFiles.push({path: newDtsFileName, contents: newDtsContents});
});
}
return renderedFiles;
// }
}
}
/**

View File

@ -1208,8 +1208,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return a collection of all the switchable variable declarations in the given module',
() => {
const program = makeProgram(MARKER_FILE);
const dtsMapper = new DtsMapper('/src', '/typings');
const host = new Esm2015ReflectionHost(false, program.getTypeChecker(), dtsMapper);
const host = new Esm2015ReflectionHost(false, program.getTypeChecker());
const file = program.getSourceFile(MARKER_FILE.name) !;
const declarations = host.getSwitchableDeclarations(file);
expect(declarations.map(d => [d.name.getText(), d.initializer !.getText()])).toEqual([
@ -1222,8 +1221,7 @@ describe('Fesm2015ReflectionHost', () => {
it('should return an array of objects for each file that has exported and decorated classes',
() => {
const program = makeProgram(...DECORATED_FILES);
const dtsMapper = new DtsMapper('/src', '/typings');
const host = new Esm2015ReflectionHost(false, program.getTypeChecker(), dtsMapper);
const host = new Esm2015ReflectionHost(false, program.getTypeChecker());
const primaryFile = program.getSourceFile(DECORATED_FILES[0].name) !;
const secondaryFile = program.getSourceFile(DECORATED_FILES[1].name) !;
const decoratedFiles = host.findDecoratedFiles(primaryFile);

View File

@ -14,18 +14,17 @@ import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer';
import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer';
import {DtsMapper} from '../../src/host/dts_mapper';
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
import {Esm2015Renderer} from '../../src/rendering/esm2015_renderer';
import {EsmRenderer} from '../../src/rendering/esm_renderer';
function setup(file: {name: string, contents: string}, transformDts: boolean = false) {
const dir = dirname(file.name);
const dtsMapper = new DtsMapper(dir, dir);
const program = makeProgram(file);
const sourceFile = program.getSourceFile(file.name) !;
const host = new Esm2015ReflectionHost(false, program.getTypeChecker());
const decorationAnalyses =
new DecorationAnalyzer(program.getTypeChecker(), host, [''], false).analyzeProgram(program);
const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(program);
const renderer = new Esm2015Renderer(host, false, null, dir, dir, dtsMapper);
const renderer = new EsmRenderer(host, false, null, dir, dir, null);
return {host, program, sourceFile, renderer, decorationAnalyses, switchMarkerAnalyses};
}

View File

@ -11,7 +11,7 @@ import {makeProgram} from '../helpers/utils';
import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer';
import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer';
import {Esm5ReflectionHost} from '../../src/host/esm5_host';
import {Esm5Renderer} from '../../src/rendering/esm5_renderer';
import {EsmRenderer} from '../../src/rendering/esm_renderer';
function setup(file: {name: string, contents: string}) {
const program = makeProgram(file);
@ -20,7 +20,7 @@ function setup(file: {name: string, contents: string}) {
const decorationAnalyses =
new DecorationAnalyzer(program.getTypeChecker(), host, [''], false).analyzeProgram(program);
const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(program);
const renderer = new Esm5Renderer(host, false, null, '', '');
const renderer = new EsmRenderer(host, false, null, '', '', null);
return {host, program, sourceFile, renderer, decorationAnalyses, switchMarkerAnalyses};
}

View File

@ -17,7 +17,7 @@ import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
import {Renderer} from '../../src/rendering/renderer';
class TestRenderer extends Renderer {
constructor(host: Esm2015ReflectionHost) { super(host, false, null, '/src', '/dist'); }
constructor(host: Esm2015ReflectionHost) { super(host, false, null, '/src', '/dist', null); }
addImports(output: MagicString, imports: {name: string, as: string}[]) {
output.prepend('\n// ADD IMPORTS\n');
}