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 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<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableCollection<UsageInfo>) {
|
||||
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<UsageInfo>) {
|
||||
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<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 ->
|
||||
|
||||
+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");
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
Reference in New Issue
Block a user