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:
@@ -34,10 +34,10 @@ import org.jetbrains.kotlin.name.Name;
|
|||||||
import org.jetbrains.kotlin.resolve.AnnotationChecker;
|
import org.jetbrains.kotlin.resolve.AnnotationChecker;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
|
|
||||||
import org.jetbrains.kotlin.resolve.constants.*;
|
import org.jetbrains.kotlin.resolve.constants.*;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
|
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil;
|
||||||
import org.jetbrains.kotlin.types.FlexibleType;
|
import org.jetbrains.kotlin.types.FlexibleType;
|
||||||
import org.jetbrains.kotlin.types.FlexibleTypesKt;
|
import org.jetbrains.kotlin.types.FlexibleTypesKt;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
@@ -376,7 +376,7 @@ public abstract class AnnotationCodegen {
|
|||||||
// We do not generate annotations whose classes are optional (annotated with `@OptionalExpectation`) because if an annotation entry
|
// We do not generate annotations whose classes are optional (annotated with `@OptionalExpectation`) because if an annotation entry
|
||||||
// is resolved to the expected declaration, this means that annotation has no actual class, and thus should not be generated.
|
// is resolved to the expected declaration, this means that annotation has no actual class, and thus should not be generated.
|
||||||
// (Otherwise we would've resolved the entry to the actual annotation class.)
|
// (Otherwise we would've resolved the entry to the actual annotation class.)
|
||||||
if (ExpectedActualDeclarationChecker.isOptionalAnnotationClass(classDescriptor)) {
|
if (OptionalAnnotationUtil.isOptionalAnnotationClass(classDescriptor)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStat
|
|||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.PackageDescriptorUtilKt;
|
import org.jetbrains.kotlin.resolve.lazy.descriptors.PackageDescriptorUtilKt;
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil;
|
||||||
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments;
|
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments;
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
import org.jetbrains.org.objectweb.asm.Type;
|
||||||
|
|
||||||
@@ -91,8 +91,8 @@ public class PackageCodegenImpl implements PackageCodegen {
|
|||||||
if (declaration instanceof KtClassOrObject) {
|
if (declaration instanceof KtClassOrObject) {
|
||||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, declaration);
|
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, declaration);
|
||||||
if (PsiUtilsKt.hasExpectModifier(declaration)) {
|
if (PsiUtilsKt.hasExpectModifier(declaration)) {
|
||||||
if (descriptor != null && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(descriptor)) {
|
if (descriptor != null && OptionalAnnotationUtil.shouldGenerateExpectClass(descriptor)) {
|
||||||
assert ExpectedActualDeclarationChecker.isOptionalAnnotationClass(descriptor) :
|
assert OptionalAnnotationUtil.isOptionalAnnotationClass(descriptor) :
|
||||||
"Expect class should be generated only if it's an optional annotation: " + descriptor;
|
"Expect class should be generated only if it's an optional annotation: " + descriptor;
|
||||||
state.getFactory().getPackagePartRegistry().getOptionalAnnotations().add(descriptor);
|
state.getFactory().getPackagePartRegistry().getOptionalAnnotations().add(descriptor);
|
||||||
}
|
}
|
||||||
|
|||||||
+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.Compatible
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ModuleFilter
|
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.resolve.source.PsiSourceFile
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
@@ -171,7 +172,7 @@ class ExpectedActualDeclarationChecker(
|
|||||||
val compatibility = ExpectedActualResolver.findActualForExpected(descriptor, module, moduleVisibilityFilter) ?: return
|
val compatibility = ExpectedActualResolver.findActualForExpected(descriptor, module, moduleVisibilityFilter) ?: return
|
||||||
|
|
||||||
// Only strong incompatibilities, but this is an OptionalExpectation -- don't report it
|
// 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
|
// Only strong incompatibilities, or error won't be reported on actual: report NO_ACTUAL_FOR_EXPECT here
|
||||||
if (compatibility.allStrongIncompatibilities() ||
|
if (compatibility.allStrongIncompatibilities() ||
|
||||||
@@ -389,41 +390,7 @@ class ExpectedActualDeclarationChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
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 =
|
fun Map<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
|
||||||
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
|
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.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||||
|
|
||||||
object OptionalExpectationChecker {
|
object OptionalExpectationChecker {
|
||||||
fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, trace: BindingTrace) {
|
fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, trace: BindingTrace) {
|
||||||
@@ -34,6 +35,6 @@ object OptionalExpectationChecker {
|
|||||||
private fun getOptionalExpectationEntry(declaration: KtDeclaration, trace: BindingTrace): KtAnnotationEntry? =
|
private fun getOptionalExpectationEntry(declaration: KtDeclaration, trace: BindingTrace): KtAnnotationEntry? =
|
||||||
declaration.annotationEntries.find { entry ->
|
declaration.annotationEntries.find { entry ->
|
||||||
val annotationDescriptor = trace.get(BindingContext.ANNOTATION, 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 com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
|
import org.jetbrains.kotlin.platform.isCommon
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.platform
|
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
|
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
|
||||||
|
|
||||||
class OptionalExpectationUsageChecker : ClassifierUsageChecker {
|
class OptionalExpectationUsageChecker : ClassifierUsageChecker {
|
||||||
override fun check(targetDescriptor: ClassifierDescriptor, element: PsiElement, context: ClassifierUsageCheckerContext) {
|
override fun check(targetDescriptor: ClassifierDescriptor, element: PsiElement, context: ClassifierUsageCheckerContext) {
|
||||||
if (!ExpectedActualDeclarationChecker.isOptionalAnnotationClass(targetDescriptor)) return
|
if (!OptionalAnnotationUtil.isOptionalAnnotationClass(targetDescriptor)) return
|
||||||
|
|
||||||
if (!element.isUsageAsAnnotationOrImport()) {
|
if (!element.isUsageAsAnnotationOrImport()) {
|
||||||
context.trace.report(Errors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY.on(element))
|
context.trace.report(Errors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY.on(element))
|
||||||
|
|||||||
+2
-2
@@ -20,9 +20,9 @@ import org.jetbrains.kotlin.ir.util.*
|
|||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||||
|
|
||||||
// `doRemove` means should expect-declaration be removed from IR
|
// `doRemove` means should expect-declaration be removed from IR
|
||||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
@@ -70,7 +70,7 @@ class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private va
|
|||||||
private fun isOptionalAnnotationClass(klass: IrClass): Boolean {
|
private fun isOptionalAnnotationClass(klass: IrClass): Boolean {
|
||||||
return klass.kind == ClassKind.ANNOTATION_CLASS &&
|
return klass.kind == ClassKind.ANNOTATION_CLASS &&
|
||||||
klass.isExpect &&
|
klass.isExpect &&
|
||||||
klass.annotations.hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)
|
klass.annotations.hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tryCopyDefaultArguments(declaration: IrValueParameter) {
|
private fun tryCopyDefaultArguments(declaration: IrValueParameter) {
|
||||||
|
|||||||
+2
-2
@@ -40,7 +40,7 @@ import org.jetbrains.kotlin.ir.util.*
|
|||||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
import org.jetbrains.org.objectweb.asm.*
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
@@ -480,4 +480,4 @@ private fun loadAnnotationTargets(targetEntry: IrConstructorCall): Set<KotlinTar
|
|||||||
private val IrClass.isOptionalAnnotationClass: Boolean
|
private val IrClass.isOptionalAnnotationClass: Boolean
|
||||||
get() = kind == ClassKind.ANNOTATION_CLASS &&
|
get() = kind == ClassKind.ANNOTATION_CLASS &&
|
||||||
isExpect &&
|
isExpect &&
|
||||||
hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)
|
hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)
|
||||||
|
|||||||
+2
-2
@@ -36,10 +36,10 @@ import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
|||||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
|
||||||
import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
@@ -334,7 +334,7 @@ fun IrClass.getVisibilityAccessFlagForClass(): Int {
|
|||||||
// TODO: Descriptor-based code also checks for `descriptor.isExpect`; we don't represent expect/actual distinction in IR thus far.
|
// TODO: Descriptor-based code also checks for `descriptor.isExpect`; we don't represent expect/actual distinction in IR thus far.
|
||||||
fun IrClass.isOptionalAnnotationClass(): Boolean =
|
fun IrClass.isOptionalAnnotationClass(): Boolean =
|
||||||
isAnnotationClass &&
|
isAnnotationClass &&
|
||||||
hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)
|
hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)
|
||||||
|
|
||||||
val IrDeclaration.isAnnotatedWithDeprecated: Boolean
|
val IrDeclaration.isAnnotatedWithDeprecated: Boolean
|
||||||
get() = annotations.hasAnnotation(FqNames.deprecated)
|
get() = annotations.hasAnnotation(FqNames.deprecated)
|
||||||
|
|||||||
+4
-4
@@ -11,18 +11,18 @@ import org.jetbrains.kotlin.library.metadata.DeserializedSourceFile
|
|||||||
import org.jetbrains.kotlin.library.metadata.KlibMetadataDeserializedPackageFragment
|
import org.jetbrains.kotlin.library.metadata.KlibMetadataDeserializedPackageFragment
|
||||||
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
|
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassConstructorDescriptor
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassConstructorDescriptor
|
|
||||||
|
|
||||||
internal val DeclarationDescriptor.isExpectMember: Boolean
|
internal val DeclarationDescriptor.isExpectMember: Boolean
|
||||||
get() = this is MemberDescriptor && this.isExpect
|
get() = this is MemberDescriptor && this.isExpect
|
||||||
|
|
||||||
internal val DeclarationDescriptor.isSerializableExpectClass: Boolean
|
internal val DeclarationDescriptor.isSerializableExpectClass: Boolean
|
||||||
get() = this is ClassDescriptor && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(this)
|
get() = this is ClassDescriptor && OptionalAnnotationUtil.shouldGenerateExpectClass(this)
|
||||||
|
|
||||||
tailrec fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor {
|
tailrec fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor {
|
||||||
return if (this is PackageFragmentDescriptor) this
|
return if (this is PackageFragmentDescriptor) this
|
||||||
|
|||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.multiplatform
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
|
||||||
|
object OptionalAnnotationUtil {
|
||||||
|
val OPTIONAL_EXPECTATION_FQ_NAME = FqName("kotlin.OptionalExpectation")
|
||||||
|
|
||||||
|
@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
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isOptionalAnnotationClass(descriptor: DeclarationDescriptor): Boolean =
|
||||||
|
descriptor is ClassDescriptor &&
|
||||||
|
descriptor.kind == ClassKind.ANNOTATION_CLASS &&
|
||||||
|
descriptor.isExpect &&
|
||||||
|
descriptor.annotations.hasAnnotation(OPTIONAL_EXPECTATION_FQ_NAME)
|
||||||
|
}
|
||||||
@@ -17,15 +17,15 @@ import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.idea.quickfix.expectactual.CreateActualClassFix
|
import org.jetbrains.kotlin.idea.quickfix.expectactual.CreateActualClassFix
|
||||||
import org.jetbrains.kotlin.platform.isCommon
|
import org.jetbrains.kotlin.platform.isCommon
|
||||||
|
import org.jetbrains.kotlin.platform.oldFashionedDescription
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.classOrObjectVisitor
|
import org.jetbrains.kotlin.psi.classOrObjectVisitor
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
|
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker.Companion.allStrongIncompatibilities
|
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker.Companion.allStrongIncompatibilities
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||||
import org.jetbrains.kotlin.platform.oldFashionedDescription
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||||
|
|
||||||
class OptionalExpectationInspection : AbstractKotlinInspection() {
|
class OptionalExpectationInspection : AbstractKotlinInspection() {
|
||||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) =
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) =
|
||||||
@@ -34,7 +34,7 @@ class OptionalExpectationInspection : AbstractKotlinInspection() {
|
|||||||
if (!classOrObject.hasExpectModifier()) return
|
if (!classOrObject.hasExpectModifier()) return
|
||||||
|
|
||||||
val descriptor = classOrObject.resolveToDescriptorIfAny() ?: return
|
val descriptor = classOrObject.resolveToDescriptorIfAny() ?: return
|
||||||
if (!descriptor.annotations.hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)) return
|
if (!descriptor.annotations.hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)) return
|
||||||
|
|
||||||
// FIXME(dsavvinov): this is wrong in HMPP model, use logic similar to ExpectedActualDeclarationChecker
|
// FIXME(dsavvinov): this is wrong in HMPP model, use logic similar to ExpectedActualDeclarationChecker
|
||||||
val implementingModules = classOrObject.findModuleDescriptor().implementingDescriptors
|
val implementingModules = classOrObject.findModuleDescriptor().implementingDescriptors
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
|
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
@@ -260,7 +260,7 @@ private fun KtPsiFactory.repairSuperTypeList(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val forbiddenAnnotationFqNames = setOf(
|
private val forbiddenAnnotationFqNames = setOf(
|
||||||
ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME,
|
OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME,
|
||||||
FqName("kotlin.ExperimentalMultiplatform"),
|
FqName("kotlin.ExperimentalMultiplatform"),
|
||||||
ExperimentalUsageChecker.OPT_IN_FQ_NAME,
|
ExperimentalUsageChecker.OPT_IN_FQ_NAME,
|
||||||
ExperimentalUsageChecker.OLD_USE_EXPERIMENTAL_FQ_NAME
|
ExperimentalUsageChecker.OLD_USE_EXPERIMENTAL_FQ_NAME
|
||||||
|
|||||||
+2
-2
@@ -18,10 +18,10 @@ import org.jetbrains.kotlin.metadata.js.JsProtoBuf
|
|||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.protobuf.CodedInputStream
|
import org.jetbrains.kotlin.protobuf.CodedInputStream
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.filterOutSourceAnnotations
|
import org.jetbrains.kotlin.resolve.descriptorUtil.filterOutSourceAnnotations
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||||
import org.jetbrains.kotlin.serialization.AnnotationSerializer
|
import org.jetbrains.kotlin.serialization.AnnotationSerializer
|
||||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||||
import org.jetbrains.kotlin.serialization.StringTableImpl
|
import org.jetbrains.kotlin.serialization.StringTableImpl
|
||||||
@@ -172,7 +172,7 @@ object KotlinJavascriptSerializationUtil {
|
|||||||
if (descriptor.module != module) return true
|
if (descriptor.module != module) return true
|
||||||
|
|
||||||
if (descriptor is MemberDescriptor && descriptor.isExpect) {
|
if (descriptor is MemberDescriptor && descriptor.isExpect) {
|
||||||
return !(descriptor is ClassDescriptor && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(descriptor))
|
return !(descriptor is ClassDescriptor && OptionalAnnotationUtil.shouldGenerateExpectClass(descriptor))
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|||||||
-4
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
@@ -155,6 +154,3 @@ val ClassDescriptor.enumEntries: List<ClassDescriptor>
|
|||||||
|
|
||||||
internal val DeclarationDescriptor.isExpectMember: Boolean
|
internal val DeclarationDescriptor.isExpectMember: Boolean
|
||||||
get() = this is MemberDescriptor && this.isExpect
|
get() = this is MemberDescriptor && this.isExpect
|
||||||
|
|
||||||
internal val DeclarationDescriptor.isSerializableExpectClass: Boolean
|
|
||||||
get() = this is ClassDescriptor && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(this)
|
|
||||||
|
|||||||
+2
-6
@@ -23,9 +23,9 @@ import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
|||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This pass removes all declarations with `isExpect == true`.
|
* This pass removes all declarations with `isExpect == true`.
|
||||||
@@ -71,11 +71,7 @@ internal class ExpectToActualDefaultValueCopier(private val irModule: IrModuleFr
|
|||||||
val index = declaration.index
|
val index = declaration.index
|
||||||
assert(function.valueParameters[index] == declaration)
|
assert(function.valueParameters[index] == declaration)
|
||||||
|
|
||||||
if (function is IrConstructor &&
|
if (function is IrConstructor && OptionalAnnotationUtil.isOptionalAnnotationClass(function.descriptor.constructedClass)) {
|
||||||
ExpectedActualDeclarationChecker.isOptionalAnnotationClass(
|
|
||||||
function.descriptor.constructedClass
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user