VarianceChecker refactoring: move checkClassOrObject to IDE
This commit is contained in:
@@ -23,8 +23,10 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyAccessorDescriptorImpl
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
|
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.source.getPsi
|
||||||
import org.jetbrains.kotlin.resolve.typeBinding.TypeBinding
|
import org.jetbrains.kotlin.resolve.typeBinding.TypeBinding
|
||||||
import org.jetbrains.kotlin.resolve.typeBinding.createTypeBinding
|
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.Variance.*
|
import org.jetbrains.kotlin.types.Variance.*
|
||||||
import org.jetbrains.kotlin.types.checkTypePosition
|
import org.jetbrains.kotlin.types.checkTypePosition
|
||||||
import org.jetbrains.kotlin.types.getAbbreviatedType
|
|
||||||
|
|
||||||
class ManualVariance(val descriptor: TypeParameterDescriptor, val variance: Variance)
|
class ManualVariance(val descriptor: TypeParameterDescriptor, val variance: Variance)
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ class VarianceConflictDiagnosticData(
|
|||||||
)
|
)
|
||||||
|
|
||||||
class VarianceCheckerCore(
|
class VarianceCheckerCore(
|
||||||
private val context: BindingContext,
|
val context: BindingContext,
|
||||||
private val diagnosticSink: DiagnosticSink,
|
private val diagnosticSink: DiagnosticSink,
|
||||||
private val manualVariance: ManualVariance? = null
|
private val manualVariance: ManualVariance? = null
|
||||||
) {
|
) {
|
||||||
@@ -62,39 +63,15 @@ class VarianceCheckerCore(
|
|||||||
checkMembers(c)
|
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) {
|
private fun checkClasses(c: TopDownAnalysisContext) {
|
||||||
for (jetClassOrObject in c.declaredClasses!!.keys) {
|
for (classOrObject in c.declaredClasses!!.keys) {
|
||||||
if (jetClassOrObject is KtClass) {
|
if (classOrObject is KtClass) {
|
||||||
checkClassHeader(jetClassOrObject)
|
checkClassHeader(classOrObject)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkClassHeader(klass: KtClass): Boolean {
|
fun checkClassHeader(klass: KtClass): Boolean {
|
||||||
var noError = true
|
var noError = true
|
||||||
for (specifier in klass.superTypeListEntries) {
|
for (specifier in klass.superTypeListEntries) {
|
||||||
noError = noError and specifier.typeReference?.checkTypePosition(context, OUT_VARIANCE)
|
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)
|
Visibilities.isPrivate(descriptor.visibility) || checkCallableDeclaration(context, member, descriptor)
|
||||||
|
|
||||||
private fun TypeParameterDescriptor.varianceWithManual() =
|
private fun TypeParameterDescriptor.varianceWithManual() =
|
||||||
|
|||||||
@@ -20,20 +20,46 @@ import com.intellij.codeInsight.FileModificationService
|
|||||||
import com.intellij.codeInspection.*
|
import com.intellij.codeInspection.*
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiElementVisitor
|
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.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtTypeParameter
|
|
||||||
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
|
||||||
import org.jetbrains.kotlin.psi.addRemoveModifier.addModifier
|
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.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.ManualVariance
|
import org.jetbrains.kotlin.resolve.ManualVariance
|
||||||
import org.jetbrains.kotlin.resolve.VarianceCheckerCore
|
import org.jetbrains.kotlin.resolve.VarianceCheckerCore
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
|
||||||
class AddVarianceModifierInspection : AbstractKotlinInspection() {
|
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 {
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
|
||||||
return object : KtVisitorVoid() {
|
return object : KtVisitorVoid() {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user