Auto-import fix also honors visibility

This commit is contained in:
Valentin Kipyatkov
2014-10-20 14:37:54 +04:00
parent 0a24dca821
commit 13d9fd083c
4 changed files with 33 additions and 30 deletions
@@ -40,7 +40,8 @@ import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo
public class KotlinIndicesHelper(private val project: Project,
private val resolveSession: ResolveSessionForBodies,
private val scope: GlobalSearchScope) {
private val scope: GlobalSearchScope,
private val visibilityFilter: (DeclarationDescriptor) -> Boolean) {
public fun getTopLevelObjects(nameFilter: (String) -> Boolean): Collection<ClassDescriptor> {
val allObjectNames = JetTopLevelObjectShortNameIndex.getInstance().getAllKeys(project).stream() +
JetFromJavaDescriptorHelper.getPossiblePackageDeclarationsNames(project, scope).stream()
@@ -66,7 +67,7 @@ public class KotlinIndicesHelper(private val project: Project,
}
}
return result
return result.filter(visibilityFilter)
}
public fun getTopLevelCallablesByName(name: String, context: JetExpression /*TODO: to be dropped*/): Collection<CallableDescriptor> {
@@ -85,7 +86,7 @@ public class KotlinIndicesHelper(private val project: Project,
result.addSourceTopLevelFunctions(name)
result.addSourceTopLevelProperties(name)
return result
return result.filter(visibilityFilter)
}
private fun MutableCollection<in FunctionDescriptor>.addSourceTopLevelFunctions(name: String) {
@@ -185,6 +186,7 @@ public class KotlinIndicesHelper(private val project: Project,
return declarationDescriptors
.filterIsInstance(javaClass<CallableDescriptor>())
.filter { it.getExtensionReceiverParameter() != null &&
visibilityFilter(it) &&
ExpressionTypingUtils.checkIsExtensionCallable(receiverValue, it, isInfixCall, bindingContext, dataFlowInfo) }
}
@@ -205,13 +207,13 @@ public class KotlinIndicesHelper(private val project: Project,
}
// Note: Can't search with psi element as analyzer could be built over temp files
return ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession.getModuleDescriptor(), classFQName)
return ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession.getModuleDescriptor(), classFQName).filter(visibilityFilter)
}
private fun findTopLevelCallables(fqName: FqName, context: JetExpression, jetScope: JetScope): Collection<CallableDescriptor> {
val importDirective = JetPsiFactory(context.getProject()).createImportDirective(ImportPath(fqName, false))
val allDescriptors = analyzeImportReference(importDirective, jetScope, BindingTraceContext(), resolveSession.getModuleDescriptor())
return allDescriptors.filterIsInstance(javaClass<CallableDescriptor>()).filter { it.getExtensionReceiverParameter() == null }
return allDescriptors.filterIsInstance(javaClass<CallableDescriptor>()).filter { it.getExtensionReceiverParameter() == null && visibilityFilter(it) }
}
private fun analyzeImportReference(
@@ -63,7 +63,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
protected val project: Project = position.getProject()
protected val searchScope: GlobalSearchScope = searchScopeForSourceElementDependencies(parameters.getOriginalFile()) ?: GlobalSearchScope.EMPTY_SCOPE
protected val indicesHelper: KotlinIndicesHelper = KotlinIndicesHelper(project, resolveSession, searchScope)
protected val indicesHelper: KotlinIndicesHelper = KotlinIndicesHelper(project, resolveSession, searchScope) { isVisibleDescriptor(it) }
protected fun isVisibleDescriptor(descriptor: DeclarationDescriptor): Boolean {
if (configuration.completeNonAccessibleDeclarations) return true
@@ -104,13 +104,11 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
protected fun getKotlinTopLevelDeclarations(): Collection<DeclarationDescriptor> {
val filter = { (name: String) -> prefixMatcher.prefixMatches(name) }
return (indicesHelper.getTopLevelCallables(filter, jetReference!!.expression) + indicesHelper.getTopLevelObjects(filter))
.filter { isVisibleDescriptor(it) }
return indicesHelper.getTopLevelCallables(filter, jetReference!!.expression) + indicesHelper.getTopLevelObjects(filter)
}
protected fun getKotlinExtensions(): Collection<CallableDescriptor> {
return indicesHelper.getCallableExtensions({ prefixMatcher.prefixMatches(it) }, jetReference!!.expression)
.filter { isVisibleDescriptor(it) }
}
protected fun addAllTypes() {
@@ -42,7 +42,7 @@ class TypesCompletion(val parameters: CompletionParameters,
val project = parameters.getOriginalFile().getProject()
val searchScope = searchScopeForSourceElementDependencies(parameters.getOriginalFile()) ?: return
result.addDescriptorElements(KotlinIndicesHelper(project, resolveSession, searchScope).getClassDescriptors { prefixMatcher.prefixMatches(it) }.filter(visibilityFilter),
result.addDescriptorElements(KotlinIndicesHelper(project, resolveSession, searchScope, visibilityFilter).getClassDescriptors { prefixMatcher.prefixMatches(it) },
suppressAutoInsertion = true)
if (!ProjectStructureUtil.isJsKotlinModule(parameters.getOriginalFile() as JetFile)) {
@@ -41,7 +41,6 @@ import org.jetbrains.jet.plugin.caches.JetShortNamesCache
import org.jetbrains.jet.plugin.caches.KotlinIndicesHelper
import org.jetbrains.jet.plugin.caches.resolve.*
import org.jetbrains.jet.plugin.project.ProjectStructureUtil
import org.jetbrains.jet.plugin.project.ResolveSessionForBodies
import org.jetbrains.jet.plugin.util.JetPsiHeuristicsUtil
import java.util.ArrayList
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
@@ -51,6 +50,9 @@ import com.intellij.openapi.module.ModuleUtilCore
import org.jetbrains.jet.plugin.util.ProjectRootsUtil
import org.jetbrains.jet.asJava.unwrapped
import org.jetbrains.jet.plugin.search.searchScopeForSourceElementDependencies
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorWithVisibility
import org.jetbrains.jet.lang.descriptors.Visibilities
/**
* Check possibility and perform fix for unresolved references.
@@ -112,40 +114,41 @@ public class AutoImportFix(element: JetSimpleNameExpression) : JetHintAction<Jet
val searchScope = searchScopeForSourceElementDependencies(file) ?: return listOf()
val resolutionScope = resolveSession.resolveToElement(element)[BindingContext.RESOLUTION_SCOPE, element] ?: return listOf()
val containingDescriptor = resolutionScope.getContainingDeclaration()
fun isVisible(descriptor: DeclarationDescriptor): Boolean {
if (descriptor is DeclarationDescriptorWithVisibility && containingDescriptor != null) {
return Visibilities.isVisible(descriptor, containingDescriptor)
}
return true
}
val result = ArrayList<PrioritizedFqName>()
val indicesHelper = KotlinIndicesHelper(file.getProject(), resolveSession, searchScope, ::isVisible)
if (!element.isImportDirectiveExpression() && !JetPsiUtil.isSelectorInQualified(element)) {
result.addAll(getClassNames(referenceName, file, searchScope))
result.addAll(getTopLevelCallables(referenceName, element, searchScope, resolveSession, file.getProject()))
result.addAll(getTopLevelCallables(referenceName, element, indicesHelper))
}
result.addAll(getExtensions(referenceName, element, searchScope, resolveSession, file.getProject()))
result.addAll(getExtensions(referenceName, element, indicesHelper))
return result
.filter { ImportInsertHelper.getInstance().needImport(ImportPath(it.fqName, false), file) }
.sortBy { it.priority.ordinal() }
.sortBy { it.priority }
.map { it.fqName }
}
private fun getTopLevelCallables(
name: String,
context: JetExpression,
searchScope: GlobalSearchScope,
resolveSession: ResolveSessionForBodies,
project: Project
): Collection<PrioritizedFqName>
= KotlinIndicesHelper(project, resolveSession, searchScope).getTopLevelCallablesByName(name, context)
private fun getTopLevelCallables(name: String, context: JetExpression, indicesHelper: KotlinIndicesHelper): Collection<PrioritizedFqName>
= indicesHelper.getTopLevelCallablesByName(name, context)
.map { PrioritizedFqName(it) }
.toSet()
private fun getExtensions(
name: String,
expression: JetSimpleNameExpression,
searchScope: GlobalSearchScope,
resolveSession: ResolveSessionForBodies,
project: Project
): Collection<PrioritizedFqName>
= KotlinIndicesHelper(project, resolveSession, searchScope).getCallableExtensions({ it == name }, expression)
private fun getExtensions(name: String, expression: JetSimpleNameExpression, indicesHelper: KotlinIndicesHelper): Collection<PrioritizedFqName>
= indicesHelper.getCallableExtensions({ it == name }, expression)
.map { PrioritizedFqName(it) }
.toSet()