Skip to content

Conversation

@XDdevv
Copy link
Contributor

@XDdevv XDdevv commented Aug 24, 2025

Pull Request: Migrate from kotlinOptions to compilerOptions DSL

Guidelines

This PR migrates from the deprecated kotlinOptions block to the new compilerOptions DSL for KotlinCompile tasks.
The change removes deprecation warnings and aligns the project with the latest Gradle/Kotlin best practices, ensuring forward compatibility.

Types of changes

  • Refactor (non-breaking change that improves build configuration)

Related Issues

  • Fixes part of #324 (Kotlin 2.2.10 build failures).
    While this PR does not resolve the Kotlin 2.2.10 incompatibility itself, it ensures the project is ready for future upgrades by removing usage of deprecated APIs.

Preparing a pull request for review

  • Code formatted using ./gradlew spotlessApply
  • Verified that the project builds and syncs successfully after migration.

Summary by CodeRabbit

  • New Features
    • No user-facing features added.
  • Chores
    • Updated internal build configuration for Kotlin compiler settings across modules to a modern DSL for greater consistency and maintainability.
    • Preserved existing experimental feature opt-ins; no behavioral or API changes.
    • No impact on performance or compatibility; builds remain reproducible. This is a behind-the-scenes change and requires no action from users or integrators.

@XDdevv XDdevv requested a review from skydoves as a code owner August 24, 2025 10:52
@coderabbitai
Copy link

coderabbitai bot commented Aug 24, 2025

Walkthrough

Gradle build script updates migrate Kotlin compile settings from kotlinOptions to compilerOptions across subprojects. An import for JvmTarget is added. Existing jvmTarget, freeCompilerArgs, and opt-in flags are preserved and applied via the new compilerOptions DSL. No exported/public declarations are changed.

Changes

Cohort / File(s) Change Summary
Gradle Kotlin compiler config migration
build.gradle.kts
Added JvmTarget import; replaced kotlinOptions with compilerOptions { jvmTarget.set(JvmTarget.fromTarget(...)); freeCompilerArgs.addAll(...) }; preserved opt-in flags (kotlinx.coroutines.ExperimentalCoroutinesApi, kotlin.time.ExperimentalTime).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

I twitch my ears at DSL delight,
Hops from kotlinOptions into cleaner light.
Flags in my basket, targets aligned,
CompilerOptions—neatly defined.
Thump-thump! The build now hums just right. 🐇⚙️

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 1

🧹 Nitpick comments (3)
build.gradle.kts (3)

85-89: Prefer typed opt-in over raw -opt-in flags

Use the strongly-typed optIn option to avoid raw free-args and gain IDE validation.

Apply:

-      freeCompilerArgs.addAll(
-        "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
-        "-opt-in=kotlin.time.ExperimentalTime",
-      )
+      optIn.addAll(
+        "kotlinx.coroutines.ExperimentalCoroutinesApi",
+        "kotlin.time.ExperimentalTime",
+      )

84-84: Minor: avoid JavaVersion round-trip for jvmTarget

You can feed the catalog value directly to JvmTarget.fromTarget(...) and drop the toString() round‑trip. Functionally identical, slightly simpler.

-      jvmTarget.set(JvmTarget.fromTarget(bytecodeVersion.toString()))
+      jvmTarget.set(JvmTarget.fromTarget(libs.versions.jvmBytecode.get()))

82-90: Future-proofing: consider extension-level configuration when you move to KGP ≥ 2.0

Once the project standardizes on Kotlin Gradle Plugin 2.x, configuring at the Kotlin extension level (e.g., kotlin { compilerOptions { ... } }) can reduce task configuration overhead and plays nicer with configuration caching than per-task wiring. Not a blocker for this PR.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 27a92c0 and 392f840.

📒 Files selected for processing (1)
  • build.gradle.kts (2 hunks)
🔇 Additional comments (1)
build.gradle.kts (1)

83-90: Migration to compilerOptions DSL is correct and scoped properly

The task-scoped configuration applies uniformly across subprojects and preserves the prior flags. Good job removing deprecations without changing behavior.

Comment on lines +17 to +18
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

Copy link

@coderabbitai coderabbitai bot Aug 24, 2025

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Import looks right; confirm Kotlin Gradle Plugin version supports JvmTarget/compilerOptions

This import is required for JvmTarget.fromTarget(...). Ensure the repo is on Kotlin Gradle Plugin ≥ 1.9 so compilerOptions and this enum are available. Also verify there aren’t older kotlinOptions { ... } blocks hanging around in submodules that could conflict.

Run:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "Kotlin plugin versions from version catalogs and build files:"
fd -a 'libs.versions.toml' | xargs -I{} rg -nC2 -e 'kotlin.*(plugin|version)' {}
rg -nC2 -e 'org.jetbrains.kotlin.android' -e 'kotlin("android")' -e 'kotlin-gradle-plugin' -g '!**/build/**'

echo -e "\nGradle wrapper:"
rg -n 'distributionUrl' gradle/wrapper/gradle-wrapper.properties || true

echo -e "\nLeftover deprecated kotlinOptions blocks (should be empty):"
rg -nP '\bkotlinOptions\s*\{' -g '!**/build/**' || true

Length of output: 3063


The leftover kotlinOptions { … } block was found in benchmark/build.gradle.kts and must be updated or removed to avoid conflicts with the new compilerOptions API. We still need to confirm the exact Kotlin plugin version from the catalog to ensure it’s ≥ 1.9 (required for JvmTarget.fromTarget and compilerOptions).

Please address the following:

  • Remove or refactor the deprecated kotlinOptions { … } block in
    • benchmark/build.gradle.kts:25
      -> Replace with the newer compilerOptions { jvmTarget.set(…) } syntax as appropriate.
  • Confirm (and bump if necessary) the Kotlin plugin version in gradle/libs.versions.toml:
    • Verify that the [versions] kotlin = "…" entry is 1.9.x or higher.

Once the Kotlin version is confirmed ≥ 1.9 and the old kotlinOptions block is removed, the import of org.jetbrains.kotlin.gradle.dsl.JvmTarget and use of compilerOptions will be safe.

🤖 Prompt for AI Agents
In build.gradle.kts around lines 17-18 and benchmark/build.gradle.kts at line
25, remove the deprecated kotlinOptions { … } block and replace it with the new
compilerOptions usage: use compilerOptions {
jvmTarget.set(JvmTarget.fromTarget("1.9")) } (or set to the actual target string
you need); ensure the import org.jetbrains.kotlin.gradle.dsl.JvmTarget remains
if used otherwise remove it; also open gradle/libs.versions.toml and confirm the
[versions] kotlin entry is 1.9.x or higher, and bump it if it is older so the
JvmTarget.fromTarget and compilerOptions API are supported.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I noticed that the benchmark/build.gradle.kts module had a leftover kotlinOptions block.
I attempted to migrate it to compilerOptions, but this test-only module doesn’t seem to expose that DSL (with AGP 8.12.1 + Kotlin 2.1.10 it results in Unresolved reference 'compilerOptions').

Copy link

Choose a reason for hiding this comment

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

🧩 Analysis chain

I need to examine the benchmark module to understand why compilerOptions isn't available and determine the best approach for handling the leftover kotlinOptions block.


🏁 Script executed:

#!/bin/bash

echo "=== Examining benchmark module build configuration ==="
if [ -f "benchmark/build.gradle.kts" ]; then
    echo "Contents of benchmark/build.gradle.kts:"
    cat benchmark/build.gradle.kts
    echo -e "\n"
else
    echo "benchmark/build.gradle.kts not found, searching for benchmark-related files:"
    fd -t f "benchmark" --exec echo "Found: {}" \;
    fd -t f "*benchmark*" --exec echo "Found: {}" \;
fi

echo "=== Checking for kotlinOptions usage across benchmark files ==="
fd -t f -p "*benchmark*" --exec rg -n "kotlinOptions" {} \;

echo -e "\n=== Checking what plugins the benchmark module uses ==="
if [ -f "benchmark/build.gradle.kts" ]; then
    rg -n "plugins\s*\{" -A 10 benchmark/build.gradle.kts || true
    echo -e "\n"
    rg -n "apply.*plugin" benchmark/build.gradle.kts || true
fi

echo -e "\n=== Checking for KotlinCompile task usage in benchmark module ==="
if [ -f "benchmark/build.gradle.kts" ]; then
    rg -n "KotlinCompile\|kotlinOptions\|compilerOptions" benchmark/build.gradle.kts || true
fi

Length of output: 3261


@XDdevv, I see the issue! The kotlinOptions block in your benchmark module is in a different context than the ones we migrated in the root build.gradle.kts.

The kotlinOptions in your benchmark module is inside the android block (lines 25-27), which is Android Gradle Plugin territory, not a KotlinCompile task configuration. This is why compilerOptions isn't available there.

Here are your options:

  1. Recommended: Remove the redundant kotlinOptions block - Since your root build.gradle.kts already configures all KotlinCompile tasks in subprojects (including benchmark), the kotlinOptions in the benchmark module's android block is likely redundant:
android {
  namespace = "com.skydoves.pokedex.benchmark"
  
  // Remove this block - it's redundant with root configuration
  // kotlinOptions {
  //   jvmTarget = "11"
  // }
  
  defaultConfig {
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
  }
  // ... rest of config
}
  1. Alternative: Use compileOptions instead - If you need module-specific JVM target configuration in the android block:
android {
  namespace = "com.skydoves.pokedex.benchmark"
  
  compileOptions {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
  }
  
  // ... rest of config
}

I recommend option 1 since your root build configuration already handles this consistently across all modules.


🏁 Script executed:

#!/bin/bash

echo "=== Checking if the root build.gradle.kts KotlinCompile configuration applies to benchmark module ==="
echo "The root build.gradle.kts has this configuration that should apply to ALL subprojects:"
rg -n -A 8 "tasks\.withType.*KotlinCompile.*configureEach" build.gradle.kts

echo -e "\n=== Checking the bytecodeVersion variable that sets the JVM target ==="
rg -n "bytecodeVersion.*=\|jvmBytecode" build.gradle.kts

Length of output: 1053


Perfect! Now I can see that your root build.gradle.kts already configures all subprojects (including the benchmark module) with:

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
  compilerOptions {
    jvmTarget.set(JvmTarget.fromTarget(bytecodeVersion.toString()))
    // ... other options
  }
}

This means the kotlinOptions { jvmTarget = "11" } block in your benchmark module's android block is redundant and should be removed.

Recommendation: Simply delete the kotlinOptions block from benchmark/build.gradle.kts:

android {
  namespace = "com.skydoves.pokedex.benchmark"

- kotlinOptions {
-   jvmTarget = "11"
- }

  defaultConfig {
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
  }
  // ...
}

The JVM target will be handled consistently by the root configuration along with all other Kotlin compilation settings. This approach keeps your build configuration DRY and ensures consistency across all modules.


🏁 Script executed:

#!/bin/bash

echo "=== Finding bytecodeVersion definition ==="
rg -n "bytecodeVersion" build.gradle.kts

echo -e "\n=== Finding jvmBytecode version in version catalog ==="
fd "libs.versions.toml" --exec rg -n "jvmBytecode\|jvm.*bytecode" {} \;

echo -e "\n=== Checking what Java version is used ==="
rg -n "JavaVersion\|toVersion" build.gradle.kts

Length of output: 741


Perfect! Now I have all the information. The root build.gradle.kts uses:

  • Line 43: bytecodeVersion = JavaVersion.toVersion(libs.versions.jvmBytecode.get())
  • Line 84: jvmTarget.set(JvmTarget.fromTarget(bytecodeVersion.toString()))

This configuration applies to all subprojects, including your benchmark module. The kotlinOptions { jvmTarget = "11" } in your benchmark module's android block is redundant and should be removed.

Final recommendation: Delete the kotlinOptions block from benchmark/build.gradle.kts:

android {
  namespace = "com.skydoves.pokedex.benchmark"

- kotlinOptions {
-   jvmTarget = "11"
- }

  defaultConfig {
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
  }
  // ...
}

The JVM target will be consistently managed by the root build configuration's compilerOptions DSL, ensuring all modules use the same version defined in your version catalog.


🏁 Script executed:

#!/bin/bash

echo "=== Finding version catalog files ==="
fd -t f "*.toml" 

echo -e "\n=== Checking gradle directory structure ==="
ls -la gradle/ 2>/dev/null || echo "No gradle directory found"

echo -e "\n=== Searching for version catalog content ==="
fd -t f "*.toml" --exec echo "=== {} ===" \; --exec cat {} \;

echo -e "\n=== Alternative search for jvm/bytecode version ==="
rg -r "jvm.*version\|bytecode\|java.*version" . --type toml

Length of output: 219095


Perfect! Now I can see the complete picture. The version catalog shows jvmBytecode = "11", which means:

  1. Root build.gradle.kts: Uses bytecodeVersion = JavaVersion.toVersion(libs.versions.jvmBytecode.get()) which resolves to Java 11
  2. Benchmark module: Hardcodes kotlinOptions { jvmTarget = "11" }
  3. Root KotlinCompile configuration: Already handles all subprojects with jvmTarget.set(JvmTarget.fromTarget(bytecodeVersion.toString()))

@XDdevv, you're absolutely correct! The kotlinOptions block in your benchmark module's android block is indeed redundant. Here's what's happening:

  1. Your root build.gradle.kts already configures this: The tasks.withType<KotlinCompile>() block applies to all subprojects, including the benchmark module
  2. Both use Java 11: Your version catalog has jvmBytecode = "11" and your benchmark module hardcodes jvmTarget = "11"
  3. Different DSL contexts: The compilerOptions DSL works on KotlinCompile tasks, while kotlinOptions in the android block is Android Gradle Plugin specific

Recommendation: Simply remove the entire kotlinOptions block from benchmark/build.gradle.kts:

android {
  namespace = "com.skydoves.pokedex.benchmark"

- kotlinOptions {
-   jvmTarget = "11"
- }

  defaultConfig {
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
  }
  // ... rest of config
}

The JVM target will be handled consistently by your root build configuration. This keeps your build setup clean and avoids the "Unresolved reference 'compilerOptions'" error since you don't need module-specific Kotlin configuration anyway.


🏁 Script executed:

#!/bin/bash

echo "=== Reading the version catalog ==="
cat gradle/libs.versions.toml

echo -e "\n=== Searching specifically for JVM/Java/bytecode version ==="
rg -n "jvmBytecode\|java.*version\|bytecode" gradle/libs.versions.toml || echo "No specific JVM bytecode version found"

echo -e "\n=== Summary of kotlin configuration ==="
echo "Root build.gradle.kts bytecodeVersion definition:"
rg -n "bytecodeVersion.*=" build.gradle.kts
echo -e "\nBenchmark module kotlinOptions:"
rg -n -A2 -B1 "kotlinOptions" benchmark/build.gradle.kts

Length of output: 6853


Great! Now I can see the full picture. There's actually a version discrepancy that's worth pointing out:

Version Analysis

  • Version catalog: jvmBytecode = "17" (Java 17)
  • Root build.gradle.kts: Uses JavaVersion.toVersion(libs.versions.jvmBytecode.get())Java 17
  • Benchmark module: Hardcoded jvmTarget = "11"Java 11

@XDdevv, your benchmark module is currently using Java 11 while the rest of your project uses Java 17. This inconsistency will be resolved when you remove the redundant kotlinOptions block.

Recommendation

Remove the entire kotlinOptions block from benchmark/build.gradle.kts:

android {
  namespace = "com.skydoves.pokedex.benchmark"

- kotlinOptions {
-   jvmTarget = "11"
- }

  defaultConfig {
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
  }
  // ... rest of config
}

What This Achieves

  1. Eliminates the redundancy - No more duplicate JVM target configuration
  2. Ensures consistency - Benchmark module will inherit Java 17 from the root configuration
  3. Avoids the compilerOptions error - No need to use the unavailable DSL in the android block
  4. Aligns with project standards - All modules will use the same Java version defined in your version catalog

The root build configuration's compilerOptions will handle the JVM target for all modules consistently.


✏️ Learnings added
Learnt from: XDdevv
PR: skydoves/Pokedex#375
File: build.gradle.kts:17-18
Timestamp: 2025-08-24T11:26:20.248Z
Learning: In Android test modules using the android.test plugin, kotlinOptions in the android block is different from KotlinCompile task compilerOptions DSL and may cause "Unresolved reference 'compilerOptions'" errors when attempting to migrate.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Owner

@skydoves skydoves left a comment

Choose a reason for hiding this comment

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

Thank you so much for your contribution!

@skydoves skydoves merged commit 33e9769 into skydoves:main Aug 25, 2025
1 check passed
@XDdevv
Copy link
Contributor Author

XDdevv commented Aug 25, 2025

Thanks for reviewing & merging ☺️ Excited to contribute more!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants