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.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.ImportPath
|
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.descriptorUtil.getImportableDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
|
import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.*
|
import org.jetbrains.kotlin.resolve.scopes.utils.*
|
||||||
|
import org.jetbrains.kotlin.types.error.ErrorSimpleFunctionDescriptorImpl
|
||||||
|
|
||||||
class KotlinImportOptimizer : ImportOptimizer {
|
class KotlinImportOptimizer : ImportOptimizer {
|
||||||
override fun supports(file: PsiFile) = file is KtFile
|
override fun supports(file: PsiFile) = file is KtFile
|
||||||
@@ -145,17 +147,27 @@ class KotlinImportOptimizer : ImportOptimizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitKtElement(element: KtElement) {
|
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
|
if (reference !is KtReference) continue
|
||||||
abstractRefs.add(AbstractReferenceImpl(reference))
|
abstractRefs.add(AbstractReferenceImpl(reference))
|
||||||
|
|
||||||
val names = reference.resolvesByNames
|
val names = reference.resolvesByNames
|
||||||
var isResolved = false
|
if (!isResolved) {
|
||||||
|
unresolvedNames += names
|
||||||
|
}
|
||||||
|
|
||||||
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
|
|
||||||
for (target in reference.targets(bindingContext)) {
|
for (target in reference.targets(bindingContext)) {
|
||||||
isResolved = true
|
|
||||||
|
|
||||||
val importableDescriptor = target.getImportableDescriptor()
|
val importableDescriptor = target.getImportableDescriptor()
|
||||||
val importableFqName = target.importableFqName ?: continue
|
val importableFqName = target.importableFqName ?: continue
|
||||||
val parentFqName = importableFqName.parent()
|
val parentFqName = importableFqName.parent()
|
||||||
@@ -171,11 +183,7 @@ class KotlinImportOptimizer : ImportOptimizer {
|
|||||||
namesToImport.getOrPut(importableFqName) { hashSetOf() } += descriptorNames
|
namesToImport.getOrPut(importableFqName) { hashSetOf() } += descriptorNames
|
||||||
descriptorsToImport += importableDescriptor
|
descriptorsToImport += importableDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isResolved && reference is KtSimpleNameReference) unresolvedNames += names
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.visitKtElement(element)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isAccessibleAsMember(target: DeclarationDescriptor, place: KtElement, bindingContext: BindingContext): Boolean {
|
private fun isAccessibleAsMember(target: DeclarationDescriptor, place: KtElement, bindingContext: BindingContext): Boolean {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import test1.MyClass
|
import test1.MyClass
|
||||||
import test1.iterator
|
import test1.iterator
|
||||||
|
import test2.iterator
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
val s = MyClass()
|
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");
|
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")
|
@TestMetadata("KT11640.kt")
|
||||||
public void testKT11640() throws Exception {
|
public void testKT11640() throws Exception {
|
||||||
runTest("idea/testData/editor/optimizeImports/common/KT11640.kt");
|
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");
|
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")
|
@TestMetadata("KT11640.kt")
|
||||||
public void testKT11640() throws Exception {
|
public void testKT11640() throws Exception {
|
||||||
runTest("idea/testData/editor/optimizeImports/common/KT11640.kt");
|
runTest("idea/testData/editor/optimizeImports/common/KT11640.kt");
|
||||||
|
|||||||
@@ -2,5 +2,8 @@
|
|||||||
package test;
|
package test;
|
||||||
|
|
||||||
import as.type.val.var.fun.is.in.object.when.typeof;
|
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`
|
||||||
|
// ERROR: Unresolved reference: `as`
|
||||||
package test
|
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