[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.annotations.argumentValue
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext 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 import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object NativeObjCNameChecker : DeclarationChecker { object NativeObjCNameChecker : DeclarationChecker {
private val objCNameFqName = FqName("kotlin.native.ObjCName") private val objCNameFqName = FqName("kotlin.native.ObjCName")
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
checkDeclaration(declaration, descriptor, context) checkDeclaration(declaration, descriptor, context)
checkOverrides(declaration, descriptor, context) if (descriptor is CallableMemberDescriptor) {
checkFakeOverrides(declaration, descriptor, context) NativeObjCNameOverridesChecker.check(declaration, descriptor, context)
}
} }
private fun checkDeclaration(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { 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) { class ObjCName(
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(
val annotation: AnnotationDescriptor val annotation: AnnotationDescriptor
) { ) {
val name: String? = annotation.argumentValue("name")?.value?.safeAs<String>()?.takeIf { it.isNotBlank() } 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.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 { is FunctionDescriptor -> buildList {
add(getObjCName()) add(getObjCName())
add(extensionReceiverParameter?.getObjCName()) add(extensionReceiverParameter?.getObjCName())
valueParameters.forEach { add(it.getObjCName()) } valueParameters.forEach { add(it.getObjCName()) }
} }
else -> listOf(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( additionalDeclarationCheckers = listOf(
NativeThrowsChecker, NativeSharedImmutableChecker, NativeThrowsChecker, NativeSharedImmutableChecker,
NativeTopLevelSingletonChecker, NativeThreadLocalChecker, NativeTopLevelSingletonChecker, NativeThreadLocalChecker,
NativeObjCNameChecker, NativeObjCRefinementChecker, NativeObjCNameChecker, NativeObjCNameOverridesChecker,
NativeObjCRefinementAnnotationChecker, NativeObjCRefinementOverridesChecker NativeObjCRefinementChecker, NativeObjCRefinementAnnotationChecker,
NativeObjCRefinementOverridesChecker
) )
) { ) {
override fun configureModuleComponents(container: StorageComponentContainer) { override fun configureModuleComponents(container: StorageComponentContainer) {