diff --git a/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api b/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api index 8cefceaa654..5710aa04885 100644 --- a/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api +++ b/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api @@ -121,11 +121,6 @@ public final class kotlinx/metadata/FlagsKt { public static final fun flagsOf ([Lkotlinx/metadata/Flag;)I } -public final class kotlinx/metadata/InconsistentKotlinMetadataException : java/lang/RuntimeException { - public fun (Ljava/lang/String;Ljava/lang/Throwable;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V -} - public final class kotlinx/metadata/KmAnnotation { public fun (Ljava/lang/String;Ljava/util/Map;)V public fun equals (Ljava/lang/Object;)Z diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt index 5baeca106b6..c42c477f7ea 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt @@ -26,6 +26,11 @@ import kotlin.LazyThreadSafetyMode.PUBLICATION * It is recommended to study documentation for each subclass and decide what subclasses one has to handle in the `when` expression, * trying to cover as much as possible. * Normally, one would need at least a [Class] and a [FileFacade], as these are two most common kinds. + * + * Most of the subclasses offer a conversion method to transform metadata into a Km data structure — for example, [KotlinClassMetadata.Class.toKmClass]. + * Km data structures represent Kotlin declarations and offer variety of properties to introspect and alter them. + * Note that parsing may be lazy, depending on the implementation; therefore, one may not see an [IllegalArgumentException] indicating malformed metadata + * until one calls `toKmClass` or a similar method. */ sealed class KotlinClassMetadata(val annotationData: Metadata) { @@ -37,16 +42,17 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { */ class Class internal constructor(annotationData: Metadata) : KotlinClassMetadata(annotationData) { private val classData by lazy(PUBLICATION) { - val data1 = (annotationData.data1.takeIf(Array<*>::isNotEmpty) - ?: throw InconsistentKotlinMetadataException("data1 must not be empty")) - JvmProtoBufUtil.readClassDataFrom(data1, annotationData.data2) + JvmProtoBufUtil.readClassDataFrom(annotationData.requireNotEmpty(), annotationData.data2) } /** * Returns a new [KmClass] instance created from this class metadata. + * + * @throws IllegalArgumentException if metadata is malformed and can't be transformed into [KmClass]. */ - fun toKmClass(): KmClass = + fun toKmClass(): KmClass = wrapIntoMetadataExceptionWhenNeeded { KmClass().apply(this::accept) + } /** * Makes the given visitor visit metadata of this class. @@ -100,16 +106,17 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { */ class FileFacade internal constructor(annotationData: Metadata) : KotlinClassMetadata(annotationData) { private val packageData by lazy(PUBLICATION) { - val data1 = (annotationData.data1.takeIf(Array<*>::isNotEmpty) - ?: throw InconsistentKotlinMetadataException("data1 must not be empty")) - JvmProtoBufUtil.readPackageDataFrom(data1, annotationData.data2) + JvmProtoBufUtil.readPackageDataFrom(annotationData.requireNotEmpty(), annotationData.data2) } /** * Creates a new [KmPackage] instance from this file facade metadata. + * + * @throws IllegalArgumentException if metadata is malformed and can't be transformed into [KmPackage]. */ - fun toKmPackage(): KmPackage = + fun toKmPackage(): KmPackage = wrapIntoMetadataExceptionWhenNeeded { KmPackage().apply(this::accept) + } /** * Makes the given visitor visit metadata of this file facade. @@ -167,9 +174,12 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { /** * Creates a new [KmLambda] instance from this synthetic class metadata. * Returns `null` if this synthetic class does not represent a lambda. + * + * @throws IllegalArgumentException if metadata is malformed and can't be transformed into [KmLambda]. */ - fun toKmLambda(): KmLambda? = + fun toKmLambda(): KmLambda? = wrapIntoMetadataExceptionWhenNeeded { if (isLambda) KmLambda().apply(this::accept) else null + } /** * Returns `true` if this synthetic class is a class file compiled for a Kotlin lambda. @@ -181,13 +191,13 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { * Makes the given visitor visit metadata of this file facade, if this synthetic class represents a Kotlin lambda * (`isLambda` == true). * - * Throws [IllegalStateException] if this synthetic class does not represent a Kotlin lambda. + * Throws [IllegalArgumentException] if this synthetic class does not represent a Kotlin lambda. * * @param v the visitor that must visit this lambda */ @Deprecated(VISITOR_API_MESSAGE) fun accept(v: KmLambdaVisitor) { - if (!isLambda) throw IllegalStateException( + if (!isLambda) throw IllegalArgumentException( "accept(KmLambdaVisitor) is only possible for synthetic classes which are lambdas (isLambda = true)" ) @@ -318,9 +328,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { */ class MultiFileClassPart internal constructor(annotationData: Metadata) : KotlinClassMetadata(annotationData) { private val packageData by lazy(PUBLICATION) { - val data1 = (annotationData.data1.takeIf(Array<*>::isNotEmpty) - ?: throw InconsistentKotlinMetadataException("data1 must not be empty")) - JvmProtoBufUtil.readPackageDataFrom(data1, annotationData.data2) + JvmProtoBufUtil.readPackageDataFrom(annotationData.requireNotEmpty(), annotationData.data2) } /** @@ -331,9 +339,12 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { /** * Creates a new [KmPackage] instance from this multi-file class part metadata. + * + * @throws IllegalArgumentException if metadata is malformed and can't be transformed into [KmPackage]. */ - fun toKmPackage(): KmPackage = + fun toKmPackage(): KmPackage = wrapIntoMetadataExceptionWhenNeeded { KmPackage().apply(this::accept) + } /** * Makes the given visitor visit metadata of this multi-file class part. @@ -395,12 +406,16 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { * [KotlinClassMetadata.COMPATIBLE_METADATA_VERSION] by default. Cannot be less (lexicographically) than `[1, 4]` * @param extraInt the value of the class-level flags to be written to the metadata (see [Metadata.extraInt]), * 0 by default + * + * @throws IllegalArgumentException if [kmClass] is not correct and cannot be written or if [metadataVersion] is not supported for writing. */ fun writeClass( kmClass: KmClass, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, extraInt: Int = 0 - ): Class = Class.Writer().also { kmClass.accept(it) }.write(metadataVersion, extraInt) + ): Class = wrapWriteIntoIAE { + Class.Writer().also { kmClass.accept(it) }.write(metadataVersion, extraInt) + } /** * Writes [kmPackage] contents as the file facade metadata. @@ -409,12 +424,16 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { * [KotlinClassMetadata.COMPATIBLE_METADATA_VERSION] by default. Cannot be less (lexicographically) than `[1, 4]` * @param extraInt the value of the class-level flags to be written to the metadata (see [Metadata.extraInt]), * 0 by default + * + * @throws IllegalArgumentException if [kmPackage] is not correct and cannot be written or if [metadataVersion] is not supported for writing. */ fun writeFileFacade( kmPackage: KmPackage, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, extraInt: Int = 0 - ): FileFacade = FileFacade.Writer().also { kmPackage.accept(it) }.write(metadataVersion, extraInt) + ): FileFacade = wrapWriteIntoIAE { + FileFacade.Writer().also { kmPackage.accept(it) }.write(metadataVersion, extraInt) + } /** * Writes [kmLambda] as the synthetic class metadata. @@ -423,12 +442,16 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { * [KotlinClassMetadata.COMPATIBLE_METADATA_VERSION] by default. Cannot be less (lexicographically) than `[1, 4]` * @param extraInt the value of the class-level flags to be written to the metadata (see [Metadata.extraInt]), * 0 by default + * + * @throws IllegalArgumentException if [kmLambda] is not correct and cannot be written or if [metadataVersion] is not supported for writing. */ fun writeLambda( kmLambda: KmLambda, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, extraInt: Int = 0 - ): SyntheticClass = SyntheticClass.Writer().also { kmLambda.accept(it) }.write(metadataVersion, extraInt) + ): SyntheticClass = wrapWriteIntoIAE { + SyntheticClass.Writer().also { kmLambda.accept(it) }.write(metadataVersion, extraInt) + } /** * Writes synthetic class metadata. @@ -437,6 +460,8 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { * [KotlinClassMetadata.COMPATIBLE_METADATA_VERSION] by default. Cannot be less (lexicographically) than `[1, 4]` * @param extraInt the value of the class-level flags to be written to the metadata (see [Metadata.extraInt]), * 0 by default + * + * @throws IllegalArgumentException if [metadataVersion] is not supported for writing. */ fun writeSyntheticClass( metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, @@ -451,6 +476,8 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { * [KotlinClassMetadata.COMPATIBLE_METADATA_VERSION] by default. Cannot be less (lexicographically) than `[1, 4]` * @param extraInt the value of the class-level flags to be written to the metadata (see [Metadata.extraInt]), * 0 by default + * + * @throws IllegalArgumentException if [metadataVersion] is not supported for writing. */ fun writeMultiFileClassFacade( partClassNames: List, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, @@ -465,24 +492,26 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { * [KotlinClassMetadata.COMPATIBLE_METADATA_VERSION] by default. Cannot be less (lexicographically) than `[1, 4]` * @param extraInt the value of the class-level flags to be written to the metadata (see [Metadata.extraInt]), * 0 by default + * + * @throws IllegalArgumentException if [kmPackage] is not correct and cannot be written or if [metadataVersion] is not supported for writing. */ fun writeMultiFileClassPart( kmPackage: KmPackage, facadeClassName: String, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION, extraInt: Int = 0 - ): MultiFileClassPart = MultiFileClassPart.Writer().also { kmPackage.accept(it) }.write(facadeClassName, metadataVersion, extraInt) - + ): MultiFileClassPart = wrapWriteIntoIAE { + MultiFileClassPart.Writer().also { kmPackage.accept(it) }.write(facadeClassName, metadataVersion, extraInt) + } /** * Reads and parses the given annotation data of a Kotlin JVM class file and returns the correct type of [KotlinClassMetadata] encoded by - * this annotation, or `null` if this annotation encodes an unsupported kind of Kotlin classes or has an unsupported metadata version. + * this annotation, or `null` if this annotation data has an unsupported metadata version. * * [annotationData] may be obtained reflectively, constructed manually or with helper [kotlinx.metadata.jvm.Metadata] function, * or equivalent [KotlinClassHeader] can be used. * - * Throws [InconsistentKotlinMetadataException] if the metadata has inconsistencies which signal that it may have been - * modified by a separate tool. + * @throws IllegalArgumentException if the metadata cannot be parsed from binary format or is inconsistent with itself */ @JvmStatic fun read(annotationData: Metadata): KotlinClassMetadata? { @@ -492,19 +521,14 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { ).isCompatibleWithCurrentCompilerVersion() ) return null - return try { - when (annotationData.kind) { - CLASS_KIND -> Class(annotationData) - FILE_FACADE_KIND -> FileFacade(annotationData) - SYNTHETIC_CLASS_KIND -> SyntheticClass(annotationData) - MULTI_FILE_CLASS_FACADE_KIND -> MultiFileClassFacade(annotationData) - MULTI_FILE_CLASS_PART_KIND -> MultiFileClassPart(annotationData) - else -> Unknown(annotationData) - } - } catch (e: InconsistentKotlinMetadataException) { - throw e - } catch (e: Throwable) { - throw InconsistentKotlinMetadataException("Exception occurred when reading Kotlin metadata", e) + // All data is loaded lazily, no exceptions here to handle + return when (annotationData.kind) { + CLASS_KIND -> Class(annotationData) + FILE_FACADE_KIND -> FileFacade(annotationData) + SYNTHETIC_CLASS_KIND -> SyntheticClass(annotationData) + MULTI_FILE_CLASS_FACADE_KIND -> MultiFileClassFacade(annotationData) + MULTI_FILE_CLASS_PART_KIND -> MultiFileClassPart(annotationData) + else -> Unknown(annotationData) } } diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt index 16aa5a5e415..56958c9dbf8 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt @@ -3,7 +3,12 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -@file:Suppress("MemberVisibilityCanBePrivate", "DEPRECATION") +@file:Suppress( + "MemberVisibilityCanBePrivate", + "DEPRECATION", + "INVISIBLE_MEMBER", // InconsistentKotlinMetadataException + "INVISIBLE_REFERENCE" +) package kotlinx.metadata.jvm @@ -11,6 +16,8 @@ import kotlinx.metadata.* import kotlinx.metadata.internal.accept import kotlinx.metadata.jvm.internal.IgnoreInApiDump import kotlinx.metadata.jvm.KotlinClassMetadata.Companion.COMPATIBLE_METADATA_VERSION +import kotlinx.metadata.jvm.internal.wrapIntoMetadataExceptionWhenNeeded +import kotlinx.metadata.jvm.internal.wrapWriteIntoIAE import org.jetbrains.kotlin.metadata.jvm.JvmModuleProtoBuf import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping @@ -123,25 +130,20 @@ class KotlinModuleMetadata(@Suppress("MemberVisibilityCanBePrivate") val bytes: * Parses the given byte array with the .kotlin_module file content and returns the [KotlinModuleMetadata] instance, * or `null` if this byte array encodes a module with an unsupported metadata version. * - * Throws [InconsistentKotlinMetadataException] if an error happened while parsing the given byte array, + * @throws IllegalArgumentException if an error happened while parsing the given byte array, * which means that it's either not the content of a .kotlin_module file, or it has been corrupted. */ @JvmStatic @UnstableMetadataApi fun read(bytes: ByteArray): KotlinModuleMetadata? { - try { + return wrapIntoMetadataExceptionWhenNeeded { val result = KotlinModuleMetadata(bytes) - if (result.data == ModuleMapping.EMPTY) return null - - if (result.data == ModuleMapping.CORRUPTED) { - throw InconsistentKotlinMetadataException("Data doesn't look like the content of a .kotlin_module file") + when (result.data) { + ModuleMapping.EMPTY -> null + ModuleMapping.CORRUPTED -> + throw InconsistentKotlinMetadataException("Data is not the content of a .kotlin_module file, or it has been corrupted.") + else -> result } - - return result - } catch (e: InconsistentKotlinMetadataException) { - throw e - } catch (e: Throwable) { - throw InconsistentKotlinMetadataException("Exception occurred when reading Kotlin metadata", e) } } @@ -150,10 +152,13 @@ class KotlinModuleMetadata(@Suppress("MemberVisibilityCanBePrivate") val bytes: * * @param metadataVersion metadata version to be written to the metadata (see [Metadata.metadataVersion]), * [KotlinClassMetadata.COMPATIBLE_METADATA_VERSION] by default + * + * @throws IllegalArgumentException if [kmModule] is not correct and cannot be written or if [metadataVersion] is not supported for writing. */ @UnstableMetadataApi - fun write(kmModule: KmModule, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION): KotlinModuleMetadata = + fun write(kmModule: KmModule, metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION): KotlinModuleMetadata = wrapWriteIntoIAE { Writer().also { kmModule.accept(it) }.write(metadataVersion) + } } } diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/internal/jvmExceptionUtils.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/internal/jvmExceptionUtils.kt new file mode 100644 index 00000000000..308be8d44bd --- /dev/null +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/internal/jvmExceptionUtils.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ +@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // InconsistentKotlinMetadataException + +package kotlinx.metadata.jvm.internal + +import kotlinx.metadata.InconsistentKotlinMetadataException + +internal fun Metadata.requireNotEmpty(): Array = data1.takeIf(Array<*>::isNotEmpty) + ?: throw InconsistentKotlinMetadataException("Metadata is missing: kotlin.Metadata.data1 must not be an empty array") + +internal inline fun wrapIntoMetadataExceptionWhenNeeded(block: () -> T): T { + return try { + block() + } catch (e: Throwable) { + throw when (e) { + is IllegalArgumentException -> e // rethrow IAE as it is already correct exception type + is VirtualMachineError, is ThreadDeath -> e // rethrow VM errors + // other exceptions, like IOOBE or InvalidProtocolBufferException from proto parser + else -> InconsistentKotlinMetadataException("Exception occurred when reading Kotlin metadata", e) + } + } +} + +internal inline fun wrapWriteIntoIAE(block: () -> T): T { + return try { + block() + } catch (e: Throwable) { + throw when (e) { + is IllegalArgumentException -> e // rethrow IAE as it is already correct exception type + is VirtualMachineError, is ThreadDeath -> e // rethrow VM errors + // lateinit vars or proto writer can throw exceptions if required data is missing + else -> IllegalArgumentException("Kotlin metadata is not correct and can not be written", e) + } + } +} \ No newline at end of file diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataExceptionsTest.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataExceptionsTest.kt new file mode 100644 index 00000000000..5f3cd3bdde4 --- /dev/null +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataExceptionsTest.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlinx.metadata.test + +import kotlinx.metadata.KmClass +import kotlinx.metadata.jvm.KotlinClassMetadata +import kotlinx.metadata.jvm.Metadata +import org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException +import org.junit.Test +import kotlin.test.assertFailsWith +import kotlin.test.assertIs + +class MetadataExceptionsTest { + @Test + fun testReadMalformedInput() { + val malformedInput = "abcdefdkdgwaydgyuawdfg543awyudfuiawty" // random string guaranteed by dropping ball on a keyboard + val malformedMetadata = + Metadata(KotlinClassMetadata.CLASS_KIND, KotlinClassMetadata.COMPATIBLE_METADATA_VERSION, arrayOf(malformedInput)) + val e = assertFailsWith { + (KotlinClassMetadata.read(malformedMetadata) as KotlinClassMetadata.Class).toKmClass() + } + assertIs(e.cause) + } + + @Test + fun testWriteMalformedClass() { + val kmClass = KmClass() // kotlin.UninitializedPropertyAccessException: lateinit property name has not been initialized + val e = assertFailsWith { + KotlinClassMetadata.writeClass(kmClass) + } + assertIs(e.cause) + } +} \ No newline at end of file diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/InconsistentKotlinMetadataException.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/InconsistentKotlinMetadataException.kt index 69c84d20f59..d662ca609e0 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/InconsistentKotlinMetadataException.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/InconsistentKotlinMetadataException.kt @@ -1,8 +1,11 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package kotlinx.metadata -class InconsistentKotlinMetadataException(message: String, cause: Throwable? = null) : RuntimeException(message, cause) +/** + * A generic exception that indicates problems with metadata deserialization. + */ +internal class InconsistentKotlinMetadataException(message: String, cause: Throwable? = null) : IllegalArgumentException(message, cause) diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/readers.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/readers.kt index ff4a60409ac..dd58ef27625 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/readers.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/readers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @file:Suppress("DEPRECATION") @@ -347,7 +347,7 @@ private inline fun ProtoBuf.TypeParameter.accept( visit: (flags: Flags, name: String, id: Int, variance: KmVariance) -> KmTypeParameterVisitor?, c: ReadContext ) { - val variance = when (variance!!) { + val variance = when (requireNotNull(variance)) { ProtoBuf.TypeParameter.Variance.IN -> KmVariance.IN ProtoBuf.TypeParameter.Variance.OUT -> KmVariance.OUT ProtoBuf.TypeParameter.Variance.INV -> KmVariance.INVARIANT @@ -384,7 +384,7 @@ private fun ProtoBuf.Type.accept(v: KmTypeVisitor, c: ReadContext) { } for (argument in argumentList) { - val variance = when (argument.projection!!) { + val variance = when (requireNotNull(argument.projection)) { ProtoBuf.Type.Argument.Projection.IN -> KmVariance.IN ProtoBuf.Type.Argument.Projection.OUT -> KmVariance.OUT ProtoBuf.Type.Argument.Projection.INV -> KmVariance.INVARIANT @@ -451,13 +451,13 @@ private fun ProtoBuf.Contract.accept(v: KmContractVisitor, c: ReadContext) { for (effect in effectList) { if (!effect.hasEffectType()) continue - val effectType = when (effect.effectType!!) { + val effectType = when (requireNotNull(effect.effectType)) { ProtoBuf.Effect.EffectType.RETURNS_CONSTANT -> KmEffectType.RETURNS_CONSTANT ProtoBuf.Effect.EffectType.CALLS -> KmEffectType.CALLS ProtoBuf.Effect.EffectType.RETURNS_NOT_NULL -> KmEffectType.RETURNS_NOT_NULL } - val effectKind = if (!effect.hasKind()) null else when (effect.kind!!) { + val effectKind = if (!effect.hasKind()) null else when (requireNotNull(effect.kind)) { ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE -> KmEffectInvocationKind.AT_MOST_ONCE ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE -> KmEffectInvocationKind.EXACTLY_ONCE ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE -> KmEffectInvocationKind.AT_LEAST_ONCE @@ -491,7 +491,7 @@ private fun ProtoBuf.Expression.accept(v: KmEffectExpressionVisitor, c: ReadCont if (hasConstantValue()) { v.visitConstantValue( - when (constantValue!!) { + when (requireNotNull(constantValue)) { ProtoBuf.Expression.ConstantValue.TRUE -> true ProtoBuf.Expression.ConstantValue.FALSE -> false ProtoBuf.Expression.ConstantValue.NULL -> null diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/nodes.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/nodes.kt index 060b5dcf158..47fa7ecb2a1 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/nodes.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/nodes.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -866,6 +866,7 @@ class KmType(var flags: Flags) : KmTypeVisitor() { * Populates the given visitor with data in this type. * * @param visitor the visitor which will visit data in this type + * @throws IllegalArgumentException if type metadata is inconsistent */ @Deprecated(VISITOR_API_MESSAGE) fun accept(visitor: KmTypeVisitor) { diff --git a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Kotlinp.kt b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Kotlinp.kt index 937445417bb..81805e62ff0 100644 --- a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Kotlinp.kt +++ b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Kotlinp.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.kotlinp -import kotlinx.metadata.InconsistentKotlinMetadataException import kotlinx.metadata.jvm.KotlinClassMetadata import kotlinx.metadata.jvm.KotlinModuleMetadata import kotlinx.metadata.jvm.UnstableMetadataApi @@ -30,7 +29,7 @@ class Kotlinp(private val settings: KotlinpSettings) { val header = file.readKotlinClassHeader() ?: throw KotlinpException("file is not a Kotlin class file: $file") return try { KotlinClassMetadata.read(header) - } catch (e: InconsistentKotlinMetadataException) { + } catch (e: IllegalArgumentException) { throw KotlinpException("inconsistent Kotlin metadata: ${e.message}") } } diff --git a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt index b2e4b6e5a05..39b94337adf 100644 --- a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt +++ b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt @@ -171,7 +171,7 @@ private fun printType(type: KmType): String { } else { val (variance, argumentType) = argument if (variance == null || argumentType == null) - throw InconsistentKotlinMetadataException("Variance and type must be set for non-star type projection") + throw IllegalArgumentException("Variance and type must be set for non-star type projection") val argumentTypeString = printType(argumentType) buildString { if (variance != KmVariance.INVARIANT) {