ICSE 2027 paper project

AutoRefactor: Towards Reliable Code Refactoring

Historical refactoring replay and sketch-driven navigation for repository-level code smell refactoring.

12 projects 691 smell instances 9 smell types

Paper introduction

Reliable refactoring needs executable plans, not only generated patches.

Large language models can propose plausible refactoring directions, but repository-level code smell refactoring requires coordinated edits that preserve global behavior. AutoRefactor uses an executable Refactoring Plan (Ref-Plan) as an intermediate representation, combining IDE-native refactoring operations with AST-based edits.

The system mines real smell-removal history, replays candidate Ref-Plans to keep only executable and effective examples, builds a task-level Refactoring SPEC for new instances, and validates each generated plan with executability, compilation, testing, and smell elimination checks.

Approach

From historical refactoring behavior to validated Ref-Plans.

AutoRefactor turns developer refactoring history into reusable operation-level experience and applies that experience through a structured, checkable generation pipeline.

AutoRefactor workflow with historical replay, SPEC construction, Ref-Plan generation, and validation
01

Historical Ref-Plan replay

Recover candidate operations from real smell-removal commits, replay them, and retain records that are both executable and smell-eliminating.

02

Refactoring SPEC construction

Retrieve similar historical records and combine them with the current smell location, involved entities, constraints, and goals.

03

Sketch-to-action navigation

Generate a high-level refactoring sketch first, then bind it to concrete IDE and AST operations with explicit parameters.

04

Multi-level validation

Accept only plans that pass operation prechecks, compilation, tests, and smell-removal validation; use feedback to repair plans.

Evaluation

Large-scale validation across projects, smells, and models.

AutoRefactor was evaluated on 691 instances from 12 open-source Java projects and 9 code smell types. The evaluation compares specialized refactoring tools, a general coding-agent baseline, and ablated AutoRefactor variants.

90.6% end-to-end success rate
+18.5 pp over SWE-agent overall
21.4% lower macro-average token usage than SWE-agent
91.44% average line coverage after test augmentation
Finding Structured Ref-Plan generation improves both refactoring success and resource cost under the same base model.
Human evaluation violin chart for AutoRefactor patch quality

Case study

Feature Envy Sample 4: why validated planning matters.

The target is Apache Commons Compress Segment.buildClassFile(int). The method repeatedly accesses ClassBands, but it also coordinates class-file assembly, constant-pool entries, source attributes, header defaults, fields, interfaces, and bytecode metadata. A safe fix therefore needs more than a direct move-method decision.

241.00 feature-envy detector score
17 references to the related ClassBands object
4/4 AutoRefactor runs pass validation
0/4 comparison tools succeed on this instance
Observation

A baseline tool can identify and apply a plausible move-method change for this case, yet the resulting patch still fails validation. The example illustrates why AutoRefactor treats refactoring as a planned, checked repository-level change rather than a single candidate transformation.

Project
commons-compress
Method
Segment.buildClassFile(int)
Envied type
ClassBands
Reference test
SegmentTest, 89.4% coverage
Segment.java source excerpt
private ClassFile buildClassFile(final int classNum) {
    final ClassFile classFile = new ClassFile();
    final int[] major = classBands.getClassVersionMajor();
    final int[] minor = classBands.getClassVersionMinor();
    if (major != null) {
        classFile.major = major[classNum];
        classFile.minor = minor[classNum];
    } else {
        classFile.major = header.getDefaultClassMajorVersion();
        classFile.minor = header.getDefaultClassMinorVersion();
    }

    final ClassConstantPool cp = classFile.pool;
    final int fullNameIndexInCpClass = classBands.getClassThisInts()[classNum];
    final String fullName = cpBands.getCpClass()[fullNameIndexInCpClass];
    final List<Attribute> classAttributes =
            classBands.getClassAttributes()[classNum];
    // Interfaces, fields, methods, and class attributes are assembled here.
}
Tool or run Outcome Validation summary Reader takeaway
AutoRefactor GLM-4.7 / GPT-5 / GLM-4.5-Air / DeepSeek-V4-Flash 4/4 Passed All four model backends generate executable Ref-Plans and pass compilation, tests, and smell-elimination validation. This case is not repaired by a one-off model response; it is consistently solved through a structured plan-execute-validate workflow.
MM-Assist Rejected A move-method patch is applied, but it fails validation. Finding a candidate is not enough if the final patch is not safe.
FETruth Not applicable The matched target cannot be applied as an IDE refactoring. A reported target still needs an executable transformation.
SWE-agent Build failed The edited repository does not pass the build check. General-purpose editing struggles with this coordinated refactoring.
JDeodorant No candidate No applicable move-method candidate is produced. Traditional candidate generation may miss this case entirely.
Takeaway

This case shows why AutoRefactor validates a concrete refactoring plan against the repository instead of relying only on a local move-method suggestion.

Read brief case study

Demonstration

End-to-end demo of the AutoRefactor workflow.

The demo shows AutoRefactor moving from smell context to sketch, Ref-Plan generation, and validation inside the development environment.

Artifacts

Public artifacts for the paper experiments.

Downloadable artifacts for the AutoRefactor experiments, grouped by dataset, project snapshots, results, and the artifact README.

AutoRefactor Supported Operations

IDE-native refactorings

  • change-signature:class
  • change-signature:method
  • convert-to-instance-method
  • copy:file
  • copy:package
  • copy:type
  • delete:field
  • delete:method
  • encapsulate:field
  • extract:class
  • extract:constant
  • extract:delegate
  • extract:field
  • extract:interface
  • extract:method
  • extract:method-object
  • extract:parameter
  • extract:superclass
  • inline:method
  • introduce:parameter-object
  • introduce:variable
  • invert:boolean
  • make-static:method
  • move:member
  • move:method
  • move:package
  • move:type
  • pullUp:field
  • pullUp:method
  • pushDown:field
  • pushDown:method
  • rename:directory
  • rename:field
  • rename:file
  • rename:local-variable
  • rename:method
  • rename:module
  • rename:package
  • rename:type
  • replace-inheritance-with-delegation

AST-based edits

  • delete:file
  • delete:import
  • delete:statement
  • delete:type
  • insert:field
  • insert:file
  • insert:import
  • insert:method
  • insert:statement
  • insert:type
  • replace:expression
  • replace:field
  • replace:file
  • replace:method
  • replace:statement
  • replace:type
  • update:field
  • update:file
  • update:method
  • update:type