Skip to content

Conversation

@skydoves
Copy link
Owner

@skydoves skydoves commented Nov 17, 2025

Shadow kotlinx.serialization to the compiler plugin. (#48)

Summary by CodeRabbit

  • Dependencies

    • Bumped kotlinxSerialization 1.8.0 → 1.9.0
    • Added Shadow plugin (8.1.1) to enable bundling of dependencies
  • Build Improvements

    • Compiler artifact now embeds runtime dependencies for improved portability and simpler distribution
    • Enabled Kotlin explicit API mode to enforce clearer public API boundaries
  • Documentation

    • Clarified build/plugin comments about runtime inclusion and serialization embedding

@skydoves skydoves self-assigned this Nov 17, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 17, 2025

Walkthrough

Adds the Shadow plugin and config to produce a fat compiler JAR (including kotlinx.serialization), bumps kotlinx.serialization to 1.9.0, enables Kotlin explicit API mode in the compiler build, and updates related plugin comments.

Changes

Cohort / File(s) Summary
Dependency versions & plugin catalog
gradle/libs.versions.toml
Bump kotlinxSerialization from 1.8.0 to 1.9.0; add shadow = "8.1.1" in [versions]; add shadow entries under [libraries] and [plugins].
Compiler build / packaging
stability-compiler/build.gradle.kts
Enable explicitApi(); apply alias(libs.plugins.shadow); add and configure shadowJar (archiveClassifier "all", runtimeClasspath sources, exclude certain META-INF entries); make jar depend on shadowJar and copy shadow output over standard jar.
Plugin comments / docs
stability-gradle/src/main/kotlin/.../StabilityAnalyzerGradlePlugin.kt
Update comments in addRuntimeToCompilerClasspath to state runtime is added to all compiler plugin classpath configurations and note kotlinx.serialization is embedded via the Shadow plugin.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Dev as Developer / CI
    participant Gradle as Gradle
    participant Shadow as Shadow Plugin (shadowJar)
    participant Jar as jar task
    note right of Shadow `#f0f0f0`: Embeds runtime deps\n(including kotlinx.serialization)
    Dev->>Gradle: run build
    Gradle->>Shadow: execute shadowJar (collect runtimeClasspath, create *-all.jar)
    Shadow-->>Gradle: produces shadow JAR
    Gradle->>Jar: run jar (dependsOn shadowJar)
    Jar->>Gradle: copy shadow JAR contents -> standard jar (replace)
    Gradle-->>Dev: final compiler JAR includes embedded serialization
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Inspect shadowJar exclusions and relocation (K/N compatibility).
  • Verify jar replacement logic (copying shadow contents into standard jar) and published artifact behavior.
  • Confirm no API visibility regressions after explicitApi() enabling and serialization version compatibility.

Possibly related PRs

Poem

🐰 Shadows stitched into a tiny jar,

I hop with bits of serial lore,
Explicit APIs line up in rows,
Bundled snug where the compiler goes,
A tiny rabbit hums: build once, explore.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is minimal and lacks the required sections from the template (Goal, Implementation details, Examples, and verification steps like spotlessApply and apiDump). Expand the description to include the Goal section explaining why shadowing is necessary, Implementation details section explaining the approach, and verify that spotlessApply and apiDump commands have been run.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main objective of the PR: shadowing kotlinx.serialization into the compiler plugin, which aligns with the actual changes made across the dependency management and build configuration files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dep/kotlinx-serialization

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a43aaae and e9db28a.

📒 Files selected for processing (2)
  • stability-compiler/build.gradle.kts (2 hunks)
  • stability-gradle/src/main/kotlin/com/skydoves/compose/stability/gradle/StabilityAnalyzerGradlePlugin.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • stability-gradle/src/main/kotlin/com/skydoves/compose/stability/gradle/StabilityAnalyzerGradlePlugin.kt
  • stability-compiler/build.gradle.kts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
stability-compiler/build.gradle.kts (2)

59-59: Classifier mismatch: archiveClassifier set to "all" but jar replaces standard artifact.

The shadowJar task has archiveClassifier.set("all"), which would normally produce a stability-compiler-all.jar artifact. However, the jar task replaces the standard jar with this content, so downstream consumers expecting either the shadowed "all" classifier or the standard jar may be confused.

Consider clarifying the artifact strategy: Is this module intended to always produce a fat jar, or should shadowJar be an optional secondary artifact?


57-73: Relocation comment could be clearer.

Lines 65-66 comment that relocation is intentionally disabled because "K/Native compiler needs original package names," but there is no actual relocation code present (the line is commented out). This comment is somewhat misleading.

Consider updating to clarify that relocation is intentionally NOT configured, or remove the misleading comment entirely.

-  // Don't relocate - K/Native compiler needs original package names
-  // relocate("kotlinx.serialization", "...")
+  // Note: Do NOT configure relocation. The K/Native compiler requires original
+  // package names for kotlinx.serialization to function correctly.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d63a89 and a43aaae.

📒 Files selected for processing (3)
  • gradle/libs.versions.toml (3 hunks)
  • stability-compiler/build.gradle.kts (2 hunks)
  • stability-gradle/src/main/kotlin/com/skydoves/compose/stability/gradle/StabilityAnalyzerGradlePlugin.kt (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Gradle Plugin Tests
  • GitHub Check: Compiler Tests (FIR/IR Dumps)
  • GitHub Check: Runtime Module Tests
  • GitHub Check: Compiler Plugin Tests
  • GitHub Check: Lint Module Tests
  • GitHub Check: Spotless check
  • GitHub Check: API check
  • GitHub Check: Build and Tests
🔇 Additional comments (3)
stability-gradle/src/main/kotlin/com/skydoves/compose/stability/gradle/StabilityAnalyzerGradlePlugin.kt (1)

176-177: Comment update aligns with shadow-based packaging.

The clarification that kotlinx.serialization is embedded in the compiler JAR via the shadow plugin is accurate and helpful context for maintainers. This correctly reflects the new build strategy introduced in this PR.

stability-compiler/build.gradle.kts (1)

28-28: Verify explicitApi() doesn't break existing public APIs.

Enabling explicit API mode requires all public declarations to have explicit visibility modifiers (public, private, internal, etc.). If existing public APIs in this compiler module lack these modifiers, the build will fail.

Ensure all public APIs in the stability-compiler module have explicit visibility modifiers by running a build and verifying no visibility-related errors occur.

gradle/libs.versions.toml (1)

8-8: Version catalog entries are correctly formatted and compatible.

The kotlinxSerialization 1.9.0 version bump is compatible with Kotlin 2.2.21 (as confirmed—kotlinx.serialization 1.9.0 targets Kotlin 2.2 and requires Kotlin 2.2.x). All version catalog entries, including the new shadow plugin entries, follow conventions correctly.

Also applies to: 18-18, 53-53

Comment on lines 76 to 88
tasks.named<Jar>("jar") {
dependsOn(tasks.shadowJar)
// Copy shadowJar content after jar is built
doLast {
val shadowTask = tasks.shadowJar.get()
val shadowJarFile = shadowTask.archiveFile.get().asFile
val jarFile = archiveFile.get().asFile

if (shadowJarFile.exists()) {
shadowJarFile.copyTo(jarFile, overwrite = true)
logger.lifecycle("Replaced ${jarFile.name} with shadowJar content")
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Jar replacement logic is fragile and non-standard.

Using doLast { ... } to overwrite the jar file with shadowJar content bypasses Gradle's task model and caching mechanisms, which can lead to non-deterministic builds and cache invalidation issues. This approach is not idiomatic for Gradle plugin development.

Consider these alternatives:

  • Configure shadowJar to output to the expected jar location instead.
  • Use Gradle's artifact management (publishArtifact) to declare shadowJar as the primary artifact.
  • Adjust the Maven publication configuration to reference shadowJar directly if used in publications.

Do you have a specific reason for the current approach, or would you prefer to refactor this to use standard Gradle patterns?

🤖 Prompt for AI Agents
In stability-compiler/build.gradle.kts around lines 76 to 88, the current doLast
block copies the shadowJar over the produced jar, which bypasses Gradle's task
model and caching; remove the doLast override and instead produce the shadow
artifact via standard Gradle semantics by one of: configure the shadowJar task
to write to the same archive location/name as the jar (set
archiveFileName/archiveClassifier appropriately and disable the default jar if
needed), or mark the shadowJar as the published/primary artifact (use
publications { ... artifact(tasks.shadowJar) { builtBy(tasks.shadowJar) } } or
publishArtifact=true) so Maven publications reference the shadow output
directly; after switching, delete the file-copying logic and ensure task
dependencies are set (e.g., jar.dependsOn shadowJar or builtBy) so builds remain
cacheable and deterministic.

@skydoves skydoves merged commit 1f00d5a into main Nov 17, 2025
10 checks passed
@skydoves skydoves deleted the dep/kotlinx-serialization branch November 17, 2025 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants