Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
3c2a130
feat(ast-transformer): allow sorting of array literals
jackofdiamond5 Oct 9, 2024
a31374f
feat(ast-transformer): allow requesting new members in obj literals t…
jackofdiamond5 Oct 10, 2024
c81bd18
feat(ast-transformer): introduce options for object literals
jackofdiamond5 Oct 10, 2024
8aa8175
feat(ast-transformer): introduce options for array literals
jackofdiamond5 Oct 10, 2024
822a0e6
refactor(ast-transformer): remove redundant update obj literal method
jackofdiamond5 Oct 10, 2024
cfe4f4d
chore(ast-transformer): update public api docs
jackofdiamond5 Oct 11, 2024
47640b6
chore(transformer-factories): plans for future improvement
jackofdiamond5 Oct 11, 2024
300a7c5
chore(ast-transformer): update docs
jackofdiamond5 Oct 11, 2024
433c3f7
feat(ng-update): allow sorting of array initializers in ng decorators
jackofdiamond5 Oct 11, 2024
f85467a
chore(ng-update): add comments
jackofdiamond5 Oct 11, 2024
ddad631
chore(ng-update): renaming
jackofdiamond5 Oct 14, 2024
190e4a8
release: 14.1.1-beta.1
jackofdiamond5 Oct 14, 2024
8828462
chore(core. igx-templates): bump ts to 5.5.4
jackofdiamond5 Oct 14, 2024
387b778
refactor(transformer-factories): extract an updateProperty function
jackofdiamond5 Oct 14, 2024
c1a25fb
Merge branch 'master' into bpenkov/reordering-array-literals
Lipata Oct 29, 2024
ffaa2de
chore: release 14.2.2-beta.0
Lipata Oct 29, 2024
471e5b8
Merge remote-tracking branch 'remotes/origin/master' into bpenkov/reo…
jackofdiamond5 Nov 11, 2024
ad03985
Merge branch 'master' into bpenkov/reordering-array-literals
jackofdiamond5 Nov 20, 2024
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
4 changes: 2 additions & 2 deletions packages/cli/templates/react/ReactTypeScriptFileUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ export class ReactTypeScriptFileUpdate extends TypeScriptFileUpdate {
this.astTransformer.requestNewMembersInArrayLiteral(
variableAsParentCondition(this.astTransformer, ROUTES_VARIABLE_NAME),
[newRoute],
prepend,
anchorElement
anchorElement,
{ prepend }
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ export class WebComponentsTypeScriptFileUpdate extends TypeScriptFileUpdate {
this.astTransformer.requestNewMembersInArrayLiteral(
variableAsParentCondition(this.astTransformer, ROUTES_VARIABLE_NAME),
[newRoute],
prepend,
anchorElement
anchorElement,
{ prepend }
);
}

Expand Down
4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
"author": "Infragistics",
"license": "MIT",
"dependencies": {
"@inquirer/prompts": "^5.4.0",
"@inquirer/prompts": "~5.4.0",
"chalk": "^2.3.2",
"glob": "^7.1.2",
"through2": "^4.0.2",
"through2": "^2.0.3",
"typescript": "~5.5.4"
},
"devDependencies": {
Expand Down
35 changes: 35 additions & 0 deletions packages/core/types/types-typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,38 @@ export interface ChangeRequest<T extends ts.Node> {
*/
node: T | ts.NodeArray<T>;
}

/**
* Options that can be applied when modifying a literal expression.
*/
export interface LiteralExpressionOptionsBase {
/**
* Whether the literal should be on multiple lines.
* @remarks This option is only applicable to {@link ts.ObjectLiteralExpression} and {@link ts.ArrayLiteralExpression}.
*/
multiline?: boolean;
}

/**
* Options that can be applied when modifying an {@link ts.ObjectLiteralExpression}.
*/
export interface ObjectLiteralExpressionEditOptions
extends LiteralExpressionOptionsBase {
/**
* Whether to override all elements of the property's initializer.
* @remarks This option is only applicable to {@link ts.PropertyAssignment} with an initializer that is {@link ts.ArrayLiteralExpression}.
* All other initializers will be overridden by default.
*/
override?: boolean;
}

/**
* Options that can be applied when modifying an {@link ts.ArrayLiteralExpression}.
*/
export interface ArrayLiteralExpressionEditOptions
extends LiteralExpressionOptionsBase {
/**
* If any elements should be added at the beginning of an {@link ts.ArrayLiteralExpression}.
*/
prepend?: boolean;
}
141 changes: 65 additions & 76 deletions packages/core/typescript/TransformerFactories.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as ts from 'typescript';
import {
ArrayLiteralExpressionEditOptions,
Identifier,
ImportDeclarationMeta,
ObjectLiteralExpressionEditOptions,
PropertyAssignment,
} from '../types';
import { SIDE_EFFECTS_IMPORT_TEMPLATE_NAME } from '../util';
Expand All @@ -26,8 +28,8 @@ import { TypeScriptExpressionCollector } from './TypeScriptExpressionCollector';
export const newMemberInObjectLiteralTransformerFactory = (
newProperty: ts.PropertyAssignment,
visitCondition: (node: ts.Node) => boolean,
multiline: boolean,
expressionCollector: TypeScriptExpressionCollector
expressionCollector: TypeScriptExpressionCollector,
options: ObjectLiteralExpressionEditOptions
): ts.TransformerFactory<ts.SourceFile> => {
return <T extends ts.Node>(context: ts.TransformationContext) => {
return (rootNode: T) => {
Expand Down Expand Up @@ -73,7 +75,8 @@ export const newMemberInObjectLiteralTransformerFactory = (
context,
node,
expressionCollector,
multiline
options?.multiline,
options?.override
);
}

Expand All @@ -91,53 +94,14 @@ export const newMemberInObjectLiteralTransformerFactory = (
};
};

/**
* Creates a {@link ts.TransformerFactory} that updates a member in a {@link ts.ObjectLiteralExpression}.
*/
export const updateForObjectLiteralMemberTransformerFactory = (
visitCondition: (node: ts.ObjectLiteralExpression) => boolean,
targetMember: PropertyAssignment
): ts.TransformerFactory<ts.SourceFile> => {
return <T extends ts.Node>(context: ts.TransformationContext) => {
return (rootNode: T) => {
const visitor = (node: ts.Node): ts.VisitResult<ts.Node> => {
if (ts.isObjectLiteralExpression(node) && visitCondition(node)) {
const newProperties = node.properties.map((property) => {
const isPropertyAssignment = ts.isPropertyAssignment(property);
if (
isPropertyAssignment &&
ts.isIdentifier(property.name) &&
property.name.text === targetMember.name
) {
return context.factory.updatePropertyAssignment(
property,
property.name,
targetMember.value
);
}
return property;
});

return context.factory.updateObjectLiteralExpression(
node,
newProperties
);
}
return ts.visitEachChild(node, visitor, context);
};
return ts.visitNode(rootNode, visitor, ts.isSourceFile);
};
};
};

/**
* Creates a {@link ts.TransformerFactory} that adds a new element to a {@link ts.ArrayLiteralExpression}.
*/
export const newMemberInArrayLiteralTransformerFactory = (
visitCondition: (node: ts.ArrayLiteralExpression) => boolean,
elements: ts.Expression[],
prepend: boolean = false,
anchorElement?: ts.StringLiteral | ts.NumericLiteral | PropertyAssignment
anchorElement?: ts.StringLiteral | ts.NumericLiteral | PropertyAssignment,
options?: ArrayLiteralExpressionEditOptions
): ts.TransformerFactory<ts.SourceFile> => {
return <T extends ts.Node>(context: ts.TransformationContext) => {
return (rootNode: T) => {
Expand Down Expand Up @@ -175,9 +139,14 @@ export const newMemberInArrayLiteralTransformerFactory = (
});
}

/**
* TODO:
* Consider extracting some of the logic to the factory that handles array literals as property initializers and reusing that here.
* The anchor element should be preserved while it should also allow for overriding of the elements, if needed.
*/
if (anchor) {
let structure!: ts.Expression[];
if (prepend) {
if (options?.prepend) {
structure = node.elements
.slice(0, node.elements.indexOf(anchor))
.concat(elements)
Expand All @@ -195,7 +164,7 @@ export const newMemberInArrayLiteralTransformerFactory = (
);
}

if (prepend) {
if (options?.prepend) {
return context.factory.updateArrayLiteralExpression(node, [
...elements,
...node.elements,
Expand All @@ -213,6 +182,27 @@ export const newMemberInArrayLiteralTransformerFactory = (
};
};

/**
* Creates a {@link ts.TransformerFactory} that sorts the elements in a {@link ts.ArrayLiteralExpression}.
*/
export const sortInArrayLiteralTransformerFactory = (
visitCondition: (node: ts.ArrayLiteralExpression) => boolean,
sortCondition: (a: ts.Expression, b: ts.Expression) => number
) => {
return <T extends ts.Node>(context: ts.TransformationContext) => {
return (rootNode: T) => {
const visitor = (node: ts.Node): ts.VisitResult<ts.Node> => {
if (ts.isArrayLiteralExpression(node) && visitCondition(node)) {
const elements = [...node.elements].sort(sortCondition);
return context.factory.updateArrayLiteralExpression(node, elements);
}
return ts.visitEachChild(node, visitor, context);
};
return ts.visitNode(rootNode, visitor, ts.isSourceFile);
};
};
};

/**
* Creates a {@link ts.TransformerFactory} that adds a new argument to a {@link ts.CallExpression}.
*/
Expand Down Expand Up @@ -488,29 +478,7 @@ function updatePropertyAssignmentWithIdentifier(
? newProperty.initializer
: newProperty.objectAssignmentInitializer;

const updatedProperty = ts.isPropertyAssignment(existingProperty)
? context.factory.updatePropertyAssignment(
existingProperty,
existingProperty.name,
newPropInitializer
)
: context.factory.updateShorthandPropertyAssignment(
existingProperty,
existingProperty.name,
newPropInitializer
);
const structure = Array.from(node.properties);
const targetIndex = structure.indexOf(existingProperty);
if (targetIndex > -1) {
// attempt to modify the property assignment and preserve the order
structure[targetIndex] = updatedProperty;
return context.factory.updateObjectLiteralExpression(node, structure);
}
// append the property assignment at the end
return context.factory.updateObjectLiteralExpression(node, [
...node.properties.filter((p) => p !== existingProperty),
updatedProperty,
]);
return updateProperty(node, existingProperty, newPropInitializer, context);
}

/**
Expand All @@ -520,14 +488,16 @@ function updatePropertyAssignmentWithIdentifier(
* @param context The transformation context.
* @param node The object literal expression node.
* @param multiline Whether the array literal should be multiline.
* @param override Whether to override all elements if the property's initializer is an array.
*/
function updatePropertyAssignmentWithArrayLiteral(
newProperty: ts.PropertyAssignment | ts.ShorthandPropertyAssignment,
existingProperty: ts.PropertyAssignment | ts.ShorthandPropertyAssignment,
context: ts.TransformationContext,
node: ts.ObjectLiteralExpression,
expressionCollector: TypeScriptExpressionCollector,
multiline: boolean
multiline: boolean,
override: boolean
): ts.ObjectLiteralExpression {
const existingPropInitializer = ts.isPropertyAssignment(existingProperty)
? existingProperty.initializer
Expand All @@ -543,25 +513,44 @@ function updatePropertyAssignmentWithArrayLiteral(
const newElements = ts.isArrayLiteralExpression(newPropInitializer)
? [...newPropInitializer.elements]
: [newPropInitializer];
const uniqueElements = expressionCollector.collectUniqueExpressions([
...elements,
...newElements,
]);
const uniqueElements = override
? expressionCollector.collectUniqueExpressions(newElements)
: expressionCollector.collectUniqueExpressions([
...elements,
...newElements,
]);

const valueExpression = context.factory.createArrayLiteralExpression(
uniqueElements,
multiline
);

return updateProperty(node, existingProperty, valueExpression, context);
}

/**
* Updates a {@link ts.PropertyAssignment} with a new {@link ts.Initializer}.
* @param node The object literal expression node.
* @param existingProperty The property to update.
* @param newInitializer The new initializer to set.
* @param context The transformation context.
*/
function updateProperty(
node: ts.ObjectLiteralExpression,
existingProperty: ts.PropertyAssignment | ts.ShorthandPropertyAssignment,
newInitializer: ts.Expression,
context: ts.TransformationContext
): ts.ObjectLiteralExpression {
const updatedProperty = ts.isPropertyAssignment(existingProperty)
? context.factory.updatePropertyAssignment(
existingProperty,
existingProperty.name,
valueExpression
newInitializer
)
: context.factory.updateShorthandPropertyAssignment(
existingProperty,
existingProperty.name,
valueExpression
newInitializer
);

const structure = Array.from(node.properties);
Expand Down
Loading
Loading