1 /*
2  * Copyright (C) 2019 Square, Inc.
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  * https://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 package com.squareup.kotlinpoet.metadata.specs
17 
18 import com.squareup.kotlinpoet.ClassName
19 import kotlin.metadata.KmClass
20 import kotlin.metadata.KmDeclarationContainer
21 import kotlin.metadata.jvm.JvmMethodSignature
22 
23 /** A basic interface for looking up JVM information about a given Class. */
24 public interface ClassInspector {
25 
26   /**
27    * Indicates if this [ClassInspector] supports [AnnotationRetention.RUNTIME]-retained annotations.
28    * This is used to indicate if manual inference of certain non-RUNTIME-retained annotations should
29    * be done, such as [JvmName].
30    */
31   public val supportsNonRuntimeRetainedAnnotations: Boolean
32 
33   /**
34    * Creates a new [ContainerData] instance for a given [declarationContainer].
35    *
36    * @param declarationContainer the source [KmDeclarationContainer] to read from.
37    * @param className the [ClassName] of the target class to to read from.
38    * @param parentClassName the parent [ClassName] name if [declarationContainer] is nested, inner,
39    * or is a companion object.
40    */
containerDatanull41   public fun containerData(
42     declarationContainer: KmDeclarationContainer,
43     className: ClassName,
44     parentClassName: ClassName?,
45   ): ContainerData
46 
47   /**
48    * Looks up other declaration containers, such as for nested members. Note that this class would
49    * always be Kotlin, so Metadata can be relied on for this.
50    *
51    * @param className The [ClassName] representation of the class.
52    * @return the read [KmDeclarationContainer] from its metadata. If no class or facade
53    *         file was found, this should throw an exception.
54    */
55   public fun declarationContainerFor(className: ClassName): KmDeclarationContainer
56 
57   /**
58    * Looks up a class and returns whether or not it is an interface. Note that this class can be
59    * Java or Kotlin, so Metadata should not be relied on for this.
60    *
61    * @param className The [ClassName] representation of the class.
62    * @return whether or not it is an interface.
63    */
64   public fun isInterface(className: ClassName): Boolean
65 
66   /**
67    * Looks up the enum entry on a given enum given its member name.
68    *
69    * @param enumClassName The [ClassName] representation of the enum class.
70    * @param memberName The simple member name.
71    * @return the [EnumEntryData]
72    */
73   public fun enumEntry(enumClassName: ClassName, memberName: String): EnumEntryData
74 
75   /**
76    * Looks up if a given [methodSignature] within [className] exists.
77    *
78    * @param className The [ClassName] representation of the class.
79    * @param methodSignature The method signature to check.
80    * @return whether or not the method exists.
81    */
82   public fun methodExists(className: ClassName, methodSignature: JvmMethodSignature): Boolean
83 }
84 
85 /**
86  * Creates a new [ContainerData] instance for a given [className].
87  *
88  * @param className the [ClassName] of the target class to to read from.
89  * @param parentClassName the parent [ClassName] name if [className] is nested, inner, or is a
90  *        companion object.
91  */
92 public fun ClassInspector.containerData(
93   className: ClassName,
94   parentClassName: ClassName?,
95 ): ContainerData {
96   return containerData(declarationContainerFor(className), className, parentClassName)
97 }
98 
99 /**
100  * Looks up other classes, such as for nested members. Note that this class would always be
101  * Kotlin, so Metadata can be relied on for this.
102  *
103  * @param className The [ClassName] representation of the class.
104  * @return the read [KmClass] from its metadata. If no class was found, this should throw
105  *         an exception.
106  */
classFornull107 public fun ClassInspector.classFor(className: ClassName): KmClass {
108   val container = declarationContainerFor(className)
109   check(container is KmClass) {
110     "Container is not a class! Was ${container.javaClass.simpleName}"
111   }
112   return container
113 }
114