Can be private: don't report when object or subclass calls the function
Questionable So #KT-22030 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
6c8276b701
commit
7786896e9b
+23
-13
@@ -28,23 +28,26 @@ import com.intellij.psi.search.GlobalSearchScope
|
|||||||
import com.intellij.psi.search.PsiSearchHelper
|
import com.intellij.psi.search.PsiSearchHelper
|
||||||
import com.intellij.psi.search.searches.ReferencesSearch
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||||
import org.jetbrains.kotlin.descriptors.effectiveVisibility
|
import org.jetbrains.kotlin.descriptors.effectiveVisibility
|
||||||
import org.jetbrains.kotlin.idea.core.isInheritable
|
import org.jetbrains.kotlin.idea.core.isInheritable
|
||||||
import org.jetbrains.kotlin.idea.core.isOverridable
|
import org.jetbrains.kotlin.idea.core.isOverridable
|
||||||
import org.jetbrains.kotlin.idea.core.toDescriptor
|
import org.jetbrains.kotlin.idea.core.toDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor
|
||||||
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
|
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
|
||||||
import org.jetbrains.kotlin.idea.refactoring.isConstructorDeclaredProperty
|
import org.jetbrains.kotlin.idea.refactoring.isConstructorDeclaredProperty
|
||||||
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.search.isCheapEnoughToSearchConsideringOperators
|
import org.jetbrains.kotlin.idea.search.isCheapEnoughToSearchConsideringOperators
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunction
|
import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunction
|
||||||
|
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||||
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
|
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
|
||||||
import org.jetbrains.kotlin.idea.util.isEffectivelyActual
|
|
||||||
import org.jetbrains.kotlin.idea.util.isExpectDeclaration
|
import org.jetbrains.kotlin.idea.util.isExpectDeclaration
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
|
||||||
class MemberVisibilityCanBePrivateInspection : AbstractKotlinInspection() {
|
class MemberVisibilityCanBePrivateInspection : AbstractKotlinInspection() {
|
||||||
|
|
||||||
@@ -118,20 +121,27 @@ class MemberVisibilityCanBePrivateInspection : AbstractKotlinInspection() {
|
|||||||
ReferencesSearch.search(declaration, restrictedScope).forEach(Processor<PsiReference> {
|
ReferencesSearch.search(declaration, restrictedScope).forEach(Processor<PsiReference> {
|
||||||
val usage = it.element
|
val usage = it.element
|
||||||
if (classOrObject != usage.getParentOfType<KtClassOrObject>(false)) {
|
if (classOrObject != usage.getParentOfType<KtClassOrObject>(false)) {
|
||||||
|
otherUsageFound = true
|
||||||
|
return@Processor false
|
||||||
|
}
|
||||||
|
val classOrObjectDescriptor = classOrObject.descriptor as? ClassDescriptor
|
||||||
|
if (classOrObjectDescriptor != null) {
|
||||||
|
val receiver = usage.getStrictParentOfType<KtQualifiedExpression>()?.receiverExpression
|
||||||
|
val receiverDescriptor = (receiver?.getCallableDescriptor()?.returnType?.constructor?.declarationDescriptor
|
||||||
|
?: (receiver?.mainReference?.resolve() as? KtClassOrObject)?.descriptor) as? ClassDescriptor
|
||||||
|
if (receiverDescriptor != null && DescriptorUtils.isSubclass(receiverDescriptor, classOrObjectDescriptor)) {
|
||||||
|
otherUsageFound = true
|
||||||
|
return@Processor false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val function = usage.getParentOfType<KtCallableDeclaration>(false)
|
||||||
|
val insideInlineFun = function?.modifierList?.let { it.hasModifier(KtTokens.INLINE_KEYWORD) && !function.isPrivate() } ?: false
|
||||||
|
if (insideInlineFun) {
|
||||||
otherUsageFound = true
|
otherUsageFound = true
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
val function = usage.getParentOfType<KtCallableDeclaration>(false)
|
inClassUsageFound = true
|
||||||
val insideInlineFun = function?.modifierList?.let {
|
true
|
||||||
it.hasModifier(KtTokens.INLINE_KEYWORD) && !function.isPrivate()
|
|
||||||
} ?: false
|
|
||||||
if (insideInlineFun) {
|
|
||||||
otherUsageFound = true
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
inClassUsageFound = true
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return inClassUsageFound && !otherUsageFound
|
return inClassUsageFound && !otherUsageFound
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
open class A {
|
||||||
|
<caret>internal fun foo() {}
|
||||||
|
|
||||||
|
fun bar(c: C) {
|
||||||
|
c.foo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class C : A()
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
open class A {
|
||||||
|
<caret>internal fun foo() {}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
O.foo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object O : A()
|
||||||
+10
@@ -2548,6 +2548,16 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
public void testJvmFieldOnProperty() throws Exception {
|
public void testJvmFieldOnProperty() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/memberVisibilityCanBePrivate/JvmFieldOnProperty.kt");
|
runTest("idea/testData/inspectionsLocal/memberVisibilityCanBePrivate/JvmFieldOnProperty.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("subClassFunctionCall.kt")
|
||||||
|
public void testSubClassFunctionCall() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/memberVisibilityCanBePrivate/subClassFunctionCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("subObjectFunctionCall.kt")
|
||||||
|
public void testSubObjectFunctionCall() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/memberVisibilityCanBePrivate/subObjectFunctionCall.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/inspectionsLocal/migrateDiagnosticSuppression")
|
@TestMetadata("idea/testData/inspectionsLocal/migrateDiagnosticSuppression")
|
||||||
|
|||||||
Reference in New Issue
Block a user