mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(compiler-cli): update ImportGenerator abstraction for new manager (#54983)
`ImportGenerator` is the abstraction used by the translator functions to insert imports for `ExternalExpr` in an AST-agnostic way. This was built specifically for the linker which does not use any of the complex import managers- but rather re-uses `ngImport` or uses `ngImport.Bla`. This commit also switches the linker AST-agnostic generator to follow the new signatures. This was rather trivial. PR Close #54983
This commit is contained in:
committed by
Dylan Hunn
parent
3253576db8
commit
4d8d324ea6
@@ -36,7 +36,7 @@ export class EmitScope<TStatement, TExpression> {
|
||||
*/
|
||||
translateDefinition(definition: LinkedDefinition): TExpression {
|
||||
const expression = this.translator.translateExpression(
|
||||
definition.expression, new LinkerImportGenerator(this.ngImport));
|
||||
definition.expression, new LinkerImportGenerator(this.factory, this.ngImport));
|
||||
|
||||
if (definition.statements.length > 0) {
|
||||
// Definition statements must be emitted "after" the declaration for which the definition is
|
||||
@@ -44,7 +44,7 @@ export class EmitScope<TStatement, TExpression> {
|
||||
// insert statements after definitions. To work around this, the linker transforms the
|
||||
// definition into an IIFE which executes the definition statements before returning the
|
||||
// definition expression.
|
||||
const importGenerator = new LinkerImportGenerator(this.ngImport);
|
||||
const importGenerator = new LinkerImportGenerator(this.factory, this.ngImport);
|
||||
return this.wrapInIifeWithStatements(
|
||||
expression,
|
||||
definition.statements.map(
|
||||
@@ -59,7 +59,7 @@ export class EmitScope<TStatement, TExpression> {
|
||||
* Return any constant statements that are shared between all uses of this `EmitScope`.
|
||||
*/
|
||||
getConstantStatements(): TStatement[] {
|
||||
const importGenerator = new LinkerImportGenerator(this.ngImport);
|
||||
const importGenerator = new LinkerImportGenerator(this.factory, this.ngImport);
|
||||
return this.constantPool.statements.map(
|
||||
statement => this.translator.translateStatement(statement, importGenerator));
|
||||
}
|
||||
|
||||
@@ -20,10 +20,11 @@ export class Translator<TStatement, TExpression> {
|
||||
* Translate the given output AST in the context of an expression.
|
||||
*/
|
||||
translateExpression(
|
||||
expression: o.Expression, imports: ImportGenerator<TExpression>,
|
||||
expression: o.Expression, imports: ImportGenerator<null, TExpression>,
|
||||
options: TranslatorOptions<TExpression> = {}): TExpression {
|
||||
return expression.visitExpression(
|
||||
new ExpressionTranslatorVisitor<TStatement, TExpression>(this.factory, imports, options),
|
||||
new ExpressionTranslatorVisitor<null, TStatement, TExpression>(
|
||||
this.factory, imports, null, options),
|
||||
new Context(false));
|
||||
}
|
||||
|
||||
@@ -31,10 +32,11 @@ export class Translator<TStatement, TExpression> {
|
||||
* Translate the given output AST in the context of a statement.
|
||||
*/
|
||||
translateStatement(
|
||||
statement: o.Statement, imports: ImportGenerator<TExpression>,
|
||||
statement: o.Statement, imports: ImportGenerator<null, TExpression>,
|
||||
options: TranslatorOptions<TExpression> = {}): TStatement {
|
||||
return statement.visitStatement(
|
||||
new ExpressionTranslatorVisitor<TStatement, TExpression>(this.factory, imports, options),
|
||||
new ExpressionTranslatorVisitor<null, TStatement, TExpression>(
|
||||
this.factory, imports, null, options),
|
||||
new Context(true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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 {ImportGenerator, NamedImport} from '../../src/ngtsc/translator';
|
||||
import {AstFactory, ImportGenerator, ImportRequest} from '../../src/ngtsc/translator';
|
||||
|
||||
import {FatalLinkerError} from './fatal_linker_error';
|
||||
|
||||
@@ -17,17 +17,19 @@ import {FatalLinkerError} from './fatal_linker_error';
|
||||
* must be achieved by property access on an `ng` namespace identifier, which is passed in via the
|
||||
* constructor.
|
||||
*/
|
||||
export class LinkerImportGenerator<TExpression> implements ImportGenerator<TExpression> {
|
||||
constructor(private ngImport: TExpression) {}
|
||||
|
||||
generateNamespaceImport(moduleName: string): TExpression {
|
||||
this.assertModuleName(moduleName);
|
||||
return this.ngImport;
|
||||
export class LinkerImportGenerator<TStatement, TExpression> implements
|
||||
ImportGenerator<null, TExpression> {
|
||||
constructor(private factory: AstFactory<TStatement, TExpression>, private ngImport: TExpression) {
|
||||
}
|
||||
|
||||
generateNamedImport(moduleName: string, originalSymbol: string): NamedImport<TExpression> {
|
||||
this.assertModuleName(moduleName);
|
||||
return {moduleImport: this.ngImport, symbol: originalSymbol};
|
||||
addImport(request: ImportRequest<null>): TExpression {
|
||||
this.assertModuleName(request.exportModuleSpecifier);
|
||||
|
||||
if (request.exportSymbolName === null) {
|
||||
return this.ngImport;
|
||||
}
|
||||
|
||||
return this.factory.createPropertyAccess(this.ngImport, request.exportSymbolName);
|
||||
}
|
||||
|
||||
private assertModuleName(moduleName: string): void {
|
||||
|
||||
@@ -6,21 +6,30 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as o from '@angular/compiler';
|
||||
import {ImportGenerator, NamedImport, TypeScriptAstFactory} from '@angular/compiler-cli/src/ngtsc/translator';
|
||||
import {TypeScriptAstFactory} from '@angular/compiler-cli/src/ngtsc/translator';
|
||||
import ts from 'typescript';
|
||||
|
||||
import {Translator} from '../../src/file_linker/translator';
|
||||
import {LinkerImportGenerator} from '../../src/linker_import_generator';
|
||||
|
||||
import {generate} from './helpers';
|
||||
|
||||
const ngImport = ts.factory.createIdentifier('ngImport');
|
||||
|
||||
describe('Translator', () => {
|
||||
let factory: TypeScriptAstFactory;
|
||||
beforeEach(() => factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false));
|
||||
let importGenerator: LinkerImportGenerator<ts.Statement, ts.Expression>;
|
||||
|
||||
beforeEach(() => {
|
||||
factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false);
|
||||
importGenerator = new LinkerImportGenerator<ts.Statement, ts.Expression>(factory, ngImport);
|
||||
});
|
||||
|
||||
describe('translateExpression()', () => {
|
||||
it('should generate expression specific output', () => {
|
||||
const translator = new Translator<ts.Statement, ts.Expression>(factory);
|
||||
const outputAst = new o.WriteVarExpr('foo', new o.LiteralExpr(42));
|
||||
const translated = translator.translateExpression(outputAst, new MockImportGenerator());
|
||||
const translated = translator.translateExpression(outputAst, importGenerator);
|
||||
expect(generate(translated)).toEqual('(foo = 42)');
|
||||
});
|
||||
});
|
||||
@@ -29,19 +38,8 @@ describe('Translator', () => {
|
||||
it('should generate statement specific output', () => {
|
||||
const translator = new Translator<ts.Statement, ts.Expression>(factory);
|
||||
const outputAst = new o.ExpressionStatement(new o.WriteVarExpr('foo', new o.LiteralExpr(42)));
|
||||
const translated = translator.translateStatement(outputAst, new MockImportGenerator());
|
||||
const translated = translator.translateStatement(outputAst, importGenerator);
|
||||
expect(generate(translated)).toEqual('foo = 42;');
|
||||
});
|
||||
});
|
||||
class MockImportGenerator implements ImportGenerator<ts.Expression> {
|
||||
generateNamespaceImport(moduleName: string): ts.Expression {
|
||||
return factory.createLiteral(moduleName);
|
||||
}
|
||||
generateNamedImport(moduleName: string, originalSymbol: string): NamedImport<ts.Expression> {
|
||||
return {
|
||||
moduleImport: factory.createLiteral(moduleName),
|
||||
symbol: originalSymbol,
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,37 +5,62 @@
|
||||
* 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 ts from 'typescript';
|
||||
|
||||
import {TypeScriptAstFactory} from '../../src/ngtsc/translator';
|
||||
import {LinkerImportGenerator} from '../src/linker_import_generator';
|
||||
|
||||
const ngImport = {
|
||||
ngImport: true
|
||||
};
|
||||
const ngImport = ts.factory.createIdentifier('ngImport');
|
||||
|
||||
describe('LinkerImportGenerator<TExpression>', () => {
|
||||
describe('generateNamespaceImport()', () => {
|
||||
it('should error if the import is not `@angular/core`', () => {
|
||||
const generator = new LinkerImportGenerator(ngImport);
|
||||
expect(() => generator.generateNamespaceImport('other/import'))
|
||||
const generator = new LinkerImportGenerator<ts.Statement, ts.Expression>(
|
||||
new TypeScriptAstFactory(false), ngImport);
|
||||
|
||||
expect(
|
||||
() => generator.addImport(
|
||||
{exportModuleSpecifier: 'other/import', exportSymbolName: null, requestedFile: null}))
|
||||
.toThrowError(`Unable to import from anything other than '@angular/core'`);
|
||||
});
|
||||
|
||||
it('should return the ngImport expression for `@angular/core`', () => {
|
||||
const generator = new LinkerImportGenerator(ngImport);
|
||||
expect(generator.generateNamespaceImport('@angular/core')).toBe(ngImport);
|
||||
const generator = new LinkerImportGenerator<ts.Statement, ts.Expression>(
|
||||
new TypeScriptAstFactory(false), ngImport);
|
||||
|
||||
expect(generator.addImport({
|
||||
exportModuleSpecifier: '@angular/core',
|
||||
exportSymbolName: null,
|
||||
requestedFile: null
|
||||
})).toBe(ngImport);
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateNamedImport()', () => {
|
||||
it('should error if the import is not `@angular/core`', () => {
|
||||
const generator = new LinkerImportGenerator(ngImport);
|
||||
expect(() => generator.generateNamedImport('other/import', 'someSymbol'))
|
||||
.toThrowError(`Unable to import from anything other than '@angular/core'`);
|
||||
const generator = new LinkerImportGenerator<ts.Statement, ts.Expression>(
|
||||
new TypeScriptAstFactory(false), ngImport);
|
||||
|
||||
expect(() => generator.addImport({
|
||||
exportModuleSpecifier: 'other/import',
|
||||
exportSymbolName: 'someSymbol',
|
||||
requestedFile: null,
|
||||
})).toThrowError(`Unable to import from anything other than '@angular/core'`);
|
||||
});
|
||||
|
||||
it('should return a `NamedImport` object containing the ngImport expression', () => {
|
||||
const generator = new LinkerImportGenerator(ngImport);
|
||||
expect(generator.generateNamedImport('@angular/core', 'someSymbol'))
|
||||
.toEqual({moduleImport: ngImport, symbol: 'someSymbol'});
|
||||
const generator = new LinkerImportGenerator<ts.Statement, ts.Expression>(
|
||||
new TypeScriptAstFactory(false), ngImport);
|
||||
|
||||
const result = generator.addImport({
|
||||
exportModuleSpecifier: '@angular/core',
|
||||
exportSymbolName: 'someSymbol',
|
||||
requestedFile: null,
|
||||
});
|
||||
|
||||
expect(ts.isPropertyAccessExpression(result)).toBe(true);
|
||||
expect((result as ts.PropertyAccessExpression).name.text).toBe('someSymbol');
|
||||
expect((result as ts.PropertyAccessExpression).expression).toBe(ngImport);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -135,7 +135,7 @@ runInEachFileSystem(() => {
|
||||
const sf = getSourceFileOrError(program, _('/index.ts'));
|
||||
const im = new ImportManager(new NoopImportRewriter(), 'i');
|
||||
const stmt = compileClassMetadata(call).toStmt();
|
||||
const tsStatement = translateStatement(stmt, im);
|
||||
const tsStatement = translateStatement(sf, stmt, im);
|
||||
const res = ts.createPrinter().printNode(ts.EmitHint.Unspecified, tsStatement, sf);
|
||||
return res.replace(/\s+/g, ' ');
|
||||
}
|
||||
|
||||
@@ -118,6 +118,10 @@ class IvyTransformationVisitor extends Visitor {
|
||||
const statements: ts.Statement[] = [];
|
||||
const members = [...node.members];
|
||||
|
||||
// Note: Class may be already transformed by e.g. Tsickle and
|
||||
// not have a direct reference to the source file.
|
||||
const sourceFile = ts.getOriginalNode(node).getSourceFile();
|
||||
|
||||
for (const field of this.classCompilationMap.get(node)!) {
|
||||
// Type-only member.
|
||||
if (field.initializer === null) {
|
||||
@@ -125,7 +129,8 @@ class IvyTransformationVisitor extends Visitor {
|
||||
}
|
||||
|
||||
// Translate the initializer for the field into TS nodes.
|
||||
const exprNode = translateExpression(field.initializer, this.importManager, translateOptions);
|
||||
const exprNode =
|
||||
translateExpression(sourceFile, field.initializer, this.importManager, translateOptions);
|
||||
|
||||
// Create a static property declaration for the new field.
|
||||
const property = ts.factory.createPropertyDeclaration(
|
||||
@@ -142,7 +147,8 @@ class IvyTransformationVisitor extends Visitor {
|
||||
/* hasTrailingNewLine */ false);
|
||||
}
|
||||
|
||||
field.statements.map(stmt => translateStatement(stmt, this.importManager, translateOptions))
|
||||
field.statements
|
||||
.map(stmt => translateStatement(sourceFile, stmt, this.importManager, translateOptions))
|
||||
.forEach(stmt => statements.push(stmt));
|
||||
|
||||
members.push(property);
|
||||
@@ -313,7 +319,7 @@ function transformIvySourceFile(
|
||||
// to the ImportManager.
|
||||
const downlevelTranslatedCode = getLocalizeCompileTarget(context) < ts.ScriptTarget.ES2015;
|
||||
const constants =
|
||||
constantPool.statements.map(stmt => translateStatement(stmt, importManager, {
|
||||
constantPool.statements.map(stmt => translateStatement(file, stmt, importManager, {
|
||||
recordWrappedNode,
|
||||
downlevelTaggedTemplates: downlevelTranslatedCode,
|
||||
downlevelVariableDeclarations: downlevelTranslatedCode,
|
||||
|
||||
@@ -6,17 +6,6 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* The symbol name and import namespace of an imported symbol,
|
||||
* which has been registered through the ImportGenerator.
|
||||
*/
|
||||
export interface NamedImport<TExpression> {
|
||||
/** The import namespace containing this imported symbol. */
|
||||
moduleImport: TExpression|null;
|
||||
/** The (possibly rewritten) name of the imported symbol. */
|
||||
symbol: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A request to import a given symbol from the given module.
|
||||
*/
|
||||
@@ -49,7 +38,6 @@ export interface ImportRequest<TFile> {
|
||||
* Implementations of these methods return a specific identifier that corresponds to the imported
|
||||
* module.
|
||||
*/
|
||||
export interface ImportGenerator<TExpression> {
|
||||
generateNamespaceImport(moduleName: string): TExpression;
|
||||
generateNamedImport(moduleName: string, originalSymbol: string): NamedImport<TExpression>;
|
||||
export interface ImportGenerator<TFile, TExpression> {
|
||||
addImport(request: ImportRequest<TFile>): TExpression;
|
||||
}
|
||||
|
||||
@@ -46,15 +46,16 @@ export interface TranslatorOptions<TExpression> {
|
||||
annotateForClosureCompiler?: boolean;
|
||||
}
|
||||
|
||||
export class ExpressionTranslatorVisitor<TStatement, TExpression> implements o.ExpressionVisitor,
|
||||
o.StatementVisitor {
|
||||
export class ExpressionTranslatorVisitor<TFile, TStatement, TExpression> implements
|
||||
o.ExpressionVisitor, o.StatementVisitor {
|
||||
private downlevelTaggedTemplates: boolean;
|
||||
private downlevelVariableDeclarations: boolean;
|
||||
private recordWrappedNode: RecordWrappedNodeFn<TExpression>;
|
||||
|
||||
constructor(
|
||||
private factory: AstFactory<TStatement, TExpression>,
|
||||
private imports: ImportGenerator<TExpression>, options: TranslatorOptions<TExpression>) {
|
||||
private imports: ImportGenerator<TFile, TExpression>, private contextFile: TFile,
|
||||
options: TranslatorOptions<TExpression>) {
|
||||
this.downlevelTaggedTemplates = options.downlevelTaggedTemplates === true;
|
||||
this.downlevelVariableDeclarations = options.downlevelVariableDeclarations === true;
|
||||
this.recordWrappedNode = options.recordWrappedNode || (() => {});
|
||||
@@ -210,11 +211,11 @@ export class ExpressionTranslatorVisitor<TStatement, TExpression> implements o.E
|
||||
private createES5TaggedTemplateFunctionCall(
|
||||
tagHandler: TExpression, {elements, expressions}: TemplateLiteral<TExpression>): TExpression {
|
||||
// Ensure that the `__makeTemplateObject()` helper has been imported.
|
||||
const {moduleImport, symbol} =
|
||||
this.imports.generateNamedImport('tslib', '__makeTemplateObject');
|
||||
const __makeTemplateObjectHelper = (moduleImport === null) ?
|
||||
this.factory.createIdentifier(symbol) :
|
||||
this.factory.createPropertyAccess(moduleImport, symbol);
|
||||
const __makeTemplateObjectHelper = this.imports.addImport({
|
||||
exportModuleSpecifier: 'tslib',
|
||||
exportSymbolName: '__makeTemplateObject',
|
||||
requestedFile: this.contextFile,
|
||||
});
|
||||
|
||||
// Collect up the cooked and raw strings into two separate arrays.
|
||||
const cooked: TExpression[] = [];
|
||||
@@ -244,20 +245,21 @@ export class ExpressionTranslatorVisitor<TStatement, TExpression> implements o.E
|
||||
if (ast.value.moduleName === null) {
|
||||
throw new Error('Invalid import without name nor moduleName');
|
||||
}
|
||||
return this.imports.generateNamespaceImport(ast.value.moduleName);
|
||||
return this.imports.addImport({
|
||||
exportModuleSpecifier: ast.value.moduleName,
|
||||
exportSymbolName: null,
|
||||
requestedFile: this.contextFile,
|
||||
});
|
||||
}
|
||||
// If a moduleName is specified, this is a normal import. If there's no module name, it's a
|
||||
// reference to a global/ambient symbol.
|
||||
if (ast.value.moduleName !== null) {
|
||||
// This is a normal import. Find the imported module.
|
||||
const {moduleImport, symbol} =
|
||||
this.imports.generateNamedImport(ast.value.moduleName, ast.value.name);
|
||||
if (moduleImport === null) {
|
||||
// The symbol was ambient after all.
|
||||
return this.factory.createIdentifier(symbol);
|
||||
} else {
|
||||
return this.factory.createPropertyAccess(moduleImport, symbol);
|
||||
}
|
||||
return this.imports.addImport({
|
||||
exportModuleSpecifier: ast.value.moduleName,
|
||||
exportSymbolName: ast.value.name,
|
||||
requestedFile: this.contextFile,
|
||||
});
|
||||
} else {
|
||||
// The symbol is ambient, so just reference it.
|
||||
return this.factory.createIdentifier(ast.value.name);
|
||||
|
||||
@@ -13,21 +13,21 @@ import {assertSuccessfulReferenceEmit, ImportFlags, OwningModule, Reference, Ref
|
||||
import {AmbientImport, ReflectionHost} from '../../reflection';
|
||||
|
||||
import {Context} from './context';
|
||||
import {ImportManager} from './import_manager';
|
||||
import {ImportManagerV2} from './import_manager/import_manager';
|
||||
import {tsNumericExpression} from './ts_util';
|
||||
import {TypeEmitter} from './type_emitter';
|
||||
|
||||
|
||||
export function translateType(
|
||||
type: o.Type, contextFile: ts.SourceFile, reflector: ReflectionHost,
|
||||
refEmitter: ReferenceEmitter, imports: ImportManager): ts.TypeNode {
|
||||
refEmitter: ReferenceEmitter, imports: ImportManagerV2): ts.TypeNode {
|
||||
return type.visitType(
|
||||
new TypeTranslatorVisitor(imports, contextFile, reflector, refEmitter), new Context(false));
|
||||
}
|
||||
|
||||
class TypeTranslatorVisitor implements o.ExpressionVisitor, o.TypeVisitor {
|
||||
constructor(
|
||||
private imports: ImportManager, private contextFile: ts.SourceFile,
|
||||
private imports: ImportManagerV2, private contextFile: ts.SourceFile,
|
||||
private reflector: ReflectionHost, private refEmitter: ReferenceEmitter) {}
|
||||
|
||||
visitBuiltinType(type: o.BuiltinType, context: Context): ts.KeywordTypeNode {
|
||||
@@ -148,12 +148,12 @@ class TypeTranslatorVisitor implements o.ExpressionVisitor, o.TypeVisitor {
|
||||
if (ast.value.moduleName === null || ast.value.name === null) {
|
||||
throw new Error(`Import unknown module or symbol`);
|
||||
}
|
||||
const {moduleImport, symbol} =
|
||||
this.imports.generateNamedImport(ast.value.moduleName, ast.value.name);
|
||||
const symbolIdentifier = ts.factory.createIdentifier(symbol);
|
||||
|
||||
const typeName = moduleImport ? ts.factory.createQualifiedName(moduleImport, symbolIdentifier) :
|
||||
symbolIdentifier;
|
||||
const typeName = this.imports.addImport({
|
||||
exportModuleSpecifier: ast.value.moduleName,
|
||||
exportSymbolName: ast.value.name,
|
||||
requestedFile: this.contextFile,
|
||||
asTypeReference: true
|
||||
});
|
||||
|
||||
const typeArguments = ast.typeParams !== null ?
|
||||
ast.typeParams.map(type => this.translateType(type, context)) :
|
||||
|
||||
@@ -15,19 +15,23 @@ import {ExpressionTranslatorVisitor, TranslatorOptions} from './translator';
|
||||
import {TypeScriptAstFactory} from './typescript_ast_factory';
|
||||
|
||||
export function translateExpression(
|
||||
expression: o.Expression, imports: ImportGenerator<ts.Expression>,
|
||||
contextFile: ts.SourceFile, expression: o.Expression,
|
||||
imports: ImportGenerator<ts.SourceFile, ts.Expression>,
|
||||
options: TranslatorOptions<ts.Expression> = {}): ts.Expression {
|
||||
return expression.visitExpression(
|
||||
new ExpressionTranslatorVisitor<ts.Statement, ts.Expression>(
|
||||
new TypeScriptAstFactory(options.annotateForClosureCompiler === true), imports, options),
|
||||
new ExpressionTranslatorVisitor<ts.SourceFile, ts.Statement, ts.Expression>(
|
||||
new TypeScriptAstFactory(options.annotateForClosureCompiler === true), imports,
|
||||
contextFile, options),
|
||||
new Context(false));
|
||||
}
|
||||
|
||||
export function translateStatement(
|
||||
statement: o.Statement, imports: ImportGenerator<ts.Expression>,
|
||||
contextFile: ts.SourceFile, statement: o.Statement,
|
||||
imports: ImportGenerator<ts.SourceFile, ts.Expression>,
|
||||
options: TranslatorOptions<ts.Expression> = {}): ts.Statement {
|
||||
return statement.visitStatement(
|
||||
new ExpressionTranslatorVisitor<ts.Statement, ts.Expression>(
|
||||
new TypeScriptAstFactory(options.annotateForClosureCompiler === true), imports, options),
|
||||
new ExpressionTranslatorVisitor<ts.SourceFile, ts.Statement, ts.Expression>(
|
||||
new TypeScriptAstFactory(options.annotateForClosureCompiler === true), imports,
|
||||
contextFile, options),
|
||||
new Context(true));
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ export class Environment extends ReferenceEmitEnvironment {
|
||||
assertSuccessfulReferenceEmit(ngExpr, this.contextFile, 'class');
|
||||
|
||||
// Use `translateExpression` to convert the `Expression` into a `ts.Expression`.
|
||||
return translateExpression(ngExpr.expression, this.importManager);
|
||||
return translateExpression(this.contextFile, ngExpr.expression, this.importManager);
|
||||
}
|
||||
|
||||
private emitTypeParameters(declaration: ClassDeclaration<ts.ClassDeclaration>):
|
||||
|
||||
@@ -22,7 +22,7 @@ import {ImportManager, translateExpression, translateType} from '../../translato
|
||||
export class ReferenceEmitEnvironment {
|
||||
constructor(
|
||||
readonly importManager: ImportManager, protected refEmitter: ReferenceEmitter,
|
||||
readonly reflector: ReflectionHost, protected contextFile: ts.SourceFile) {}
|
||||
readonly reflector: ReflectionHost, public contextFile: ts.SourceFile) {}
|
||||
|
||||
canReferenceType(
|
||||
ref: Reference,
|
||||
@@ -57,7 +57,7 @@ export class ReferenceEmitEnvironment {
|
||||
*/
|
||||
referenceExternalSymbol(moduleName: string, name: string): ts.Expression {
|
||||
const external = new ExternalExpr({moduleName, name});
|
||||
return translateExpression(external, this.importManager);
|
||||
return translateExpression(this.contextFile, external, this.importManager);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user