KT-11806: increase visibility quick fix, private --> internal, also for members
This commit is contained in:
@@ -24,32 +24,47 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory3
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
class IncreaseVisibilityFix(element: KtModifierListOwner, private val elementName: String) :
|
||||
KotlinQuickFixAction<KtModifierListOwner>(element), CleanupFix {
|
||||
override fun getText() = "Make $elementName internal"
|
||||
override fun getFamilyName() = "Make top-level declaration internal"
|
||||
class IncreaseVisibilityFix(
|
||||
element: KtModifierListOwner,
|
||||
private val elementName: String,
|
||||
private val visibilityModifier: KtModifierKeywordToken
|
||||
) : KotlinQuickFixAction<KtModifierListOwner>(element), CleanupFix {
|
||||
|
||||
override fun getText() = "Make $elementName $visibilityModifier"
|
||||
override fun getFamilyName() = "Make $visibilityModifier"
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||
element.addModifier(KtTokens.INTERNAL_KEYWORD)
|
||||
element.addModifier(visibilityModifier)
|
||||
}
|
||||
|
||||
companion object : KotlinSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val element = diagnostic.psiElement as? KtElement ?: return null
|
||||
val context = element.analyze(BodyResolveMode.PARTIAL)
|
||||
val usageModule = context.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, element.getContainingKtFile())?.module
|
||||
?: return null
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val factory = diagnostic.factory as DiagnosticFactory3<*, DeclarationDescriptor, *, DeclarationDescriptor>
|
||||
val descriptor = factory.cast(diagnostic).c
|
||||
if (!DescriptorUtils.isTopLevelDeclaration(descriptor) ||
|
||||
descriptor !is DeclarationDescriptorWithVisibility ||
|
||||
descriptor.visibility != Visibilities.PRIVATE) return null
|
||||
val descriptor = factory.cast(diagnostic).c as? DeclarationDescriptorWithVisibility ?: return null
|
||||
|
||||
val module = DescriptorUtils.getContainingModule(descriptor)
|
||||
if (module != usageModule) return null
|
||||
val declaration = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor) as? KtModifierListOwner ?: return null
|
||||
return IncreaseVisibilityFix(declaration, descriptor.name.asString())
|
||||
if (descriptor.visibility != Visibilities.PRIVATE) return null
|
||||
return IncreaseVisibilityFix(declaration, descriptor.name.asString(), KtTokens.INTERNAL_KEYWORD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
package test
|
||||
|
||||
class First {
|
||||
internal fun foo() = 42
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Make foo internal" "true"
|
||||
// ERROR: Cannot access 'foo': it is 'private' in 'First'
|
||||
|
||||
package test
|
||||
|
||||
class Second(val f: First) {
|
||||
fun bar() = f.<caret>foo()
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
package test
|
||||
|
||||
class First {
|
||||
private fun foo() = 42
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Make foo internal" "true"
|
||||
// ERROR: Cannot access 'foo': it is 'private' in 'First'
|
||||
|
||||
package test
|
||||
|
||||
class Second(val f: First) {
|
||||
fun bar() = f.<caret>foo()
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Make x internal" "true"
|
||||
class First(private val x: Int)
|
||||
|
||||
class Second(f: First) {
|
||||
val y = f.<caret>x
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Make x internal" "true"
|
||||
class First(internal val x: Int)
|
||||
|
||||
class Second(f: First) {
|
||||
val y = f.x
|
||||
}
|
||||
@@ -1294,6 +1294,12 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/increaseVisibility"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("privateMemberToInternalMultiFile.before.Main.kt")
|
||||
public void testPrivateMemberToInternalMultiFile() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/privateMemberToInternalMultiFile.before.Main.kt");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("privateTopLevelFunInFile.before.Main.kt")
|
||||
public void testPrivateTopLevelFunInFile() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/privateTopLevelFunInFile.before.Main.kt");
|
||||
|
||||
@@ -4711,6 +4711,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/increaseVisibility")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class IncreaseVisibility extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInIncreaseVisibility() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/increaseVisibility"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("privateMemberToInternalSingleFile.kt")
|
||||
public void testPrivateMemberToInternalSingleFile() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/increaseVisibility/privateMemberToInternalSingleFile.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/initializeWithConstructorParameter")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user