Improve transformation robustness, filtering, and structural operations#48
Conversation
…unused import optimization) Left optimizations: 1. Import of a class from the same package. 2. Unused import. Both imports above are removed when references are updated in a file that uses a renamed class/method.
…aming transformations
… `java.lang.Object` (don't filter)
…ilter overrides before grouping
…MethodTransformation`
…ethodTransformation`
…lassTransformation`
… in `RenameMethodTransformation`
… in `RenameClassTransformation`
…leFilters` method in `RenameVariableTransformation`
…nsformation` and update documentation
…hods in reverse-alphabetical order
…er` and related components
…ion and persistent memory components
…and CLI support via `RewriteProblemStatementStarter`
… and integrate with CLI starters
- Introduced `BenchmarkInstanceIO` for JSON parsing and transformation of benchmark records.
- Updated `RewriteProblemStatementStarter` and `TransformTextsStarter` to process `{title, body}` pairs and `resolved_issues`.
- Added `TextBlock` data class to support coherent updates across textual fields.
- Enhanced Gradle tasks `rewriteProblemStatement` and `transformMetamorphicTexts` with improved input/output handling.
…n-deterministic behavior during project close and renaming operations
… prevent inconsistent state during subsequent operations
… inconsistent behavior across transformations
Changes: - Skip override check for static methods to avoid false positives caused by unrelated name matches. - Ensure instance methods are genuine overrides by verifying super-methods are within the declared inheritance chain.
…` transformations in `FixImportHunks`
…leTransformation` to avoid additional modifications in base+test_patch run
…ansformation` with exponential backoff and robustness enhancements
…by explicitly attaching transitive overriders to the rename processor `RenameProcessor`'s implicit override expansion via `RenameJavaMethodProcessor.prepareRenaming` + `OverridingMethodsSearch` silently dropped sibling overloads' overriders when multiple same-name overloads were renamed to the same target name through a single processor — only the seed overload's overrider got renamed, the others kept the old name. The post-rename safety net `verifyAndPatchMissedCallSites` only inspected `PsiMethodCallExpression` nodes, never `PsiMethod` declarations, so missed override definitions were invisible to it. Reproducer: an abstract base `A` with `write(JsonValue)` + `write(String)` and `B extends A` overriding both. After renaming `A.write` to `A.writeTo`, `B.write(JsonValue)` followed but `B.write(String)` was left dangling with the old name. In `tryRenameMethodFamily`, after the existing overload-sibling `addElement` loop, enumerate transitive overriders via `OverridingMethodsSearch.search(method, checkDeep = true)` for every family method and attach each (skipping family members already added and overriders in libraries) as a first-class rename target. Adding them explicitly forces the same rename path that already works for the seed; when implicit expansion would have caught them anyway, it is a no-op via `myAllRenames` dedup, so the change is backward compatible.
…sformation` with exponential backoff Mirror the robust LLM call path already used in `RenameVariableTransformation`: each file now issues a single batched LLM request listing every overload family (chunked at LLM_BATCH_SIZE=20 to keep prompt size manageable since each entry embeds a method body), with up to LLM_MAX_ATTEMPTS=3 retries per batch and exponential backoff (4s → 8s, capped at 12s) on transient failures. `ProcessCanceledException` is rethrown per IntelliJ contract; permanent failures return an empty list so affected families are skipped (no rename, no memory write) without failing the whole transformation, and other batches and other files keep progressing. Wire format: replace `MethodNameSuggestions(suggestions)` with `MethodFamilyRenaming(familyKey, suggestions)` + `MethodRenameSuggestions(renamings)`. Each overload family carries a precomputed `familyKey` of the form `<classFqn>#<methodName>[<static|instance>]` so the model can echo it back per entry — the `[static]/[instance]` tag prevents same-name static/instance siblings in the same class from colliding in the batch. `generateRenamesForFamilies` now matches results back via `familyKey == family.familyKey` and pipes them through the unchanged `buildSuggestionList` helper. `extractRenamesFromMemoryForFamilies`, `tryRenameMethodFamily`, the overrider-attachment / verify-and-patch / rich-logging code, and the memory key format are untouched.
…oting discovery reads to smart-mode
`RenameProcessor.run()` + `commitAllDocuments()` + `saveAllDocuments()`
drops the IDE back into dumb mode while the stub index is recomputed,
so the next file's transformation can land mid-reindex. Any read action
that resolves a super-class hierarchy then hits the stub index and
throws. Reproduced on Multi-SWE-Bench:
- `RenameClassTransformation` — `psiClass.allFields` walks `MemberCache`
→ `getSupers()` → `findSpecialSuperClass()` → `JavaFullClassNameIndex`.
- `RenameMethodTransformation` — `method.findSuperMethods()` builds a
hierarchical signature → `getSuperTypes()` →
`findClass(java.lang.Object)`.
Per the `IndexNotReadyException` Javadoc, promote the topmost read
action to smart mode. Add a `withSmartReadAction(project) { ... }`
companion helper on `IntelliJAwareTransformation` (mirrors
`withReadAction` but uses suspending `smartReadAction(project)`, so the
block waits for index readiness before running) and use it at the
discovery sites:
- `RenameClassTransformation.apply` — the `findAllValidClasses(...)`
wrap (also covers the per-class `ReferencesSearch.search(cls)` and
`fileIndex.isInTestSourceContent(...)` calls inside).
- `RenameClassTransformation.generateNewClassNames` — the PSI-context
extraction (covers `psiClass.allFields` — the exact line that threw).
- `RenameMethodTransformation.apply` — the
`findAllValidMethodFamilies(...)` wrap (covers `findSuperMethods()`,
`psiClass.supers`, and `ReferencesSearch.search(method)` inside the
override-filter walk).
`tryRenameClassAndUsages` and `tryRenameMethodFamily` keep using plain
`withReadAction { ... }` — they run after the discovery walk (the
natural index-settling point) and adding `runBlocking` inside their
existing `invokeAndWait` envelopes risks deadlocks. Cancellation
contract preserved: `smartReadAction` honours `ProcessCanceledException`
propagation.
|
Copilot given the changes in this PR create a description and a title for it |
Proposed PR title: Proposed PR description: Reference commit: |
Qodana Community for JVM3 new problems were found
💡 Qodana analysis was run in the pull request mode: only the changed files were checked View the detailed Qodana reportTo be able to view the detailed Qodana report, you can either:
To get - name: 'Qodana Scan'
uses: JetBrains/qodana-action@v2025.1.1
with:
upload-result: trueContact Qodana teamContact us at qodana-support@jetbrains.com
|
Andrei Drăgoi (dragoi75)
left a comment
There was a problem hiding this comment.
LGTM 👍
In interest of both our time, I did not add any nitpicks. But thank you for all the changes!
You can merge
Should we also close #47 ?
Description
Introduced changes:
withSmartReadAction: similar towithReadActionhelper that awaits the smart mode execution context (I had some scenarios where it mattered in Multi-SWE-Bench) + used it in the transformations.