Skip to content

Instantly share code, notes, and snippets.

@Jordan-Hall
Created October 26, 2024 19:41
Show Gist options
  • Save Jordan-Hall/b0fdeaa5e2215b05e09096189faeb450 to your computer and use it in GitHub Desktop.
Save Jordan-Hall/b0fdeaa5e2215b05e09096189faeb450 to your computer and use it in GitHub Desktop.
Make the functions return state correctly for ivy
import * as ts from "typescript";
// Input function
const sourceCode = `
function example() {
let test = 1;
let helloWorld;
const add = (by) => {
test += by;
};
function remove(by) {
test -= by;
}
}
`;
// Transformer function
function transformFunctionToReturnGetSetAndMethods(sourceCode: string): string {
const sourceFile = ts.createSourceFile(
"example.ts",
sourceCode,
ts.ScriptTarget.Latest,
true,
ts.ScriptKind.TS
);
const printer = ts.createPrinter();
const transformer: ts.TransformerFactory<ts.SourceFile> = (context) => {
const visit: ts.Visitor = (node) => {
// Identify top-level functions only
if (ts.isFunctionDeclaration(node) && node.body) {
const statements = node.body.statements;
const returnProperties: ts.ObjectLiteralElementLike[] = [];
statements.forEach((statement) => {
if (ts.isVariableStatement(statement)) {
statement.declarationList.declarations.forEach((declaration) => {
if (ts.isIdentifier(declaration.name)) {
const name = declaration.name.getText();
if (declaration?.initializer && ts.isArrowFunction(declaration?.initializer)) {
returnProperties.push(
ts.factory.createShorthandPropertyAssignment(name)
);
return
}
// Create getter for variable
const getter = ts.factory.createGetAccessorDeclaration(
undefined, // No modifiers
name, // Name of the accessor
[], // No parameters for getter
undefined, // Return type is inferred
ts.factory.createBlock([
ts.factory.createReturnStatement(
ts.factory.createIdentifier(name)
),
], true)
);
// Create setter for variable
const setter = ts.factory.createSetAccessorDeclaration(
undefined, // No modifiers
name, // Name of the accessor
[
ts.factory.createParameterDeclaration(
undefined, undefined, ts.factory.createIdentifier("value"), undefined, undefined
)
],
ts.factory.createBlock([
ts.factory.createExpressionStatement(
ts.factory.createBinaryExpression(
ts.factory.createIdentifier(name),
ts.SyntaxKind.EqualsToken,
ts.factory.createIdentifier("value")
)
),
], true)
);
returnProperties.push(getter, setter);
}
});
} else if (ts.isFunctionDeclaration(statement)) {
const name = statement.name?.getText();
if (name) {
returnProperties.push(
ts.factory.createShorthandPropertyAssignment(name)
);
}
}
});
// Add return statement at the end of the function
const returnStatement = ts.factory.createReturnStatement(
ts.factory.createObjectLiteralExpression(returnProperties, true)
);
const updatedBody = ts.factory.updateBlock(node.body, [
...node.body.statements,
returnStatement,
]);
node = ts.factory.updateFunctionDeclaration(
node,
node.modifiers,
node.asteriskToken,
node.name,
node.typeParameters,
node.parameters,
node.type,
updatedBody
);
}
return ts.visitEachChild(node, visit, context);
};
return (node: ts.SourceFile) => ts.visitNode(node, visit) as ts.SourceFile;
};
const result = ts.transform(sourceFile, [transformer]);
const transformedSourceFile = result.transformed[0] as ts.SourceFile;
const transformedSource = printer.printFile(transformedSourceFile);
result.dispose();
return transformedSource;
}
// Transformed output
console.log(transformFunctionToReturnGetSetAndMethods(sourceCode));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment