Move: Perform extension import insertion after reference shortening
This commit is contained in:
+43
-5
@@ -18,22 +18,31 @@ package org.jetbrains.kotlin.idea.codeInsight.shorten
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.SmartPsiElementPointer
|
import com.intellij.psi.SmartPsiElementPointer
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
|
||||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
|
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.psi.SmartPointerManager
|
import com.intellij.psi.SmartPointerManager
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiMember
|
||||||
|
import org.jetbrains.kotlin.asJava.unwrapped
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.getJavaMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
import org.jetbrains.kotlin.idea.core.ShortenReferences.Options
|
import org.jetbrains.kotlin.idea.core.ShortenReferences.Options
|
||||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||||
import org.jetbrains.kotlin.psi.CopyableUserDataProperty
|
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
interface DelayedRefactoringRequest
|
interface DelayedRefactoringRequest
|
||||||
|
|
||||||
class ShorteningRequest(val pointer: SmartPsiElementPointer<KtElement>, val options: Options) : DelayedRefactoringRequest
|
class ShorteningRequest(val pointer: SmartPsiElementPointer<KtElement>, val options: Options) : DelayedRefactoringRequest
|
||||||
|
class ImportRequest(
|
||||||
|
val elementToImportPointer: SmartPsiElementPointer<PsiElement>,
|
||||||
|
val filePointer: SmartPsiElementPointer<KtFile>
|
||||||
|
) : DelayedRefactoringRequest
|
||||||
|
|
||||||
private var Project.delayedRefactoringRequests: MutableSet<DelayedRefactoringRequest>?
|
private var Project.delayedRefactoringRequests: MutableSet<DelayedRefactoringRequest>?
|
||||||
by UserDataProperty(Key.create("DELAYED_REFACTORING_REQUESTS"))
|
by UserDataProperty(Key.create("DELAYED_REFACTORING_REQUESTS"))
|
||||||
@@ -73,15 +82,44 @@ fun KtElement.addToShorteningWaitSet(options: Options = Options.DEFAULT) {
|
|||||||
project.getOrCreateRefactoringRequests().add(ShorteningRequest(elementPointer, options))
|
project.getOrCreateRefactoringRequests().add(ShorteningRequest(elementPointer, options))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addDelayedImportRequest(elementToImport: PsiElement, file: KtFile) {
|
||||||
|
assert(ApplicationManager.getApplication()!!.isWriteAccessAllowed) { "Write access needed" }
|
||||||
|
file.project.getOrCreateRefactoringRequests() += ImportRequest(elementToImport.createSmartPointer(), file.createSmartPointer())
|
||||||
|
}
|
||||||
|
|
||||||
fun performDelayedRefactoringRequests(project: Project) {
|
fun performDelayedRefactoringRequests(project: Project) {
|
||||||
project.delayedRefactoringRequests?.let { requests ->
|
project.delayedRefactoringRequests?.let { requests ->
|
||||||
project.delayedRefactoringRequests = null
|
project.delayedRefactoringRequests = null
|
||||||
|
|
||||||
val shorteningRequests = requests.filterIsInstance<ShorteningRequest>()
|
val shorteningRequests = ArrayList<ShorteningRequest>()
|
||||||
|
val importRequests = ArrayList<ImportRequest>()
|
||||||
|
requests.forEach {
|
||||||
|
when (it) {
|
||||||
|
is ShorteningRequest -> shorteningRequests += it
|
||||||
|
is ImportRequest -> importRequests += it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val elementToOptions = shorteningRequests.mapNotNull { req -> req.pointer.element?.let { it to req.options } }.toMap()
|
val elementToOptions = shorteningRequests.mapNotNull { req -> req.pointer.element?.let { it to req.options } }.toMap()
|
||||||
val elements = elementToOptions.keys
|
val elements = elementToOptions.keys
|
||||||
//TODO: this is not correct because it should not shorten deep into the elements!
|
//TODO: this is not correct because it should not shorten deep into the elements!
|
||||||
ShortenReferences({ elementToOptions[it] ?: Options.DEFAULT }).process(elements)
|
ShortenReferences({ elementToOptions[it] ?: Options.DEFAULT }).process(elements)
|
||||||
|
|
||||||
|
val importInsertHelper = ImportInsertHelper.getInstance(project)
|
||||||
|
|
||||||
|
for ((file, requestsForFile) in importRequests.groupBy { it.filePointer.element }) {
|
||||||
|
if (file == null) continue
|
||||||
|
|
||||||
|
for (requestForFile in requestsForFile) {
|
||||||
|
val elementToImport = requestForFile.elementToImportPointer.element?.unwrapped ?: continue
|
||||||
|
val descriptorToImport = when (elementToImport) {
|
||||||
|
is KtDeclaration -> elementToImport.resolveToDescriptor(BodyResolveMode.PARTIAL)
|
||||||
|
is PsiMember -> elementToImport.getJavaMemberDescriptor()
|
||||||
|
else -> null
|
||||||
|
} ?: continue
|
||||||
|
importInsertHelper.importDescriptor(file, descriptorToImport)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.KotlinFileReferencesResolver
|
import org.jetbrains.kotlin.idea.codeInsight.KotlinFileReferencesResolver
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.addDelayedImportRequest
|
||||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
import org.jetbrains.kotlin.idea.refactoring.fqName.isImported
|
import org.jetbrains.kotlin.idea.refactoring.fqName.isImported
|
||||||
import org.jetbrains.kotlin.idea.refactoring.isInJavaSourceRoot
|
import org.jetbrains.kotlin.idea.refactoring.isInJavaSourceRoot
|
||||||
@@ -358,7 +359,7 @@ fun postProcessMoveUsages(usages: Collection<UsageInfo>,
|
|||||||
is UnqualifiableMoveRenameUsageInfo -> {
|
is UnqualifiableMoveRenameUsageInfo -> {
|
||||||
val file = with(usage) { if (addImportToOriginalFile) originalFile else counterpart(originalFile) } as KtFile
|
val file = with(usage) { if (addImportToOriginalFile) originalFile else counterpart(originalFile) } as KtFile
|
||||||
val declaration = counterpart(usage.referencedElement!!).unwrapped as KtDeclaration
|
val declaration = counterpart(usage.referencedElement!!).unwrapped as KtDeclaration
|
||||||
ImportInsertHelper.getInstance(usage.project).importDescriptor(file, declaration.resolveToDescriptor())
|
addDelayedImportRequest(declaration, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
is MoveRenameUsageInfo -> {
|
is MoveRenameUsageInfo -> {
|
||||||
|
|||||||
Reference in New Issue
Block a user