From 19021ec1aabc2b7420c8b4921d85cde0648c7343 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 27 Apr 2017 20:51:34 +0300 Subject: [PATCH] VarianceChecker refactoring: move checkClassOrObject to IDE --- .../kotlin/resolve/VarianceChecker.kt | 43 +++++-------------- .../AddVarianceModifierInspection.kt | 32 ++++++++++++-- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt index 1ec1635af1c..c8b47387cf5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt @@ -23,8 +23,10 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyAccessorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType +import org.jetbrains.kotlin.psi.KtCallableDeclaration +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtTypeParameterListOwner +import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.typeBinding.TypeBinding import org.jetbrains.kotlin.resolve.typeBinding.createTypeBinding @@ -33,7 +35,6 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance.* import org.jetbrains.kotlin.types.checkTypePosition -import org.jetbrains.kotlin.types.getAbbreviatedType class ManualVariance(val descriptor: TypeParameterDescriptor, val variance: Variance) @@ -52,7 +53,7 @@ class VarianceConflictDiagnosticData( ) class VarianceCheckerCore( - private val context: BindingContext, + val context: BindingContext, private val diagnosticSink: DiagnosticSink, private val manualVariance: ManualVariance? = null ) { @@ -62,39 +63,15 @@ class VarianceCheckerCore( checkMembers(c) } - fun checkClassOrObject(klass: KtClassOrObject): Boolean { - if (klass is KtClass) { - if (!checkClassHeader(klass)) return false - if (klass.getSuperTypeList()?.anyDescendantOfType { !checkClassOrObject(it) } == true) return false - } - for (member in klass.declarations + klass.primaryConstructorParameters) { - val descriptor = when (member) { - is KtParameter -> context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, member) - is KtDeclaration -> context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, member) - else -> null - } as? MemberDescriptor ?: continue - when (member) { - is KtClassOrObject -> { - if (!checkClassOrObject(member)) return false - } - is KtCallableDeclaration -> { - if (descriptor is CallableMemberDescriptor && !checkMember(member, descriptor)) return false - if (member.anyDescendantOfType { !checkClassOrObject(it) }) return false - } - } - } - return true - } - private fun checkClasses(c: TopDownAnalysisContext) { - for (jetClassOrObject in c.declaredClasses!!.keys) { - if (jetClassOrObject is KtClass) { - checkClassHeader(jetClassOrObject) + for (classOrObject in c.declaredClasses!!.keys) { + if (classOrObject is KtClass) { + checkClassHeader(classOrObject) } } } - private fun checkClassHeader(klass: KtClass): Boolean { + fun checkClassHeader(klass: KtClass): Boolean { var noError = true for (specifier in klass.superTypeListEntries) { noError = noError and specifier.typeReference?.checkTypePosition(context, OUT_VARIANCE) @@ -108,7 +85,7 @@ class VarianceCheckerCore( } } - private fun checkMember(member: KtCallableDeclaration, descriptor: CallableMemberDescriptor) = + fun checkMember(member: KtCallableDeclaration, descriptor: CallableMemberDescriptor) = Visibilities.isPrivate(descriptor.visibility) || checkCallableDeclaration(context, member, descriptor) private fun TypeParameterDescriptor.varianceWithManual() = diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/AddVarianceModifierInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/AddVarianceModifierInspection.kt index 85e10aaec4f..ed94065a9a8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/AddVarianceModifierInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/AddVarianceModifierInspection.kt @@ -20,20 +20,46 @@ import com.intellij.codeInsight.FileModificationService import com.intellij.codeInspection.* import com.intellij.openapi.project.Project import com.intellij.psi.PsiElementVisitor +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.MemberDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtTypeParameter -import org.jetbrains.kotlin.psi.KtVisitorVoid +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.addRemoveModifier.addModifier +import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.ManualVariance import org.jetbrains.kotlin.resolve.VarianceCheckerCore import org.jetbrains.kotlin.types.Variance class AddVarianceModifierInspection : AbstractKotlinInspection() { + + private fun VarianceCheckerCore.checkClassOrObject(klass: KtClassOrObject): Boolean { + if (klass is KtClass) { + if (!checkClassHeader(klass)) return false + if (klass.getSuperTypeList()?.anyDescendantOfType { !checkClassOrObject(it) } == true) return false + } + for (member in klass.declarations + klass.primaryConstructorParameters) { + val descriptor = when (member) { + is KtParameter -> context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, member) + is KtDeclaration -> context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, member) + else -> null + } as? MemberDescriptor ?: continue + when (member) { + is KtClassOrObject -> { + if (!checkClassOrObject(member)) return false + } + is KtCallableDeclaration -> { + if (descriptor is CallableMemberDescriptor && !checkMember(member, descriptor)) return false + if (member.anyDescendantOfType { !checkClassOrObject(it) }) return false + } + } + } + return true + } + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { return object : KtVisitorVoid() {