[FE 1.0] Extract NativeObjCNameOverridesChecker from NativeObjCNameChecker

This commit is contained in:
Rick Clephas
2022-08-19 18:57:07 +02:00
committed by teamcity
parent 77bfe542c3
commit 115db22c12
3 changed files with 60 additions and 39 deletions
@@ -16,17 +16,17 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object NativeObjCNameChecker : DeclarationChecker {
private val objCNameFqName = FqName("kotlin.native.ObjCName")
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
checkDeclaration(declaration, descriptor, context)
checkOverrides(declaration, descriptor, context)
checkFakeOverrides(declaration, descriptor, context)
if (descriptor is CallableMemberDescriptor) {
NativeObjCNameOverridesChecker.check(declaration, descriptor, context)
}
}
private fun checkDeclaration(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
@@ -84,29 +84,7 @@ object NativeObjCNameChecker : DeclarationChecker {
}
}
private fun checkOverrides(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor !is CallableMemberDescriptor || descriptor.overriddenDescriptors.isEmpty()) return
val objCNames = descriptor.overriddenDescriptors.map { it.getFirstBaseDescriptor().getObjCNames() }
if (!objCNames.allNamesEquals()) {
val containingDeclarations = descriptor.overriddenDescriptors.map { it.containingDeclaration }
context.trace.report(ErrorsNative.INCOMPATIBLE_OBJC_NAME_OVERRIDE.on(declaration, descriptor, containingDeclarations))
}
}
private fun checkFakeOverrides(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor !is ClassDescriptor) return
descriptor.defaultType.memberScope
.getContributedDescriptors(DescriptorKindFilter.ALL, MemberScope.Companion.ALL_NAME_FILTER)
.forEach {
if (it !is CallableMemberDescriptor || it.kind.isReal) return@forEach
checkOverrides(declaration, it, context)
}
}
private fun CallableMemberDescriptor.getFirstBaseDescriptor(): CallableMemberDescriptor =
if (overriddenDescriptors.isEmpty()) this else overriddenDescriptors.first().getFirstBaseDescriptor()
private class ObjCName(
class ObjCName(
val annotation: AnnotationDescriptor
) {
val name: String? = annotation.argumentValue("name")?.value?.safeAs<String>()?.takeIf { it.isNotBlank() }
@@ -126,20 +104,13 @@ object NativeObjCNameChecker : DeclarationChecker {
private fun DeclarationDescriptor.getObjCName(): ObjCName? = annotations.findAnnotation(objCNameFqName)?.let(::ObjCName)
private fun DeclarationDescriptor.getObjCNames(): List<ObjCName?> = when (this) {
fun DeclarationDescriptor.getObjCNames(): List<ObjCName?> = when (this) {
is FunctionDescriptor -> buildList {
add(getObjCName())
add(extensionReceiverParameter?.getObjCName())
valueParameters.forEach { add(it.getObjCName()) }
}
else -> listOf(getObjCName())
}
private fun List<List<ObjCName?>>.allNamesEquals(): Boolean {
val first = this[0]
for (i in 1 until size) {
if (first != this[i]) return false
}
return true
}
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2022 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.konan.diagnostics
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.konan.diagnostics.NativeObjCNameChecker.getObjCNames
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
object NativeObjCNameOverridesChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor !is ClassDescriptor) return
descriptor.defaultType.memberScope
.getContributedDescriptors(DescriptorKindFilter.ALL, MemberScope.Companion.ALL_NAME_FILTER)
.forEach {
if (it !is CallableMemberDescriptor || it.kind.isReal) return@forEach
check(declaration, it, context)
}
}
fun check(declaration: KtDeclaration, descriptor: CallableMemberDescriptor, context: DeclarationCheckerContext) {
if (descriptor.overriddenDescriptors.isEmpty()) return
val objCNames = descriptor.overriddenDescriptors.map { it.getFirstBaseDescriptor().getObjCNames() }
if (!objCNames.allNamesEquals()) {
val containingDeclarations = descriptor.overriddenDescriptors.map { it.containingDeclaration }
context.trace.report(ErrorsNative.INCOMPATIBLE_OBJC_NAME_OVERRIDE.on(declaration, descriptor, containingDeclarations))
}
}
private fun CallableMemberDescriptor.getFirstBaseDescriptor(): CallableMemberDescriptor =
if (overriddenDescriptors.isEmpty()) this else overriddenDescriptors.first().getFirstBaseDescriptor()
private fun List<List<NativeObjCNameChecker.ObjCName?>>.allNamesEquals(): Boolean {
val first = this[0]
for (i in 1 until size) {
if (first != this[i]) return false
}
return true
}
}
@@ -24,8 +24,9 @@ object NativePlatformConfigurator : PlatformConfiguratorBase(
additionalDeclarationCheckers = listOf(
NativeThrowsChecker, NativeSharedImmutableChecker,
NativeTopLevelSingletonChecker, NativeThreadLocalChecker,
NativeObjCNameChecker, NativeObjCRefinementChecker,
NativeObjCRefinementAnnotationChecker, NativeObjCRefinementOverridesChecker
NativeObjCNameChecker, NativeObjCNameOverridesChecker,
NativeObjCRefinementChecker, NativeObjCRefinementAnnotationChecker,
NativeObjCRefinementOverridesChecker
)
) {
override fun configureModuleComponents(container: StorageComponentContainer) {