fix: AST-based rename fallback for interface fields (#39) #40

Merged
fred merged 1 commit from fix/39-ast-rename-fallback into main 2026-03-08 10:35:56 +00:00
Collaborator

Summary

Fixes #39jdt_rename_element throws NPE in v0.2.17 when renaming interface fields.

Root cause: RenameFieldProcessor.checkFinalConditions() throws IllegalArgumentException (without message!) for interface fields (public static final in an interface). The preference initialization retry from #38 was a false lead — the IAE is not about preferences.

Changes

  • AST-based rename fallback using SearchEngine + ASTRewrite — works reliably in headless mode without Participants or Preferences
  • Fallback triggers:
    • checkFinalConditions throws IAE → AST fallback
    • Processor produces empty changes (childCount:0) → AST fallback
  • Removed ineffective initializeHeadlessPreferences()
  • Fixed NPE from List.of(null) when IAE has no message

How the AST fallback works

  1. SearchEngine.search() finds all references (workspace scope, accurate matches only)
  2. ASTRewrite renames the declaration via NodeFinder + SimpleName replacement
  3. Text edits applied to all referencing compilation units (back-to-front for stable offsets)

Analysis

Agent jdt-vogel (Lars Vogel) confirmed: the IAE is specific to interface fields, not a preferences issue. AST-based rename is the recommended approach for headless mode.

Test plan

  • Build: mvn clean package passes
  • JDTMCP_SKIP_BUILD=1 ./install-local.sh succeeds
  • Rename interface constant cross-module (VocabCg#CACHED_AT scenario)
  • Rename regular class field (non-interface)
  • Rename method (virtual + non-virtual)
  • Preview mode returns correct changes
  • Verify fallback flag in response when AST path is used

🤖 Generated with Claude Code

## Summary Fixes #39 — `jdt_rename_element` throws NPE in v0.2.17 when renaming interface fields. **Root cause:** `RenameFieldProcessor.checkFinalConditions()` throws `IllegalArgumentException` (without message!) for interface fields (`public static final` in an interface). The preference initialization retry from #38 was a false lead — the IAE is not about preferences. ### Changes - **AST-based rename fallback** using `SearchEngine` + `ASTRewrite` — works reliably in headless mode without Participants or Preferences - **Fallback triggers:** - `checkFinalConditions` throws IAE → AST fallback - Processor produces empty changes (childCount:0) → AST fallback - **Removed** ineffective `initializeHeadlessPreferences()` - **Fixed** NPE from `List.of(null)` when IAE has no message ### How the AST fallback works 1. `SearchEngine.search()` finds all references (workspace scope, accurate matches only) 2. `ASTRewrite` renames the declaration via `NodeFinder` + `SimpleName` replacement 3. Text edits applied to all referencing compilation units (back-to-front for stable offsets) ### Analysis Agent jdt-vogel (Lars Vogel) confirmed: the IAE is specific to interface fields, not a preferences issue. AST-based rename is the recommended approach for headless mode. ## Test plan - [ ] Build: `mvn clean package` passes - [ ] `JDTMCP_SKIP_BUILD=1 ./install-local.sh` succeeds - [ ] Rename interface constant cross-module (VocabCg#CACHED_AT scenario) - [ ] Rename regular class field (non-interface) - [ ] Rename method (virtual + non-virtual) - [ ] Preview mode returns correct changes - [ ] Verify fallback flag in response when AST path is used 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix: AST-based rename fallback for interface fields (#39)
All checks were successful
Build and Release / build (push) Successful in 3m43s
76b4e6a352
Root cause: RenameFieldProcessor.checkFinalConditions() throws
IllegalArgumentException (without message) for interface fields
(public static final in an interface). The preference initialization
retry from v0.2.17 was ineffective — the IAE is not about preferences.

Changes:
- Add AST-based rename fallback using SearchEngine + ASTRewrite
  (works reliably in headless mode without Participants or Preferences)
- Fall back to AST rename on IAE from checkFinalConditions
- Fall back to AST rename on empty changes (childCount:0)
- Remove ineffective initializeHeadlessPreferences()
- Fix NPE from List.of(null) when IAE has no message

The AST fallback:
1. Finds all references via SearchEngine (workspace scope)
2. Renames declaration via ASTRewrite
3. Applies text edits to all referencing compilation units

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fred merged commit 76b4e6a352 into main 2026-03-08 10:35:56 +00:00
fred deleted branch fix/39-ast-rename-fallback 2026-03-08 10:35:56 +00:00
Sign in to join this conversation.
No description provided.