|
| 1 | +--- |
| 2 | +name: kotlin-tooling-java-to-kotlin |
| 3 | +description: > |
| 4 | + Use when converting Java source files to idiomatic Kotlin, when user mentions |
| 5 | + "java to kotlin", "j2k", "convert java", "migrate java to kotlin", or when |
| 6 | + working with .java files that need to become .kt files. Handles framework-aware |
| 7 | + conversion for Spring, Lombok, Hibernate, Jackson, Micronaut, Quarkus, Dagger/Hilt, |
| 8 | + RxJava, JUnit, Guice, Retrofit, and Mockito. |
| 9 | +license: Apache-2.0 |
| 10 | +metadata: |
| 11 | + author: JetBrains |
| 12 | + version: "1.0.0" |
| 13 | +--- |
| 14 | + |
| 15 | +# Java to Kotlin Conversion |
| 16 | + |
| 17 | +Convert Java source files to idiomatic Kotlin using a disciplined 4-step conversion |
| 18 | +methodology with 5 invariants checked at each step. Supports framework-aware conversion |
| 19 | +that handles annotation site targets, library idioms, and API preservation. |
| 20 | + |
| 21 | +## Workflow |
| 22 | + |
| 23 | +```dot |
| 24 | +digraph j2k_workflow { |
| 25 | + rankdir=TB; |
| 26 | + "User specifies files" -> "Step 0: Scan & Detect"; |
| 27 | + "Step 0: Scan & Detect" -> "Load framework guides"; |
| 28 | + "Load framework guides" -> "Step 1: Convert"; |
| 29 | + "Step 1: Convert" -> "Step 2: Write .kt"; |
| 30 | + "Step 2: Write .kt" -> "Step 3: Git rename"; |
| 31 | + "Step 3: Git rename" -> "Step 4: Verify"; |
| 32 | + "Step 4: Verify" -> "Next file?" [label="pass"]; |
| 33 | + "Step 4: Verify" -> "Fix issues" [label="fail"]; |
| 34 | + "Fix issues" -> "Step 1: Convert"; |
| 35 | + "Next file?" -> "Step 0: Scan & Detect" [label="batch: yes"]; |
| 36 | + "Next file?" -> "Done" [label="no more files"]; |
| 37 | +} |
| 38 | +``` |
| 39 | + |
| 40 | +## Step 0: Scan & Detect Frameworks |
| 41 | + |
| 42 | +Before converting, scan the Java file's import statements to detect which frameworks |
| 43 | +are in use. Load ONLY the matching framework reference files to keep context focused. |
| 44 | + |
| 45 | +### Framework Detection Table |
| 46 | + |
| 47 | +| Import prefix | Framework guide | |
| 48 | +|---|---| |
| 49 | +| `org.springframework.*` | [SPRING.md](references/frameworks/SPRING.md) | |
| 50 | +| `lombok.*` | [LOMBOK.md](references/frameworks/LOMBOK.md) | |
| 51 | +| `javax.persistence.*`, `jakarta.persistence.*`, `org.hibernate.*` | [HIBERNATE.md](references/frameworks/HIBERNATE.md) | |
| 52 | +| `com.fasterxml.jackson.*` | [JACKSON.md](references/frameworks/JACKSON.md) | |
| 53 | +| `io.micronaut.*` | [MICRONAUT.md](references/frameworks/MICRONAUT.md) | |
| 54 | +| `io.quarkus.*`, `javax.enterprise.*`, `jakarta.enterprise.*` | [QUARKUS.md](references/frameworks/QUARKUS.md) | |
| 55 | +| `dagger.*`, `dagger.hilt.*` | [DAGGER-HILT.md](references/frameworks/DAGGER-HILT.md) | |
| 56 | +| `io.reactivex.*`, `rx.*` | [RXJAVA.md](references/frameworks/RXJAVA.md) | |
| 57 | +| `org.junit.*`, `org.testng.*` | [JUNIT.md](references/frameworks/JUNIT.md) | |
| 58 | +| `com.google.inject.*` | [GUICE.md](references/frameworks/GUICE.md) | |
| 59 | +| `retrofit2.*`, `okhttp3.*` | [RETROFIT.md](references/frameworks/RETROFIT.md) | |
| 60 | +| `org.mockito.*` | [MOCKITO.md](references/frameworks/MOCKITO.md) | |
| 61 | + |
| 62 | +If `javax.inject.*` is detected, check for Dagger/Hilt vs Guice by looking for other |
| 63 | +imports from those frameworks. If ambiguous, load both guides. |
| 64 | + |
| 65 | +## Step 1: Convert |
| 66 | + |
| 67 | +Apply the conversion methodology from [CONVERSION-METHODOLOGY.md](references/CONVERSION-METHODOLOGY.md). |
| 68 | + |
| 69 | +This is a 4-step chain-of-thought process: |
| 70 | +1. **Faithful 1:1 translation** — exact semantics preserved |
| 71 | +2. **Nullability & mutability audit** — val/var, nullable types |
| 72 | +3. **Collection type conversion** — Java mutable → Kotlin types |
| 73 | +4. **Idiomatic transformations** — properties, string templates, lambdas |
| 74 | + |
| 75 | +Five invariants are checked after each step. If any invariant is violated, revert |
| 76 | +to the previous step and redo. |
| 77 | + |
| 78 | +Apply any loaded framework-specific guidance during step 4 (idiomatic transformations). |
| 79 | + |
| 80 | +## Step 2: Write Output |
| 81 | + |
| 82 | +Write the converted Kotlin code to a `.kt` file with the same name as the original |
| 83 | +Java file, in the same directory. |
| 84 | + |
| 85 | +## Step 3: Preserve Git History |
| 86 | + |
| 87 | +To preserve `git blame` history, use a two-phase approach: |
| 88 | + |
| 89 | +```bash |
| 90 | +# Phase 1: Rename (creates rename tracking) |
| 91 | +git mv src/main/java/com/example/Foo.java src/main/kotlin/com/example/Foo.kt |
| 92 | +git commit -m "Rename Foo.java to Foo.kt" |
| 93 | + |
| 94 | +# Phase 2: Replace content (tracked as modification, not new file) |
| 95 | +# Write the converted Kotlin content to Foo.kt |
| 96 | +git commit -m "Convert Foo from Java to Kotlin" |
| 97 | +``` |
| 98 | + |
| 99 | +If the project keeps Java and Kotlin in the same source root (e.g., `src/main/java/`), |
| 100 | +rename in place: |
| 101 | + |
| 102 | +```bash |
| 103 | +git mv src/main/java/com/example/Foo.java src/main/java/com/example/Foo.kt |
| 104 | +``` |
| 105 | + |
| 106 | +If the project does not use Git, simply write the `.kt` file and delete the `.java` file. |
| 107 | + |
| 108 | +## Step 4: Verify |
| 109 | + |
| 110 | +After conversion, verify using [checklist.md](assets/checklist.md): |
| 111 | +- Attempt to compile the converted file |
| 112 | +- Run existing tests |
| 113 | +- Check annotation site targets |
| 114 | +- Confirm no behavioral changes |
| 115 | + |
| 116 | +## Batch Conversion |
| 117 | + |
| 118 | +When converting multiple files (a directory or package): |
| 119 | + |
| 120 | +1. **List all `.java` files** in the target scope |
| 121 | +2. **Sort by dependency order** — convert leaf dependencies first (files that don't |
| 122 | + import other files in the conversion set), then work up to files that depend on them |
| 123 | +3. **Convert one file at a time** — apply the full workflow (steps 0-4) for each |
| 124 | +4. **Track progress** — report which files are done, which remain |
| 125 | +5. **Handle cross-references** — after converting a file, update imports in other Java |
| 126 | + files if needed (e.g., if a class moved packages) |
| 127 | + |
| 128 | +For large batches, consider converting in packages (bottom-up from leaf packages). |
| 129 | + |
| 130 | +## Common Pitfalls |
| 131 | + |
| 132 | +See [KNOWN-ISSUES.md](references/KNOWN-ISSUES.md) for: |
| 133 | +- Kotlin keyword conflicts (`when`, `in`, `is`, `object`) |
| 134 | +- SAM conversion ambiguity |
| 135 | +- Platform types from Java interop |
| 136 | +- `@JvmStatic` / `@JvmField` / `@JvmOverloads` usage |
| 137 | +- Checked exceptions and `@Throws` |
| 138 | +- Wildcard generics → Kotlin variance |
0 commit comments