ImportOptimizer: add cases for unresolved references
Part of #KT-31331
This commit is contained in:
@@ -28,10 +28,12 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.ImportPath
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.*
|
||||
import org.jetbrains.kotlin.types.error.ErrorSimpleFunctionDescriptorImpl
|
||||
|
||||
class KotlinImportOptimizer : ImportOptimizer {
|
||||
override fun supports(file: PsiFile) = file is KtFile
|
||||
@@ -145,17 +147,27 @@ class KotlinImportOptimizer : ImportOptimizer {
|
||||
}
|
||||
|
||||
override fun visitKtElement(element: KtElement) {
|
||||
for (reference in element.references) {
|
||||
super.visitKtElement(element)
|
||||
|
||||
val references = element.references.ifEmpty { return }
|
||||
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
|
||||
val isResolved = if (element is KtCallElement)
|
||||
element.getResolvedCall(bindingContext) != null
|
||||
else
|
||||
element.mainReference?.resolveToDescriptors(bindingContext)?.let { descriptors ->
|
||||
descriptors.isNotEmpty() && descriptors.none { it is ErrorSimpleFunctionDescriptorImpl }
|
||||
} == true
|
||||
|
||||
for (reference in references) {
|
||||
if (reference !is KtReference) continue
|
||||
abstractRefs.add(AbstractReferenceImpl(reference))
|
||||
|
||||
val names = reference.resolvesByNames
|
||||
var isResolved = false
|
||||
if (!isResolved) {
|
||||
unresolvedNames += names
|
||||
}
|
||||
|
||||
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
|
||||
for (target in reference.targets(bindingContext)) {
|
||||
isResolved = true
|
||||
|
||||
val importableDescriptor = target.getImportableDescriptor()
|
||||
val importableFqName = target.importableFqName ?: continue
|
||||
val parentFqName = importableFqName.parent()
|
||||
@@ -171,11 +183,7 @@ class KotlinImportOptimizer : ImportOptimizer {
|
||||
namesToImport.getOrPut(importableFqName) { hashSetOf() } += descriptorNames
|
||||
descriptorsToImport += importableDescriptor
|
||||
}
|
||||
|
||||
if (!isResolved && reference is KtSimpleNameReference) unresolvedNames += names
|
||||
}
|
||||
|
||||
super.visitKtElement(element)
|
||||
}
|
||||
|
||||
private fun isAccessibleAsMember(target: DeclarationDescriptor, place: KtElement, bindingContext: BindingContext): Boolean {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import test1.MyClass
|
||||
import test1.iterator
|
||||
import test2.iterator
|
||||
|
||||
fun foo() {
|
||||
val s = MyClass()
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import test1.MyClass
|
||||
import test1.iterator
|
||||
import test2.iterator
|
||||
import test3.notIterator
|
||||
import test1.invoke
|
||||
import test4.*
|
||||
|
||||
fun foo() {
|
||||
val s = MyClass()
|
||||
for (i in s) {}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import test1.MyClass
|
||||
import test1.invoke
|
||||
import test1.iterator
|
||||
import test2.iterator
|
||||
import test4.*
|
||||
|
||||
fun foo() {
|
||||
val s = MyClass()
|
||||
for (i in s) {}
|
||||
}
|
||||
+5
@@ -133,6 +133,11 @@ public class JsOptimizeImportsTestGenerated extends AbstractJsOptimizeImportsTes
|
||||
runTest("idea/testData/editor/optimizeImports/common/IteratorFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("IteratorFunction2.kt")
|
||||
public void testIteratorFunction2() throws Exception {
|
||||
runTest("idea/testData/editor/optimizeImports/common/IteratorFunction2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("KT11640.kt")
|
||||
public void testKT11640() throws Exception {
|
||||
runTest("idea/testData/editor/optimizeImports/common/KT11640.kt");
|
||||
|
||||
+5
@@ -331,6 +331,11 @@ public class JvmOptimizeImportsTestGenerated extends AbstractJvmOptimizeImportsT
|
||||
runTest("idea/testData/editor/optimizeImports/common/IteratorFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("IteratorFunction2.kt")
|
||||
public void testIteratorFunction2() throws Exception {
|
||||
runTest("idea/testData/editor/optimizeImports/common/IteratorFunction2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("KT11640.kt")
|
||||
public void testKT11640() throws Exception {
|
||||
runTest("idea/testData/editor/optimizeImports/common/KT11640.kt");
|
||||
|
||||
@@ -2,5 +2,8 @@
|
||||
package test;
|
||||
|
||||
import as.type.val.var.fun.is.in.object.when.typeof;
|
||||
import as.type.val.var.fun.is.in.object.when.typeof.as;
|
||||
|
||||
class Test {}
|
||||
class Test {
|
||||
public void foo(as a) { }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// ERROR: Unresolved reference: `as`
|
||||
// ERROR: Unresolved reference: `as`
|
||||
package test
|
||||
|
||||
import `as`.type.`val`.`var`.`fun`.`is`.`in`.`object`.`when`.`typeof`
|
||||
import `as`.type.`val`.`var`.`fun`.`is`.`in`.`object`.`when`.`typeof`.`as`
|
||||
|
||||
internal class Test
|
||||
internal class Test {
|
||||
fun foo(a: `as`?) {}
|
||||
}
|
||||
Reference in New Issue
Block a user