Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
595439a
feat: cherry-pick method renaming with overload families
dragoi75 Apr 13, 2026
6e9c165
feat: add some changes in `configureCodeStyle` (cannot fully prevent …
Vladislav0Art Apr 16, 2026
0589f47
feat: parameterize `searchInComments` of `RenameProcessor` in all ren…
Vladislav0Art Apr 16, 2026
fc7393b
feat: print whitelisted annotations and log whether class/method is w…
Vladislav0Art Apr 17, 2026
206d3bf
feat: print filter-out reason for classes/methods
Vladislav0Art Apr 17, 2026
eccbd42
feat: filter out method overload families + check when super class is…
Vladislav0Art Apr 17, 2026
6f37f26
feat: remove Public API Guard filter (allow public API with no refs b…
Vladislav0Art Apr 17, 2026
3ed461f
feat: print override methods in log
Vladislav0Art Apr 17, 2026
0031db8
feat: separate static and instance methods in overload grouping and f…
Vladislav0Art Apr 17, 2026
4e1caa0
feat: log overload family details in `RenameMethodTransformation`
Vladislav0Art Apr 17, 2026
688d959
feat: group overload families by class and improve logging in `Rename…
Vladislav0Art Apr 17, 2026
19d74a1
feat: add annotation filtering mode (whitelist/blacklist) in `RenameM…
Vladislav0Art Apr 17, 2026
1006379
feat: add annotation filtering mode (whitelist/blacklist) in `RenameC…
Vladislav0Art Apr 17, 2026
52c75a1
feat: support default blacklist merging and improve blacklist logging…
Vladislav0Art Apr 17, 2026
36f9f57
feat: support default blacklist merging and improve blacklist logging…
Vladislav0Art Apr 17, 2026
2a70887
feat: update readme and agents md files
Vladislav0Art Apr 17, 2026
2754449
feat: extract variable filtering logic into a dedicated `passesVariab…
Vladislav0Art Apr 18, 2026
396e3ce
feat: add annotation filtering (blacklist mode) to `RenameVariableTra…
Vladislav0Art Apr 18, 2026
9424cda
feat: Add support for transforming `problem_statement` using transfor…
dragoi75 Apr 13, 2026
c040190
feat: delete transform_metamorphic_texts.py
Vladislav0Art Apr 23, 2026
c61e25c
feat: move `MoveFileIntoSuggestedDirectoryTransformation` to `structu…
Vladislav0Art Apr 25, 2026
6a19de2
feat: implement `ReorderClassMethodsTransformation` that reorders met…
Vladislav0Art Apr 25, 2026
7de90e1
refactor: remove `interfaceDesc` field from `MetamorphicTextTransform…
Vladislav0Art Apr 25, 2026
b5a2289
refactor: replace `memoryDir` with `memoryFilepath` across configurat…
Vladislav0Art Apr 25, 2026
374fa4b
feat: add `ParaphraseTextTransformer` for problem statement rewrites …
Vladislav0Art Apr 25, 2026
0788360
feat: add `BenchmarkInstanceIO` for JSON-based benchmark manipulation…
Vladislav0Art Apr 25, 2026
227859d
fix: ensure all documents are committed and saved to disk to avoid no…
Vladislav0Art Apr 26, 2026
c03351a
fix: ensure all documents are committed and saved after file moves to…
Vladislav0Art Apr 26, 2026
69252d7
fix: ensure modified files are snapshotted before renaming to prevent…
Vladislav0Art Apr 26, 2026
f13e69d
fix: improve override detection logic in `RenameMethodTransformation`
Vladislav0Art Apr 26, 2026
0078695
fix!: remove blocking `withReadAction` calls in `RenameMethodTransfor…
Vladislav0Art Apr 27, 2026
1c26f44
fix: commit and save all documents after transformations to ensure co…
Vladislav0Art Apr 27, 2026
8aecff5
fix: skip no-op file move suggestions in `MoveFileIntoSuggestedDirect…
Vladislav0Art Apr 29, 2026
5669456
fix: avoid hanging on failed suggestion in `MoveFileIntoSuggestedDire…
Vladislav0Art Apr 29, 2026
10a56fa
fix: remove unconditional `successfullyMoved.complete(false)`
Vladislav0Art Apr 29, 2026
5336890
fix: set `successfullyMoved` to false on found conflicts when tried f…
Vladislav0Art May 1, 2026
aaa62c6
feat: output succeeded/failed/skipped transformation ids
Vladislav0Art May 2, 2026
056721e
fix: handle non-physical, compiled, and anonymous classes in method r…
Vladislav0Art May 2, 2026
351be5b
refactor: don't skip anonymous classes from reordering methods
Vladislav0Art May 2, 2026
3b93d35
refactor: use `className` extension to handle anonymous class names
Vladislav0Art May 2, 2026
8227d59
fix: patch method-rename call sites missed by PSI overload resolver
Vladislav0Art May 3, 2026
0145f97
feat: pre-expand wildcard imports + enrich safety-net diagnostics
Vladislav0Art May 3, 2026
a913a4d
fix: skip patching method references inside annotation arguments
Vladislav0Art May 3, 2026
bc24944
fix: WildcardImportExpander attribution under static inheritance
Vladislav0Art May 3, 2026
2d21b70
fix: harden WildcardImportExpander against stale PSI element references
Vladislav0Art May 3, 2026
09a81ef
refactor: comment out use of `WildcardImportExpander`
Vladislav0Art May 3, 2026
e39845c
fix: add timeout handling for move operations to avoid indefinite hangs
Vladislav0Art May 4, 2026
8d7e4cf
feat: add agent for fixing import reordering/wildcard import removals…
Vladislav0Art May 4, 2026
b834e83
feat: update fix hunk agent defaults
Vladislav0Art May 4, 2026
e397ddf
refactor: clarify autonomy requirements and disallow confirmation pro…
Vladislav0Art May 4, 2026
1184d89
feat: update `HunkSpec` definition and prompting
Vladislav0Art May 4, 2026
c8c32b3
fix: annotate `FixImportHunks` with `ExperimentalSerializationApi` usage
Vladislav0Art May 4, 2026
3f478d1
feat: add filesystem verification and enhanced logging for `FixImport…
Vladislav0Art May 5, 2026
48af1e4
feat: add support for verifying and reverting `import_cross_hunk_move…
Vladislav0Art May 5, 2026
b38b923
feat: add output file support and enhanced batch processing in `FixHu…
Vladislav0Art May 5, 2026
be4ecfb
refactor: optimize imports
Vladislav0Art May 5, 2026
6743341
feat: don't exit with non-zero code for partial fixes in fix hunks agent
Vladislav0Art May 5, 2026
f16d823
fix: seal variable rename order and signature safety in `RenameVariab…
Vladislav0Art May 5, 2026
8ce617d
feat: add batching and retry logic for LLM calls in `RenameVariableTr…
Vladislav0Art May 5, 2026
f359ffe
fix: rename all overloaded overrides in `RenameMethodTransformation` …
Vladislav0Art May 6, 2026
e53f516
feat: add rich logging to `RenameMethodTransformation`
Vladislav0Art May 6, 2026
5eaae49
feat: log transformations application order before running them
Vladislav0Art May 6, 2026
5b35bc7
feat: deem file move transformation as skipped when no suggestions fit
Vladislav0Art May 6, 2026
1452ead
feat: forbid case-only change in renaming for classes in `RenameClass…
Vladislav0Art May 6, 2026
2ed7dbd
feat(`RenameVariableTransformation`): batchsize: 40, base retry backo…
Vladislav0Art May 7, 2026
5ad56d7
feat: add batching and retry logic for LLM calls in `RenameMethodTran…
Vladislav0Art May 7, 2026
36823e7
fix: avoid `IndexNotReadyException` in rename transformations by prom…
Vladislav0Art May 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 32 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,43 @@ CodeCocoon is an IntelliJ Platform plugin for **metamorphic testing** of Java pr
- Self-managed: `SelfManagedTransformation` (uses refactoring processors)

3. **Built-in transformations**:
- `rename-method-transformation` - Rename methods via LLM suggestions
- `rename-class-transformation` - Rename classes
- `rename-variable-transformation` - Rename fields/parameters/locals
- `rename-method-transformation` - Rename methods via LLM suggestions (supports annotation whitelist/blacklist)
- `rename-class-transformation` - Rename classes via LLM suggestions (supports annotation whitelist/blacklist)
- `rename-variable-transformation` - Rename fields/parameters/locals via LLM suggestions (supports annotation blacklist only)
- `move-file-into-suggested-directory-transformation/ai` - Move files (LLM suggests destination)
- `move-file-into-suggested-directory-transformation/config` - Move files (config specifies destination)
- `add-comment-transformation` - Example transformation (adds comment to file start)

4. **LLM Integration**: Uses Grazie/Koog to generate semantically similar names

5. **Memory System**: Caches LLM suggestions in `.codecocoon-memory/` to avoid redundant API calls

6. **Configuration**: `codecocoon.yml` in project root defines transformations and target files

7. **Important Threading Rules**:
5. **Memory System**:
- Persistent cache storing LLM suggestions in `.codecocoon-memory/<project-name>.json`
- Signature-based: Each element (class/method/variable/file) gets unique signature
- Controlled via `useMemory` and `generateWhenNotInMemory` config options
- Auto-saves on transformation completion via `PersistentMemory.use {}`

6. **Annotation Filtering**:
- **Methods/Classes**: Support both whitelist and blacklist modes
- **Whitelist mode**: Only rename elements WITH specified annotations
- **Blacklist mode** (recommended): Rename all EXCEPT those with specified annotations
- **Variables**: Support blacklist mode only (no whitelist)
- **`"_default"` keyword**: Merges 35-40+ framework annotations with custom ones
- Methods: 40+ annotations (Spring, JPA, JAX-RS, JUnit, etc.)
- Classes: 25+ annotations (JPA, Spring, JAX-RS, JAXB, etc.)
- Variables: 35+ annotations (JPA, Jackson, JAXB, Spring, validation, CDI, etc.)
- Warning logged if blacklist used without `"_default"`

7. **Configuration**: `codecocoon.yml` in project root defines transformations and target files

8. **Important Threading Rules**:
- PSI reads require `readAction { }` or `IntelliJAwareTransformation.withReadAction { }`
- PSI writes require `writeCommandAction { }` or use self-managed refactoring processors

9. **Import Optimization Prevention**: Code style settings configured to prevent wildcard imports and minimize automatic import modifications
- ✅ Prevents wildcard imports (`import package.*`)
- ✅ Forces single class imports
- ❌ Cannot prevent unused import removal (IntelliJ limitation)

## Common Tasks

- **Adding a transformation**: Implement `IntelliJAwareTransformation`, register in `TransformationRegistry.kt`
Expand All @@ -46,10 +67,13 @@ CodeCocoon is an IntelliJ Platform plugin for **metamorphic testing** of Java pr
## When to Consult CLAUDE.md

Refer to [`CLAUDE.md`](./CLAUDE.md) for:
- **Import optimization prevention** - Detailed explanation of settings and limitations
- Detailed architecture explanations
- PSI utilities and helper functions
- Configuration schema and examples
- Transformation implementation details
- Memory system internals (`PsiSignatureGenerator`, signature format)
- Annotation filtering implementation (whitelist/blacklist logic)
- Error handling patterns
- File structure overview
- Dependencies and testing
Expand Down
189 changes: 173 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,179 @@ transformations:
- "src/main"
```

## Built-in transformations

- Rename Method (id: `rename-method-transformation`)
- Renames Java methods to an LLM-suggested, semantically similar name and updates usages/overrides.
- Skips: overrides, tests, interface methods extending library interfaces, annotated methods, constructors, toString/get*/set*/is*, public methods with no refs, and methods referenced from non-Java/Kotlin files.
- Rename Class (id: `rename-class-transformation`)
- Renames Java classes to an LLM-suggested, semantically similar name and updates usages/overrides.
- Skips: classes referenced from non-Java files, test class names and annotated classes.
- Rename Variable (id: `rename-variable-transformation`)
- Renames Java variables to an LLM-suggested, semantically similar name and updates usages.
- Skips: variables in test classes, enums, and those declared in library-files.
- Move File Into Directory Suggested By AI (id: `move-file-into-suggested-directory-transformation/ai`)
- Moves a Java file into another directory suggested by an LLM based on the file content.
- Move File Into Directory From Config (id: `move-file-into-suggested-directory-transformation/config`)
- Moves a Java file into a directory provided in the config under `destination` entry.
- The directory MUST be within the project BUT may be either new or existing.
## Memory System

CodeCocoon includes a **persistent memory system** that caches LLM-generated suggestions to avoid redundant API calls and ensure consistency across runs. Memory is stored in `.codecocoon-memory/` directory as JSON files, one per project.

**Key features:**
- Signature-based caching: Each renamed element (class/method/variable) gets a unique signature
- Automatic persistence: Memory is saved automatically when transformations complete
- Reusability: Run the same transformation multiple times without re-querying the LLM
- Optional generation: Configure whether to generate new suggestions for missing entries

All renaming transformations support memory via `useMemory` and `generateWhenNotInMemory` config options.

## Built-in Transformations

### 1. Rename Method (`rename-method-transformation`)

Renames Java methods to LLM-suggested, semantically similar names and updates all usages/overrides. Processes methods in **overload families** to ensure consistency.

**Filters (methods are skipped if):**
- Override super methods
- In test sources
- In interfaces extending library interfaces
- Belong to library classes
- Are constructors or Object methods (equals, hashCode, toString, etc.)
- Match excluded patterns (toString, get*, set*, is*)
- Have no public references
- Referenced from non-Java/Kotlin files
- Fail annotation filter (whitelist/blacklist mode)

**Configuration:**
```yaml
- id: "rename-method-transformation"
config:
# Memory configuration
useMemory: true # Optional, default: false. Use cached suggestions
generateWhenNotInMemory: true # Optional, default: false. Generate if not cached
searchInComments: false # Optional, default: false. Rename in comments too

# Annotation filtering (choose whitelist OR blacklist mode)
annotationFilterMode: "blacklist" # Optional, default: "blacklist" if blacklistedAnnotations non-empty, else "whitelist"

# Blacklist mode (recommended): Rename all methods EXCEPT those with these annotations
blacklistedAnnotations:
- "_default" # Special keyword: includes 40+ framework annotations (Spring, JPA, JAX-RS, JUnit, etc.)
- "MyCustomAnnotation" # Add your own annotations

# Whitelist mode: Only rename methods WITH these annotations
whitelistedAnnotations:
- "SuppressWarnings"
- "Deprecated"
```

**Annotation filter modes:**
- **Blacklist** (recommended): Rename everything EXCEPT framework-managed methods. Use `"_default"` to include all standard framework annotations (Spring `@RequestMapping`, JPA `@PrePersist`, JAX-RS `@GET`/`@POST`, JUnit `@Test`/`@BeforeEach`, etc.) plus custom ones.
- **Whitelist**: Only rename methods with specific annotations. Empty whitelist = only non-annotated methods.
- **⚠ Warning**: Omitting `"_default"` in blacklist mode will NOT exclude framework annotations automatically.

---

### 2. Rename Class (`rename-class-transformation`)

Renames Java classes to LLM-suggested, semantically similar names and updates all usages.

**Filters (classes are skipped if):**
- Referenced from non-Java files
- In test sources
- Class name is null or ≤1 character
- Fail annotation filter (whitelist/blacklist mode)

**Configuration:**
```yaml
- id: "rename-class-transformation"
config:
# Memory configuration
useMemory: true # Optional, default: false
generateWhenNotInMemory: true # Optional, default: false
searchInComments: false # Optional, default: false

# Annotation filtering (choose whitelist OR blacklist mode)
annotationFilterMode: "blacklist" # Optional, default: "blacklist" if blacklistedAnnotations non-empty, else "whitelist"

# Blacklist mode (recommended): Rename all classes EXCEPT those with these annotations
blacklistedAnnotations:
- "_default" # Special keyword: includes 25+ framework annotations (JPA, Spring, JAX-RS, JAXB, etc.)
- "MyCustomAnnotation"

# Whitelist mode: Only rename classes WITH these annotations
whitelistedAnnotations:
- "Deprecated"
```

**Annotation filter modes:** Same as rename-method (see above). Default blacklist includes JPA `@Entity`/`@Table`, Spring `@Component`/`@Service`/`@Controller`, JAX-RS `@Path`, JAXB `@XmlRootElement`, etc.

---

### 3. Rename Variable (`rename-variable-transformation`)

Renames Java variables (fields, parameters, locals) to LLM-suggested, semantically similar names and updates all usages.

**Filters (variables are skipped if):**
- In test sources
- Enum constants
- Fail annotation filter (blacklist mode only - no whitelist support)
- Declared in library/compiled code
- Public/protected fields (to avoid breaking external consumers)

**Configuration:**
```yaml
- id: "rename-variable-transformation"
config:
# Memory configuration
useMemory: true # Optional, default: false
generateWhenNotInMemory: true # Optional, default: false
searchInComments: false # Optional, default: false

# Annotation blacklist filtering (no whitelist support)
blacklistedAnnotations:
- "_default" # Special keyword: includes 35+ framework annotations (JPA, Jackson, JAXB, Spring, validation, etc.)
- "MyCustomAnnotation" # Add your own annotations
```

**Annotation filtering (blacklist mode only):**
- **Blacklist mode**: Rename all variables EXCEPT those with specified annotations. Use `"_default"` to include JPA (`@Column`/`@Id`/`@JoinColumn`), Jackson (`@JsonProperty`), JAXB (`@XmlElement`/`@XmlAttribute`), Spring (`@Value`/`@Autowired`), validation (`@NotNull`/`@Size`/`@Email`), and CDI (`@Inject`) annotations.
- **⚠ Warning**: Omitting `"_default"` in blacklist will NOT exclude framework annotations automatically.
- **Note**: Variables do NOT support whitelist mode (methods/classes only).

---

### 4. Move File (AI-Suggested) (`move-file-into-suggested-directory-transformation/ai`)

Moves Java files into directories suggested by an LLM based on file content and project structure.

**Filters (files are skipped if):**
- Not a Java file
- In test sources
- Contains package-local classes used by other files (would break compilation)

**Configuration:**
```yaml
- id: "move-file-into-suggested-directory-transformation/ai"
config:
useMemory: true # Optional, default: null (no memory)
generateWhenNotInMemory: true # Optional, default: false
maxAgentIterations: 60 # Optional, default: 50. Max LLM iterations for directory search
```

---

### 5. Move File (Config-Specified) (`move-file-into-suggested-directory-transformation/config`)

Moves Java files into a specific directory provided in the configuration.

**Configuration:**
```yaml
- id: "move-file-into-suggested-directory-transformation/config"
config:
destination: "src/main/java/services/impl" # Required. Absolute or relative to project root. Can be new or existing.
```

**Note:** This transformation does NOT use memory (destination is explicit).

---

### 6. Add Comment (`add-comment-transformation`)

**Example transformation** that adds a comment at the beginning of a file. Not for production use.

**Configuration:**
```yaml
- id: "add-comment-transformation"
config:
message: "This file was transformed" # Required. Comment text (without "//" prefix)
```

## Template ToDo list
- [x] Create a new [IntelliJ Platform Plugin Template][template] project.
Expand Down
69 changes: 69 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -235,5 +235,74 @@ intellijPlatformTesting {
)
}
}

// Custom task for metamorphic text transformation (runs within IntelliJ platform).
// Reads a benchmark-record JSON file, applies rename/move sync block by block,
// and writes a same-schema JSON file.
register("transformMetamorphicTexts") {
task {
args(listOf("transform-texts"))

val memoryFile = project.findProperty("memoryFile") as? String ?: ""
val inputFile = project.findProperty("inputFile") as? String ?: ""
val outputFile = project.findProperty("outputFile") as? String ?: ""

jvmArgs(
"-Xmx4G",
"-Djava.awt.headless=true",
"--add-exports", "java.base/jdk.internal.vm=ALL-UNNAMED",
"-Dtransform.memoryFile=${memoryFile}",
"-Dtransform.inputFile=${inputFile}",
"-Dtransform.outputFile=${outputFile}",
)
}
}

// Custom task for reverting unwanted import-hunks via a Koog agent.
// Reads a hunks JSON file (repo_root + list of import_reorder /
// wildcard_import_removal hunks) and runs an agent that surgically
// reverts each hunk in the corresponding Java source file.
// Usage: ./gradlew agentFixHunks -Pinput=/abs/path/to/hunks.json
// [-PbatchSize=5] [-PmaxAgentIterations=60]
register("agentFixHunks") {
task {
args(listOf("agent-fix-hunks"))

val inputFile = project.findProperty("input") as? String ?: ""
val outputFile = project.findProperty("output") as? String ?: ""
val batchSize = project.findProperty("batchSize") as? String ?: ""
val maxAgentIterations = project.findProperty("maxAgentIterations") as? String ?: ""

jvmArgs(
"-Xmx4G",
"-Djava.awt.headless=true",
"--add-exports", "java.base/jdk.internal.vm=ALL-UNNAMED",
"-Dfix.inputFile=${inputFile}",
"-Dfix.outputFile=${outputFile}",
"-Dfix.batchSize=${batchSize}",
"-Dfix.maxAgentIterations=${maxAgentIterations}",
)
}
}

// Custom task for paraphrasing benchmark-record texts (semantic-preserving rewrite).
// Reads a benchmark-record JSON file, paraphrases each {title, body} block,
// and writes a same-schema JSON file.
register("rewriteProblemStatement") {
task {
args(listOf("rewrite-problem-statement"))

val inputFile = project.findProperty("inputFile") as? String ?: ""
val outputFile = project.findProperty("outputFile") as? String ?: ""

jvmArgs(
"-Xmx4G",
"-Djava.awt.headless=true",
"--add-exports", "java.base/jdk.internal.vm=ALL-UNNAMED",
"-Drewrite.inputFile=${inputFile}",
"-Drewrite.outputFile=${outputFile}",
)
}
}
}
}
10 changes: 5 additions & 5 deletions codecocoon.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ projectRoot: "/path/to/project/root"
# Optional: limit transformations to these files (relative to the root). Leave empty to target the entire project
files: []

# Optional: directory where memory files are stored (for deterministic rename transformations)
# If not specified, defaults to '.codecocoon-memory' in the same directory as this config file
# Optional: full path to the JSON memory file (for deterministic rename transformations)
# If not specified, defaults to '.codecocoon-memory.json' in the same directory as this config file
# Can be:
# - Absolute path: "/absolute/path/to/memory"
# - Relative path: "my-memory-dir" (relative to this config file's directory)
memoryDir: ".codecocoon-memory"
# - Absolute path: "/absolute/path/to/memory.json"
# - Relative path: "my-memory.json" (relative to this config file's directory)
memoryFilepath: ".codecocoon-memory.json"

# The transformation pipeline. Order matters. Each transformation has:
# - id: unique identifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package com.github.pderakhshanfar.codecocoonplugin.memory
* Use with `.use {}` blocks to guarantee data is saved:
*
* ```kotlin
* PersistentMemory(projectName, memoryDir).use { memory ->
* PersistentMemory(memoryFilepath).use { memory ->
* memory.put("key", "value")
* // memory.save() called automatically on close
* }
Expand Down
Loading
Loading