1 /* 2 * Copyright (C) 2023 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger.hilt.processor.internal.kotlin 18 19 import androidx.room.compiler.processing.XAnnotation 20 import androidx.room.compiler.processing.XFieldElement 21 import androidx.room.compiler.processing.XMethodElement 22 import androidx.room.compiler.processing.XTypeElement 23 import kotlin.Metadata 24 import kotlin.metadata.declaresDefaultValue 25 import kotlin.metadata.KmClass 26 import kotlin.metadata.KmConstructor 27 import kotlin.metadata.KmFunction 28 import kotlin.metadata.KmProperty 29 import kotlin.metadata.KmValueParameter 30 import kotlin.metadata.jvm.KotlinClassMetadata 31 import kotlin.metadata.jvm.fieldSignature 32 import kotlin.metadata.jvm.getterSignature 33 import kotlin.metadata.jvm.signature 34 import kotlin.metadata.jvm.syntheticMethodForAnnotations 35 36 /** Container classes for kotlin metadata types. */ 37 class ClassMetadata private constructor(private val kmClass: KmClass) { <lambda>null38 val functionsBySignature = buildList<FunctionMetadata> { 39 addAll(kmClass.constructors.map { ConstructorMetadata(it) }) 40 addAll(kmClass.functions.map { MethodMetadata(it) }) 41 }.associateBy { it.signature } 42 43 val propertiesBySignature = 44 kmClass.properties <lambda>null45 .filter { it.fieldSignature != null } <lambda>null46 .map { PropertyMetadata(it) } <lambda>null47 .associateBy { it.fieldSignature } 48 constructorsnull49 fun constructors(): List<FunctionMetadata> = 50 functionsBySignature.values.filterIsInstance<ConstructorMetadata>() 51 52 companion object { 53 /** Parse Kotlin class metadata from a given type element. */ 54 @JvmStatic 55 fun of(typeElement: XTypeElement): ClassMetadata { 56 val metadataAnnotation = checkNotNull(typeElement.getAnnotation(Metadata::class)).value 57 return when (val classMetadata = KotlinClassMetadata.readStrict(metadataAnnotation)) { 58 is KotlinClassMetadata.Class -> ClassMetadata(classMetadata.kmClass) 59 else -> error("Unsupported metadata type: ${classMetadata}") 60 } 61 } 62 } 63 } 64 65 class ConstructorMetadata(private val kmConstructor: KmConstructor) : FunctionMetadata { 66 override val name = "<init>" 67 override val signature = kmConstructor.signature!!.toString() <lambda>null68 override val parameters = kmConstructor.valueParameters.map { ParameterMetadata(it) } 69 } 70 71 class MethodMetadata(private val kmFunction: KmFunction) : FunctionMetadata { 72 override val name = kmFunction.name 73 override val signature = kmFunction.signature!!.toString() <lambda>null74 override val parameters = kmFunction.valueParameters.map { ParameterMetadata(it) } 75 } 76 77 interface FunctionMetadata { 78 val name: String 79 val signature: String 80 val parameters: List<ParameterMetadata> 81 } 82 83 class PropertyMetadata(private val kmProperty: KmProperty) { 84 val name = kmProperty.name 85 86 /** Returns the JVM field descriptor of the backing field of this property. */ 87 val fieldSignature = kmProperty.fieldSignature?.toString() 88 89 val getterSignature = kmProperty.getterSignature?.toString() 90 91 /** Returns JVM method descriptor of the synthetic method for property annotations. */ 92 val methodForAnnotationsSignature = kmProperty.syntheticMethodForAnnotations?.toString() 93 } 94 95 class ParameterMetadata(private val kmValueParameter: KmValueParameter) { 96 val name = kmValueParameter.name 97 declaresDefaultValuenull98 fun declaresDefaultValue() = kmValueParameter.declaresDefaultValue 99 } 100 101