Extract Superclass/Interface: Fix bogus visibility warning inside a member when it's being moved as abstract

#KT-15635 Fixed
This commit is contained in:
Alexey Sedunov
2017-01-11 17:09:37 +03:00
parent 65b9049d59
commit 57d364e7d4
8 changed files with 82 additions and 4 deletions
+1
View File
@@ -482,6 +482,7 @@ These artifacts include extensions for the types available in the latter JDKs, s
- [`KT-15640`](https://youtrack.jetbrains.com/issue/KT-15640) Extract Interface/Pull Up: Drop 'final' modifier when moving to an interface - [`KT-15640`](https://youtrack.jetbrains.com/issue/KT-15640) Extract Interface/Pull Up: Drop 'final' modifier when moving to an interface
- [`KT-15639`](https://youtrack.jetbrains.com/issue/KT-15639) Extract Superclass/Interface/Pull Up: Add spaces between 'abstract' modifier and annotations - [`KT-15639`](https://youtrack.jetbrains.com/issue/KT-15639) Extract Superclass/Interface/Pull Up: Add spaces between 'abstract' modifier and annotations
- [`KT-15606`](https://youtrack.jetbrains.com/issue/KT-15606) Extract Interface/Pull Up: Warn about private members with usages in the original class - [`KT-15606`](https://youtrack.jetbrains.com/issue/KT-15606) Extract Interface/Pull Up: Warn about private members with usages in the original class
- [`KT-15635`](https://youtrack.jetbrains.com/issue/KT-15635) Extract Superclass/Interface: Fix bogus visibility warning inside a member when it's being moved as abstract
#### Intention actions, inspections and quickfixes #### Intention actions, inspections and quickfixes
@@ -145,7 +145,13 @@ class ExtractSuperRefactoring(
else { else {
KotlinMoveTargetForExistingElement(targetParent as KtElement) KotlinMoveTargetForExistingElement(targetParent as KtElement)
} }
val conflictChecker = MoveConflictChecker(project, elementsToMove, moveTarget, originalClass) val conflictChecker = MoveConflictChecker(
project,
elementsToMove,
moveTarget,
originalClass,
memberInfos.filter { it.isToAbstract }.mapNotNull { it.member }
)
project.runSynchronouslyWithProgress(RefactoringBundle.message("detecting.possible.conflicts"), true) { project.runSynchronouslyWithProgress(RefactoringBundle.message("detecting.possible.conflicts"), true) {
runReadAction { runReadAction {
@@ -51,7 +51,8 @@ class MoveConflictChecker(
private val project: Project, private val project: Project,
private val elementsToMove: Collection<KtElement>, private val elementsToMove: Collection<KtElement>,
private val moveTarget: KotlinMoveTarget, private val moveTarget: KotlinMoveTarget,
contextElement: KtElement contextElement: KtElement,
private val doNotGoIn: Collection<KtElement> = emptyList()
) { ) {
private val resolutionFacade = contextElement.getResolutionFacade() private val resolutionFacade = contextElement.getResolutionFacade()
@@ -148,7 +149,7 @@ class MoveConflictChecker(
val sourceRoot = moveTarget.targetFile ?: return val sourceRoot = moveTarget.targetFile ?: return
val targetModule = ModuleUtilCore.findModuleForFile(sourceRoot, project) ?: return val targetModule = ModuleUtilCore.findModuleForFile(sourceRoot, project) ?: return
val resolveScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(targetModule) val resolveScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(targetModule)
for (declaration in elementsToMove) { for (declaration in elementsToMove - doNotGoIn) {
declaration.forEachDescendantOfType<KtReferenceExpression> { refExpr -> declaration.forEachDescendantOfType<KtReferenceExpression> { refExpr ->
val targetDescriptor = refExpr.analyze(BodyResolveMode.PARTIAL)[BindingContext.REFERENCE_TARGET, refExpr] ?: return@forEachDescendantOfType val targetDescriptor = refExpr.analyze(BodyResolveMode.PARTIAL)[BindingContext.REFERENCE_TARGET, refExpr] ?: return@forEachDescendantOfType
@@ -206,7 +207,7 @@ class MoveConflictChecker(
fun checkVisibilityInDeclarations(conflicts: MultiMap<PsiElement, String>) { fun checkVisibilityInDeclarations(conflicts: MultiMap<PsiElement, String>) {
val targetContainer = moveTarget.getContainerDescriptor() ?: return val targetContainer = moveTarget.getContainerDescriptor() ?: return
for (declaration in elementsToMove) { for (declaration in elementsToMove - doNotGoIn) {
declaration.forEachDescendantOfType<KtReferenceExpression> { refExpr -> declaration.forEachDescendantOfType<KtReferenceExpression> { refExpr ->
refExpr.references refExpr.references
.forEach { ref -> .forEach { ref ->
@@ -0,0 +1,12 @@
// NAME: I
// SIBLING:
class <caret>BrokenRef {
private fun fun1() {}
fun fun2() {}
// INFO: {checked: "true", toAbstract: "true"}
fun refer() {
fun1()
fun2()
}
}
@@ -0,0 +1,17 @@
interface I {
// INFO: {checked: "true", toAbstract: "true"}
fun refer()
}
// NAME: I
// SIBLING:
class BrokenRef : I {
private fun fun1() {}
fun fun2() {}
// INFO: {checked: "true", toAbstract: "true"}
override fun refer() {
fun1()
fun2()
}
}
@@ -0,0 +1,12 @@
// NAME: A
// SIBLING:
class <caret>BrokenRef {
private fun fun1() {}
fun fun2() {}
// INFO: {checked: "true", toAbstract: "true"}
fun refer() {
fun1()
fun2()
}
}
@@ -0,0 +1,17 @@
abstract class A {
// INFO: {checked: "true", toAbstract: "true"}
abstract fun refer()
}
// NAME: A
// SIBLING:
class BrokenRef : A() {
private fun fun1() {}
fun fun2() {}
// INFO: {checked: "true", toAbstract: "true"}
override fun refer() {
fun1()
fun2()
}
}
@@ -4295,6 +4295,12 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
doExtractSuperclassTest(fileName); doExtractSuperclassTest(fileName);
} }
@TestMetadata("noWarningOnVisibilityInsideAbstractedMember.kt")
public void testNoWarningOnVisibilityInsideAbstractedMember() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractSuperclass/noWarningOnVisibilityInsideAbstractedMember.kt");
doExtractSuperclassTest(fileName);
}
@TestMetadata("privateClass.kt") @TestMetadata("privateClass.kt")
public void testPrivateClass() throws Exception { public void testPrivateClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractSuperclass/privateClass.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractSuperclass/privateClass.kt");
@@ -4376,6 +4382,12 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
doExtractInterfaceTest(fileName); doExtractInterfaceTest(fileName);
} }
@TestMetadata("noWarningOnVisibilityInsideAbstractedMember.kt")
public void testNoWarningOnVisibilityInsideAbstractedMember() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractInterface/noWarningOnVisibilityInsideAbstractedMember.kt");
doExtractInterfaceTest(fileName);
}
@TestMetadata("privateMemberWithUsages.kt") @TestMetadata("privateMemberWithUsages.kt")
public void testPrivateMemberWithUsages() throws Exception { public void testPrivateMemberWithUsages() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractInterface/privateMemberWithUsages.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractInterface/privateMemberWithUsages.kt");