Offer to make INVISIBLE_MEMBER protected if referenced from subclass
So #KT-19614 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
0adf1d210f
commit
f0f6a252a5
@@ -17,21 +17,25 @@
|
|||||||
package org.jetbrains.kotlin.idea.quickfix
|
package org.jetbrains.kotlin.idea.quickfix
|
||||||
|
|
||||||
import com.intellij.codeInsight.intention.IntentionAction
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities.*
|
import org.jetbrains.kotlin.descriptors.Visibilities.*
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory3
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory3
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperclassesWithoutAny
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
|
||||||
object MakeVisibleFactory : KotlinIntentionActionsFactory() {
|
object MakeVisibleFactory : KotlinIntentionActionsFactory() {
|
||||||
override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> {
|
override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> {
|
||||||
val element = diagnostic.psiElement as? KtElement ?: return emptyList()
|
val element = diagnostic.psiElement as? KtElement ?: return emptyList()
|
||||||
val context = element.analyze(BodyResolveMode.PARTIAL)
|
val context = element.analyze(BodyResolveMode.PARTIAL)
|
||||||
@@ -44,7 +48,11 @@ object MakeVisibleFactory : KotlinIntentionActionsFactory() {
|
|||||||
|
|
||||||
val module = DescriptorUtils.getContainingModule(descriptor)
|
val module = DescriptorUtils.getContainingModule(descriptor)
|
||||||
val targetVisibilities = when (descriptor.visibility) {
|
val targetVisibilities = when (descriptor.visibility) {
|
||||||
PRIVATE, INVISIBLE_FAKE -> if (module != usageModule) listOf(PUBLIC) else listOf(PUBLIC, INTERNAL)
|
PRIVATE, INVISIBLE_FAKE -> mutableListOf(PUBLIC).apply {
|
||||||
|
if (module == usageModule) add(INTERNAL)
|
||||||
|
val superClasses = (element.containingClass()?.descriptor as? ClassDescriptor)?.getAllSuperclassesWithoutAny()
|
||||||
|
if (superClasses?.contains(declaration.containingClass()?.descriptor) == true) add(PROTECTED)
|
||||||
|
}
|
||||||
else -> listOf(PUBLIC)
|
else -> listOf(PUBLIC)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// "Make 'doSth' protected" "false"
|
||||||
|
// ACTION: Make 'doSth' public
|
||||||
|
// ACTION: Make 'doSth' internal
|
||||||
|
// ERROR: Cannot access 'doSth': it is private in 'A'
|
||||||
|
|
||||||
|
class A {
|
||||||
|
private fun doSth() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
fun bar() {
|
||||||
|
A().<caret>doSth()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// "Make 'doSth' protected" "true"
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
private fun doSth() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
fun bar() {
|
||||||
|
<caret>doSth()
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// "Make 'doSth' protected" "true"
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
protected fun doSth() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
fun bar() {
|
||||||
|
doSth()
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// "Make 'doSth' protected" "true"
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
private fun doSth() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class B : A()
|
||||||
|
|
||||||
|
class C : B() {
|
||||||
|
fun bar() {
|
||||||
|
<caret>doSth()
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// "Make 'doSth' protected" "true"
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
protected fun doSth() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class B : A()
|
||||||
|
|
||||||
|
class C : B() {
|
||||||
|
fun bar() {
|
||||||
|
doSth()
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// "Make 'foo' protected" "false"
|
||||||
|
// ACTION: Make 'foo' public
|
||||||
|
// ACTION: Make 'foo' internal
|
||||||
|
// ACTION: Introduce local variable
|
||||||
|
// ERROR: Cannot access 'foo': it is private in 'A'
|
||||||
|
|
||||||
|
class A {
|
||||||
|
private val foo = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
fun bar() {
|
||||||
|
A().<caret>foo
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// "Make 'foo' protected" "true"
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
private val foo = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
fun bar() {
|
||||||
|
<caret>foo
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// "Make 'foo' protected" "true"
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
protected val foo = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
fun bar() {
|
||||||
|
foo
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// "Make 'foo' protected" "true"
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
private val foo = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
open class B : A()
|
||||||
|
|
||||||
|
class C : B() {
|
||||||
|
fun bar() {
|
||||||
|
<caret>foo
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// "Make 'foo' protected" "true"
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
protected val foo = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
open class B : A()
|
||||||
|
|
||||||
|
class C : B() {
|
||||||
|
fun bar() {
|
||||||
|
foo
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6301,6 +6301,24 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("methodToNotProtected.kt")
|
||||||
|
public void testMethodToNotProtected() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/invisibleFake/methodToNotProtected.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("methodToProtected.kt")
|
||||||
|
public void testMethodToProtected() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/invisibleFake/methodToProtected.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("methodToProtected2.kt")
|
||||||
|
public void testMethodToProtected2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/invisibleFake/methodToProtected2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("methodToPublic.kt")
|
@TestMetadata("methodToPublic.kt")
|
||||||
public void testMethodToPublic() throws Exception {
|
public void testMethodToPublic() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/invisibleFake/methodToPublic.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/invisibleFake/methodToPublic.kt");
|
||||||
@@ -6313,6 +6331,24 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyToNotProtected.kt")
|
||||||
|
public void testPropertyToNotProtected() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/invisibleFake/propertyToNotProtected.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyToProtected.kt")
|
||||||
|
public void testPropertyToProtected() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/invisibleFake/propertyToProtected.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyToProtected2.kt")
|
||||||
|
public void testPropertyToProtected2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/invisibleFake/propertyToProtected2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("propertyToPublic.kt")
|
@TestMetadata("propertyToPublic.kt")
|
||||||
public void testPropertyToPublic() throws Exception {
|
public void testPropertyToPublic() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/invisibleFake/propertyToPublic.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/invisibleFake/propertyToPublic.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user