VarianceChecker refactoring: move checkClassOrObject to IDE

This commit is contained in:
Mikhail Glukhikh
2017-04-27 20:51:34 +03:00
parent b66401a41d
commit 19021ec1aa
2 changed files with 39 additions and 36 deletions
@@ -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<KtClassOrObject> { !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<KtClassOrObject> { !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() =
@@ -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<KtClassOrObject> { !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<KtClassOrObject> { !checkClassOrObject(it) }) return false
}
}
}
return true
}
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
return object : KtVisitorVoid() {