Development¶
This guide covers local development, testing, versioning, and publishing for kotlin-acyclic.
Prerequisites¶
- JDK 21 for the annotations library, compiler plugin, and Gradle plugin
- JDK 17-compatible environment for the IntelliJ plugin target
- the checked-in Gradle wrapper
The main build settings are pinned in:
Gradle Project Names¶
Gradle project names:
:kotlin-acyclic:kotlin-acyclic-plugin:kotlin-acyclic-gradle-plugin:kotlin-acyclic-ij-plugin
The annotations library lives under library/, but its Gradle project name is :kotlin-acyclic.
Common Commands¶
From the repository root:
./gradlew build
./gradlew projects
./gradlew :kotlin-acyclic:compileKotlinMetadata
./gradlew :kotlin-acyclic-plugin:test
./gradlew :kotlin-acyclic-gradle-plugin:test
./gradlew :kotlin-acyclic-ij-plugin:test
Targeted examples:
./gradlew :kotlin-acyclic-plugin:test --tests 'one.wabbit.acyclic.CompilerIntegrationTest'
./gradlew :kotlin-acyclic-gradle-plugin:test --tests 'one.wabbit.acyclic.gradle.AcyclicGradlePluginTest'
./gradlew :kotlin-acyclic-ij-plugin:test --tests 'one.wabbit.acyclic.idea.AcyclicCompilerPluginDetectorTest'
Testing Against Different Kotlin Versions¶
The Kotlin publish/test matrix is driven by:
defaultKotlinVersionsupportedKotlinVersions
Both are defined in gradle.properties.
To run the compiler plugin against a specific supported Kotlin line:
./gradlew -PkotlinVersion=2.3.10 :kotlin-acyclic-plugin:test
./gradlew -PkotlinVersion=2.4.0-Beta1 :kotlin-acyclic-plugin:test
The same override works for the Gradle and IntelliJ modules when you need Kotlin-line-specific verification.
Local Publishing¶
For local downstream testing, publish the pieces you need:
./gradlew :kotlin-acyclic:publishToMavenLocal
./gradlew -PkotlinVersion=2.3.10 :kotlin-acyclic-plugin:publishToMavenLocal
./gradlew :kotlin-acyclic-gradle-plugin:publishToMavenLocal
If the downstream project also needs IDE support artifacts, publish the IntelliJ plugin separately through its own packaging flow.
For local consumer wiring examples, the Gradle plugin tests are a useful reference:
Composite-Build Consumer Testing¶
Before publication, downstream Gradle repos should use both forms of composite-build wiring:
pluginManagement {
includeBuild("../kotlin-acyclic")
}
includeBuild("../kotlin-acyclic")
Both are required:
pluginManagement.includeBuild(...)resolves the Gradle plugin ID- root
includeBuild(...)lets Gradle substitute the annotations and compiler-plugin artifacts
This distinction is easy to forget and is worth keeping explicit in local consumer tests.
For a local downstream setup, a practical flow is:
- use both
pluginManagement.includeBuild(...)and rootincludeBuild(...) - publish the annotations library to Maven Local when the consumer needs normal dependency resolution
- publish the Kotlin-line-specific compiler plugin variant needed by that consumer
- use the same
-PkotlinVersion=...line locally that the downstream build expects
Versioning Model¶
Base version:
projectVersioningradle.properties
Kotlin matrix:
supportedKotlinVersionsingradle.properties
Published versions:
- annotations library publishes exactly
projectVersion - Gradle plugin publishes exactly
projectVersion - compiler plugin publishes
<projectVersion>-kotlin-<kotlinVersion>
The Kotlin suffix matters because compiler-plugin binaries are tied to the Kotlin compiler APIs they were built against.
Release And Snapshot Workflows¶
GitHub workflows:
Release/snapshot behavior is driven from repo configuration rather than hardcoded per compiler line. The workflow fanout reads the Kotlin matrix from supportedKotlinVersions.
Where To Change What¶
Change rule semantics¶
Start in:
compiler-plugin/src/main/kotlin/one/wabbit/acyclic/AcyclicFileAnalysis.ktcompiler-plugin/src/main/kotlin/one/wabbit/acyclic/AcyclicDeclarationGraph.ktcompiler-plugin/src/main/kotlin/one/wabbit/acyclic/AcyclicDependencyGraph.ktcompiler-plugin/src/test/kotlin/one/wabbit/acyclic/CompilerIntegrationTest.kt
The compiler integration tests compile real Kotlin snippets through the actual compiler pipeline. They are the main confidence source for semantics changes.
Change source-level controls¶
Start in:
Be careful with:
- annotation targets
- annotation retention
- precedence wording
These choices directly affect compiler behavior and public user docs.
Change Gradle wiring¶
Start in:
gradle-plugin/src/main/kotlin/one/wabbit/acyclic/gradle/AcyclicGradlePlugin.kt- the shared
compilerPluginArtifactVersion(...)helper from the includedkotlin-gradle-plugin-commonbuild - Gradle plugin unit/functional tests under
gradle-plugin/src/test/kotlin/
Change IntelliJ behavior¶
Start in:
ij-plugin/src/main/kotlin/one/wabbit/acyclic/idea/AcyclicCompilerPluginDetector.ktij-plugin/src/main/kotlin/one/wabbit/acyclic/idea/AcyclicIdeSupportCoordinator.ktij-plugin/src/main/kotlin/one/wabbit/acyclic/idea/AcyclicIdeSupportActivity.kt
Documentation And Backlog¶
The most useful repo docs during development are:
- user-guide.md
- api-reference.md
- troubleshooting.md
- migration.md
- ARCHITECTURE.md
compiler-plugin/GOAL.mdcompiler-plugin/WALKTHROUGH.mdcompiler-plugin/PLAN.md
Suggested Reading Order¶
If you are new to the codebase, this order usually works well: