aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt29
-rw-r--r--compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt6
-rw-r--r--compiler-plugin/testData/api/getAnnotationByTypeWithInnerDefault.kt42
-rw-r--r--compiler-plugin/testData/api/getByName.kt3
-rw-r--r--test-utils/src/main/kotlin/com/google/devtools/ksp/processor/GetAnnotationByTypeProcessor.kt36
-rw-r--r--test-utils/src/main/kotlin/com/google/devtools/ksp/processor/GetByNameProcessor.kt12
6 files changed, 124 insertions, 4 deletions
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt
index 2a32b5df..69aff1e1 100644
--- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt
@@ -20,6 +20,7 @@ package com.google.devtools.ksp.symbol.impl.binary
import com.google.devtools.ksp.ExceptionMessage
import com.google.devtools.ksp.KSObjectCache
import com.google.devtools.ksp.findPsi
+import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.processing.impl.ResolverImpl
import com.google.devtools.ksp.symbol.*
import com.google.devtools.ksp.symbol.impl.java.KSAnnotationJavaImpl
@@ -35,6 +36,7 @@ import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.NotFoundClasses
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.load.java.components.JavaAnnotationDescriptor
@@ -53,7 +55,9 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
import org.jetbrains.kotlin.resolve.constants.*
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
@@ -160,14 +164,31 @@ internal fun AnnotationDescriptor.getDefaultArguments(ownerAnnotation: KSAnnotat
return this.type.getDefaultConstructorArguments(emptyList(), ownerAnnotation)
}
+internal fun TypeConstructor.toDeclarationDescriptor(): ClassDescriptor? {
+ if (this.declarationDescriptor !is NotFoundClasses.MockClassDescriptor) {
+ return this.declarationDescriptor as? ClassDescriptor
+ }
+ val fqName = (this.declarationDescriptor as? ClassDescriptor)?.fqNameSafe ?: return null
+ val shortNames = fqName.shortName().asString().split("$")
+ var parent = ResolverImpl.instance!!
+ .getClassDeclarationByName("${fqName.parent().asString()}.${shortNames.first()}")
+ for (i in 1 until shortNames.size) {
+ if (parent == null) {
+ return null
+ }
+ parent = parent.declarations
+ .filterIsInstance<KSClassDeclaration>()
+ .singleOrNull { it.simpleName.asString() == shortNames[i] }
+ }
+ return parent?.let { ResolverImpl.instance!!.resolveClassDeclaration(it) }
+}
+
internal fun KotlinType.getDefaultConstructorArguments(
excludeNames: List<String>,
ownerAnnotation: KSAnnotation
): List<KSValueArgument> {
- return (this.constructor.declarationDescriptor as? ClassDescriptor)?.constructors?.single()
- ?.let { argumentsFromDefault ->
- argumentsFromDefault.getAbsentDefaultArguments(excludeNames, ownerAnnotation)
- } ?: emptyList()
+ return this.constructor.toDeclarationDescriptor()?.constructors?.single()
+ ?.getAbsentDefaultArguments(excludeNames, ownerAnnotation) ?: emptyList()
}
fun ClassConstructorDescriptor.getAbsentDefaultArguments(
diff --git a/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt b/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt
index 58ebfee6..aa3c8506 100644
--- a/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt
+++ b/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt
@@ -230,6 +230,12 @@ class KSPCompilerPluginTest : AbstractKSPCompilerPluginTest() {
runTest("testData/api/functionTypes.kt")
}
+ @TestMetadata("getAnnotationByTypeWithInnerDefault.kt")
+ @Test
+ fun testGetAnnotationByTypeWithInnerDefault() {
+ runTest("testData/api/getAnnotationByTypeWithInnerDefault.kt")
+ }
+
@DisabledOnOs(OS.WINDOWS)
@TestMetadata("getPackage.kt")
@Test
diff --git a/compiler-plugin/testData/api/getAnnotationByTypeWithInnerDefault.kt b/compiler-plugin/testData/api/getAnnotationByTypeWithInnerDefault.kt
new file mode 100644
index 00000000..56346813
--- /dev/null
+++ b/compiler-plugin/testData/api/getAnnotationByTypeWithInnerDefault.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2022 Google LLC
+ * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// WITH_RUNTIME
+// TEST PROCESSOR: GetAnnotationByTypeProcessor
+// EXPECTED:
+// com.google.devtools.ksp.processor.KotlinAnnotationWithInnerDefaults.InnerAnnotation[innerAnnotationDefault=7, moreInnerAnnotation=com.google.devtools.ksp.processor.KotlinAnnotationWithInnerDefaults.InnerAnnotation.MoreInnerAnnotation[moreInnerAnnotationDefault=OK]]
+// END
+// MODULE: lib
+// FILE: KotlinAnnotationWithInnerDefaults.kt
+package com.google.devtools.ksp.processor
+annotation class KotlinAnnotationWithInnerDefaults(
+ val innerAnnotationVal: InnerAnnotation = InnerAnnotation(innerAnnotationDefault = 7)
+) {
+ annotation class InnerAnnotation(
+ val innerAnnotationDefault: Int,
+ val moreInnerAnnotation: MoreInnerAnnotation = MoreInnerAnnotation("OK")
+ ) {
+ annotation class MoreInnerAnnotation(val moreInnerAnnotationDefault: String)
+ }
+}
+
+// MODULE: main(lib)
+// FILE: com/google/devtools/ksp/processor/a.kt
+package com.google.devtools.ksp.processor
+
+@KotlinAnnotationWithInnerDefaults
+class A
diff --git a/compiler-plugin/testData/api/getByName.kt b/compiler-plugin/testData/api/getByName.kt
index 5ab44ce5..51f826b0 100644
--- a/compiler-plugin/testData/api/getByName.kt
+++ b/compiler-plugin/testData/api/getByName.kt
@@ -28,6 +28,8 @@ open class Foo {
fun overload(a: Int) = "Overload"
fun overload() = "Overload"
val lib1MemberProp = 1.0
+
+ class FooNested {}
}
fun lib1TopFun(): Int {
@@ -61,6 +63,7 @@ package source
class FooInSource {
fun sourceMemberFun() = 1
val sourceMemberProp = 1.0
+ class FooInSourceNested
}
val propInSource = 1
diff --git a/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/GetAnnotationByTypeProcessor.kt b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/GetAnnotationByTypeProcessor.kt
new file mode 100644
index 00000000..8615cdb8
--- /dev/null
+++ b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/GetAnnotationByTypeProcessor.kt
@@ -0,0 +1,36 @@
+package com.google.devtools.ksp.processor
+
+import com.google.devtools.ksp.KspExperimental
+import com.google.devtools.ksp.getAnnotationsByType
+import com.google.devtools.ksp.processing.Resolver
+import com.google.devtools.ksp.symbol.KSAnnotated
+import com.google.devtools.ksp.symbol.KSClassDeclaration
+
+annotation class KotlinAnnotationWithInnerDefaults(
+ val innerAnnotationVal: InnerAnnotation = InnerAnnotation(innerAnnotationDefault = 7)
+) {
+ annotation class InnerAnnotation(
+ val innerAnnotationDefault: Int,
+ val moreInnerAnnotation: MoreInnerAnnotation = MoreInnerAnnotation("OK")
+ ) {
+ annotation class MoreInnerAnnotation(val moreInnerAnnotationDefault: String)
+ }
+}
+
+class GetAnnotationByTypeProcessor : AbstractTestProcessor() {
+ val results = mutableListOf<String>()
+ private val annotationKClass = KotlinAnnotationWithInnerDefaults::class
+
+ override fun toResult(): List<String> {
+ return results
+ }
+
+ @OptIn(KspExperimental::class)
+ override fun process(resolver: Resolver): List<KSAnnotated> {
+ val decl = resolver.getAllFiles().single().declarations
+ .single { it.simpleName.asString() == "A" } as KSClassDeclaration
+ val anno = decl.getAnnotationsByType(annotationKClass).first()
+ results.add(anno.innerAnnotationVal.toString())
+ return emptyList()
+ }
+}
diff --git a/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/GetByNameProcessor.kt b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/GetByNameProcessor.kt
index bc406df2..c7e49eec 100644
--- a/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/GetByNameProcessor.kt
+++ b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/GetByNameProcessor.kt
@@ -1,5 +1,6 @@
package com.google.devtools.ksp.processor
+import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.getFunctionDeclarationsByName
import com.google.devtools.ksp.getPropertyDeclarationByName
import com.google.devtools.ksp.processing.Resolver
@@ -13,6 +14,12 @@ class GetByNameProcessor : AbstractTestProcessor() {
}
override fun process(resolver: Resolver): List<KSAnnotated> {
+ val classNames = listOf(
+ "lib1.Foo",
+ "lib1.Foo.FooNested",
+ "source.FooInSource",
+ "source.FooInSource.FooInSourceNested"
+ )
val funNames = listOf(
"lib1.Foo.lib1MemberFun",
"lib1.lib1TopFun",
@@ -28,6 +35,11 @@ class GetByNameProcessor : AbstractTestProcessor() {
"source.FooInSource.sourceMemberProp",
"source.propInSource",
)
+ for (className in classNames) {
+ if (resolver.getClassDeclarationByName(className) == null) {
+ results.add("failed to get $className")
+ }
+ }
for (funName in funNames) {
if (resolver.getFunctionDeclarationsByName(funName, true).none()) {
results.add("failed to get $funName")