"Rename on import" hides importing of the same symbol by other imports with the original name

This commit is contained in:
Valentin Kipyatkov
2016-01-13 20:22:40 +03:00
parent 47041885ca
commit 5a079defc7
13 changed files with 111 additions and 32 deletions
@@ -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(
@@ -2,4 +2,7 @@ package a
import a.A as ER
class A()
interface A {
val a: A
val b: ER
}
@@ -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]
}
@@ -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>){}
@@ -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()
}
@@ -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