Skip to content

Commit

Permalink
fix(migrations): account for explicit standalone: false in migration (#…
Browse files Browse the repository at this point in the history
…57803)

Fixes that the standalone migration was duplicating the `standalone` flag if the declaration was `standalone: false`.

PR Close #57803
  • Loading branch information
crisbeto authored and pkozlowski-opensource committed Sep 13, 2024
1 parent 55e3a3a commit 6144612
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,13 @@ export function convertNgModuleDeclarationToStandalone(
const hasTrailingComma =
importsToAdd.length > 2 &&
!!extractMetadataLiteral(directiveMeta.decorator)?.properties.hasTrailingComma;
decorator = addPropertyToAngularDecorator(
decorator = setPropertyOnAngularDecorator(
decorator,
ts.factory.createPropertyAssignment(
'imports',
ts.factory.createArrayLiteralExpression(
// Create a multi-line array when it has a trailing comma.
ts.factory.createNodeArray(importsToAdd, hasTrailingComma),
hasTrailingComma,
),
'imports',
ts.factory.createArrayLiteralExpression(
// Create a multi-line array when it has a trailing comma.
ts.factory.createNodeArray(importsToAdd, hasTrailingComma),
hasTrailingComma,
),
);
}
Expand Down Expand Up @@ -430,23 +428,24 @@ function moveDeclarationsToImports(

/** Adds `standalone: true` to a decorator node. */
function addStandaloneToDecorator(node: ts.Decorator): ts.Decorator {
return addPropertyToAngularDecorator(
return setPropertyOnAngularDecorator(
node,
ts.factory.createPropertyAssignment(
'standalone',
ts.factory.createToken(ts.SyntaxKind.TrueKeyword),
),
'standalone',
ts.factory.createToken(ts.SyntaxKind.TrueKeyword),
);
}

/**
* Adds a property to an Angular decorator node.
* Sets a property on an Angular decorator node. If the property
* already exists, its initializer will be replaced.
* @param node Decorator to which to add the property.
* @param property Property to add.
* @param name Name of the property to be added.
* @param initializer Initializer for the new property.
*/
function addPropertyToAngularDecorator(
function setPropertyOnAngularDecorator(
node: ts.Decorator,
property: ts.PropertyAssignment,
name: string,
initializer: ts.Expression,
): ts.Decorator {
// Invalid decorator.
if (!ts.isCallExpression(node.expression) || node.expression.arguments.length > 1) {
Expand All @@ -457,10 +456,22 @@ function addPropertyToAngularDecorator(
let hasTrailingComma = false;

if (node.expression.arguments.length === 0) {
literalProperties = [property];
literalProperties = [ts.factory.createPropertyAssignment(name, initializer)];
} else if (ts.isObjectLiteralExpression(node.expression.arguments[0])) {
hasTrailingComma = node.expression.arguments[0].properties.hasTrailingComma;
literalProperties = [...node.expression.arguments[0].properties, property];
const literal = node.expression.arguments[0];
const existingProperty = findLiteralProperty(literal, name);
hasTrailingComma = literal.properties.hasTrailingComma;

if (existingProperty && ts.isPropertyAssignment(existingProperty)) {
literalProperties = literal.properties.slice();
literalProperties[literalProperties.indexOf(existingProperty)] =
ts.factory.updatePropertyAssignment(existingProperty, existingProperty.name, initializer);
} else {
literalProperties = [
...literal.properties,
ts.factory.createPropertyAssignment(name, initializer),
];
}
} else {
// Unsupported case (e.g. `@Component(SOME_CONST)`). Return the original node.
return node;
Expand Down Expand Up @@ -756,12 +767,10 @@ export function migrateTestDeclarations(

tracker.replaceNode(
decorator.node,
addPropertyToAngularDecorator(
setPropertyOnAngularDecorator(
newDecorator,
ts.factory.createPropertyAssignment(
'imports',
ts.factory.createArrayLiteralExpression(importsArray),
),
'imports',
ts.factory.createArrayLiteralExpression(importsArray),
),
);
} else {
Expand Down
26 changes: 26 additions & 0 deletions packages/core/schematics/test/standalone_migration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2218,6 +2218,32 @@ describe('standalone migration', () => {
);
});

it('should handle a directive that is explicitly standalone: false', async () => {
writeFile(
'module.ts',
`
import {NgModule, Directive} from '@angular/core';
@Directive({selector: '[dir]', standalone: false})
export class MyDir {}
@NgModule({declarations: [MyDir], exports: [MyDir]})
export class Mod {}
`,
);

await runMigration('convert-to-standalone');

const result = tree.readContent('module.ts');

expect(stripWhitespace(result)).toContain(
stripWhitespace(`@Directive({selector: '[dir]', standalone: true})`),
);
expect(stripWhitespace(result)).toContain(
stripWhitespace(`@NgModule({imports: [MyDir], exports: [MyDir]})`),
);
});

it('should remove a module that only has imports and exports', async () => {
writeFile(
'app.module.ts',
Expand Down

0 comments on commit 6144612

Please sign in to comment.