やること
以下のクラスのコンストラクタの引数について、それぞれの型/型引数のnullability
を取得します。
data class Foo(val nonNullList: List<Any>, val nullableList: List<Any?>, val starList: List<*>?)
やり方
ソースコード全体は以下の通りです。
細かい部分はコメントに記述してあります。
import kotlinx.metadata.Flag
import kotlinx.metadata.KmClass
import kotlinx.metadata.KmConstructor
import kotlinx.metadata.KmType
import kotlinx.metadata.jvm.KotlinClassHeader
import kotlinx.metadata.jvm.KotlinClassMetadata
data class Foo(val nonNullList: List<Any>, val nullableList: List<Any?>, val starList: List<*>?)
fun Metadata.toKotlinClassHeader() = KotlinClassHeader(
this.kind,
this.metadataVersion,
this.data1,
this.data2,
this.extraString,
this.packageName,
this.extraInt
)
val KmType.isNullable: Boolean get() = Flag.Type.IS_NULLABLE(flags)
fun main() {
// メタデータ取得 -> クラス情報に変換 -> 対象となるコンストラクタを取得
val metadata: KotlinClassMetadata.Class = (Foo::class.java.annotations.first { it is Metadata } as Metadata)
.toKotlinClassHeader()
.let { KotlinClassMetadata.read(it) as KotlinClassMetadata.Class }
val kmClass: KmClass = metadata.toKmClass()
val constructor: KmConstructor = kmClass.constructors.single()
// コンストラクタの引数の型情報、typeプロパティは引数がvarargだった場合nullになる
val parameterTypes: List<KmType?> = constructor.valueParameters.map { it.type }
// 引数のnullability確認(今回はvararg引数が無いため強制アンラップ)
println(parameterTypes.map { it!!.isNullable }) // -> [false, false, true]
// 型引数情報、argumentsは型引数一覧で、今回の処理対象はListで型引数は1つなためsingle()している
val typeParameters: List<KmType?> = parameterTypes.map { it!!.arguments.single().type }
// 型引数のnullability確認、指定がスタープロジェクションだった場合nullになる
println(typeParameters.map { it?.isNullable }) // -> [false, true, null]
}