Resolve references in background thread in PlainTextPasteImportResolver
#KT-16774 Fixed
This commit is contained in:
+48
-29
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.referenceExpression
|
import org.jetbrains.kotlin.psi.psiUtil.referenceExpression
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class PlainTextPasteImportResolver(private val dataForConversion: DataForConversion, val targetFile: KtFile) {
|
class PlainTextPasteImportResolver(private val dataForConversion: DataForConversion, val targetFile: KtFile) {
|
||||||
private val file = dataForConversion.file
|
private val file = dataForConversion.file
|
||||||
@@ -57,7 +56,7 @@ class PlainTextPasteImportResolver(private val dataForConversion: DataForConvers
|
|||||||
private var ambiguityInResolution = false
|
private var ambiguityInResolution = false
|
||||||
private var couldNotResolve = false
|
private var couldNotResolve = false
|
||||||
|
|
||||||
val addedImports = ArrayList<PsiImportStatementBase>()
|
val addedImports = mutableListOf<PsiImportStatementBase>()
|
||||||
|
|
||||||
private fun canBeImported(descriptor: DeclarationDescriptorWithVisibility?): Boolean {
|
private fun canBeImported(descriptor: DeclarationDescriptorWithVisibility?): Boolean {
|
||||||
return descriptor != null
|
return descriptor != null
|
||||||
@@ -65,17 +64,17 @@ class PlainTextPasteImportResolver(private val dataForConversion: DataForConvers
|
|||||||
&& descriptor.isVisible(targetFile, null, bindingContext, resolutionFacade)
|
&& descriptor.isVisible(targetFile, null, bindingContext, resolutionFacade)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addImport(importStatement: PsiImportStatementBase, shouldAddToTarget: Boolean = false) {
|
private fun addImport(addImportData: AddImportData) {
|
||||||
importList.add(importStatement)
|
importList.add(addImportData.importStatement)
|
||||||
if (shouldAddToTarget)
|
if (addImportData.shouldAddToTarget)
|
||||||
addedImports.add(importStatement)
|
addedImports.add(addImportData.importStatement)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addImportsFromTargetFile() {
|
fun addImportsFromTargetFile() {
|
||||||
if (importList in dataForConversion.elementsAndTexts.toList()) return
|
if (importList in dataForConversion.elementsAndTexts.toList()) return
|
||||||
|
|
||||||
val task = {
|
val task = {
|
||||||
val addImportList = mutableListOf<PsiImportStatementBase>()
|
val addImportList = mutableListOf<AddImportData>()
|
||||||
|
|
||||||
fun tryConvertKotlinImport(importDirective: KtImportDirective) {
|
fun tryConvertKotlinImport(importDirective: KtImportDirective) {
|
||||||
val importPath = importDirective.importPath
|
val importPath = importDirective.importPath
|
||||||
@@ -100,33 +99,28 @@ class PlainTextPasteImportResolver(private val dataForConversion: DataForConvers
|
|||||||
when {
|
when {
|
||||||
isClassReceiver ->
|
isClassReceiver ->
|
||||||
addImportList.add(
|
addImportList.add(
|
||||||
psiElementFactory.createImportStaticStatement(
|
AddImportData(psiElementFactory.createImportStaticStatement(receiver as PsiClass, "*"))
|
||||||
receiver as PsiClass,
|
|
||||||
"*"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
isPackageReceiver ->
|
isPackageReceiver ->
|
||||||
addImportList.add(
|
addImportList.add(
|
||||||
psiElementFactory.createImportStatementOnDemand(
|
AddImportData(psiElementFactory.createImportStatementOnDemand((receiver as PsiPackage).qualifiedName))
|
||||||
(receiver as PsiPackage).qualifiedName
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
when {
|
when {
|
||||||
isClassSelector ->
|
isClassSelector ->
|
||||||
addImportList.add(
|
addImportList.add(
|
||||||
psiElementFactory.createImportStatement(
|
AddImportData(psiElementFactory.createImportStatement(selector as PsiClass))
|
||||||
selector as PsiClass
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
isClassReceiver ->
|
isClassReceiver ->
|
||||||
addImportList.add(
|
addImportList.add(
|
||||||
|
AddImportData(
|
||||||
psiElementFactory.createImportStaticStatement(
|
psiElementFactory.createImportStaticStatement(
|
||||||
receiver as PsiClass,
|
receiver as PsiClass,
|
||||||
importPath.importedName!!.asString()
|
importPath.importedName!!.asString()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,13 +144,11 @@ class PlainTextPasteImportResolver(private val dataForConversion: DataForConvers
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tryResolveReferences() {
|
private data class AddImportData(val importStatement: PsiImportStatementBase, val shouldAddToTarget: Boolean = false)
|
||||||
val elementsWithUnresolvedRef = PsiTreeUtil.collectElements(file) { element ->
|
|
||||||
element.reference != null
|
|
||||||
&& element.reference is PsiQualifiedReference
|
|
||||||
&& element.reference?.resolve() == null
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fun tryResolveReferences() {
|
||||||
|
val task = {
|
||||||
|
val addImportList = mutableListOf<AddImportData>()
|
||||||
fun tryResolveReference(reference: PsiQualifiedReference): Boolean {
|
fun tryResolveReference(reference: PsiQualifiedReference): Boolean {
|
||||||
if (reference.resolve() != null) return true
|
if (reference.resolve() != null) return true
|
||||||
val referenceName = reference.referenceName ?: return false
|
val referenceName = reference.referenceName ?: return false
|
||||||
@@ -173,12 +165,12 @@ class PlainTextPasteImportResolver(private val dataForConversion: DataForConvers
|
|||||||
classes.find { (_, descriptor) ->
|
classes.find { (_, descriptor) ->
|
||||||
JavaToKotlinClassMap.mapPlatformClass(descriptor!!).isNotEmpty()
|
JavaToKotlinClassMap.mapPlatformClass(descriptor!!).isNotEmpty()
|
||||||
}?.let { (psiClass, _) ->
|
}?.let { (psiClass, _) ->
|
||||||
addImport(psiElementFactory.createImportStatement(psiClass))
|
addImportList.add(AddImportData(psiElementFactory.createImportStatement(psiClass)))
|
||||||
}
|
}
|
||||||
if (reference.resolve() != null) return true
|
if (reference.resolve() != null) return true
|
||||||
|
|
||||||
classes.singleOrNull()?.let { (psiClass, _) ->
|
classes.singleOrNull()?.let { (psiClass, _) ->
|
||||||
addImport(psiElementFactory.createImportStatement(psiClass), true)
|
addImportList.add(AddImportData(psiElementFactory.createImportStatement(psiClass), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
@@ -199,7 +191,12 @@ class PlainTextPasteImportResolver(private val dataForConversion: DataForConvers
|
|||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
members.singleOrNull()?.let { (psiMember, _) ->
|
members.singleOrNull()?.let { (psiMember, _) ->
|
||||||
addImport(psiElementFactory.createImportStaticStatement(psiMember.containingClass!!, psiMember.name!!), true)
|
addImportList.add(
|
||||||
|
AddImportData(
|
||||||
|
psiElementFactory.createImportStaticStatement(psiMember.containingClass!!, psiMember.name!!),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
@@ -210,10 +207,25 @@ class PlainTextPasteImportResolver(private val dataForConversion: DataForConvers
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val elementsWithUnresolvedRef = runReadAction {
|
||||||
|
PsiTreeUtil.collectElements(file) { element ->
|
||||||
|
element.reference != null
|
||||||
|
&& element.reference is PsiQualifiedReference
|
||||||
|
&& element.reference?.resolve() == null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val reversed = elementsWithUnresolvedRef.reversedArray()
|
||||||
|
reversed.forEachIndexed { index, value ->
|
||||||
|
ProgressManager.getInstance().progressIndicator?.fraction = 1.0 * index / reversed.size
|
||||||
|
val reference = value.reference as PsiQualifiedReference
|
||||||
|
addImportList.clear()
|
||||||
|
val tryResolveReference = runReadAction { tryResolveReference(reference) }
|
||||||
|
if (!tryResolveReference) {
|
||||||
|
ApplicationManager.getApplication().invokeAndWait {
|
||||||
runWriteAction {
|
runWriteAction {
|
||||||
elementsWithUnresolvedRef.reversed().forEach {
|
addImportList.forEach { addImport(it) }
|
||||||
val reference = it.reference as PsiQualifiedReference
|
|
||||||
if (!tryResolveReference(reference)) {
|
|
||||||
val referenceName = reference.referenceName
|
val referenceName = reference.referenceName
|
||||||
if (referenceName != null) {
|
if (referenceName != null) {
|
||||||
failedToResolveReferenceNames += referenceName
|
failedToResolveReferenceNames += referenceName
|
||||||
@@ -223,3 +235,10 @@ class PlainTextPasteImportResolver(private val dataForConversion: DataForConvers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||||
|
task, "Resolving references ...", true, project
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user