1 /*
2  * Copyright 2018 The Android Open Source Project
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 androidx.room.ext
18 
19 import me.eugeniomarletti.kotlin.metadata.KotlinClassMetadata
20 import me.eugeniomarletti.kotlin.metadata.KotlinMetadataUtils
21 import me.eugeniomarletti.kotlin.metadata.jvm.getJvmConstructorSignature
22 import me.eugeniomarletti.kotlin.metadata.shadow.metadata.ProtoBuf
23 import me.eugeniomarletti.kotlin.metadata.shadow.serialization.deserialization.getName
24 import javax.lang.model.element.ExecutableElement
25 
26 /**
27  * Utility interface for processors that wants to run kotlin specific code.
28  */
29 interface KotlinMetadataProcessor : KotlinMetadataUtils {
30     /**
31      * Returns the parameter names of the function if all have names embedded in the metadata.
32      */
KotlinClassMetadatanull33     fun KotlinClassMetadata.getParameterNames(method: ExecutableElement): List<String>? {
34         val valueParameterList = this.data.getFunctionOrNull(method)?.valueParameterList
35                 ?: findConstructor(method)?.valueParameterList
36                 ?: return null
37         return if (valueParameterList.all { it.hasName() }) {
38             valueParameterList.map {
39                 data.nameResolver.getName(it.name)
40                         .asString()
41                         .replace("`", "")
42                         .removeSuffix("?")
43                         .trim()
44             }
45         } else {
46             null
47         }
48     }
49 
50     /**
51      * Finds the kotlin metadata for a constructor.
52      */
findConstructornull53     private fun KotlinClassMetadata.findConstructor(
54             executableElement: ExecutableElement
55     ): ProtoBuf.Constructor? {
56         val (nameResolver, classProto) = data
57         val jvmSignature = executableElement.jvmMethodSignature
58         // find constructor
59         return classProto.constructorList.singleOrNull {
60             it.getJvmConstructorSignature(nameResolver, classProto.typeTable) == jvmSignature
61         }
62     }
63 }