mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
refactor(compiler-cli): switch jit transforms to use new import manager (#54819)
Switches the JIT transforms to use the new import manager. PR Close #54819
This commit is contained in:
parent
dc80046132
commit
94bc3afc23
7 changed files with 32 additions and 37 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<ts.SourceFile> {
|
||||
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<ts.Node, ts.Node> {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
`));
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue