Move optional annotation utilities to module 'resolution'
To avoid depending on a heavy module 'frontend' in parts of the compiler where checking for optional annotations is needed, such as in 'ir.serialization.common'.
This commit is contained in:
+2
-35
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compati
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Compatible
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ModuleFilter
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -171,7 +172,7 @@ class ExpectedActualDeclarationChecker(
|
||||
val compatibility = ExpectedActualResolver.findActualForExpected(descriptor, module, moduleVisibilityFilter) ?: return
|
||||
|
||||
// Only strong incompatibilities, but this is an OptionalExpectation -- don't report it
|
||||
if (compatibility.allStrongIncompatibilities() && isOptionalAnnotationClass(descriptor)) return
|
||||
if (compatibility.allStrongIncompatibilities() && OptionalAnnotationUtil.isOptionalAnnotationClass(descriptor)) return
|
||||
|
||||
// Only strong incompatibilities, or error won't be reported on actual: report NO_ACTUAL_FOR_EXPECT here
|
||||
if (compatibility.allStrongIncompatibilities() ||
|
||||
@@ -389,41 +390,7 @@ class ExpectedActualDeclarationChecker(
|
||||
}
|
||||
|
||||
companion object {
|
||||
val OPTIONAL_EXPECTATION_FQ_NAME = FqName("kotlin.OptionalExpectation")
|
||||
|
||||
@JvmStatic
|
||||
fun isOptionalAnnotationClass(descriptor: DeclarationDescriptor): Boolean =
|
||||
descriptor is ClassDescriptor &&
|
||||
descriptor.kind == ClassKind.ANNOTATION_CLASS &&
|
||||
descriptor.isExpect &&
|
||||
descriptor.annotations.hasAnnotation(OPTIONAL_EXPECTATION_FQ_NAME)
|
||||
|
||||
// TODO: move to some other place which is accessible both from backend-common and js.serializer
|
||||
@JvmStatic
|
||||
fun shouldGenerateExpectClass(descriptor: ClassDescriptor): Boolean {
|
||||
assert(descriptor.isExpect) { "Not an expected class: $descriptor" }
|
||||
|
||||
if (isOptionalAnnotationClass(descriptor)) {
|
||||
with(ExpectedActualResolver) {
|
||||
return descriptor.findCompatibleActualForExpected(descriptor.module).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun Map<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
|
||||
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
|
||||
|
||||
private fun <K, V> LinkedHashMap<K, List<V>>.merge(other: Map<K, List<V>>): LinkedHashMap<K, List<V>> {
|
||||
for ((key, newValue) in other) {
|
||||
val oldValue = this[key] ?: emptyList()
|
||||
this[key] = oldValue + newValue
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
private fun ModuleInfo.unwrapModuleInfo(): List<ModuleInfo> = if (this is CombinedModuleInfo) this.containedModules else listOf(this)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||
|
||||
object OptionalExpectationChecker {
|
||||
fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, trace: BindingTrace) {
|
||||
@@ -34,6 +35,6 @@ object OptionalExpectationChecker {
|
||||
private fun getOptionalExpectationEntry(declaration: KtDeclaration, trace: BindingTrace): KtAnnotationEntry? =
|
||||
declaration.annotationEntries.find { entry ->
|
||||
val annotationDescriptor = trace.get(BindingContext.ANNOTATION, entry)
|
||||
annotationDescriptor?.fqName == ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME
|
||||
annotationDescriptor?.fqName == OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -8,14 +8,15 @@ package org.jetbrains.kotlin.resolve.checkers
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.platform
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
|
||||
|
||||
class OptionalExpectationUsageChecker : ClassifierUsageChecker {
|
||||
override fun check(targetDescriptor: ClassifierDescriptor, element: PsiElement, context: ClassifierUsageCheckerContext) {
|
||||
if (!ExpectedActualDeclarationChecker.isOptionalAnnotationClass(targetDescriptor)) return
|
||||
if (!OptionalAnnotationUtil.isOptionalAnnotationClass(targetDescriptor)) return
|
||||
|
||||
if (!element.isUsageAsAnnotationOrImport()) {
|
||||
context.trace.report(Errors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY.on(element))
|
||||
|
||||
Reference in New Issue
Block a user