Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7722068
Kotlin: Update kotlin_rules to 2.2.0 and remove support for Kotlin 1.…
andersfugmann Dec 4, 2025
79ce26b
Kotlin: Remove resource_strip_prefix for kotlin extraction
andersfugmann Dec 4, 2025
0350521
Kotlin: Silence compilation warnings
andersfugmann Dec 4, 2025
a8e6d32
Kotlin: Add support for Kotlin 2.3.0
andersfugmann Dec 4, 2025
62891de
Kotlin: Update compiler plugin for Kotlin 2.3.0
andersfugmann Dec 4, 2025
d514516
Kotlin: Fix bazel format and address copilot review comments
andersfugmann Dec 5, 2025
b3ff9c5
Kotlin: Strip prefix when building plugin
andersfugmann Dec 20, 2025
6f5ff01
Kotlin: Create IrSimpleType factory function to support constructor c…
andersfugmann Jan 5, 2026
783f805
Kotlin: Fix spelling
andersfugmann Jan 5, 2026
2dd4b73
Kotlin: Remove obsolete file
andersfugmann Jan 5, 2026
dedc416
Kotlin: Remove support for Kotlin versions 1.6 and 1.7
andersfugmann Jan 5, 2026
8fb2b26
Kotlin: Add additional warning suppresion to v1_9_0 and remove copy i…
andersfugmann Jan 5, 2026
6852a54
Kotlin: Do not skip writing of getter and setters if the local deliga…
andersfugmann Jan 6, 2026
1c1e17c
Kotlin: Add changenotes for Kotlin 2.3 support and removal of support…
andersfugmann Jan 8, 2026
3d123c8
Kotlin: Bump versions in documentation
andersfugmann Jan 7, 2026
19d4ce2
Kotlin: Bump upper bound for supported kotlin version in integration …
andersfugmann Jan 7, 2026
6b7005b
Kotlin: Update kotlin compiler version in integration tests
andersfugmann Jan 8, 2026
8289f2a
Kotlin: Update kotlin serialization integration test to use Kotlin co…
andersfugmann Jan 8, 2026
01acfac
Kotlin: Accept column location changes in tests
andersfugmann Jan 14, 2026
f4995c6
Kotlin: Add bitwise 'and' operation expected by Kotlin 2.3 compiler t…
andersfugmann Jan 15, 2026
d8fd574
Kotlin: Accept test changes
andersfugmann Jan 15, 2026
4c3a082
Kotlin: Accept test changes
andersfugmann Jan 15, 2026
f296f8d
Kotlin: Address detections from kotin internal queries
andersfugmann Jan 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ bazel_dep(name = "bazel_skylib", version = "1.8.1")
bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "absl")
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
bazel_dep(name = "fmt", version = "12.1.0-codeql.1")
bazel_dep(name = "rules_kotlin", version = "2.1.3-codeql.1")
bazel_dep(name = "rules_kotlin", version = "2.2.0-codeql.1")
bazel_dep(name = "gazelle", version = "0.40.0")
bazel_dep(name = "rules_dotnet", version = "0.21.5-codeql.1")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
Expand Down Expand Up @@ -221,10 +221,6 @@ use_repo(
kotlin_extractor_deps,
"codeql_kotlin_defaults",
"codeql_kotlin_embeddable",
"kotlin-compiler-1.6.0",
"kotlin-compiler-1.6.20",
"kotlin-compiler-1.7.0",
"kotlin-compiler-1.7.20",
"kotlin-compiler-1.8.0",
"kotlin-compiler-1.9.0-Beta",
"kotlin-compiler-1.9.20-Beta",
Expand All @@ -234,10 +230,7 @@ use_repo(
"kotlin-compiler-2.1.20-Beta1",
"kotlin-compiler-2.2.0-Beta1",
"kotlin-compiler-2.2.20-Beta2",
"kotlin-compiler-embeddable-1.6.0",
"kotlin-compiler-embeddable-1.6.20",
"kotlin-compiler-embeddable-1.7.0",
"kotlin-compiler-embeddable-1.7.20",
"kotlin-compiler-2.3.0",
"kotlin-compiler-embeddable-1.8.0",
"kotlin-compiler-embeddable-1.9.0-Beta",
"kotlin-compiler-embeddable-1.9.20-Beta",
Expand All @@ -247,10 +240,7 @@ use_repo(
"kotlin-compiler-embeddable-2.1.20-Beta1",
"kotlin-compiler-embeddable-2.2.0-Beta1",
"kotlin-compiler-embeddable-2.2.20-Beta2",
"kotlin-stdlib-1.6.0",
"kotlin-stdlib-1.6.20",
"kotlin-stdlib-1.7.0",
"kotlin-stdlib-1.7.20",
"kotlin-compiler-embeddable-2.3.0",
"kotlin-stdlib-1.8.0",
"kotlin-stdlib-1.9.0-Beta",
"kotlin-stdlib-1.9.20-Beta",
Expand All @@ -260,6 +250,7 @@ use_repo(
"kotlin-stdlib-2.1.20-Beta1",
"kotlin-stdlib-2.2.0-Beta1",
"kotlin-stdlib-2.2.20-Beta2",
"kotlin-stdlib-2.3.0",
)

go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
Expand Down
3 changes: 1 addition & 2 deletions docs/codeql/reusables/supported-versions-compilers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
Java,"Java 7 to 25 [6]_","javac (OpenJDK and Oracle JDK),

Eclipse compiler for Java (ECJ) [7]_",``.java``
Kotlin,"Kotlin 1.6.0 [15]_ to 2.2.2\ *x*","kotlinc",``.kt``
Kotlin,"Kotlin 1.8.0 to 2.3.0\ *x*","kotlinc",``.kt``
JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [8]_"
Python [9]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py``
Ruby [10]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
Expand All @@ -45,4 +45,3 @@
.. [12] Support for the analysis of Swift requires macOS.
.. [13] Embedded Swift is not supported.
.. [14] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default.
.. [15] Support for Kotlin versions 1.6 and 1.7 is deprecated and will be removed in release 2.24.1.
8 changes: 1 addition & 7 deletions java/kotlin-extractor/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,7 @@ kt_javac_options(
javac_opts = ":javac-options",
kotlinc_opts = ":kotlinc-options-%s" % v,
module_name = "codeql-kotlin-extractor",
# resource_strip_prefix is very nit-picky: the following makes it work from
# `codeql`, `@codeql_kotlin_embeddable` and `semmle-code`
resource_strip_prefix = (
("../%s/" % repo_name() if repo_name() else "") +
("%s/" % package_name() if package_name() else "") +
v
),
resource_strip_prefix = v,
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm guessing the situation has improved since I did this, and the simple v is enough. making it work from @codeql is a nice to have, but it has to work from @codeql_kotlin_embeddable

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'm not familiar with the @codeql_kotlin_embeddable. Where are those needed, and, more importantly, how do I test them?

resources = [
":resources-%s" % v,
],
Expand Down
3 changes: 0 additions & 3 deletions java/kotlin-extractor/deps/kotlin-compiler-1.6.0.jar

This file was deleted.

3 changes: 0 additions & 3 deletions java/kotlin-extractor/deps/kotlin-compiler-1.6.20.jar

This file was deleted.

3 changes: 0 additions & 3 deletions java/kotlin-extractor/deps/kotlin-compiler-1.7.0.jar

This file was deleted.

3 changes: 0 additions & 3 deletions java/kotlin-extractor/deps/kotlin-compiler-1.7.20.jar

This file was deleted.

3 changes: 3 additions & 0 deletions java/kotlin-extractor/deps/kotlin-compiler-2.3.0.jar
Git LFS file not shown

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Git LFS file not shown
3 changes: 0 additions & 3 deletions java/kotlin-extractor/deps/kotlin-stdlib-1.6.0.jar

This file was deleted.

3 changes: 0 additions & 3 deletions java/kotlin-extractor/deps/kotlin-stdlib-1.6.20.jar

This file was deleted.

3 changes: 0 additions & 3 deletions java/kotlin-extractor/deps/kotlin-stdlib-1.7.0.jar

This file was deleted.

3 changes: 0 additions & 3 deletions java/kotlin-extractor/deps/kotlin-stdlib-1.7.20.jar

This file was deleted.

3 changes: 3 additions & 0 deletions java/kotlin-extractor/deps/kotlin-stdlib-2.3.0.jar
Git LFS file not shown
2 changes: 1 addition & 1 deletion java/kotlin-extractor/dev/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import io
import os

DEFAULT_VERSION = "2.2.0"
DEFAULT_VERSION = "2.3.0"


def options():
Expand Down
28 changes: 19 additions & 9 deletions java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ open class KotlinFileExtractor(

private fun extractClassModifiers(c: IrClass, id: Label<out DbClassorinterface>) {
with("class modifiers", c) {
@Suppress("REDUNDANT_ELSE_IN_WHEN")
when (c.modality) {
Modality.FINAL -> addModifiers(id, "final")
Modality.SEALED -> addModifiers(id, "sealed")
Expand Down Expand Up @@ -1342,7 +1343,7 @@ open class KotlinFileExtractor(
extractTypeAccessRecursive(substitutedType, location, id, -1)
}
val syntheticParameterNames =
isUnderscoreParameter(vp) ||
vp.origin == IrDeclarationOrigin.UNDERSCORE_PARAMETER ||
((vp.parent as? IrFunction)?.let { hasSynthesizedParameterNames(it) } ?: true)
val javaParameter =
when (val callable = (vp.parent as? IrFunction)?.let { getJavaCallable(it) }) {
Expand Down Expand Up @@ -1644,7 +1645,7 @@ open class KotlinFileExtractor(
extractMethodAndParameterTypeAccesses: Boolean,
typeSubstitution: TypeSubstitution?,
classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?
) =
) : Label<out DbCallable> =
forceExtractFunction(
f,
parentId,
Expand Down Expand Up @@ -2801,6 +2802,7 @@ open class KotlinFileExtractor(

private fun extractBody(b: IrBody, callable: Label<out DbCallable>) {
with("body", b) {
@Suppress("REDUNDANT_ELSE_IN_WHEN")
when (b) {
is IrBlockBody -> extractBlockBody(b, callable)
is IrSyntheticBody -> extractSyntheticBody(b, callable)
Expand Down Expand Up @@ -2834,7 +2836,7 @@ open class KotlinFileExtractor(
when {
kind == IrSyntheticBodyKind.ENUM_VALUES -> tw.writeKtSyntheticBody(callable, 1)
kind == IrSyntheticBodyKind.ENUM_VALUEOF -> tw.writeKtSyntheticBody(callable, 2)
kind == kind_ENUM_ENTRIES -> tw.writeKtSyntheticBody(callable, 3)
kind == IrSyntheticBodyKind.ENUM_ENTRIES -> tw.writeKtSyntheticBody(callable, 3)
else -> {
logger.errorElement("Unhandled synthetic body kind " + kind, b)
}
Expand Down Expand Up @@ -2973,13 +2975,21 @@ open class KotlinFileExtractor(
val locId = tw.getLocation(s)
tw.writeStmts_block(blockId, parent, idx, callable)
tw.writeHasLocation(blockId, locId)
extractVariable(s.delegate, callable, blockId, 0)

// For Kotlin < 2.3, s.delegate is not-nullable. Cast to be nullable,
// as a workaround to silence warnings for kotlin < 2.3 about the elvis
// operator being redundant.
val delegate: IrVariable? = cast(s.delegate)
val propId = tw.getFreshIdLabel<DbKt_property>()
tw.writeKtProperties(propId, s.name.asString())
tw.writeHasLocation(propId, locId)
tw.writeKtPropertyDelegates(propId, useVariable(s.delegate))

if (delegate == null) {
// This is not expected to happen, as the plugin hooks into the pipeline before IR lowering.
logger.errorElement("Local delegated property is missing delegate", s)
} else {
extractVariable(delegate, callable, blockId, 0)
tw.writeKtProperties(propId, s.name.asString())
tw.writeHasLocation(propId, locId)
tw.writeKtPropertyDelegates(propId, useVariable(delegate))
}
// Getter:
extractStatement(s.getter, callable, blockId, 1)
val getterLabel = getLocallyVisibleFunctionLabels(s.getter).function
Expand Down Expand Up @@ -3332,7 +3342,7 @@ open class KotlinFileExtractor(
// that specified the default values, which will in turn dynamically dispatch back to the
// relevant override.
val overriddenCallTarget =
(callTarget as? IrSimpleFunction)?.allOverriddenIncludingSelf()?.firstOrNull {
(callTarget as? IrSimpleFunction)?.allOverridden(includeSelf = true)?.firstOrNull {
it.overriddenSymbols.isEmpty() &&
it.valueParameters.any { p -> p.defaultValue != null }
} ?: callTarget
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -849,9 +849,6 @@ open class KotlinUsesExtractor(
}

private fun useSimpleType(s: IrSimpleType, context: TypeContext): TypeResults {
if (s.abbreviation != null) {
// TODO: Extract this information
}
// We use this when we don't actually have an IrClass for a class
// we want to refer to
// TODO: Eliminate the need for this if possible
Expand Down Expand Up @@ -939,7 +936,7 @@ open class KotlinUsesExtractor(
return arrayInfo.componentTypeResults
}
owner is IrClass -> {
val args = if (s.codeQlIsRawType()) null else s.arguments
val args = if (s.isRawType()) null else s.arguments

return useSimpleTypeClass(owner, args, s.isNullableCodeQL())
}
Expand Down Expand Up @@ -1836,6 +1833,7 @@ open class KotlinUsesExtractor(

// Note this function doesn't return a signature because type arguments are never
// incorporated into function signatures.
@Suppress("REDUNDANT_ELSE_IN_WHEN")
return when (arg) {
is IrStarProjection -> {
val anyTypeLabel =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.github.codeql

import com.github.codeql.utils.versions.copyParameterToFunction
import com.github.codeql.utils.versions.createImplicitParameterDeclarationWithWrappedDescriptor
import java.lang.annotation.ElementType
import java.util.HashSet
Expand All @@ -21,7 +20,9 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrClassReference
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
Expand All @@ -31,6 +32,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.constructedClass
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.copyTo
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
Expand Down Expand Up @@ -330,7 +332,7 @@ class MetaAnnotationSupport(
)
return
}
val newParam = copyParameterToFunction(thisReceiever, this)
val newParam = thisReceiever.copyTo(this)
dispatchReceiverParameter = newParam
body =
factory
Expand Down
36 changes: 36 additions & 0 deletions java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
import org.jetbrains.kotlin.load.kotlin.FacadeClassSource
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass
import org.jetbrains.kotlin.name.FqName

// Adapted from Kotlin's interpreter/Utils.kt function 'internalName'
// Translates class names into their JLS section 13.1 binary name,
Expand All @@ -31,6 +33,40 @@ fun getFileClassName(f: IrFile) =
.replaceFirst(Regex("""\.kt$"""), "")
.replaceFirstChar { it.uppercase() }) + "Kt")

fun getFileClassFqName(d: IrDeclaration): FqName? {
// d is in a file class.
// Get the name in a similar way to the compiler's ExternalPackageParentPatcherLowering
// visitMemberAccess/generateOrGetFacadeClass.

// But first, fields aren't IrMemberWithContainerSource, so we need
// to get back to the property (if there is one)
if (d is IrField) {
val propSym = d.correspondingPropertySymbol
if (propSym != null) {
return getFileClassFqName(propSym.owner)
}
}

// Now the main code
if (d is IrMemberWithContainerSource) {
val containerSource = d.containerSource
if (containerSource is FacadeClassSource) {
val facadeClassName = containerSource.facadeClassName
if (facadeClassName != null) {
// TODO: This is really a multifile-class rather than a file-class,
// but for now we treat them the same.
return facadeClassName.fqNameForTopLevelClassMaybeWithDollars
} else {
return containerSource.className.fqNameForTopLevelClassMaybeWithDollars
}
} else {
return null
}
} else {
return null
}
}

fun getIrElementBinaryName(that: IrElement): String {
if (that is IrFile) {
val shortName = getFileClassName(that)
Expand Down
17 changes: 15 additions & 2 deletions java/kotlin-extractor/src/main/kotlin/utils/GetByFqName.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,38 @@ package com.github.codeql.utils

import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name

fun getClassByFqName(pluginContext: IrPluginContext, fqName: FqName): IrClassSymbol? {
val id = ClassId.topLevel(fqName)
return getClassByClassId(pluginContext, id)
}

fun getClassByFqName(pluginContext: IrPluginContext, fqName: String): IrClassSymbol? {
return getClassByFqName(pluginContext, FqName(fqName))
}

fun getClassByClassId(pluginContext: IrPluginContext, id: ClassId): IrClassSymbol? {
return pluginContext.referenceClass(id)
}

fun getFunctionsByFqName(
pluginContext: IrPluginContext,
pkgName: String,
name: String
): Collection<IrSimpleFunctionSymbol> {
return getFunctionsByFqName(pluginContext, FqName(pkgName), Name.identifier(name))
val id = CallableId(FqName(pkgName), Name.identifier(name))
return pluginContext.referenceFunctions(id)
}

fun getPropertiesByFqName(
pluginContext: IrPluginContext,
pkgName: String,
name: String
): Collection<IrPropertySymbol> {
return getPropertiesByFqName(pluginContext, FqName(pkgName), Name.identifier(name))
val id = CallableId(FqName(pkgName), Name.identifier(name))
return pluginContext.referenceProperties(id)
}
3 changes: 3 additions & 0 deletions java/kotlin-extractor/src/main/kotlin/utils/Helpers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ fun IrFunction.isLocalFunction(): Boolean {

val IrClass.isInterfaceLike
get() = kind == ClassKind.INTERFACE || kind == ClassKind.ANNOTATION_CLASS

@Suppress("UNCHECKED_CAST")
fun <T> cast(value: Any?): T = value as T
Loading
Loading