From ae7124a0e15dee25d2c6eb3209e3494904a36c3c Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Wed, 8 Jan 2025 17:28:23 +0000 Subject: [PATCH] Kotlin: Add support for 2.0.20 --- .../supported-versions-compilers.rst | 2 +- .../src/main/kotlin/KotlinFileExtractor.kt | 8 ++--- .../src/main/kotlin/KotlinUsesExtractor.kt | 32 +++++++++---------- .../src/main/kotlin/utils/TypeSubstitution.kt | 10 +++--- .../utils/versions/v_1_5_0/isNullable.kt | 11 ------- .../utils/versions/v_1_5_0/typeUtils.kt | 11 +++++++ .../utils/versions/v_1_6_0/IrBuiltIns.kt | 2 +- .../versions/v_2_1_0-Beta1/isNullable.kt | 11 ------- .../versions/v_2_1_20-Beta1/isNullable.kt | 1 - .../versions/v_2_1_20-Beta1/typeUtils.kt | 12 +++++++ .../diagnostics.expected | 2 +- 11 files changed, 51 insertions(+), 51 deletions(-) delete mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/isNullable.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/typeUtils.kt delete mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_0-Beta1/isNullable.kt delete mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_20-Beta1/isNullable.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_20-Beta1/typeUtils.kt diff --git a/docs/codeql/reusables/supported-versions-compilers.rst b/docs/codeql/reusables/supported-versions-compilers.rst index 168b5170cf0f3..9831e48e1a9bd 100644 --- a/docs/codeql/reusables/supported-versions-compilers.rst +++ b/docs/codeql/reusables/supported-versions-compilers.rst @@ -20,7 +20,7 @@ Java,"Java 7 to 22 [5]_","javac (OpenJDK and Oracle JDK), Eclipse compiler for Java (ECJ) [6]_",``.java`` - Kotlin,"Kotlin 1.5.0 to 2.1.0\ *x*","kotlinc",``.kt`` + Kotlin,"Kotlin 1.5.0 to 2.1.20\ *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`` [7]_" Python [8]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py`` Ruby [9]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 902387d43e651..f1f4131002b49 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -2305,7 +2305,7 @@ open class KotlinFileExtractor( // synthesised and inherit the annotation from the delegate (which given it has // @NotNull, is likely written in Java) JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION.takeUnless { - t.isNullable() || + t.isNullableCodeQL() || primitiveTypeMapping.getPrimitiveInfo(t) != null || hasExistingAnnotation(it) } @@ -3987,7 +3987,7 @@ open class KotlinFileExtractor( target.parent } else { val st = extensionReceiverParameter.type as? IrSimpleType - if (isNullable != null && st?.isNullable() != isNullable) { + if (isNullable != null && st?.isNullableCodeQL() != isNullable) { verboseln("Nullablility of type didn't match") return false } @@ -4633,9 +4633,9 @@ open class KotlinFileExtractor( val isPrimitiveArrayCreation = !isBuiltinCallKotlin(c, "arrayOf") val elementType = if (isPrimitiveArrayCreation) { - c.type.getArrayElementType(pluginContext.irBuiltIns) + c.type.getArrayElementTypeCodeQL(pluginContext.irBuiltIns) } else { - // TODO: is there any reason not to always use getArrayElementType? + // TODO: is there any reason not to always use getArrayElementTypeCodeQL? if (c.typeArgumentsCount == 1) { c.getTypeArgument(0).also { if (it == null) { diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index ead0a23374acf..a401d017a0286 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -696,7 +696,7 @@ open class KotlinUsesExtractor( private fun getInvariantNullableArrayType(arrayType: IrSimpleType): IrSimpleType = if (arrayType.isPrimitiveArray()) arrayType else { - val componentType = arrayType.getArrayElementType(pluginContext.irBuiltIns) + val componentType = arrayType.getArrayElementTypeCodeQL(pluginContext.irBuiltIns) val componentTypeBroadened = when (componentType) { is IrSimpleType -> @@ -707,7 +707,7 @@ open class KotlinUsesExtractor( val unchanged = componentType == componentTypeBroadened && (arrayType.arguments[0] as? IrTypeProjection)?.variance == Variance.INVARIANT && - componentType.isNullable() + componentType.isNullableCodeQL() if (unchanged) arrayType else IrSimpleTypeImpl( @@ -722,7 +722,7 @@ open class KotlinUsesExtractor( Kotlin arrays can be broken down as: isArray(t) - |- t.isBoxedArray + |- t.isBoxedArrayCodeQL | |- t.isArray() e.g. Array, Array | |- t.isNullableArray() e.g. Array?, Array? |- t.isPrimitiveArray() e.g. BooleanArray @@ -732,7 +732,7 @@ open class KotlinUsesExtractor( Primitive arrays are represented as e.g. boolean[]. */ - private fun isArray(t: IrType) = t.isBoxedArray || t.isPrimitiveArray() + private fun isArray(t: IrType) = t.isBoxedArrayCodeQL || t.isPrimitiveArray() data class ArrayInfo( val elementTypeResults: TypeResults, @@ -773,7 +773,7 @@ open class KotlinUsesExtractor( ) { pluginContext.irBuiltIns.anyType } else { - t.getArrayElementType(pluginContext.irBuiltIns) + t.getArrayElementTypeCodeQL(pluginContext.irBuiltIns) } val recInfo = useArrayType(elementType, t.isPrimitiveArray()) @@ -861,7 +861,7 @@ open class KotlinUsesExtractor( if ( (context == TypeContext.RETURN || (context == TypeContext.OTHER && otherIsPrimitive)) && - !s.isNullable() && + !s.isNullableCodeQL() && getKotlinType(s)?.hasEnhancedNullability() != true && primitiveName != null ) { @@ -877,7 +877,7 @@ open class KotlinUsesExtractor( val kotlinClassId = useClassInstance(kotlinClass, listOf()).typeResult.id val kotlinResult = if (true) TypeResult(fakeKotlinType(), "TODO", "TODO") - else if (s.isNullable()) { + else if (s.isNullableCodeQL()) { val kotlinSignature = "$kotlinPackageName.$kotlinClassName?" // TODO: Is this right? val kotlinLabel = "@\"kt_type;nullable;$kotlinPackageName.$kotlinClassName\"" @@ -919,21 +919,21 @@ open class KotlinUsesExtractor( return extractErrorType() } } - (s.isBoxedArray && s.arguments.isNotEmpty()) || s.isPrimitiveArray() -> { + (s.isBoxedArrayCodeQL && s.arguments.isNotEmpty()) || s.isPrimitiveArray() -> { val arrayInfo = useArrayType(s, false) return arrayInfo.componentTypeResults } owner is IrClass -> { val args = if (s.codeQlIsRawType()) null else s.arguments - return useSimpleTypeClass(owner, args, s.isNullable()) + return useSimpleTypeClass(owner, args, s.isNullableCodeQL()) } owner is IrTypeParameter -> { val javaResult = useTypeParameter(owner) val aClassId = makeClass("kotlin", "TypeParam") // TODO: Wrong val kotlinResult = if (true) TypeResult(fakeKotlinType(), "TODO", "TODO") - else if (s.isNullable()) { + else if (s.isNullableCodeQL()) { val kotlinSignature = "${javaResult.signature}?" // TODO: Wrong val kotlinLabel = "@\"kt_type;nullable;type_param\"" // TODO: Wrong val kotlinId: Label = @@ -1217,7 +1217,7 @@ open class KotlinUsesExtractor( } private fun extendsAdditionAllowed(t: IrType) = - if (t.isBoxedArray) { + if (t.isBoxedArrayCodeQL) { if (t is IrSimpleType) { arrayExtendsAdditionAllowed(t) } else { @@ -1510,7 +1510,7 @@ open class KotlinUsesExtractor( } } else { t.classOrNull?.let { tCls -> - if (t.isBoxedArray) { + if (t.isBoxedArrayCodeQL) { (t.arguments.singleOrNull() as? IrTypeProjection)?.let { elementTypeArg -> val elementType = elementTypeArg.type @@ -1523,7 +1523,7 @@ open class KotlinUsesExtractor( ) return tCls .typeWithArguments(listOf(newArg)) - .codeQlWithHasQuestionMark(t.isNullable()) + .codeQlWithHasQuestionMark(t.isNullableCodeQL()) } } } @@ -2103,12 +2103,12 @@ open class KotlinUsesExtractor( } if (owner is IrClass) { - if (t.isBoxedArray) { - val elementType = t.getArrayElementType(pluginContext.irBuiltIns) + if (t.isBoxedArrayCodeQL) { + val elementType = t.getArrayElementTypeCodeQL(pluginContext.irBuiltIns) val erasedElementType = erase(elementType) return owner .typeWith(erasedElementType) - .codeQlWithHasQuestionMark(t.isNullable()) + .codeQlWithHasQuestionMark(t.isNullableCodeQL()) } return if (t.arguments.isNotEmpty()) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/TypeSubstitution.kt b/java/kotlin-extractor/src/main/kotlin/utils/TypeSubstitution.kt index aacc15c56647f..fb39b6675759a 100644 --- a/java/kotlin-extractor/src/main/kotlin/utils/TypeSubstitution.kt +++ b/java/kotlin-extractor/src/main/kotlin/utils/TypeSubstitution.kt @@ -61,7 +61,7 @@ private fun IrSimpleType.substituteTypeArguments( } } - return IrSimpleTypeImpl(classifier, isNullable(), newArguments, annotations) + return IrSimpleTypeImpl(classifier, isNullableCodeQL(), newArguments, annotations) } /** @@ -100,7 +100,7 @@ private fun subProjectedType( else { val newProjectedType = substitutedTypeArg.type.let { - if (t.isNullable()) it.codeQlWithHasQuestionMark(true) else it + if (t.isNullableCodeQL()) it.codeQlWithHasQuestionMark(true) else it } val newVariance = combineVariance(outerVariance, substitutedTypeArg.variance) makeTypeProjection(newProjectedType, newVariance) @@ -117,7 +117,7 @@ private fun IrTypeArgument.upperBound(context: IrPluginContext) = when (this.variance) { Variance.INVARIANT -> this.type Variance.IN_VARIANCE -> - if (this.type.isNullable()) context.irBuiltIns.anyNType + if (this.type.isNullableCodeQL()) context.irBuiltIns.anyNType else context.irBuiltIns.anyType Variance.OUT_VARIANCE -> this.type } @@ -132,7 +132,7 @@ private fun IrTypeArgument.lowerBound(context: IrPluginContext) = Variance.INVARIANT -> this.type Variance.IN_VARIANCE -> this.type Variance.OUT_VARIANCE -> - if (this.type.isNullable()) context.irBuiltIns.nothingNType + if (this.type.isNullableCodeQL()) context.irBuiltIns.nothingNType else context.irBuiltIns.nothingType } else -> context.irBuiltIns.nothingType @@ -215,7 +215,7 @@ fun IrTypeArgument.withQuestionMark(b: Boolean): IrTypeArgument = this.type.let { when (it) { is IrSimpleType -> - if (it.isNullable() == b) this + if (it.isNullableCodeQL() == b) this else makeTypeProjection(it.codeQlWithHasQuestionMark(b), this.variance) else -> this } diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/isNullable.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/isNullable.kt deleted file mode 100644 index b98ad476f124b..0000000000000 --- a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/isNullable.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.github.codeql.utils.versions - -import org.jetbrains.kotlin.ir.types.* - -fun IrType.isNullable(): Boolean = - isNullable() - -val IrType.isBoxedArray: Boolean by IrType::isBoxedArray - -fun IrType.getArrayElementType(irBuiltIns: IrBuiltIns): IrType = - getArrayElementType(irBuiltIns) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/typeUtils.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/typeUtils.kt new file mode 100644 index 0000000000000..06829377a6b7c --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/typeUtils.kt @@ -0,0 +1,11 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.ir.types.* + +fun IrType.isNullableCodeQL(): Boolean = + this.isNullable() + +val IrType.isBoxedArrayCodeQL: Boolean by IrType::isBoxedArray + +fun IrType.getArrayElementTypeCodeQL(irBuiltIns: IrBuiltIns): IrType = + this.getArrayElementType(irBuiltIns) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_6_0/IrBuiltIns.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_6_0/IrBuiltIns.kt index 79b7f29ea409f..1bb2ca62aa211 100644 --- a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_6_0/IrBuiltIns.kt +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_6_0/IrBuiltIns.kt @@ -2,4 +2,4 @@ package com.github.codeql.utils.versions import org.jetbrains.kotlin.ir.IrBuiltIns -typealias IrBuiltIns = IrBuiltIns +typealias IrBuiltIns = org.jetbrains.kotlin.ir.IrBuiltIns diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_0-Beta1/isNullable.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_0-Beta1/isNullable.kt deleted file mode 100644 index b98ad476f124b..0000000000000 --- a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_0-Beta1/isNullable.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.github.codeql.utils.versions - -import org.jetbrains.kotlin.ir.types.* - -fun IrType.isNullable(): Boolean = - isNullable() - -val IrType.isBoxedArray: Boolean by IrType::isBoxedArray - -fun IrType.getArrayElementType(irBuiltIns: IrBuiltIns): IrType = - getArrayElementType(irBuiltIns) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_20-Beta1/isNullable.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_20-Beta1/isNullable.kt deleted file mode 100644 index 9c103006099f3..0000000000000 --- a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_20-Beta1/isNullable.kt +++ /dev/null @@ -1 +0,0 @@ -// Nothing to do diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_20-Beta1/typeUtils.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_20-Beta1/typeUtils.kt new file mode 100644 index 0000000000000..ac34e633116f7 --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_1_20-Beta1/typeUtils.kt @@ -0,0 +1,12 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.* + +fun IrType.isNullableCodeQL(): Boolean = + this.isNullable() + +val IrType.isBoxedArrayCodeQL: Boolean by IrType::isBoxedArray + +fun IrType.getArrayElementTypeCodeQL(irBuiltIns: IrBuiltIns): IrType = + this.getArrayElementType(irBuiltIns) diff --git a/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected b/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected index 401eaa6ee9d1a..9a2cbdc1ab080 100644 --- a/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected +++ b/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected @@ -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.1.10.", + "markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 2.1.30.", "severity": "error", "source": { "extractorName": "java",