Visibility can be private: do not perform too expensive search
Also, additional test for usage via accessor was added So #KT-18617 Fixed
This commit is contained in:
+26
-6
@@ -16,18 +16,24 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.codeInspection.*
|
||||
import com.intellij.codeInspection.IntentionWrapper
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.search.LocalSearchScope
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.PsiSearchHelper
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.util.Processor
|
||||
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
|
||||
import org.jetbrains.kotlin.idea.refactoring.isConstructorDeclaredProperty
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isInheritable
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isOverridable
|
||||
|
||||
class MemberVisibilityCanPrivateInspection : AbstractKotlinInspection() {
|
||||
|
||||
@@ -57,20 +63,34 @@ class MemberVisibilityCanPrivateInspection : AbstractKotlinInspection() {
|
||||
}
|
||||
|
||||
|
||||
private fun canBePrivate(declaration: KtDeclaration): Boolean {
|
||||
private fun canBePrivate(declaration: KtNamedDeclaration): Boolean {
|
||||
if (declaration.hasModifier(KtTokens.PRIVATE_KEYWORD) || declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return false
|
||||
val classOrObject = declaration.containingClassOrObject ?: return false
|
||||
val inheritable = classOrObject is KtClass && classOrObject.isInheritable()
|
||||
if (!inheritable && declaration.hasModifier(KtTokens.PROTECTED_KEYWORD)) return false //reported by ProtectedInFinalInspection
|
||||
if (declaration.isOverridable()) return false
|
||||
|
||||
val psiSearchHelper = PsiSearchHelper.SERVICE.getInstance(declaration.project)
|
||||
val useScope = declaration.useScope
|
||||
val name = declaration.name ?: return false
|
||||
if (useScope is GlobalSearchScope) {
|
||||
when (psiSearchHelper.isCheapEnoughToSearch(name, useScope, null, null)) {
|
||||
PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES -> return false
|
||||
PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES -> return false
|
||||
PsiSearchHelper.SearchCostResult.FEW_OCCURRENCES -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var otherUsageFound = false
|
||||
var inClassUsageFound = false
|
||||
ReferencesSearch.search(declaration, declaration.useScope).forEach(Processor<PsiReference> {
|
||||
ReferencesSearch.search(declaration, useScope).forEach(Processor<PsiReference> {
|
||||
val usage = it.element
|
||||
if (classOrObject != usage.getParentOfType<KtClassOrObject>(false)) {
|
||||
otherUsageFound = true
|
||||
false
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
inClassUsageFound = true
|
||||
true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Add 'private' modifier" "false"
|
||||
// ACTION: Convert to secondary constructor
|
||||
// ACTION: Create test
|
||||
// ACTION: Move to class body
|
||||
|
||||
class My(val <caret>parameter: Int) {
|
||||
val other = parameter
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class User {
|
||||
public static int foo(My my) {
|
||||
return my.getParameter();
|
||||
}
|
||||
}
|
||||
@@ -1665,6 +1665,21 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/memberVisibilityCanBePrivate")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class MemberVisibilityCanBePrivate extends AbstractQuickFixMultiFileTest {
|
||||
public void testAllFilesPresentInMemberVisibilityCanBePrivate() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/memberVisibilityCanBePrivate"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("getter.before.Main.kt")
|
||||
public void testGetter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/memberVisibilityCanBePrivate/getter.before.Main.kt");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/migration")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user