diff --git a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/input_function.ts b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/input_function.ts index 0d258d443d9..15827243dcf 100644 --- a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/input_function.ts +++ b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/input_function.ts @@ -54,10 +54,11 @@ export const signalInputsTransform: PropertyTransform = ( 'transform': factory.createIdentifier('undefined'), }; + const sourceFile = member.getSourceFile(); const newDecorator = factory.createDecorator( factory.createCallExpression( createSyntheticAngularCoreDecoratorAccess( - factory, importManager, classDecorator, 'Input'), + factory, importManager, classDecorator, sourceFile, 'Input'), undefined, [ // Cast to `any` because `isSignal` will be private, and in case this diff --git a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/model_function.ts b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/model_function.ts index ad7c197bd15..d006e2d5dba 100644 --- a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/model_function.ts +++ b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/model_function.ts @@ -6,12 +6,13 @@ * found in the LICENSE file at https://angular.io/license */ +import {Decorator} from '@angular/compiler-cli/src/ngtsc/reflection'; import ts from 'typescript'; import {isAngularDecorator, tryParseSignalModelMapping} from '../../../ngtsc/annotations'; -import {ImportManager} from '../../../ngtsc/translator'; +import {ImportManagerV2} from '../../../ngtsc/translator'; -import {PropertyTransform} from './transform_api'; +import {createSyntheticAngularCoreDecoratorAccess, PropertyTransform} from './transform_api'; /** * Transform that automatically adds `@Input` and `@Output` to members initialized as `model()`. @@ -23,7 +24,7 @@ export const signalModelTransform: PropertyTransform = ( factory, importTracker, importManager, - decorator, + classDecorator, isCore, ) => { if (host.getDecoratorsOfDeclaration(member)?.some(d => { @@ -42,10 +43,6 @@ export const signalModelTransform: PropertyTransform = ( return member; } - const classDecoratorIdentifier = ts.isIdentifier(decorator.identifier) ? - decorator.identifier : - decorator.identifier.expression; - const inputConfig = factory.createObjectLiteralExpression([ factory.createPropertyAssignment( 'isSignal', modelMapping.input.isSignal ? factory.createTrue() : factory.createFalse()), @@ -55,6 +52,7 @@ export const signalModelTransform: PropertyTransform = ( 'required', modelMapping.input.required ? factory.createTrue() : factory.createFalse()), ]); + const sourceFile = member.getSourceFile(); const inputDecorator = createDecorator( 'Input', // Config is cast to `any` because `isSignal` will be private, and in case this @@ -62,11 +60,11 @@ export const signalModelTransform: PropertyTransform = ( // not fail. It is already validated now due to us parsing the input metadata. factory.createAsExpression( inputConfig, factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)), - classDecoratorIdentifier, factory, importManager); + classDecorator, factory, sourceFile, importManager); const outputDecorator = createDecorator( 'Output', factory.createStringLiteral(modelMapping.output.bindingPropertyName), - classDecoratorIdentifier, factory, importManager); + classDecorator, factory, sourceFile, importManager); return factory.updatePropertyDeclaration( member, @@ -79,14 +77,10 @@ export const signalModelTransform: PropertyTransform = ( }; function createDecorator( - name: string, config: ts.Expression, classDecoratorIdentifier: ts.Identifier, - factory: ts.NodeFactory, importManager: ImportManager): ts.Decorator { - const callTarget = factory.createPropertyAccessExpression( - importManager.generateNamespaceImport('@angular/core'), - // The synthetic identifier may be checked later by the downlevel decorators - // transform to resolve to an Angular import using `getSymbolAtLocation`. We trick - // the transform to think it's not synthetic and comes from Angular core. - ts.setOriginalNode(factory.createIdentifier(name), classDecoratorIdentifier)); + name: string, config: ts.Expression, classDecorator: Decorator, factory: ts.NodeFactory, + sourceFile: ts.SourceFile, importManager: ImportManagerV2): ts.Decorator { + const callTarget = createSyntheticAngularCoreDecoratorAccess( + factory, importManager, classDecorator, sourceFile, name); return factory.createDecorator(factory.createCallExpression(callTarget, undefined, [config])); } diff --git a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/output_function.ts b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/output_function.ts index 5453e8ec4ad..6d1cda62c67 100644 --- a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/output_function.ts +++ b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/output_function.ts @@ -43,10 +43,11 @@ export const initializerApiOutputTransform: PropertyTransform = ( return member; } + const sourceFile = member.getSourceFile(); const newDecorator = factory.createDecorator( factory.createCallExpression( createSyntheticAngularCoreDecoratorAccess( - factory, importManager, classDecorator, 'Output'), + factory, importManager, classDecorator, sourceFile, 'Output'), undefined, [factory.createStringLiteral(output.metadata.bindingPropertyName)]), ); diff --git a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/query_functions.ts b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/query_functions.ts index 605679d01cf..e5f16934640 100644 --- a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/query_functions.ts +++ b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/query_functions.ts @@ -56,11 +56,12 @@ export const queryFunctionsTransforms: PropertyTransform = ( return member; } + const sourceFile = member.getSourceFile(); const callArgs = queryDefinition.call.arguments; const newDecorator = factory.createDecorator( factory.createCallExpression( createSyntheticAngularCoreDecoratorAccess( - factory, importManager, classDecorator, + factory, importManager, classDecorator, sourceFile, queryFunctionToDecorator[queryDefinition.name]), undefined, // All positional arguments of the query functions can be mostly re-used as is diff --git a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/transform.ts b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/transform.ts index cf2a30eb10b..6c309b35bdb 100644 --- a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/transform.ts +++ b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/transform.ts @@ -11,8 +11,7 @@ import ts from 'typescript'; import {isAngularDecorator} from '../../../ngtsc/annotations'; import {ImportedSymbolsTracker} from '../../../ngtsc/imports'; import {ReflectionHost} from '../../../ngtsc/reflection'; -import {addImports} from '../../../ngtsc/transform'; -import {ImportManager} from '../../../ngtsc/translator'; +import {ImportManagerV2} from '../../../ngtsc/translator'; import {signalInputsTransform} from './input_function'; import {signalModelTransform} from './model_function'; @@ -48,7 +47,7 @@ export function getInitializerApiJitTransform( ): ts.TransformerFactory { return ctx => { return sourceFile => { - const importManager = new ImportManager(undefined, undefined, ctx.factory); + const importManager = new ImportManagerV2(); sourceFile = ts.visitNode( sourceFile, @@ -56,12 +55,7 @@ export function getInitializerApiJitTransform( ts.isSourceFile, ); - const newImports = importManager.getAllImports(sourceFile.fileName); - if (newImports.length > 0) { - sourceFile = addImports(ctx.factory, importManager, sourceFile); - } - - return sourceFile; + return importManager.transformTsFile(ctx, sourceFile); }; }; } @@ -69,7 +63,7 @@ export function getInitializerApiJitTransform( function createTransformVisitor( ctx: ts.TransformationContext, host: ReflectionHost, - importManager: ImportManager, + importManager: ImportManagerV2, importTracker: ImportedSymbolsTracker, isCore: boolean, ): ts.Visitor { diff --git a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/transform_api.ts b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/transform_api.ts index bad537e6acb..55db779fdcc 100644 --- a/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/transform_api.ts +++ b/packages/compiler-cli/src/transformers/jit_transforms/initializer_api_transforms/transform_api.ts @@ -10,13 +10,13 @@ import ts from 'typescript'; import {ImportedSymbolsTracker} from '../../../ngtsc/imports'; import {Decorator, ReflectionHost} from '../../../ngtsc/reflection'; -import {ImportManager} from '../../../ngtsc/translator'; +import {ImportManagerV2} from '../../../ngtsc/translator'; /** Function that can be used to transform class properties. */ export type PropertyTransform = (node: ts.PropertyDeclaration&{name: ts.Identifier | ts.StringLiteralLike}, host: ReflectionHost, factory: ts.NodeFactory, importTracker: ImportedSymbolsTracker, - importManager: ImportManager, classDecorator: Decorator, isCore: boolean) => + importManager: ImportManagerV2, classDecorator: Decorator, isCore: boolean) => ts.PropertyDeclaration; /** @@ -26,14 +26,18 @@ export type PropertyTransform = * decorator downlevel transform. */ export function createSyntheticAngularCoreDecoratorAccess( - factory: ts.NodeFactory, importManager: ImportManager, ngClassDecorator: Decorator, - decoratorName: string): ts.PropertyAccessExpression { + factory: ts.NodeFactory, importManager: ImportManagerV2, ngClassDecorator: Decorator, + sourceFile: ts.SourceFile, decoratorName: string): ts.PropertyAccessExpression { const classDecoratorIdentifier = ts.isIdentifier(ngClassDecorator.identifier) ? ngClassDecorator.identifier : ngClassDecorator.identifier.expression; return factory.createPropertyAccessExpression( - importManager.generateNamespaceImport('@angular/core'), + importManager.addImport({ + exportModuleSpecifier: '@angular/core', + exportSymbolName: null, + requestedFile: sourceFile, + }), // The synthetic identifier may be checked later by the downlevel decorators // transform to resolve to an Angular import using `getSymbolAtLocation`. We trick // the transform to think it's not synthetic and comes from Angular core. diff --git a/packages/compiler-cli/test/signal_queries_metadata_transform_spec.ts b/packages/compiler-cli/test/signal_queries_metadata_transform_spec.ts index e5ccc24cd7d..0e50e21175f 100644 --- a/packages/compiler-cli/test/signal_queries_metadata_transform_spec.ts +++ b/packages/compiler-cli/test/signal_queries_metadata_transform_spec.ts @@ -137,12 +137,12 @@ describe('signal queries metadata transform', () => { expect(result).toContain(omitLeadingWhitespace(` __decorate([ - i0.ViewChild('el', { ...{ read: SomeToken }, isSignal: true }) + bla.ViewChild('el', { ...{ read: SomeToken }, isSignal: true }) ], MyDir.prototype, "el", void 0); `)); expect(result).toContain(omitLeadingWhitespace(` __decorate([ - i0.ViewChild('el', { ...{ read: bla.Component }, isSignal: true }) + bla.ViewChild('el', { ...{ read: bla.Component }, isSignal: true }) ], MyDir.prototype, "el2", void 0); `)); });