Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,28 @@ describe('action modal migration', () => {

const expected = [
`import { Component, inject } from '@angular/core';`,
`import { AlertDialogResult, SiActionDialogService } from '@siemens/element-ng/action-modal';`,
`import { SiActionDialogService } from '@siemens/element-ng/action-modal';`,
`@Component({ selector: 'app-test-action-modal' })`,
`export class TestActionModalComponent {`,
`showDialog() { inject(SiActionDialogService).showActionDialog({ type: 'alert', message: 'Message', heading: 'Heading', confirmBtnName: 'Confirmation button text' }) } }`
];

await checkTemplateMigration(original, expected);
});

it('should clean-up imports', async () => {
const original = [
`import { Component, inject } from '@angular/core';`,
`import { AlertDialogResult, SiActionDialogService, SiUnrelated } from '@siemens/element-ng';`,
`import { DeleteConfirmationDialogResult } from '@siemens/element-ng/action-modal';`,
`@Component({ selector: 'app-test-action-modal' })`,
`export class TestActionModalComponent {`,
`showDialog() { inject(SiActionDialogService).showAlertDialog('Message', 'Heading', 'Confirmation button text') } }`
];

const expected = [
`import { Component, inject } from '@angular/core';`,
`import { SiActionDialogService, SiUnrelated } from '@siemens/element-ng';`,
`@Component({ selector: 'app-test-action-modal' })`,
`export class TestActionModalComponent {`,
`showDialog() { inject(SiActionDialogService).showActionDialog({ type: 'alert', message: 'Message', heading: 'Heading', confirmBtnName: 'Confirmation button text' }) } }`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,13 @@ export const actionModalMigrationRule = (options: { path: string }): Rule => {
}

const pendingTransformations: CodeTransformation[] = [];
const usedIdentifier = new Set<string>();

const visitNodeAndCollectTransformations = (node: ts.Node): void => {
if (ts.isImportDeclaration(node)) {
return;
}

// Collect method call transformations
if (ts.isCallExpression(node)) {
const methodTransformation = createActionDialogMethodCallTransformation(node);
Expand All @@ -70,12 +75,19 @@ export const actionModalMigrationRule = (options: { path: string }): Rule => {
const typeTransformation = createActionDialogTypeTransformation(node);
if (typeTransformation) {
pendingTransformations.push(typeTransformation);
// We remove the usage here. In order to avoid counting it as used identifier, we skip further processing.
return;
}
}

if (ts.isIdentifier(node)) {
usedIdentifier.add(node.text);
}

node.forEachChild(visitNodeAndCollectTransformations);
};
sourceFile.forEachChild(visitNodeAndCollectTransformations);
pendingTransformations.push(...removeUnusedImports(sourceFile, usedIdentifier));

if (pendingTransformations.length > 0) {
applyCodeTransformations(tree, filePath, pendingTransformations);
Expand Down Expand Up @@ -117,8 +129,7 @@ const createActionDialogMethodCallTransformation = (

return {
node,
newCode,
type: 'method-call'
newCode
};
};

Expand All @@ -137,8 +148,7 @@ const createActionDialogTypeTransformation = (

return {
node,
newCode: `'${matchingReplacement.new}'`,
type: 'type-reference'
newCode: `'${matchingReplacement.new}'`
};
};

Expand Down Expand Up @@ -192,3 +202,57 @@ const applyCodeTransformations = (
});
tree.commitUpdate(recorder);
};

const removeUnusedImports = (
sourceFile: ts.SourceFile,
usedIdentifier: Set<string>
): CodeTransformation[] => {
const printer = ts.createPrinter();
const importFinder = (node: ts.Node): CodeTransformation | undefined => {
if (
ts.isImportDeclaration(node) &&
ts.isStringLiteral(node.moduleSpecifier) &&
/@(siemens|simpl)\/element-ng(\/action-modal)?/.test(node.moduleSpecifier.text) &&
node.importClause?.namedBindings &&
ts.isNamedImports(node.importClause.namedBindings)
) {
const usedBindings = node.importClause.namedBindings.elements.filter(
element =>
// This script anyway is not capable of handling aliasing imports, so we can ignore them here.
usedIdentifier.has(element.name.text) || !ACTION_MODAL_SYMBOLS.includes(element.name.text)
);

if (usedBindings.length === node.importClause.namedBindings.elements.length) {
// All bindings are used, no changes needed
return undefined;
}

if (usedBindings.length === 0) {
// No bindings are used, remove the entire import statement
return {
node,
newCode: ''
};
}

// Recreate import statement with only used bindings
const newImport = ts.factory.createImportDeclaration(
node.modifiers,
ts.factory.createImportClause(
node.importClause.isTypeOnly,
node.importClause.name,
ts.factory.createNamedImports(usedBindings)
),
node.moduleSpecifier,
node.attributes
);

return {
node,
newCode: printer.printNode(ts.EmitHint.Unspecified, newImport, sourceFile)
};
}
return undefined;
};
return sourceFile.statements.map(importFinder).filter(transform => transform !== undefined);
};
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export interface DialogMethodConfig {
export interface CodeTransformation {
node: ts.Node;
newCode: string;
type: 'method-call' | 'type-reference';
}

export const DIALOG_METHOD_CONFIGS: Record<LegacyMethodName, DialogMethodConfig> = {
Expand Down
Loading