Fixed references move refactoring for NonCode usages
We need to try correctly refactor NonCode usages of Java-like facade FQ names i.e. if we have file A.kt with method foo we need to check AKt.foo and foo entries for non-code text search Fixed #KT-36382
This commit is contained in:
+47
-8
@@ -31,6 +31,7 @@ import com.intellij.util.IncorrectOperationException
|
|||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
import gnu.trove.THashMap
|
import gnu.trove.THashMap
|
||||||
import gnu.trove.TObjectHashingStrategy
|
import gnu.trove.TObjectHashingStrategy
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
|
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
|
||||||
import org.jetbrains.kotlin.asJava.findFacadeClass
|
import org.jetbrains.kotlin.asJava.findFacadeClass
|
||||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
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.ifEmpty
|
||||||
import org.jetbrains.kotlin.utils.keysToMap
|
import org.jetbrains.kotlin.utils.keysToMap
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
interface Mover : (KtNamedDeclaration, KtElement) -> KtNamedDeclaration {
|
interface Mover : (KtNamedDeclaration, KtElement) -> KtNamedDeclaration {
|
||||||
object Default : Mover {
|
object Default : Mover {
|
||||||
@@ -195,6 +199,13 @@ class MoveKotlinDeclarationsProcessor(
|
|||||||
return null
|
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<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableCollection<UsageInfo>) {
|
fun collectUsages(kotlinToLightElements: Map<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableCollection<UsageInfo>) {
|
||||||
kotlinToLightElements.values.flatten().flatMapTo(result) { lightElement ->
|
kotlinToLightElements.values.flatten().flatMapTo(result) { lightElement ->
|
||||||
val searchScope = getSearchScope(lightElement) ?: return@flatMapTo emptyList()
|
val searchScope = getSearchScope(lightElement) ?: return@flatMapTo emptyList()
|
||||||
@@ -212,14 +223,42 @@ class MoveKotlinDeclarationsProcessor(
|
|||||||
|
|
||||||
val name = lightElement.getKotlinFqName()?.quoteIfNeeded()?.asString()
|
val name = lightElement.getKotlinFqName()?.quoteIfNeeded()?.asString()
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
TextOccurrencesUtil.findNonCodeUsages(
|
fun searchForKotlinNameUsages(results: ArrayList<UsageInfo>) {
|
||||||
lightElement,
|
TextOccurrencesUtil.findNonCodeUsages(
|
||||||
name,
|
lightElement,
|
||||||
descriptor.searchInCommentsAndStrings,
|
name,
|
||||||
descriptor.searchInNonCode,
|
descriptor.searchInCommentsAndStrings,
|
||||||
FqName(newFqName).quoteIfNeeded().asString(),
|
descriptor.searchInNonCode,
|
||||||
results
|
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<UsageInfo>().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 ->
|
MoveClassHandler.EP_NAME.extensions.filter { it !is MoveKotlinClassHandler }.forEach { handler ->
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package code.anotherPackage
|
||||||
|
|
||||||
|
fun MyTest() {}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package code
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
// MyTest
|
||||||
|
// code.anotherPackage.MyTest
|
||||||
|
// code.anotherPackage.TestKt.MyTest
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package code
|
||||||
|
|
||||||
|
fun <caret>MyTest() {}
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
// MyTest
|
||||||
|
// code.MyTest
|
||||||
|
// code.TestKt.MyTest
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"mainFile": "code/test.kt",
|
||||||
|
"type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS",
|
||||||
|
"targetPackage": "code.anotherPackage"
|
||||||
|
}
|
||||||
+4
@@ -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
|
||||||
+4
@@ -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
|
||||||
@@ -588,6 +588,11 @@ public class MoveTestGenerated extends AbstractMoveTest {
|
|||||||
runTest("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/mutualDependency/MutualDependency.test");
|
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")
|
@TestMetadata("kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithQuotedName/nonCodeUsageWithQuotedName.test")
|
||||||
public void testKotlin_moveTopLevelDeclarations_misc_nonCodeUsagesWithQuotedName_NonCodeUsageWithQuotedName() throws Exception {
|
public void testKotlin_moveTopLevelDeclarations_misc_nonCodeUsagesWithQuotedName_NonCodeUsageWithQuotedName() throws Exception {
|
||||||
runTest("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithQuotedName/nonCodeUsageWithQuotedName.test");
|
runTest("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/nonCodeUsagesWithQuotedName/nonCodeUsageWithQuotedName.test");
|
||||||
|
|||||||
Reference in New Issue
Block a user