[go: nahoru, domu]

blob: 75a123d54ee8f486542a449a1bfd77a9c9bde801 [file] [log] [blame]
/*
* Copyright 2021 The Android Open Source Project
*
* 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.
*/
package androidx.room.compiler.processing.ksp
import androidx.room.compiler.processing.XElement
import androidx.room.compiler.processing.XRoundEnv
import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticPropertyMethodElement
import com.google.devtools.ksp.KspExperimental
import com.google.devtools.ksp.symbol.ClassKind
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
import com.google.devtools.ksp.symbol.KSPropertyAccessor
import com.google.devtools.ksp.symbol.KSPropertyDeclaration
import com.google.devtools.ksp.symbol.KSValueParameter
import kotlin.reflect.KClass
internal class KspRoundEnv(
private val env: KspProcessingEnv?, // null on last round (i.e. isProcessingOver == true)
) : XRoundEnv {
override val isProcessingOver: Boolean
get() = env == null
override fun getElementsAnnotatedWith(klass: KClass<out Annotation>): Set<XElement> {
return getElementsAnnotatedWith(
annotationQualifiedName = klass.qualifiedName ?: error("No qualified name for $klass")
)
}
@OptIn(KspExperimental::class)
override fun getElementsAnnotatedWith(annotationQualifiedName: String): Set<XElement> {
if (annotationQualifiedName == "*") {
return emptySet()
}
if (isProcessingOver) {
return emptySet()
}
checkNotNull(env)
return buildSet {
env.resolver.getSymbolsWithAnnotation(annotationQualifiedName)
.forEach { symbol ->
when (symbol) {
is KSPropertyDeclaration -> {
add(KspFieldElement.create(env, symbol))
}
is KSClassDeclaration -> {
when (symbol.classKind) {
ClassKind.ENUM_ENTRY ->
add(KspEnumEntry.create(env, symbol))
else -> add(KspTypeElement.create(env, symbol))
}
}
is KSFunctionDeclaration -> {
add(env.wrapFunctionDeclaration(symbol))
}
is KSPropertyAccessor -> {
if (symbol.receiver.isStatic() &&
symbol.receiver.parentDeclaration is KSClassDeclaration &&
(symbol.receiver.hasJvmStaticAnnotation() ||
symbol.hasJvmStaticAnnotation())) {
// Getter/setter can be copied from companion object to its
// outer class if the field is annotated with @JvmStatic.
add(
KspSyntheticPropertyMethodElement.create(
env, symbol, isSyntheticStatic = true
)
)
}
// static fields are the properties that are coming from the companion.
// Whether we'll generate method for it or not depends on the JVMStatic
// annotation
if (!symbol.receiver.isStatic() ||
symbol.receiver.hasJvmStaticAnnotation() ||
symbol.hasJvmStaticAnnotation() ||
symbol.receiver.parentDeclaration !is KSClassDeclaration
) {
add(
KspSyntheticPropertyMethodElement.create(
env, symbol, isSyntheticStatic = false
)
)
}
}
is KSValueParameter -> {
add(KspExecutableParameterElement.create(env, symbol))
}
else ->
error("Unsupported $symbol with annotation $annotationQualifiedName")
}
}
env.resolver.getPackagesWithAnnotation(annotationQualifiedName)
.forEach { packageName ->
add(KspPackageElement(env, packageName))
}
}
.filter {
// Due to the bug in https://github.com/google/ksp/issues/1198, KSP may incorrectly
// copy annotations from a constructor KSValueParameter to its KSPropertyDeclaration
// which we remove manually, so check here to make sure this is in sync with the
// actual annotations on the element.
it.getAllAnnotations().any { it.qualifiedName == annotationQualifiedName }
}.toSet()
}
}