#KT-25674: Fix unexpected reference renames in literals when moving referenced files.
This commit is contained in:
+17
-1
@@ -64,7 +64,6 @@ import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
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.lang.AssertionError
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
interface Mover : (KtNamedDeclaration, KtElement) -> KtNamedDeclaration {
|
interface Mover : (KtNamedDeclaration, KtElement) -> KtNamedDeclaration {
|
||||||
@@ -205,6 +204,10 @@ class MoveKotlinDeclarationsProcessor(
|
|||||||
val searchScope = getSearchScope(lightElement) ?: return@flatMapTo emptyList()
|
val searchScope = getSearchScope(lightElement) ?: return@flatMapTo emptyList()
|
||||||
|
|
||||||
val newFqName = StringUtil.getQualifiedName(newContainerName, lightElement.name)
|
val newFqName = StringUtil.getQualifiedName(newContainerName, lightElement.name)
|
||||||
|
val newFqNameForKt = StringUtil.getQualifiedName(
|
||||||
|
newContainerName,
|
||||||
|
lightElement.namedUnwrappedElement?.name?: lightElement.name
|
||||||
|
)
|
||||||
|
|
||||||
val foundReferences = HashSet<PsiReference>()
|
val foundReferences = HashSet<PsiReference>()
|
||||||
val results = ReferencesSearch
|
val results = ReferencesSearch
|
||||||
@@ -232,6 +235,19 @@ class MoveKotlinDeclarationsProcessor(
|
|||||||
if (handler !is MoveKotlinClassHandler) handler.preprocessUsages(results)
|
if (handler !is MoveKotlinClassHandler) handler.preprocessUsages(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
results
|
||||||
|
.filter { it is NonCodeUsageInfo && it.file is KtFile }
|
||||||
|
.forEach {
|
||||||
|
val newText = NonCodeUsageInfo::class.java.getField("newText")
|
||||||
|
// A 'newText' is marked as final initially, but here we need to change it to prevent
|
||||||
|
// light-class names in kotlin files.
|
||||||
|
val oldAccessibility = newText.isAccessible
|
||||||
|
newText.isAccessible = true
|
||||||
|
newText.set(it, newFqNameForKt)
|
||||||
|
// Restore initial accessibility of 'newText' field.
|
||||||
|
newText.isAccessible = oldAccessibility
|
||||||
|
}
|
||||||
|
|
||||||
results
|
results
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-19
@@ -24,42 +24,55 @@ import com.intellij.psi.PsiReferenceRegistrar
|
|||||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FilePathReferenceProvider
|
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FilePathReferenceProvider
|
||||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference
|
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
|
import org.jetbrains.kotlin.idea.completion.KotlinCompletionCharFilter
|
||||||
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
|
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getContentRange
|
import org.jetbrains.kotlin.psi.psiUtil.getContentRange
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isPlain
|
import org.jetbrains.kotlin.psi.psiUtil.isPlain
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.plainContent
|
import org.jetbrains.kotlin.psi.psiUtil.plainContent
|
||||||
import org.jetbrains.kotlin.idea.completion.KotlinCompletionCharFilter
|
|
||||||
|
|
||||||
class KotlinFilePathReferenceContributor : AbstractKotlinReferenceContributor() {
|
class KotlinFilePathReferenceContributor : AbstractKotlinReferenceContributor() {
|
||||||
object KotlinFilePathReferenceProvider : FilePathReferenceProvider() {
|
object KotlinFilePathReferenceProvider : FilePathReferenceProvider() {
|
||||||
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<out PsiReference> {
|
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<out PsiReference> {
|
||||||
if (element !is KtStringTemplateExpression) return PsiReference.EMPTY_ARRAY
|
if (element !is KtStringTemplateExpression) return PsiReference.EMPTY_ARRAY
|
||||||
if (!element.isPlain()) return PsiReference.EMPTY_ARRAY
|
if (!element.isPlain()) return PsiReference.EMPTY_ARRAY
|
||||||
return getReferencesByElement(element, element.plainContent, element.getContentRange().startOffset, true)
|
val refByElem = getReferencesByElement(element, element.plainContent, element.getContentRange().startOffset, true)
|
||||||
.map {
|
val res = refByElem
|
||||||
if (it is FileReference) {
|
.map {
|
||||||
object: FileReference(it.fileReferenceSet, it.rangeInElement, it.index, it.text) {
|
if (it is FileReference) {
|
||||||
override fun getVariants(): Array<out Any> {
|
object : FileReference(it.fileReferenceSet, it.rangeInElement, it.index, it.text) {
|
||||||
return super.getVariants()
|
override fun getVariants(): Array<out Any> {
|
||||||
.map {
|
return super.getVariants()
|
||||||
(it as? LookupElement)?.apply {
|
.map {
|
||||||
putUserData(KotlinCompletionCharFilter.SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING, Unit)
|
(it as? LookupElement)?.apply {
|
||||||
} ?: it
|
putUserData(KotlinCompletionCharFilter.SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING, Unit)
|
||||||
}
|
} ?: it
|
||||||
.toTypedArray()
|
}
|
||||||
}
|
.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: this is a hack that prevents IDE from renaming paths in string literals when doing move.
|
||||||
|
// TODO: find another way of doing this (that may need re-implementing move files refactoring using .java move)
|
||||||
|
override fun getLastFileReference() = null
|
||||||
|
|
||||||
|
override fun bindToElement(element: PsiElement): PsiElement {
|
||||||
|
return rename(element.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bindToElement(element: PsiElement, absolute: Boolean): PsiElement {
|
||||||
|
return rename(element.text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else it
|
} else it
|
||||||
}
|
}
|
||||||
.toTypedArray()
|
.toTypedArray()
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
|
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
|
||||||
registrar.registerReferenceProvider(
|
registrar.registerReferenceProvider(
|
||||||
PlatformPatterns.psiElement(KtStringTemplateExpression::class.java),
|
PlatformPatterns.psiElement(KtStringTemplateExpression::class.java),
|
||||||
KotlinFilePathReferenceProvider
|
KotlinFilePathReferenceProvider
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user