diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt index 41dbcfe0d17..8f3926ccde1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt @@ -31,6 +31,7 @@ import com.intellij.util.IncorrectOperationException import com.intellij.util.containers.MultiMap import gnu.trove.THashMap import gnu.trove.TObjectHashingStrategy +import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration import org.jetbrains.kotlin.asJava.findFacadeClass import org.jetbrains.kotlin.asJava.namedUnwrappedElement @@ -55,6 +56,9 @@ import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.utils.ifEmpty import org.jetbrains.kotlin.utils.keysToMap import java.util.* +import kotlin.collections.ArrayList +import kotlin.math.max +import kotlin.math.min interface Mover : (KtNamedDeclaration, KtElement) -> KtNamedDeclaration { object Default : Mover { @@ -195,6 +199,13 @@ class MoveKotlinDeclarationsProcessor( return null } + fun UsageInfo.intersectsWith(usage: UsageInfo): Boolean { + if (element?.containingFile != usage.element?.containingFile) return false + val firstSegment = segment ?: return false + val secondSegment = usage.segment ?: return false + return max(firstSegment.startOffset, secondSegment.startOffset) <= min(firstSegment.endOffset, secondSegment.endOffset) + } + fun collectUsages(kotlinToLightElements: Map>, result: MutableCollection) { kotlinToLightElements.values.flatten().flatMapTo(result) { lightElement -> val searchScope = getSearchScope(lightElement) ?: return@flatMapTo emptyList() @@ -212,14 +223,42 @@ class MoveKotlinDeclarationsProcessor( val name = lightElement.getKotlinFqName()?.quoteIfNeeded()?.asString() if (name != null) { - TextOccurrencesUtil.findNonCodeUsages( - lightElement, - name, - descriptor.searchInCommentsAndStrings, - descriptor.searchInNonCode, - FqName(newFqName).quoteIfNeeded().asString(), - results - ) + fun searchForKotlinNameUsages(results: ArrayList) { + TextOccurrencesUtil.findNonCodeUsages( + lightElement, + name, + descriptor.searchInCommentsAndStrings, + descriptor.searchInNonCode, + FqName(newFqName).quoteIfNeeded().asString(), + results + ) + } + + val facadeContainer = lightElement.parent as? KtLightClassForFacade + if (facadeContainer != null) { + val oldFqNameWithFacade = StringUtil.getQualifiedName(facadeContainer.qualifiedName, elementName) + val newFqNameWithFacade = StringUtil.getQualifiedName( + StringUtil.getQualifiedName(newContainerName, facadeContainer.name), + elementName + ) + + TextOccurrencesUtil.findNonCodeUsages( + lightElement, + oldFqNameWithFacade, + descriptor.searchInCommentsAndStrings, + descriptor.searchInNonCode, + FqName(newFqNameWithFacade).quoteIfNeeded().asString(), + results + ) + + ArrayList().also { searchForKotlinNameUsages(it) }.forEach { kotlinNonCodeUsage -> + if (results.none { it.intersectsWith(kotlinNonCodeUsage) }) { + results.add(kotlinNonCodeUsage) + } + } + } else { + searchForKotlinNameUsages(results) + } } MoveClassHandler.EP_NAME.extensions.filter { it !is MoveKotlinClassHandler }.forEach { handler -> diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/after/code/anotherPackage/MyTest.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/after/code/anotherPackage/MyTest.kt new file mode 100644 index 00000000000..41735fd78c6 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/after/code/anotherPackage/MyTest.kt @@ -0,0 +1,3 @@ +package code.anotherPackage + +fun MyTest() {} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/after/code/test.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/after/code/test.kt new file mode 100644 index 00000000000..c1a72d1e950 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/after/code/test.kt @@ -0,0 +1,7 @@ +package code + +fun main(args: Array) { +// MyTest +// code.anotherPackage.MyTest +// code.anotherPackage.TestKt.MyTest +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/before/code/test.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/before/code/test.kt new file mode 100644 index 00000000000..e76e61f89d3 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/before/code/test.kt @@ -0,0 +1,9 @@ +package code + +fun MyTest() {} + +fun main(args: Array) { +// MyTest +// code.MyTest +// code.TestKt.MyTest +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/nonCodeUsagesWithJavaFacadeMethod.test b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/nonCodeUsagesWithJavaFacadeMethod.test new file mode 100644 index 00000000000..8d014f03220 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/nonCodeUsagesWithJavaFacadeMethod.test @@ -0,0 +1,5 @@ +{ + "mainFile": "code/test.kt", + "type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS", + "targetPackage": "code.anotherPackage" +} diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/moveOnlyFunctionToPackageUsedInJava/after/nonCodeUsage.txt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/moveOnlyFunctionToPackageUsedInJava/after/nonCodeUsage.txt new file mode 100644 index 00000000000..2bb8c69549e --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/moveOnlyFunctionToPackageUsedInJava/after/nonCodeUsage.txt @@ -0,0 +1,4 @@ + +//Here we are using newPackage.foo name for test pure kotlin naming of top level kotlin function + +//And we are using newPackage.FunKt.foo name for test java naming of top level kotlin function \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/moveOnlyFunctionToPackageUsedInJava/before/nonCodeUsage.txt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/moveOnlyFunctionToPackageUsedInJava/before/nonCodeUsage.txt new file mode 100644 index 00000000000..abb6b744b11 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/moveOnlyFunctionToPackageUsedInJava/before/nonCodeUsage.txt @@ -0,0 +1,4 @@ + +//Here we are using oldPackage.foo name for test pure kotlin naming of top level kotlin function + +//And we are using oldPackage.FunKt.foo name for test java naming of top level kotlin function \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java index df5a49ad3d3..ec70d800011 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java @@ -588,6 +588,11 @@ public class MoveTestGenerated extends AbstractMoveTest { runTest("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/mutualDependency/MutualDependency.test"); } + @TestMetadata("kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/nonCodeUsagesWithJavaFacadeMethod.test") + public void testKotlin_moveTopLevelDeclarations_misc_nonCodeUsagesWithJavaFacadeMethod_NonCodeUsagesWithJavaFacadeMethod() throws Exception { + runTest("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithJavaFacadeMethod/nonCodeUsagesWithJavaFacadeMethod.test"); + } + @TestMetadata("kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithQuotedName/nonCodeUsageWithQuotedName.test") public void testKotlin_moveTopLevelDeclarations_misc_nonCodeUsagesWithQuotedName_NonCodeUsageWithQuotedName() throws Exception { runTest("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithQuotedName/nonCodeUsageWithQuotedName.test");