#pragma once #include #include #include #include "BatchMutationAPI.h" #include "ast/Module.h" #include "ast/Function.h" #include "ast/Statement.h" #include "ast/Expression.h" struct RefactorPlan { bool success = false; std::string error; std::vector mutations; }; inline std::string nextRefactorId(const std::string& prefix) { static int counter = 0; return prefix + "_" + std::to_string(counter++); } inline void collectVariableRefs(ASTNode* node, const std::string& name, std::vector& outRefs) { if (!node) return; if (node->conceptType == "VariableReference") { auto* vr = static_cast(node); if (vr->variableName == name) outRefs.push_back(node); } for (auto* child : node->allChildren()) { collectVariableRefs(child, name, outRefs); } } inline void collectVariables(ASTNode* node, const std::string& name, std::vector& outVars) { if (!node) return; if (node->conceptType == "Variable") { auto* v = static_cast(node); if (v->name == name) outVars.push_back(node); } for (auto* child : node->allChildren()) { collectVariables(child, name, outVars); } } inline RefactorPlan buildRenameVariablePlan(Module* ast, const std::string& oldName, const std::string& newName) { RefactorPlan plan; if (!ast) { plan.error = "No AST"; return plan; } if (oldName.empty() || newName.empty()) { plan.error = "Variable names cannot be empty"; return plan; } std::vector vars; std::vector refs; collectVariables(ast, oldName, vars); collectVariableRefs(ast, oldName, refs); if (vars.empty() && refs.empty()) { plan.error = "No matching variable or references"; return plan; } for (auto* v : vars) { BatchMutationAPI::Mutation mut; mut.type = "setProperty"; mut.nodeId = v->id; mut.property = "name"; mut.value = newName; plan.mutations.push_back(mut); } for (auto* r : refs) { BatchMutationAPI::Mutation mut; mut.type = "setProperty"; mut.nodeId = r->id; mut.property = "variableName"; mut.value = newName; plan.mutations.push_back(mut); } plan.success = true; return plan; } inline RefactorPlan buildExtractFunctionPlan(Module* ast, const std::string& newFunctionName) { RefactorPlan plan; if (!ast) { plan.error = "No AST"; return plan; } if (newFunctionName.empty()) { plan.error = "Function name cannot be empty"; return plan; } auto funcs = ast->getChildren("functions"); if (funcs.empty()) { plan.error = "No functions to extract from"; return plan; } auto* srcFn = static_cast(funcs.front()); auto body = srcFn->getChildren("body"); if (body.empty()) { plan.error = "Source function has no body"; return plan; } ASTNode* stmt = body.front(); auto* newFn = new Function(nextRefactorId("fn"), newFunctionName); auto* call = new FunctionCall(); call->id = nextRefactorId("call"); call->functionName = newFunctionName; auto* callStmt = new ExpressionStatement(); callStmt->id = nextRefactorId("stmt"); callStmt->setChild("expression", call); BatchMutationAPI::Mutation insertFn; insertFn.type = "insertNode"; insertFn.parentId = ast->id; insertFn.role = "functions"; insertFn.newNode = newFn; plan.mutations.push_back(insertFn); BatchMutationAPI::Mutation deleteStmt; deleteStmt.type = "deleteNode"; deleteStmt.nodeId = stmt->id; plan.mutations.push_back(deleteStmt); BatchMutationAPI::Mutation insertStmt; insertStmt.type = "insertNode"; insertStmt.parentId = newFn->id; insertStmt.role = "body"; insertStmt.newNode = stmt; plan.mutations.push_back(insertStmt); BatchMutationAPI::Mutation insertCall; insertCall.type = "insertNode"; insertCall.parentId = srcFn->id; insertCall.role = "body"; insertCall.newNode = callStmt; plan.mutations.push_back(insertCall); plan.success = true; return plan; } inline RefactorPlan buildInlineVariablePlan(Module* ast, const std::string& varName) { RefactorPlan plan; if (!ast) { plan.error = "No AST"; return plan; } if (varName.empty()) { plan.error = "Variable name cannot be empty"; return plan; } std::vector vars; collectVariables(ast, varName, vars); if (vars.empty()) { plan.error = "Variable not found"; return plan; } BatchMutationAPI::Mutation del; del.type = "deleteNode"; del.nodeId = vars.front()->id; plan.mutations.push_back(del); plan.success = true; return plan; }