Skip to content

[STATUS] Multi-file quickfix/cleanup API: Implemented & merged (usage, examples, limitations, TODOs) #67

Description

@carstenartur

[STATUS] Multi-file Quickfix/Cleanup API: Implemented & Merged

This issue is now resolved — the new API and infrastructure have been implemented and merged as of PR #68. Below is a detailed documentation of what is included, how to use it, sample code, key behaviors, and open limitations.


✨ What the PR Really Implements

PR #68 brings first-class support for writing cleanups and quickfixes that coordinate edits across multiple Java files and provide an atomic, unified preview and undo.

  • New public API:

    • IMultiFileCleanUp interface lets you implement cross-file cleanups.
    • Upwards-compatible: legacy ICleanUp continues to work for single-file scenarios.
    • New interface is found in the package: org.eclipse.jdt.ui.cleanup.
  • Refactoring Orchestration Changes:

    • CleanUpRefactoring aggregates all selected/related compilation units.
    • If the cleanup implements IMultiFileCleanUp, all contexts for all files are passed in one batch.
    • Resulting changes are bundled in a single CompositeChange for atomic preview and undo.
  • Atomic Multi-File Preview and Undo:

    • The Eclipse refactoring/cleanup UI now offers a unified preview whenever a multi-file cleanup is run.
    • All edits are previewed as a tree of changes (one per file and top-level logical change), and applied together or not at all.
  • Concrete Example Implementation:

    • RemoveUnusedMethodCleanUp:
      • Scans all selected files and builds a global call graph/usage map.
      • Finds all method declarations that are never referenced.
      • If the unused method is declared in an interface/superclass, it is removed from both the interface and class files in a coordinated change.
      • Example scenario with 3 files (IService.java, ServiceImpl.java, Main.java) is covered and tested.
  • Test Coverage and Documentation:

    • Multiple tests (see RemoveUnusedMethodCleanUpTest) verify multi-file behavior.
    • Documentation found in MULTI_FILE_CLEANUP.md and IMPLEMENTATION_SUMMARY.md.

🚀 How to Use the Multi-File Cleanup API

Implementing a new multi-file cleanup:

// 1. Implement the new API
public class MyMultiFileCleanup implements IMultiFileCleanUp {
    @Override
    public CompositeChange createFix(List<CleanUpContext> contexts) {
        // Analyze all contexts together to determine needed edits
        // For each fix, create a TextFileChange and add it to CompositeChange
        return new CompositeChange("My multi-file fix", List.of(
            /* new TextFileChange("File1.java", edit1), ... */
        ));
    }
}

// 2. Register in the usual cleanup extension point/configuration
// Now your cleanup will receive all relevant compilation units in a single batch.

Sample usage in code:

IMultiFileCleanUp cleanup = new RemoveUnusedMethodCleanUp();
List<CleanUpContext> contexts = List.of(/* context per file */);
CompositeChange change = cleanup.createFix(contexts);
// Present CompositeChange in UI, preview and apply atomically

UI/End-User Flow:

  • Select one or more files/packages/projects for cleanup.
  • If any applicable cleanup supports multi-file (IMultiFileCleanUp), all relevant files/contexts are analyzed together and a coordinated set of changes is proposed.
  • In the preview dialog, all file changes are shown in a hierarchical structure.
  • User can review the total impact and undo all changes as a unit.

🟢 Example: Remove Unused Method

Before:

// IService.java
public interface IService {
    void usedMethod();
    void unusedMethod(); // Never called
}

// ServiceImpl.java
public class ServiceImpl implements IService {
    public void usedMethod() { System.out.println("Used"); }
    public void unusedMethod() { System.out.println("Unused"); }
}
// Main.java
public class Main {
    public static void main(String[] args) {
        IService s = new ServiceImpl();
        s.usedMethod();
    }
}

After multi-file cleanup:

  • unusedMethod is removed from both interface and implementation, in both files, in one transaction.

📚 Documentation Links

  • API reference: See MULTI_FILE_CLEANUP.md for design details and usage patterns.
  • Test cases: See RemoveUnusedMethodCleanUpTest.
  • Branch/PR: PR #68
  • Technical summary: See IMPLEMENTATION_SUMMARY.md

⚠️ What Is Still Missing / Limitations

The following improvements are not yet part of the merged implementation:

  • Selective Acceptance of Changes in Preview:

    • Unchecking an individual change in the preview UI does not (yet) trigger a recomputation of the remaining fixes. This could lead to broken state if a user disables a logically dependent change.
    • Atomically apply all or nothing; partial application is at user risk in complex cases.
  • Dependency Tracking:

    • No UI or API yet to explicitly flag change dependencies (e.g. "change B depends on A").
    • Users are not warned if a sequence of omits might break the build.
  • Fresh AST Re-Analysis:

    • If the user disables changes and continues with the rest, the AST is not re-parsed for follow-up cleanups—meaning stale state is possible.
    • "getFreshAST=true" option or automatic recomputation is not yet available (currently under design, see enhancement discussion).
  • Advanced UX for Sequence Workflows:

    • Not yet possible to chain multiple cleanups with user acceptance driving re-analysis between steps.
    • No integrated UI for expressing/jumping into such workflows.

These are being tracked as follow-up enhancements:


📝 Summary

The new infrastructure lets you build and run cleanups/quickfixes that coordinate atomic edits across multiple Java files, with unified preview and full undo/redo support. This enables transformations like "delete unused method from interface and its implementation" in one step, tested and documented.

For advanced workflows — especially selective acceptance, dependency-aware changes, and recomputation — further enhancements are planned.

Feedback is welcome! If you have a real-world use case for sequenced, dependency-aware multi-file cleanups, please comment or open an issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions