Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

/**
* @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 {ImportRewriter, validateAndRewriteCoreSymbol} from '../../../ngtsc/imports';

export class NgccFlatImportRewriter implements ImportRewriter {
shouldImportSymbol(symbol: string, specifier: string): boolean {
if (specifier === '@angular/core') {
// Don't use imports for @angular/core symbols in a flat bundle, as they'll be visible
// directly.
return false;
} else {
return true;
}
}

rewriteSymbol(symbol: string, specifier: string): string {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No empty line between methods 😞

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

if (specifier === '@angular/core') {
return validateAndRewriteCoreSymbol(symbol);
} else {
return symbol;
}
}

rewriteSpecifier(originalModulePath: string, inContextOfFile: string): string {
return originalModulePath;
}
}
32 changes: 21 additions & 11 deletions packages/compiler-cli/src/ngcc/src/rendering/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import {basename, dirname, relative, resolve} from 'canonical-path';
import {SourceMapConsumer, SourceMapGenerator, RawSourceMap} from 'source-map';
import * as ts from 'typescript';

import {NoopImportRewriter, ImportRewriter, R3SymbolsImportRewriter} from '@angular/compiler-cli/src/ngtsc/imports';
import {CompileResult} from '@angular/compiler-cli/src/ngtsc/transform';
import {translateStatement, translateType, ImportManager} from '../../../ngtsc/translator';
import {NgccImportManager} from './ngcc_import_manager';
import {NgccFlatImportRewriter} from './ngcc_import_rewriter';
import {CompiledClass, CompiledFile, DecorationAnalyses} from '../analysis/decoration_analyzer';
import {ModuleWithProvidersInfo, ModuleWithProvidersAnalyses} from '../analysis/module_with_providers_analyzer';
import {PrivateDeclarationsAnalyses, ExportInfo} from '../analysis/private_declarations_analyzer';
Expand Down Expand Up @@ -135,7 +136,8 @@ export abstract class Renderer {
}

if (compiledFile) {
const importManager = new NgccImportManager(this.bundle.isFlat, this.isCore, IMPORT_PREFIX);
const importManager = new ImportManager(
this.getImportRewriter(this.bundle.src.r3SymbolsFile, this.bundle.isFlat), IMPORT_PREFIX);

// TODO: remove constructor param metadata and property decorators (we need info from the
// handlers to do this)
Expand All @@ -152,9 +154,7 @@ export abstract class Renderer {
renderConstantPool(compiledFile.sourceFile, compiledFile.constantPool, importManager),
compiledFile.sourceFile);

this.addImports(
outputText, importManager.getAllImports(
compiledFile.sourceFile.fileName, this.bundle.src.r3SymbolsFile));
this.addImports(outputText, importManager.getAllImports(compiledFile.sourceFile.fileName));
}

// Add exports to the entry-point file
Expand All @@ -169,7 +169,8 @@ export abstract class Renderer {
renderDtsFile(dtsFile: ts.SourceFile, renderInfo: DtsRenderInfo): FileInfo[] {
const input = this.extractSourceMap(dtsFile);
const outputText = new MagicString(input.source);
const importManager = new NgccImportManager(false, this.isCore, IMPORT_PREFIX);
const importManager = new ImportManager(
this.getImportRewriter(this.bundle.dts !.r3SymbolsFile, false), IMPORT_PREFIX);

renderInfo.classInfo.forEach(dtsClass => {
const endOfClass = dtsClass.dtsDeclaration.getEnd();
Expand All @@ -181,8 +182,7 @@ export abstract class Renderer {
});

this.addModuleWithProvidersParams(outputText, renderInfo.moduleWithProviders, importManager);
this.addImports(
outputText, importManager.getAllImports(dtsFile.fileName, this.bundle.dts !.r3SymbolsFile));
this.addImports(outputText, importManager.getAllImports(dtsFile.fileName));

this.addExports(outputText, dtsFile.fileName, renderInfo.privateExports);

Expand All @@ -199,7 +199,7 @@ export abstract class Renderer {
*/
protected addModuleWithProvidersParams(
outputText: MagicString, moduleWithProviders: ModuleWithProvidersInfo[],
importManager: NgccImportManager): void {
importManager: ImportManager): void {
moduleWithProviders.forEach(info => {
const ngModuleName = (info.ngModule.node as ts.ClassDeclaration).name !.text;
const declarationFile = info.declaration.getSourceFile().fileName;
Expand Down Expand Up @@ -417,6 +417,16 @@ export abstract class Renderer {
return (
id && id.name === 'ModuleWithProviders' && (this.isCore || id.from === '@angular/core'));
}

private getImportRewriter(r3SymbolsFile: ts.SourceFile|null, isFlat: boolean): ImportRewriter {
if (this.isCore && isFlat) {
return new NgccFlatImportRewriter();
} else if (this.isCore) {
return new R3SymbolsImportRewriter(r3SymbolsFile !.fileName);
} else {
return new NoopImportRewriter();
}
}
}

/**
Expand Down Expand Up @@ -451,7 +461,7 @@ export function mergeSourceMaps(
* Render the constant pool as source code for the given class.
*/
export function renderConstantPool(
sourceFile: ts.SourceFile, constantPool: ConstantPool, imports: NgccImportManager): string {
sourceFile: ts.SourceFile, constantPool: ConstantPool, imports: ImportManager): string {
const printer = ts.createPrinter();
return constantPool.statements.map(stmt => translateStatement(stmt, imports))
.map(stmt => printer.printNode(ts.EmitHint.Unspecified, stmt, sourceFile))
Expand All @@ -467,7 +477,7 @@ export function renderConstantPool(
* @param imports An object that tracks the imports that are needed by the rendered definitions.
*/
export function renderDefinitions(
sourceFile: ts.SourceFile, compiledClass: CompiledClass, imports: NgccImportManager): string {
sourceFile: ts.SourceFile, compiledClass: CompiledClass, imports: ImportManager): string {
const printer = ts.createPrinter();
const name = (compiledClass.declaration as ts.NamedDeclaration).name !;
const definitions =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import * as ts from 'typescript';

import {NoopImportRewriter} from '../../imports';
import {TypeScriptReflectionHost} from '../../reflection';
import {getDeclaration, makeProgram} from '../../testing/in_memory_typescript';
import {ImportManager, translateStatement} from '../../translator';
Expand Down Expand Up @@ -87,7 +88,7 @@ function compileAndPrint(contents: string): string {
return '';
}
const sf = program.getSourceFile('index.ts') !;
const im = new ImportManager(false, 'i');
const im = new ImportManager(new NoopImportRewriter(), 'i');
const tsStatement = translateStatement(call, im);
const res = ts.createPrinter().printNode(ts.EmitHint.Unspecified, tsStatement, sf);
return res.replace(/\s+/g, ' ');
Expand Down
1 change: 1 addition & 0 deletions packages/compiler-cli/src/ngtsc/imports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/

export {ImportRewriter, NoopImportRewriter, R3SymbolsImportRewriter, validateAndRewriteCoreSymbol} from './src/core';
export {AbsoluteReference, ImportMode, NodeReference, Reference, ResolvedReference} from './src/references';
export {ReferenceResolver, TsReferenceResolver} from './src/resolver';
103 changes: 103 additions & 0 deletions packages/compiler-cli/src/ngtsc/imports/src/core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
* @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 {relativePathBetween} from '../../util/src/path';

/**
* Rewrites imports of symbols being written into generated code.
*/
export interface ImportRewriter {
/**
* Should the given symbol be imported at all?
*
* If `true`, the symbol should be imported from the given specifier. If `false`, the symbol
* should be referenced directly, without an import.
*/
shouldImportSymbol(symbol: string, specifier: string): boolean;

/**
* Optionally rewrite a reference to an imported symbol, changing either the binding prefix or the
* symbol name itself.
*/
rewriteSymbol(symbol: string, specifier: string): string;

/**
* Optionally rewrite the given module specifier in the context of a given file.
*/
rewriteSpecifier(specifier: string, inContextOfFile: string): string;
}

/**
* `ImportRewriter` that does no rewriting.
*/
export class NoopImportRewriter implements ImportRewriter {
shouldImportSymbol(symbol: string, specifier: string): boolean { return true; }

rewriteSymbol(symbol: string, specifier: string): string { return symbol; }

rewriteSpecifier(specifier: string, inContextOfFile: string): string { return specifier; }
}

/**
* A mapping of supported symbols that can be imported from within @angular/core, and the names by
* which they're exported from r3_symbols.
*/
const CORE_SUPPORTED_SYMBOLS = new Map<string, string>([
['defineInjectable', 'defineInjectable'],
['defineInjector', 'defineInjector'],
['ɵdefineNgModule', 'defineNgModule'],
['inject', 'inject'],
['ɵsetClassMetadata', 'setClassMetadata'],
['ɵInjectableDef', 'InjectableDef'],
['ɵInjectorDef', 'InjectorDef'],
['ɵNgModuleDefWithMeta', 'NgModuleDefWithMeta'],
['ɵNgModuleFactory', 'NgModuleFactory'],
]);

const CORE_MODULE = '@angular/core';

/**
* `ImportRewriter` that rewrites imports from '@angular/core' to be imported from the r3_symbols.ts
* file instead.
*/
export class R3SymbolsImportRewriter implements ImportRewriter {
constructor(private r3SymbolsPath: string) {}

shouldImportSymbol(symbol: string, specifier: string): boolean { return true; }

rewriteSymbol(symbol: string, specifier: string): string {
if (specifier !== CORE_MODULE) {
// This import isn't from core, so ignore it.
return symbol;
}

return validateAndRewriteCoreSymbol(symbol);
}

rewriteSpecifier(specifier: string, inContextOfFile: string): string {
if (specifier !== CORE_MODULE) {
// This module isn't core, so ignore it.
return specifier;
}

const relativePathToR3Symbols = relativePathBetween(inContextOfFile, this.r3SymbolsPath);
if (relativePathToR3Symbols === null) {
throw new Error(
`Failed to rewrite import inside ${CORE_MODULE}: ${inContextOfFile} -> ${this.r3SymbolsPath}`);
}

return relativePathToR3Symbols;
}
}

export function validateAndRewriteCoreSymbol(name: string): string {
if (!CORE_SUPPORTED_SYMBOLS.has(name)) {
throw new Error(`Importing unexpected symbol ${name} while compiling ${CORE_MODULE}`);
}
return CORE_SUPPORTED_SYMBOLS.get(name) !;
}
19 changes: 15 additions & 4 deletions packages/compiler-cli/src/ngtsc/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecorato
import {BaseDefDecoratorHandler} from './annotations/src/base_def';
import {ErrorCode, ngErrorCode} from './diagnostics';
import {FlatIndexGenerator, ReferenceGraph, checkForPrivateExports, findFlatIndexEntryPoint} from './entry_point';
import {Reference, TsReferenceResolver} from './imports';
import {ImportRewriter, NoopImportRewriter, R3SymbolsImportRewriter, Reference, TsReferenceResolver} from './imports';
import {PartialEvaluator} from './partial_evaluator';
import {TypeScriptReflectionHost} from './reflection';
import {FileResourceLoader, HostResourceLoader} from './resource_loader';
Expand All @@ -34,6 +34,7 @@ export class NgtscProgram implements api.Program {
private sourceToFactorySymbols: Map<string, Set<string>>|null = null;
private host: ts.CompilerHost;
private _coreImportsFrom: ts.SourceFile|null|undefined = undefined;
private _importRewriter: ImportRewriter|undefined = undefined;
private _reflector: TypeScriptReflectionHost|undefined = undefined;
private _isCore: boolean|undefined = undefined;
private rootDirs: string[];
Expand Down Expand Up @@ -234,11 +235,11 @@ export class NgtscProgram implements api.Program {

const customTransforms = opts && opts.customTransformers;
const beforeTransforms =
[ivyTransformFactory(this.compilation !, this.reflector, this.coreImportsFrom)];
[ivyTransformFactory(this.compilation !, this.reflector, this.importRewriter, this.isCore)];

if (this.factoryToSourceInfo !== null) {
beforeTransforms.push(
generatedFactoryTransform(this.factoryToSourceInfo, this.coreImportsFrom));
generatedFactoryTransform(this.factoryToSourceInfo, this.importRewriter));
}
if (this.isCore) {
beforeTransforms.push(ivySwitchTransform);
Expand Down Expand Up @@ -303,7 +304,7 @@ export class NgtscProgram implements api.Program {
];

return new IvyCompilation(
handlers, checker, this.reflector, this.coreImportsFrom, this.sourceToFactorySymbols);
handlers, checker, this.reflector, this.importRewriter, this.sourceToFactorySymbols);
}

private get reflector(): TypeScriptReflectionHost {
Expand All @@ -326,6 +327,16 @@ export class NgtscProgram implements api.Program {
}
return this._isCore;
}

private get importRewriter(): ImportRewriter {
if (this._importRewriter === undefined) {
const coreImportsFrom = this.coreImportsFrom;
this._importRewriter = coreImportsFrom !== null ?
new R3SymbolsImportRewriter(coreImportsFrom.fileName) :
new NoopImportRewriter();
}
return this._importRewriter;
}
}

const defaultEmitCallback: api.TsEmitCallback =
Expand Down
1 change: 1 addition & 0 deletions packages/compiler-cli/src/ngtsc/shims/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ ts_library(
module_name = "@angular/compiler-cli/src/ngtsc/shims",
deps = [
"//packages/compiler",
"//packages/compiler-cli/src/ngtsc/imports",
"//packages/compiler-cli/src/ngtsc/util",
"@ngdeps//@types/node",
"@ngdeps//typescript",
Expand Down
Loading