Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
93e6135
Kotlin: add 2.4.20-RC artifacts
andersfugmann Aug 26, 2026
c1b4fe6
Kotlin: address KT-85816
andersfugmann Aug 26, 2026
0724caf
Kotlin: address KT-86046
andersfugmann Aug 26, 2026
96ac5ba
Kotlin: preserve generated forwarder locations
andersfugmann Aug 26, 2026
8b8b961
Kotlin: enable 2.4.20-RC support
andersfugmann Aug 26, 2026
f146aa6
Kotlin: make 2.4.20-RC the test default
andersfugmann Aug 26, 2026
b9c81d5
Kotlin: document preliminary 2.4.20-RC support
andersfugmann Aug 26, 2026
63553e3
Kotlin: support 2.4.20-RC2
andersfugmann Aug 28, 2026
2f4571b
Kotlin: cover full value class extraction
andersfugmann Aug 28, 2026
06042b1
Kotlin: cover name-based destructuring
andersfugmann Aug 28, 2026
3d99697
Kotlin: expose missing context parameters
andersfugmann Aug 28, 2026
2942d70
Kotlin: extract context parameters and arguments
andersfugmann Aug 28, 2026
05357c2
Kotlin: cover context parameter setters
andersfugmann Aug 28, 2026
8595a36
Kotlin: cover collection literal extraction
andersfugmann Aug 28, 2026
7015661
Kotlin: cover companion blocks and extensions
andersfugmann Aug 28, 2026
dedba97
Kotlin: cover invokedynamic when extraction
andersfugmann Aug 28, 2026
aa583f8
Kotlin: keep full value class coverage focused
andersfugmann Aug 28, 2026
701a005
Kotlin: assign stable context parameter indices
andersfugmann Aug 28, 2026
01235a2
Kotlin: gate full value class coverage
andersfugmann Aug 31, 2026
b514ee0
Kotlin: gate name-based destructuring coverage
andersfugmann Aug 31, 2026
0778371
Kotlin: gate context parameter coverage
andersfugmann Aug 31, 2026
a0cf379
Kotlin: gate collection literal coverage
andersfugmann Aug 31, 2026
131ef8e
Kotlin: gate companion extension coverage
andersfugmann Aug 31, 2026
8630d5a
Kotlin: gate invokedynamic when coverage
andersfugmann Aug 31, 2026
b0fab01
Kotlin: extract context parameters from 2.2.20
andersfugmann Aug 31, 2026
44f0616
Kotlin: stabilise implicit context argument locations
andersfugmann Aug 31, 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
Prev Previous commit
Next Next commit
Kotlin: extract context parameters from 2.2.20
Use the unified parameter and argument layout introduced in Kotlin 2.2.20-Beta2 so context parameters and their implicit call arguments are included before the old accessors disappear in Kotlin 2.4.\n\nAssign parameter indices after excluding receiver slots, and give compiler-generated context arguments a stable whole-file location when the earlier compiler supplies inconsistent offsets. This fixes the version-gated function, getter, and setter regression test without changing its expected output. Earlier compilers retain the legacy compatibility implementation because they do not accept the tested context-parameter syntax.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Loading branch information
andersfugmann committed Aug 31, 2026
commit b0fab01ec33a10c8e262df779bbb558b786e1092
87 changes: 66 additions & 21 deletions java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3590,7 +3590,9 @@ open class KotlinFileExtractor(
valueArguments,
enclosingStmt,
enclosingCallable,
idxOffset
idxOffset,
valueParameters = syntacticCallTarget.codeQlValueParameters,
invalidArgumentLocation = tw.getWholeFileLocation()
)
},
dispatchReceiver?.type,
Expand Down Expand Up @@ -3804,50 +3806,93 @@ open class KotlinFileExtractor(
enclosingStmt: Label<out DbStmt>,
enclosingCallable: Label<out DbCallable>,
idxOffset: Int
) =
) {
extractCallValueArguments(
callId,
(0 until call.codeQlValueArgumentsCount).map { call.codeQlGetValueArgument(it) },
enclosingStmt,
enclosingCallable,
idxOffset
idxOffset,
valueParameters = call.symbol.owner.codeQlValueParameters,
invalidArgumentLocation = tw.getWholeFileLocation()
)
}

private fun extractCallValueArguments(
callId: Label<out DbExprparent>,
valueArguments: List<IrExpression?>,
enclosingStmt: Label<out DbStmt>,
enclosingCallable: Label<out DbCallable>,
idxOffset: Int,
extractVarargAsArray: Boolean = false
extractVarargAsArray: Boolean = false,
valueParameters: List<IrValueParameter>? = null,
invalidArgumentLocation: Label<DbLocation>? = null
) {
var i = 0
valueArguments.forEach { arg ->
valueArguments.forEachIndexed { argumentIndex, arg ->
if (arg != null) {
if (arg is IrVararg && !extractVarargAsArray) {
arg.elements.forEachIndexed { varargNo, vararg ->
extractVarargElement(
vararg,
enclosingCallable,
callId,
i + idxOffset + varargNo,
enclosingStmt
)
}
i += arg.elements.size
} else {
extractExpressionExpr(
arg,
enclosingCallable,
val parameter = valueParameters?.getOrNull(argumentIndex)
if (
parameter?.isCodeQlContextParameter() == true &&
arg is IrGetValue &&
(arg.startOffset < 0 || arg.endOffset < 0) &&
invalidArgumentLocation != null
) {
extractVariableAccess(
useValueDeclaration(arg.symbol.owner),
arg.type,
invalidArgumentLocation,
callId,
(i++) + idxOffset,
i++ + idxOffset,
enclosingCallable,
enclosingStmt
)
} else {
i +=
extractCallValueArgument(
callId,
arg,
enclosingStmt,
enclosingCallable,
i + idxOffset,
extractVarargAsArray
)
}
}
}
}

private fun extractCallValueArgument(
callId: Label<out DbExprparent>,
argument: IrExpression,
enclosingStmt: Label<out DbStmt>,
enclosingCallable: Label<out DbCallable>,
outputIndex: Int,
extractVarargAsArray: Boolean = false
): Int {
if (argument is IrVararg && !extractVarargAsArray) {
argument.elements.forEachIndexed { varargIndex, element ->
extractVarargElement(
element,
enclosingCallable,
callId,
outputIndex + varargIndex,
enclosingStmt
)
}
return argument.elements.size
}

extractExpressionExpr(
argument,
enclosingCallable,
callId,
outputIndex,
enclosingStmt
)
return 1
}

private fun findFunction(cls: IrClass, name: String): IrFunction? =
cls.declarations.findSubType<IrFunction> { it.name.asString() == name }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.github.codeql.utils.versions

import org.jetbrains.kotlin.ir.declarations.IrValueParameter

fun IrValueParameter.isCodeQlContextParameter() = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.github.codeql.utils.versions

import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrMutableAnnotationContainer
import org.jetbrains.kotlin.ir.declarations.IrParameterKind
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.fromSymbolOwner
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.addAnnotations

private fun IrParameterKind.isCodeQlValueParameter() =
this == IrParameterKind.Context || this == IrParameterKind.Regular

val IrFunction.codeQlValueParameters: List<IrValueParameter>
get() = parameters.filter { it.kind.isCodeQlValueParameter() }

val IrFunction.codeQlExtensionReceiverParameter: IrValueParameter?
get() = extensionReceiverParameter

private fun IrMemberAccessExpression<*>.valueArgumentIndices(): List<Int> {
val owner = symbol.owner as? IrFunction ?: return arguments.indices.toList()
return owner.parameters.mapIndexedNotNull { index, parameter ->
index.takeIf { parameter.kind.isCodeQlValueParameter() }
}
}

val IrMemberAccessExpression<*>.codeQlValueArgumentsCount: Int
get() = valueArgumentIndices().size

fun IrMemberAccessExpression<*>.codeQlGetValueArgument(index: Int): IrExpression? =
arguments[valueArgumentIndices()[index]]

fun IrMemberAccessExpression<*>.codeQlPutValueArgument(index: Int, value: IrExpression?) {
arguments[valueArgumentIndices()[index]] = value
}

val IrMemberAccessExpression<*>.codeQlExtensionReceiver: IrExpression?
get() = extensionReceiver

val IrMemberAccessExpression<*>.codeQlTypeArgumentsCount: Int
get() = typeArgumentsCount

fun IrMemberAccessExpression<*>.codeQlGetTypeArgument(index: Int): IrType? = getTypeArgument(index)

fun IrType.codeQlAddAnnotations(annotations: List<IrConstructorCall>): IrType =
addAnnotations(annotations)

fun codeQlSetAnnotations(
container: IrMutableAnnotationContainer,
annotations: List<IrConstructorCall>
) {
container.annotations = annotations
}

fun IrFunction.codeQlSetDispatchReceiverParameter(param: IrValueParameter?) {
dispatchReceiverParameter = param
}

fun codeQlAnnotationFromSymbolOwner(
startOffset: Int,
endOffset: Int,
type: IrType,
symbol: IrConstructorSymbol,
typeArgumentsCount: Int
): IrConstructorCall =
IrConstructorCallImpl.fromSymbolOwner(
startOffset,
endOffset,
type,
symbol,
typeArgumentsCount
)

fun codeQlAnnotationFromSymbolOwner(
type: IrType,
symbol: IrConstructorSymbol
): IrConstructorCall = IrConstructorCallImpl.fromSymbolOwner(type, symbol)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.github.codeql.utils.versions

import org.jetbrains.kotlin.ir.declarations.IrParameterKind
import org.jetbrains.kotlin.ir.declarations.IrValueParameter

fun IrValueParameter.isCodeQlContextParameter() = kind == IrParameterKind.Context
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.github.codeql.utils.versions

import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrParameterKind
import org.jetbrains.kotlin.ir.declarations.IrValueParameter

fun parameterIndexExcludingReceivers(vp: IrValueParameter): Int {
if (
vp.kind == IrParameterKind.DispatchReceiver ||
vp.kind == IrParameterKind.ExtensionReceiver
) {
return -1
}
return (vp.parent as? IrFunction)
?.parameters
?.take(vp.indexInParameters)
?.count { it.kind == IrParameterKind.Context || it.kind == IrParameterKind.Regular }
?: vp.indexInParameters
}