From afe1b7eab19e3fc3ce21194c77193cd77dc4eb84 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Thu, 11 Aug 2016 20:18:17 +0300 Subject: [PATCH] Allow to exclude specific types from packages imported by default. --- .../kotlin/resolve/AllUnderImportScope.kt | 9 +++--- .../resolve/QualifiedExpressionResolver.kt | 4 +-- .../kotlin/resolve/lazy/FileScopeFactory.kt | 28 +++++++++++-------- .../kotlin/resolve/lazy/LazyImportScope.kt | 4 +-- .../load/kotlin/reflect/RuntimeModuleData.kt | 2 +- .../kotlin/descriptors/ModuleDescriptor.kt | 4 ++- .../jetbrains/kotlin/types/ErrorUtils.java | 6 ++++ .../idea/caches/resolve/resolutionApi.kt | 2 +- .../caches/resolve/CodeFragmentAnalyzer.kt | 2 +- .../navigation/SourceNavigationHelper.java | 5 +++- 10 files changed, 41 insertions(+), 25 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AllUnderImportScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AllUnderImportScope.kt index b9d5ac71e30..42843e9a371 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AllUnderImportScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AllUnderImportScope.kt @@ -27,7 +27,7 @@ import org.jetbrains.kotlin.utils.Printer class AllUnderImportScope( descriptor: DeclarationDescriptor, - aliasImportNames: Collection + excludedImportNames: Collection ) : BaseImportingScope(null) { private val scopes: List = if (descriptor is ClassDescriptor) { @@ -40,12 +40,13 @@ class AllUnderImportScope( listOf((descriptor as PackageViewDescriptor).memberScope) } - private val excludedNames = if (aliasImportNames.isEmpty()) { // optimization - emptyList() + private val excludedNames: Set = if (excludedImportNames.isEmpty()) { // optimization + emptySet() } else { val fqName = DescriptorUtils.getFqNameSafe(descriptor) - aliasImportNames.mapNotNull { if (it.parent() == fqName) it.shortName() else null } + // toSet() is used here instead mapNotNullTo(hashSetOf()) because it results in not keeping empty sets as separate instances + excludedImportNames.mapNotNull { if (it.parent() == fqName) it.shortName() else null }.toSet() } override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): List { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt index 18efdb7dc36..2157a9f9d44 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt @@ -158,7 +158,7 @@ class QualifiedExpressionResolver(val classifierUsageCheckers: Iterable, + excludedImportNames: Collection, packageFragmentForVisibilityCheck: PackageFragmentDescriptor? ): ImportingScope? { // null if some error happened val importedReference = importDirective.importedReference ?: return null @@ -182,7 +182,7 @@ class QualifiedExpressionResolver(val classifierUsageCheckers: Iterable Collection.concat(other: Collection?) = + if (other == null || other.isEmpty()) this else this + other + 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) - ?: error("Could not find fragment ${file.packageFqName} for file ${file.name}") - - fun createImportResolver(indexedImports: IndexedImports, trace: BindingTrace) - = LazyImportResolver(storageManager, qualifiedExpressionResolver, moduleDescriptor, indexedImports, aliasImportNames, trace, packageFragment) - - val explicitImportResolver = createImportResolver(ExplicitImportsIndexed(imports), bindingTrace) - val allUnderImportResolver = createImportResolver(AllUnderImportsIndexed(imports), bindingTrace) - val extraImports = file.originalFile.virtualFile?.let { vFile -> val scriptExternalDependencies = getScriptExternalDependencies(vFile, file.project) ktImportsFactory.createImportDirectives(scriptExternalDependencies?.imports?.map { ImportPath(it) }.orEmpty()) } - val allImplicitImports = defaultImports + extraImports.orEmpty() + val allImplicitImports = defaultImports concat extraImports val defaultImportsFiltered = if (aliasImportNames.isEmpty()) { // optimization allImplicitImports @@ -85,8 +78,19 @@ class FileScopeFactory( else { allImplicitImports.filter { it.isAllUnder || it.importedFqName !in aliasImportNames } } + + val packageView = moduleDescriptor.getPackage(file.packageFqName) + val packageFragment = topLevelDescriptorProvider.getPackageFragment(file.packageFqName) + ?: error("Could not find fragment ${file.packageFqName} for file ${file.name}") + + fun createImportResolver(indexedImports: IndexedImports, trace: BindingTrace, excludedImports: List? = null) + = LazyImportResolver(storageManager, qualifiedExpressionResolver, moduleDescriptor, indexedImports, aliasImportNames concat excludedImports, trace, packageFragment) + + val explicitImportResolver = createImportResolver(ExplicitImportsIndexed(imports), bindingTrace) + val allUnderImportResolver = createImportResolver(AllUnderImportsIndexed(imports), bindingTrace) // TODO: should we count excludedImports here also? + val defaultExplicitImportResolver = createImportResolver(ExplicitImportsIndexed(defaultImportsFiltered), tempTrace) - val defaultAllUnderImportResolver = createImportResolver(AllUnderImportsIndexed(defaultImportsFiltered), tempTrace) + val defaultAllUnderImportResolver = createImportResolver(AllUnderImportsIndexed(defaultImportsFiltered), tempTrace, moduleDescriptor.excludedImports) val dummyContainerDescriptor = DummyContainerDescriptor(file, packageFragment) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt index 035eda4830d..e4386bef560 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt @@ -75,14 +75,14 @@ class LazyImportResolver( val qualifiedExpressionResolver: QualifiedExpressionResolver, val moduleDescriptor: ModuleDescriptor, val indexedImports: IndexedImports, - aliasImportNames: Collection, + excludedImportNames: Collection, private val traceForImportResolve: BindingTrace, private val packageFragment: PackageFragmentDescriptor ) : ImportResolver { private val importedScopesProvider = storageManager.createMemoizedFunctionWithNullableValues { directive: KtImportDirective -> val directiveImportScope = qualifiedExpressionResolver.processImportReference( - directive, moduleDescriptor, traceForImportResolve, aliasImportNames, packageFragment) ?: return@createMemoizedFunctionWithNullableValues null + directive, moduleDescriptor, traceForImportResolve, excludedImportNames, packageFragment) ?: return@createMemoizedFunctionWithNullableValues null if (!directive.isAllUnder) { PlatformTypesMappedToKotlinChecker.checkPlatformTypesMappedToKotlin( diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt index d621048ed09..446d7620868 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt @@ -49,7 +49,7 @@ class RuntimeModuleData private constructor(val deserialization: Deserialization val storageManager = LockBasedStorageManager() val builtIns = JvmBuiltIns(storageManager) val module = ModuleDescriptorImpl(Name.special(""), storageManager, - ModuleParameters(listOf(), JavaToKotlinClassMap.INSTANCE), builtIns) + ModuleParameters(emptyList(), emptyList(), JavaToKotlinClassMap.INSTANCE), builtIns) val reflectKotlinClassFinder = ReflectKotlinClassFinder(classLoader) val deserializedDescriptorResolver = DeserializedDescriptorResolver(RuntimeErrorReporter) diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt index 53ceaa2e9ed..eca88077d00 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt @@ -49,6 +49,7 @@ interface ModuleDescriptor : DeclarationDescriptor, ModuleParameters { interface ModuleParameters { val defaultImports: List + val excludedImports: List get() = emptyList() val platformToKotlinClassMap: PlatformToKotlinClassMap object Empty: ModuleParameters { @@ -57,8 +58,9 @@ interface ModuleParameters { } } -fun ModuleParameters(defaultImports: List, platformToKotlinClassMap: PlatformToKotlinClassMap): ModuleParameters = +fun ModuleParameters(defaultImports: List, excludedImports: List, platformToKotlinClassMap: PlatformToKotlinClassMap): ModuleParameters = object : ModuleParameters { override val defaultImports: List = defaultImports + override val excludedImports: List get() = excludedImports override val platformToKotlinClassMap: PlatformToKotlinClassMap = platformToKotlinClassMap } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java index d6cdcf82495..cf2724eee11 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java @@ -69,6 +69,12 @@ public class ErrorUtils { return emptyList(); } + @NotNull + @Override + public List getExcludedImports() { + return emptyList(); + } + @NotNull @Override public Annotations getAnnotations() { diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt index f0baf7c3d01..a4d600fe20e 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt @@ -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(), aliasImportNames = emptyList(), packageFragmentForVisibilityCheck = null)?.getContributedDescriptors() ?: emptyList() + importDirective, moduleDescriptor, BindingTraceContext(), excludedImportNames = emptyList(), packageFragmentForVisibilityCheck = null)?.getContributedDescriptors() ?: emptyList() } \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt index 4739dc288af..32300a73cb3 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt @@ -136,7 +136,7 @@ class CodeFragmentAnalyzer( val importScopes = importList.imports.mapNotNull { qualifierResolver.processImportReference(it, resolveSession.moduleDescriptor, resolveSession.trace, - aliasImportNames = emptyList(), packageFragmentForVisibilityCheck = null) + excludedImportNames = emptyList(), packageFragmentForVisibilityCheck = null) } return scopeForContextElement.addImportingScopes(importScopes) to dataFlowInfo diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/SourceNavigationHelper.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/SourceNavigationHelper.java index 6d57bcc148e..a72d628ac6c 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/SourceNavigationHelper.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/SourceNavigationHelper.java @@ -45,6 +45,7 @@ import org.jetbrains.kotlin.context.ContextKt; import org.jetbrains.kotlin.context.MutableModuleContext; import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.ModuleDescriptorKt; +import org.jetbrains.kotlin.descriptors.ModuleParameters; import org.jetbrains.kotlin.frontend.di.InjectionKt; import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex; import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope; @@ -239,10 +240,12 @@ public class SourceNavigationHelper { ) { TargetPlatform platform = TargetPlatform.Default.INSTANCE; + ModuleParameters defaultJvmModuleParameters = JvmPlatform.INSTANCE.getDefaultModuleParameters(); MutableModuleContext newModuleContext = ContextKt.ContextForNewModule( project, Name.special(""), ModuleDescriptorKt.ModuleParameters( - JvmPlatform.INSTANCE.getDefaultModuleParameters().getDefaultImports(), + defaultJvmModuleParameters.getDefaultImports(), + defaultJvmModuleParameters.getExcludedImports(), PlatformToKotlinClassMap.EMPTY ), DefaultBuiltIns.getInstance()