"Make private" intention: fix some false positive cases
This commit is contained in:
committed by
Mikhail Glukhikh
parent
7488056249
commit
061aa63a73
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
|||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.idea.util.hasJvmFieldAnnotation
|
import org.jetbrains.kotlin.idea.util.hasJvmFieldAnnotation
|
||||||
|
import org.jetbrains.kotlin.idea.util.isExpectDeclaration
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -282,6 +283,17 @@ fun KtModifierListOwner.canBePrivate(): Boolean {
|
|||||||
if (modifierList?.hasModifier(KtTokens.ABSTRACT_KEYWORD) == true) return false
|
if (modifierList?.hasModifier(KtTokens.ABSTRACT_KEYWORD) == true) return false
|
||||||
if (this.isAnnotationClassPrimaryConstructor()) return false
|
if (this.isAnnotationClassPrimaryConstructor()) return false
|
||||||
if (this is KtProperty && this.hasJvmFieldAnnotation()) return false
|
if (this is KtProperty && this.hasJvmFieldAnnotation()) return false
|
||||||
|
|
||||||
|
if (this is KtDeclaration) {
|
||||||
|
if (hasActualModifier() || isExpectDeclaration()) return false
|
||||||
|
val containingClassOrObject = containingClassOrObject ?: return true
|
||||||
|
if (containingClassOrObject is KtClass &&
|
||||||
|
(containingClassOrObject.isInterface() || containingClassOrObject.isAnnotation())
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -33,6 +33,7 @@ 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.caches.resolve.resolveToCall
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||||
|
import org.jetbrains.kotlin.idea.core.canBePrivate
|
||||||
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
|
||||||
@@ -42,7 +43,6 @@ import org.jetbrains.kotlin.idea.search.isCheapEnoughToSearchConsideringOperator
|
|||||||
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.search.usagesSearch.descriptor
|
||||||
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
|
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
|
||||||
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.*
|
||||||
@@ -77,7 +77,6 @@ class MemberVisibilityCanBePrivateInspection : AbstractKotlinInspection() {
|
|||||||
private fun canBePrivate(declaration: KtNamedDeclaration): Boolean {
|
private fun canBePrivate(declaration: KtNamedDeclaration): Boolean {
|
||||||
if (declaration.hasModifier(KtTokens.PRIVATE_KEYWORD) || declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return false
|
if (declaration.hasModifier(KtTokens.PRIVATE_KEYWORD) || declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return false
|
||||||
if (declaration.annotationEntries.isNotEmpty()) return false
|
if (declaration.annotationEntries.isNotEmpty()) return false
|
||||||
if (declaration.hasActualModifier() || declaration.isExpectDeclaration()) return false
|
|
||||||
|
|
||||||
val descriptor = (declaration.toDescriptor() as? DeclarationDescriptorWithVisibility) ?: return false
|
val descriptor = (declaration.toDescriptor() as? DeclarationDescriptorWithVisibility) ?: return false
|
||||||
when (descriptor.effectiveVisibility()) {
|
when (descriptor.effectiveVisibility()) {
|
||||||
@@ -85,8 +84,6 @@ class MemberVisibilityCanBePrivateInspection : AbstractKotlinInspection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val classOrObject = declaration.containingClassOrObject ?: return false
|
val classOrObject = declaration.containingClassOrObject ?: return false
|
||||||
if (classOrObject.isAnnotation()) return false
|
|
||||||
|
|
||||||
val inheritable = classOrObject is KtClass && classOrObject.isInheritable()
|
val inheritable = classOrObject is KtClass && classOrObject.isInheritable()
|
||||||
if (!inheritable && declaration.hasModifier(KtTokens.PROTECTED_KEYWORD)) return false //reported by ProtectedInFinalInspection
|
if (!inheritable && declaration.hasModifier(KtTokens.PROTECTED_KEYWORD)) return false //reported by ProtectedInFinalInspection
|
||||||
if (declaration.isOverridable()) return false
|
if (declaration.isOverridable()) return false
|
||||||
@@ -100,6 +97,8 @@ class MemberVisibilityCanBePrivateInspection : AbstractKotlinInspection() {
|
|||||||
)
|
)
|
||||||
) return false
|
) return false
|
||||||
|
|
||||||
|
if (!declaration.canBePrivate()) return false
|
||||||
|
|
||||||
// properties can be referred by component1/component2, which is too expensive to search, don't analyze them
|
// properties can be referred by component1/component2, which is too expensive to search, don't analyze them
|
||||||
if (declaration is KtParameter && declaration.dataClassComponentFunction() != null) return false
|
if (declaration is KtParameter && declaration.dataClassComponentFunction() != null) return false
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// SKIP_ERRORS_BEFORE
|
||||||
|
// SKIP_ERRORS_AFTER
|
||||||
|
|
||||||
|
// IS_APPLICABLE: false
|
||||||
|
expect class C {
|
||||||
|
fun test()
|
||||||
|
}
|
||||||
|
|
||||||
|
<caret>actual class C {
|
||||||
|
actual fun test() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// SKIP_ERRORS_BEFORE
|
||||||
|
// SKIP_ERRORS_AFTER
|
||||||
|
|
||||||
|
// IS_APPLICABLE: false
|
||||||
|
expect class C {
|
||||||
|
fun test()
|
||||||
|
}
|
||||||
|
|
||||||
|
actual class C {
|
||||||
|
<caret>actual fun test() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// SKIP_ERRORS_BEFORE
|
||||||
|
// SKIP_ERRORS_AFTER
|
||||||
|
|
||||||
|
// IS_APPLICABLE: false
|
||||||
|
<caret>expect class C {
|
||||||
|
fun test()
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// SKIP_ERRORS_BEFORE
|
||||||
|
// SKIP_ERRORS_AFTER
|
||||||
|
|
||||||
|
// IS_APPLICABLE: false
|
||||||
|
expect class C {
|
||||||
|
<caret>fun test()
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
|
||||||
|
annotation class Ann(va<caret>l x: Int)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
interface Interface {
|
||||||
|
<caret>val x: String
|
||||||
|
}
|
||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// "Implement members" "false"
|
// "Implement members" "false"
|
||||||
// ACTION: Create test
|
// ACTION: Create test
|
||||||
// ACTION: Make internal
|
// ACTION: Make internal
|
||||||
// ACTION: Make private
|
|
||||||
// ACTION: Move 'A' to separate file
|
// ACTION: Move 'A' to separate file
|
||||||
|
|
||||||
interface I {
|
interface I {
|
||||||
|
|||||||
@@ -3539,6 +3539,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("actual.kt")
|
||||||
|
public void testActual() throws Exception {
|
||||||
|
runTest("idea/testData/intentions/changeVisibility/private/actual.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("actual2.kt")
|
||||||
|
public void testActual2() throws Exception {
|
||||||
|
runTest("idea/testData/intentions/changeVisibility/private/actual2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInPrivate() throws Exception {
|
public void testAllFilesPresentInPrivate() throws Exception {
|
||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/changeVisibility/private"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/changeVisibility/private"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
@@ -3548,6 +3558,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
runTest("idea/testData/intentions/changeVisibility/private/annotated.kt");
|
runTest("idea/testData/intentions/changeVisibility/private/annotated.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expect.kt")
|
||||||
|
public void testExpect() throws Exception {
|
||||||
|
runTest("idea/testData/intentions/changeVisibility/private/expect.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expect2.kt")
|
||||||
|
public void testExpect2() throws Exception {
|
||||||
|
runTest("idea/testData/intentions/changeVisibility/private/expect2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("hasModifier1.kt")
|
@TestMetadata("hasModifier1.kt")
|
||||||
public void testHasModifier1() throws Exception {
|
public void testHasModifier1() throws Exception {
|
||||||
runTest("idea/testData/intentions/changeVisibility/private/hasModifier1.kt");
|
runTest("idea/testData/intentions/changeVisibility/private/hasModifier1.kt");
|
||||||
@@ -3568,6 +3588,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
runTest("idea/testData/intentions/changeVisibility/private/hasModifier4.kt");
|
runTest("idea/testData/intentions/changeVisibility/private/hasModifier4.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inAnnotation.kt")
|
||||||
|
public void testInAnnotation() throws Exception {
|
||||||
|
runTest("idea/testData/intentions/changeVisibility/private/inAnnotation.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("interface.kt")
|
||||||
|
public void testInterface() throws Exception {
|
||||||
|
runTest("idea/testData/intentions/changeVisibility/private/interface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("jvmField.kt")
|
@TestMetadata("jvmField.kt")
|
||||||
public void testJvmField() throws Exception {
|
public void testJvmField() throws Exception {
|
||||||
runTest("idea/testData/intentions/changeVisibility/private/jvmField.kt");
|
runTest("idea/testData/intentions/changeVisibility/private/jvmField.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user