"Rename on import" hides importing of the same symbol by other imports with the original name
This commit is contained in:
@@ -16,17 +16,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.BaseImportingScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
|
||||
class AllUnderImportScope(descriptor: DeclarationDescriptor) : BaseImportingScope(null) {
|
||||
class AllUnderImportScope(
|
||||
descriptor: DeclarationDescriptor,
|
||||
aliasImportNames: Collection<FqName>
|
||||
) : BaseImportingScope(null) {
|
||||
|
||||
private val scopes: List<ResolutionScope> = if (descriptor is ClassDescriptor) {
|
||||
listOf(descriptor.staticScope, descriptor.unsubstitutedInnerClassesScope)
|
||||
}
|
||||
@@ -37,17 +40,39 @@ class AllUnderImportScope(descriptor: DeclarationDescriptor) : BaseImportingScop
|
||||
listOf((descriptor as PackageViewDescriptor).memberScope)
|
||||
}
|
||||
|
||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
|
||||
= scopes.flatMap { it.getContributedDescriptors(kindFilter, nameFilter) }
|
||||
private val excludedNames = if (aliasImportNames.isEmpty()) { // optimization
|
||||
emptyList<Name>()
|
||||
}
|
||||
else {
|
||||
val fqName = DescriptorUtils.getFqNameSafe(descriptor)
|
||||
aliasImportNames.mapNotNull { if (it.parent() == fqName) it.shortName() else null }
|
||||
}
|
||||
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation)
|
||||
= scopes.asSequence().mapNotNull { it.getContributedClassifier(name, location) }.singleOrNull()
|
||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): List<DeclarationDescriptor> {
|
||||
val nameFilterToUse = if (excludedNames.isEmpty()) { // optimization
|
||||
nameFilter
|
||||
}
|
||||
else {
|
||||
{ it !in excludedNames && nameFilter(it) }
|
||||
}
|
||||
|
||||
override fun getContributedVariables(name: Name, location: LookupLocation)
|
||||
= scopes.flatMap { it.getContributedVariables(name, location) }
|
||||
return scopes.flatMap { it.getContributedDescriptors(kindFilter, nameFilterToUse) }
|
||||
}
|
||||
|
||||
override fun getContributedFunctions(name: Name, location: LookupLocation)
|
||||
= scopes.flatMap { it.getContributedFunctions(name, location) }
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
|
||||
if (name in excludedNames) return null
|
||||
return scopes.asSequence().mapNotNull { it.getContributedClassifier(name, location) }.singleOrNull()
|
||||
}
|
||||
|
||||
override fun getContributedVariables(name: Name, location: LookupLocation): List<VariableDescriptor> {
|
||||
if (name in excludedNames) return emptyList()
|
||||
return scopes.flatMap { it.getContributedVariables(name, location) }
|
||||
}
|
||||
|
||||
override fun getContributedFunctions(name: Name, location: LookupLocation): List<FunctionDescriptor> {
|
||||
if (name in excludedNames) return emptyList()
|
||||
return scopes.flatMap { it.getContributedFunctions(name, location) }
|
||||
}
|
||||
|
||||
override fun printStructure(p: Printer) {
|
||||
p.println(javaClass.simpleName)
|
||||
|
||||
@@ -134,6 +134,7 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
||||
importDirective: KtImportDirective,
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
trace: BindingTrace,
|
||||
aliasImportNames: Collection<FqName>,
|
||||
packageFragmentForVisibilityCheck: PackageFragmentDescriptor?
|
||||
): ImportingScope? { // null if some error happened
|
||||
val importedReference = importDirective.importedReference ?: return null
|
||||
@@ -156,7 +157,7 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
||||
return null
|
||||
}
|
||||
|
||||
return AllUnderImportScope(packageOrClassDescriptor)
|
||||
return AllUnderImportScope(packageOrClassDescriptor, aliasImportNames)
|
||||
}
|
||||
else {
|
||||
return processSingleImport(moduleDescriptor, trace, importDirective, path, lastPart, packageFragmentForCheck)
|
||||
|
||||
@@ -60,17 +60,26 @@ open class FileScopeProviderImpl(
|
||||
|
||||
val imports = file.importDirectives
|
||||
|
||||
val aliasImportNames = imports.mapNotNull { if (it.aliasName != null) it.importedFqName else null }
|
||||
|
||||
val packageView = moduleDescriptor.getPackage(file.packageFqName)
|
||||
val packageFragment = topLevelDescriptorProvider.getPackageFragment(file.packageFqName)
|
||||
.sure { "Could not find fragment ${file.packageFqName} for file ${file.name}" }
|
||||
|
||||
fun createImportResolver(indexedImports: IndexedImports, trace: BindingTrace)
|
||||
= LazyImportResolver(storageManager, qualifiedExpressionResolver, moduleDescriptor, indexedImports, trace, packageFragment)
|
||||
= LazyImportResolver(storageManager, qualifiedExpressionResolver, moduleDescriptor, indexedImports, aliasImportNames, trace, packageFragment)
|
||||
|
||||
val aliasImportResolver = createImportResolver(AliasImportsIndexed(imports), bindingTrace)
|
||||
val explicitImportResolver = createImportResolver(ExplicitImportsIndexed(imports), bindingTrace)
|
||||
val allUnderImportResolver = createImportResolver(AllUnderImportsIndexed(imports), bindingTrace)
|
||||
val defaultAliasImportResolver = createImportResolver(AliasImportsIndexed(defaultImports), tempTrace)
|
||||
val defaultAllUnderImportResolver = createImportResolver(AllUnderImportsIndexed(defaultImports), tempTrace)
|
||||
|
||||
val defaultImportsFiltered = if (aliasImportNames.isEmpty()) { // optimization
|
||||
defaultImports
|
||||
}
|
||||
else {
|
||||
defaultImports.filter { it.isAllUnder || it.importedFqName !in aliasImportNames }
|
||||
}
|
||||
val defaultExplicitImportResolver = createImportResolver(ExplicitImportsIndexed(defaultImportsFiltered), tempTrace)
|
||||
val defaultAllUnderImportResolver = createImportResolver(AllUnderImportsIndexed(defaultImportsFiltered), tempTrace)
|
||||
|
||||
var scope: ImportingScope
|
||||
|
||||
@@ -86,14 +95,14 @@ open class FileScopeProviderImpl(
|
||||
scope = LazyImportScope(scope, allUnderImportResolver, LazyImportScope.FilteringKind.VISIBLE_CLASSES,
|
||||
"All under imports in $debugName (visible classes)")
|
||||
|
||||
scope = LazyImportScope(scope, defaultAliasImportResolver, LazyImportScope.FilteringKind.ALL,
|
||||
"Default alias imports in $debugName")
|
||||
scope = LazyImportScope(scope, defaultExplicitImportResolver, LazyImportScope.FilteringKind.ALL,
|
||||
"Default explicit imports in $debugName")
|
||||
|
||||
scope = SubpackagesImportingScope(scope, moduleDescriptor, FqName.ROOT)
|
||||
|
||||
scope = packageView.memberScope.memberScopeAsImportingScope(scope) //TODO: problems with visibility too
|
||||
|
||||
scope = LazyImportScope(scope, aliasImportResolver, LazyImportScope.FilteringKind.ALL, "Alias imports in $debugName")
|
||||
scope = LazyImportScope(scope, explicitImportResolver, LazyImportScope.FilteringKind.ALL, "Explicit imports in $debugName")
|
||||
|
||||
val lexicalScope = LexicalScope.empty(scope, packageFragment)
|
||||
|
||||
@@ -101,7 +110,7 @@ open class FileScopeProviderImpl(
|
||||
|
||||
val importResolver = object : ImportResolver {
|
||||
override fun forceResolveAllImports() {
|
||||
aliasImportResolver.forceResolveAllImports()
|
||||
explicitImportResolver.forceResolveAllImports()
|
||||
allUnderImportResolver.forceResolveAllImports()
|
||||
}
|
||||
|
||||
@@ -110,7 +119,7 @@ open class FileScopeProviderImpl(
|
||||
allUnderImportResolver.forceResolveImport(importDirective)
|
||||
}
|
||||
else {
|
||||
aliasImportResolver.forceResolveImport(importDirective)
|
||||
explicitImportResolver.forceResolveImport(importDirective)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
@@ -46,7 +47,7 @@ class AllUnderImportsIndexed(allImports: Collection<KtImportDirective>) : Indexe
|
||||
override fun importsForName(name: Name) = imports
|
||||
}
|
||||
|
||||
class AliasImportsIndexed(allImports: Collection<KtImportDirective>) : IndexedImports {
|
||||
class ExplicitImportsIndexed(allImports: Collection<KtImportDirective>) : IndexedImports {
|
||||
override val imports = allImports.filter { !it.isAllUnder() }
|
||||
|
||||
private val nameToDirectives: ListMultimap<Name, KtImportDirective> by lazy {
|
||||
@@ -74,13 +75,14 @@ class LazyImportResolver(
|
||||
val qualifiedExpressionResolver: QualifiedExpressionResolver,
|
||||
val moduleDescriptor: ModuleDescriptor,
|
||||
val indexedImports: IndexedImports,
|
||||
aliasImportNames: Collection<FqName>,
|
||||
private val traceForImportResolve: BindingTrace,
|
||||
private val packageFragment: PackageFragmentDescriptor
|
||||
) : ImportResolver {
|
||||
private val importedScopesProvider = storageManager.createMemoizedFunctionWithNullableValues {
|
||||
directive: KtImportDirective ->
|
||||
val directiveImportScope = qualifiedExpressionResolver.processImportReference(
|
||||
directive, moduleDescriptor, traceForImportResolve, packageFragment) ?: return@createMemoizedFunctionWithNullableValues null
|
||||
directive, moduleDescriptor, traceForImportResolve, aliasImportNames, packageFragment) ?: return@createMemoizedFunctionWithNullableValues null
|
||||
|
||||
if (!directive.isAllUnder) {
|
||||
PlatformTypesMappedToKotlinChecker.checkPlatformTypesMappedToKotlin(
|
||||
|
||||
+4
-1
@@ -2,4 +2,7 @@ package a
|
||||
|
||||
import a.A as ER
|
||||
|
||||
class A()
|
||||
interface A {
|
||||
val a: A
|
||||
val b: ER
|
||||
}
|
||||
|
||||
+3
-2
@@ -2,8 +2,9 @@ package
|
||||
|
||||
package a {
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
public interface A {
|
||||
public abstract val a: a.A
|
||||
public abstract val b: a.A
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
@@ -2,10 +2,21 @@
|
||||
package a
|
||||
|
||||
val x = 1
|
||||
val y = 1
|
||||
|
||||
// FILE: b.kt
|
||||
package b
|
||||
|
||||
import a.x as AX
|
||||
val x = ""
|
||||
|
||||
val y = AX
|
||||
// FILE: c.kt
|
||||
package c
|
||||
|
||||
import a.x as AX
|
||||
import a.*
|
||||
import b.*
|
||||
import a.y as AY
|
||||
|
||||
val v1: Int = AX
|
||||
val v2: String = x
|
||||
val v3 = <!UNRESOLVED_REFERENCE!>y<!>
|
||||
|
||||
@@ -2,8 +2,15 @@ package
|
||||
|
||||
package a {
|
||||
public val x: kotlin.Int = 1
|
||||
public val y: kotlin.Int = 1
|
||||
}
|
||||
|
||||
package b {
|
||||
public val y: kotlin.Int = 1
|
||||
public val x: kotlin.String = ""
|
||||
}
|
||||
|
||||
package c {
|
||||
public val v1: kotlin.Int = 1
|
||||
public val v2: kotlin.String = ""
|
||||
public val v3: [ERROR : Type for y]
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import kotlin.collections.map as map1
|
||||
import kotlin.Array as KotlinArray
|
||||
|
||||
fun f() {
|
||||
listOf(1).map1 { it.hashCode() }
|
||||
listOf(1).<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>map<!> { <!UNRESOLVED_REFERENCE!>it<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>hashCode<!>() }
|
||||
}
|
||||
|
||||
fun g(<!UNUSED_PARAMETER!>a1<!>: KotlinArray<Int>, <!UNUSED_PARAMETER!>a2<!>: <!UNRESOLVED_REFERENCE!>Array<!><Int>){}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun f(): kotlin.Unit
|
||||
public fun g(/*0*/ a1: kotlin.Array<kotlin.Int>, /*1*/ a2: [ERROR : Array<Int>]<kotlin.Int>): kotlin.Unit
|
||||
@@ -125,6 +125,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("RenameOnImportHidesDefaultImport.kt")
|
||||
public void testRenameOnImportHidesDefaultImport() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/RenameOnImportHidesDefaultImport.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -85,5 +85,5 @@ fun ResolutionFacade.resolveImportReference(
|
||||
val importDirective = KtPsiFactory(project).createImportDirective(ImportPath(fqName, false))
|
||||
val qualifiedExpressionResolver = this.getFrontendService(moduleDescriptor, QualifiedExpressionResolver::class.java)
|
||||
return qualifiedExpressionResolver.processImportReference(
|
||||
importDirective, moduleDescriptor, BindingTraceContext(), packageFragmentForVisibilityCheck = null)?.getContributedDescriptors() ?: emptyList()
|
||||
importDirective, moduleDescriptor, BindingTraceContext(), aliasImportNames = emptyList(), packageFragmentForVisibilityCheck = null)?.getContributedDescriptors() ?: emptyList()
|
||||
}
|
||||
+2
-1
@@ -146,7 +146,8 @@ class CodeFragmentAnalyzer(
|
||||
}
|
||||
|
||||
val importScopes = importList.imports.mapNotNull {
|
||||
qualifierResolver.processImportReference(it, resolveSession.moduleDescriptor, resolveSession.trace, null)
|
||||
qualifierResolver.processImportReference(it, resolveSession.moduleDescriptor, resolveSession.trace,
|
||||
aliasImportNames = emptyList(), packageFragmentForVisibilityCheck = null)
|
||||
}
|
||||
|
||||
return scopeForContextElement.addImportingScopes(importScopes) to dataFlowInfo
|
||||
|
||||
Reference in New Issue
Block a user