Kotlin: add Kotlin 2.4.0 support#21970
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request updates the Java/Kotlin extractor and its test infrastructure to support Kotlin 2.4.0, while dropping Kotlin 1.x support (minimum Kotlin version becomes 2.0.0) and updating baselines/docs accordingly.
Changes:
- Add Kotlin 2.4.0 compiler/stdlib dependencies and extractor compatibility shims for Kotlin IR API changes in 2.4.0.
- Switch Kotlin integration tests that previously used Kotlin 1.x language mode to use
-language-version 2.0, and update expected outputs. - Update docs and change notes to reflect the new supported Kotlin version range and deprecation of Kotlin < 2.0.
Show a summary per file
| File | Description |
|---|---|
| MODULE.bazel | Adds Bazel repos for Kotlin 2.4.0 compiler/embeddable/stdlib artifacts. |
| java/ql/test/query-tests/security/CWE-312/android/CleartextStorage/DB-CHECK.expected | Updated test baseline output (dbcheck). |
| java/ql/test/query-tests/security/CWE-312/android/CleartextStorage/CleartextStorageSharedPrefsTest.expected | Updated test baseline output. |
| java/ql/test/library-tests/pathsanitizer/test.expected | Updated test baseline output. |
| java/ql/test/library-tests/pathsanitizer/DB-CHECK.expected | Updated test baseline output (dbcheck). |
| java/ql/lib/change-notes/2026-06-08-kotlin-drop-1x.md | Adds change note deprecating Kotlin < 2.0. |
| java/ql/lib/change-notes/2026-06-04-kotlin-2.4.0.md | Adds change note for Kotlin 2.4.0 support. |
| java/ql/integration-tests/kotlin/all-platforms/kotlin_java_lowering_wildcards/test.py | Moves test compilation to -language-version 2.0. |
| java/ql/integration-tests/kotlin/all-platforms/kotlin_java_lowering_wildcards/test.expected | Updates expected output for wildcard lowering changes. |
| java/ql/integration-tests/kotlin/all-platforms/kotlin_java_lowering_wildcards/DB-CHECK.expected | Updated test baseline output (dbcheck). |
| java/ql/integration-tests/kotlin/all-platforms/java-interface-redeclares-tostring/test.py | Moves test compilation to -language-version 2.0. |
| java/ql/integration-tests/kotlin/all-platforms/java-interface-redeclares-tostring/test.expected | Updates expected output for interface toString redeclare scenario. |
| java/ql/integration-tests/kotlin/all-platforms/file_classes/test.py | Moves test compilation to -language-version 2.0. |
| java/ql/integration-tests/kotlin/all-platforms/file_classes/classes.expected | Updates expected class extraction output. |
| java/ql/integration-tests/kotlin/all-platforms/extractor_information_kotlin1/test.py | Moves test compilation to -language-version 2.0. |
| java/ql/integration-tests/kotlin/all-platforms/extractor_information_kotlin1/ExtractorInformation.expected | Updates expected extractor info (Uses Kotlin 2 flag). |
| java/ql/integration-tests/kotlin/all-platforms/external-property-overloads/test.py | Moves test compilation to -language-version 2.0. |
| java/ql/integration-tests/kotlin/all-platforms/external-property-overloads/test.expected | Updates expected external binary location formatting. |
| java/ql/integration-tests/kotlin/all-platforms/enhanced-nullability/test.py | Moves test compilation to -language-version 2.0. |
| java/ql/integration-tests/kotlin/all-platforms/enhanced-nullability/test.expected | Updates expected output for enhanced nullability extraction. |
| java/ql/integration-tests/kotlin/all-platforms/enhanced-nullability/DB-CHECK.expected | Updated test baseline output (dbcheck). |
| java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected | Updates max-supported-version diagnostic message. |
| java/kotlin-extractor/versions.bzl | Adds 2.4.0 to supported versions list; adjusts language-version mapping. |
| java/kotlin-extractor/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar | Adds service registration for Kotlin 2.4+ compiler plugin registrar. |
| java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_4_0/parameterIndexExcludingReceivers.kt | Adds Kotlin 2.4.0-specific parameter indexing logic (handles new receiver kinds). |
| java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_4_0/Kotlin2ComponentRegistrar.kt | Introduces Kotlin 2.4.0 CompilerPluginRegistrar-based registration path. |
| java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_4_0/IrCompat.kt | Adds Kotlin 2.4.0 IR compatibility accessors for removed APIs. |
| java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_9_0-Beta/Kotlin2ComponentRegistrar.kt | Refactors older registrar to route through doRegisterExtensions and centralize extension registration. |
| java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_8_0/Kotlin2ComponentRegistrar.kt | Refactors older registrar to route through doRegisterExtensions. |
| java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_8_0/IrCompat.kt | Adds pre-2.4.0 IR compatibility wrappers matching the new shim API. |
| java/kotlin-extractor/src/main/kotlin/utils/TypeSubstitution.kt | Switches annotation handling to compatibility wrappers (codeQlAddAnnotations / codeQlAnnotationFromSymbolOwner). |
| java/kotlin-extractor/src/main/kotlin/utils/JvmNames.kt | Switches annotation argument access to compatibility wrappers. |
| java/kotlin-extractor/src/main/kotlin/TrapWriter.kt | Switches extension receiver access to compatibility wrapper. |
| java/kotlin-extractor/src/main/kotlin/MetaAnnotationSupport.kt | Switches IR annotation construction/mutation to compatibility wrappers. |
| java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt | Switches parameter/receiver access to compatibility wrappers. |
| java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | Switches multiple IR access patterns to compatibility wrappers; updates related comment/docs. |
| java/kotlin-extractor/src/main/kotlin/KotlinExtractorComponentRegistrar.kt | Refactors registrar to use doRegisterExtensions and centralized extension registration. |
| java/kotlin-extractor/src/main/kotlin/comments/CommentExtractor.kt | Switches extension receiver detection to compatibility wrapper. |
| java/kotlin-extractor/dev/wrapper.py | Bumps default wrapper Kotlin version to 2.4.0. |
| java/kotlin-extractor/deps/kotlin-stdlib-2.4.0.jar | Adds Kotlin 2.4.0 stdlib (LFS pointer). |
| java/kotlin-extractor/deps/kotlin-compiler-embeddable-2.4.0.jar | Adds Kotlin 2.4.0 embeddable compiler (LFS pointer). |
| java/kotlin-extractor/deps/kotlin-compiler-2.4.0.jar | Adds Kotlin 2.4.0 compiler (LFS pointer). |
| java/kotlin-extractor/BUILD.bazel | Conditionally packages CompilerPluginRegistrar service file for Kotlin >= 2.4.0. |
| docs/codeql/reusables/supported-versions-compilers.rst | Updates documented supported Kotlin version range to 2.0.0–2.4.x. |
Copilot's findings
- Files reviewed: 44/44 changed files
- Comments generated: 4
| * this.dispatchReceiver = dispatchReceiver | ||
| * this.extensionReceiver = extensionReceiver | ||
| * this.codeQlExtensionReceiver = extensionReceiver | ||
| * } |
30b0a30 to
547c78f
Compare
Add the Kotlin 2.4.0 compiler plugin variant (component registrar, IR compatibility shims, and version-specific utilities), bundle the 2.4.0 compiler dependencies, and update the build wiring, supported version metadata and the too-new diagnostic bound. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mark the integration tests that require a Kotlin 1.x language version with @pytest.mark.kotlin1 so CI can run them on a pinned pre-2.4 compiler (Kotlin 2.4 no longer accepts -language-version 1.9). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
79437b8 to
1b785a8
Compare
jketema
left a comment
There was a problem hiding this comment.
Some comments and questions. Nothing major here.
| // Register with LoadingOrder.LAST to ensure the extractor runs after other | ||
| // IR generation plugins (like kotlinx.serialization) have generated their code. |
There was a problem hiding this comment.
This comment is here, but not in the 1.8 version. Should we make this uniform?
There was a problem hiding this comment.
IIRC, there were some changes on how the component was registered so we needed this for force that our plugin last. I agree it would make sense to see if we can make this more uniform.
There was a problem hiding this comment.
The code looks identical to me between 1.8 and 1.9, or are there differences?
| get() = parameters.firstOrNull { it.kind == org.jetbrains.kotlin.ir.declarations.IrParameterKind.ExtensionReceiver } | ||
|
|
||
| // Helper: get the offset of value arguments in the arguments list | ||
| // In 2.4.0, arguments[] includes dispatch/extension receivers before regular params |
There was a problem hiding this comment.
This comment about arguments[] is important, but seems a bit misplaced. Should probably be attached to the next three functions.
There was a problem hiding this comment.
Feel free to update.
| // For IrCall/IrFunctionReference, look at symbol.owner (IrFunction) directly. | ||
| // For IrPropertyReference, symbol.owner is IrProperty; use the getter's parameters instead. |
There was a problem hiding this comment.
I'm not able to related this to this implementation of this function. Is this supposed to be about the next function?
There was a problem hiding this comment.
You are right. Its related to the lookup logic in extensionReceiverParameterIndex() , not the getter specifically.
Should we change it to:
// Re-add accessor for the extensionReceiver property removed in Kotlin 2.4.0.extensionReceiver property.
val IrMemberAccessExpression<*>.codeQlExtensionReceiver: IrExpression? {and
// Find the argument index corresponding to the extension receiver parameter.
// Calls and function references expose an IrFunction owner directly; property
// references need to look through their getter or setter.
private fun IrMemberAccessExpression<*>.extensionReceiverParameterIndex(): Int? {There was a problem hiding this comment.
That would make sense to me. If you're changing this, it's probably best if you also address https://github.com/github/codeql/pull/21970/files#r3434446772
| private fun IrMemberAccessExpression<*>.extensionReceiverParameterIndex(): Int? { | ||
| // Direct function owner (IrCall, IrFunctionReference, etc.) | ||
| (symbol.owner as? IrFunction)?.codeQlExtensionReceiverParameter?.let { | ||
| return it.indexInParameters |
There was a problem hiding this comment.
This is me being naive about Kotlin: where is it coming from?
There was a problem hiding this comment.
Kotlin automatically binds 'it' to ....codeQlExtensionReceiverParameter inside the let { ... } construct when evaluating the body when its not null.
There was a problem hiding this comment.
We chould make it more explicit by changing it to
private fun IrMemberAccessExpression<*>.extensionReceiverParameterIndex(): Int? {
// Direct function owner (IrCall, IrFunctionReference, etc.)
(symbol.owner as? IrFunction)?.codeQlExtensionReceiverParameter?.let {
extensionReceiverParameter -> return extensionReceiverParameter.indexInParameters
}to increase readability
There was a problem hiding this comment.
I think it's fine as it is. I would only change it if it were uncommon Kotlin idiom, but I doubt that's the case.
| fun parameterIndexExcludingReceivers(vp: IrValueParameter): Int { | ||
| val offset = | ||
| (vp.parent as? IrFunction)?.let { f -> | ||
| f.parameters.count { it.kind == IrParameterKind.DispatchReceiver || it.kind == IrParameterKind.ExtensionReceiver || it.kind == IrParameterKind.Context } | ||
| } ?: 0 | ||
| return vp.indexInParameters - offset | ||
| } |
There was a problem hiding this comment.
Is there a reason this is not in IrCompat.kt?
There was a problem hiding this comment.
Not particular reason. I'd have to ask the LLM.
There was a problem hiding this comment.
Looking futher, I think it could very well be rolled into IrCompat.kt to reduce number of files.
| @@ -1,5 +1,5 @@ | |||
| { | |||
| "markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 2.3.30.", | |||
| "markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 2.4.10.", | |||
There was a problem hiding this comment.
There's probably a better place to comment on this, but given what I read here about Kotlin release numbering, would it make sense to just allow anything below 2.5.0?
There was a problem hiding this comment.
I don't have an opinion on that tbh. It's following the existing pattern that has been used for previous kotlin updates.
There was a problem hiding this comment.
That's fine. I'm just wondering out loud here, and this is not something we necessarily need to address here.
There was a problem hiding this comment.
If you look in java/kotlin-extractor/src/main/kotlin/utils/versions, we had to make changes for 2.2.20, 2.1.20, etc.
There was a problem hiding this comment.
Yes. The Kotlin compiler api you are using is unstable, but you could set the max version to 2.4.10, like you did in the past.
The next planned version of Kotlin is 2.4.20, containing compiler changes.
Like I mentioned in the ticket, you should really not use the IR api for analyzing code, but the analysis api also used by IntelliJ or detekt or ksp 2.
jketema
left a comment
There was a problem hiding this comment.
We generally do not leave empty lines between imports in integration tests.
| import pathlib | ||
|
|
||
| import pytest |
There was a problem hiding this comment.
| import pathlib | |
| import pytest | |
| import pathlib | |
| import pytest |
| import commands | ||
|
|
||
| import pytest |
There was a problem hiding this comment.
| import commands | |
| import pytest | |
| import commands | |
| import pytest |
| import commands | ||
|
|
||
| import pytest |
There was a problem hiding this comment.
| import commands | |
| import pytest | |
| import commands | |
| import pytest |
| import commands | ||
|
|
||
| import pytest |
There was a problem hiding this comment.
| import commands | |
| import pytest | |
| import commands | |
| import pytest |
| import commands | ||
|
|
||
| import pytest |
There was a problem hiding this comment.
| import commands | |
| import pytest | |
| import commands | |
| import pytest |
|
|
||
| Eclipse compiler for Java (ECJ) [7]_",``.java`` | ||
| Kotlin,"Kotlin 1.8.0 to 2.3.2\ *x*","kotlinc",``.kt`` | ||
| Kotlin,"Kotlin 1.8.0 to 2.4.\ *x*","kotlinc",``.kt`` |
Add extractor support for Kotlin 2.4.0 and adjust the integration tests that depend on a pre-2.4 compiler.
Changes
BUILD.bazel,versions.bzl,MODULE.bazel,dev/wrapper.py), refreshes the supported-versions documentation, and raises the "Kotlin version too new" diagnostic bound from 2.3.30 to 2.4.10.kotlin1integration tests. Six integration tests pass-language-version 1.9, which Kotlin 2.4 no longer accepts. They are marked with@pytest.mark.kotlin1so CI can run them on a pinned pre-2.4 compiler.Notes
kotlin-version-too-newdiagnostic.-language-version 1.9is no longer available) are a needed follow-up investigation.