More efficient code completion + fixed a few bugs

This commit is contained in:
Valentin Kipyatkov
2014-11-02 14:32:10 +03:00
parent f31832dea9
commit fe5dbbf9b3
21 changed files with 166 additions and 74 deletions
@@ -28,9 +28,9 @@ import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils
import java.util.*
import org.jetbrains.jet.lang.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.jet.lang.resolve.descriptorUtil.isExtension
import org.jetbrains.jet.lang.resolve.name.Name
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.jet.lang.resolve.scopes.getDescriptorsFiltered
public object TipsManager{
@@ -64,9 +64,8 @@ public object TipsManager{
val qualifier = context[BindingContext.QUALIFIER, receiverExpression]
if (qualifier != null) {
//TODO: filter out extensions!
// It's impossible to add extension function for package or class (if it's class object, expression type is not null)
qualifier.scope.getDescriptors(kindFilterMask and JetScope.NON_EXTENSIONS_MASK, nameFilter).filterTo(descriptors, ::filterIfInfix)
qualifier.scope.getDescriptorsFiltered(kindFilterMask and JetScope.NON_EXTENSIONS_MASK, nameFilter).filterTo(descriptors, ::filterIfInfix)
}
val expressionType = context[BindingContext.EXPRESSION_TYPE, receiverExpression]
@@ -74,12 +73,12 @@ public object TipsManager{
val receiverValue = ExpressionReceiver(receiverExpression, expressionType)
val dataFlowInfo = context.getDataFlowInfo(expression)
val mask = kindFilterMask and JetScope.NON_EXTENSIONS_MASK and JetScope.TYPE.inv()
for (variant in SmartCastUtils.getSmartCastVariants(receiverValue, context, dataFlowInfo)) {
//TODO: filter out nested classes!
variant.getMemberScope().getDescriptors(kindFilterMask, nameFilter).filterTo(descriptors) { filterIfInfix(it) && !it.isExtension }
variant.getMemberScope().getDescriptorsFiltered(mask, nameFilter).filterTo(descriptors, ::filterIfInfix)
}
descriptors.addAll(getCallableExtensions(resolutionScope, listOf(receiverValue), context, dataFlowInfo, isInfixCall, kindFilterMask, nameFilter))
descriptors.addCallableExtensions(resolutionScope, receiverValue, context, dataFlowInfo, isInfixCall, kindFilterMask, nameFilter)
}
return descriptors
@@ -87,21 +86,21 @@ public object TipsManager{
}
if (parent is JetImportDirective || parent is JetPackageDirective) {
return excludeNonPackageDescriptors(resolutionScope.getDescriptors(kindFilterMask and JetScope.PACKAGE, nameFilter))
if (kindFilterMask and JetScope.PACKAGE == 0) return listOf()
return resolutionScope.getDescriptorsFiltered(JetScope.PACKAGE, nameFilter)
}
else {
val descriptorsSet = HashSet<DeclarationDescriptor>()
val receivers = resolutionScope.getImplicitReceiversHierarchy()
for (receiver in receivers) {
receiver.getType().getMemberScope().getDescriptors(kindFilterMask and JetScope.NON_EXTENSIONS_MASK, nameFilter)
.filterTo(descriptorsSet) { !it.isExtension }
receivers.flatMapTo(descriptorsSet) {
it.getType().getMemberScope().getDescriptorsFiltered(kindFilterMask and JetScope.NON_EXTENSIONS_MASK, nameFilter)
}
val dataFlowInfo = context.getDataFlowInfo(expression)
val receiverValues = receivers.map { it.getValue() }
resolutionScope.getDescriptors(kindFilterMask, nameFilter).filterTo(descriptorsSet) {
resolutionScope.getDescriptorsFiltered(kindFilterMask, nameFilter).filterTo(descriptorsSet) {
if (it is CallableDescriptor && it.getExtensionReceiverParameter() != null) {
it.isExtensionCallable(receiverValues, context, dataFlowInfo, false)
}
@@ -113,23 +112,21 @@ public object TipsManager{
}
}
public fun getCallableExtensions(
private fun MutableCollection<DeclarationDescriptor>.addCallableExtensions(
resolutionScope: JetScope,
receivers: Collection<ReceiverValue>,
receiver: ReceiverValue,
context: BindingContext,
dataFlowInfo: DataFlowInfo,
isInfixCall: Boolean,
kindFilterMask: Int,
nameFilter: (Name) -> Boolean): Collection<CallableDescriptor> {
nameFilter: (Name) -> Boolean) {
val mask = kindFilterMask and JetScope.EXTENSIONS_MASK
if (mask == 0) return listOf()
return resolutionScope.getDescriptors(mask, nameFilter)
.stream()
.filterIsInstance(javaClass<CallableDescriptor>())
.filter {
it.getExtensionReceiverParameter() != null && it.isExtensionCallable(receivers, context, dataFlowInfo, isInfixCall)
}
.toList()
if (mask != 0) {
resolutionScope.getDescriptorsFiltered(mask, nameFilter)
.stream()
.filterIsInstance(javaClass<CallableDescriptor>())
.filterTo(this) { ExpressionTypingUtils.checkIsExtensionCallable(receiver, it, isInfixCall, context, dataFlowInfo) }
}
}
public fun CallableDescriptor.isExtensionCallable(receivers: Collection<ReceiverValue>,
@@ -145,20 +142,6 @@ public object TipsManager{
context: BindingContext,
nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
val resolutionScope = context[BindingContext.RESOLUTION_SCOPE, expression] ?: return listOf()
return excludeNonPackageDescriptors(resolutionScope.getDescriptors(JetScope.PACKAGE, nameFilter))
}
private fun excludeNonPackageDescriptors(descriptors: Collection<DeclarationDescriptor>): Collection<DeclarationDescriptor> {
return descriptors.filter{
if (it is PackageViewDescriptor) {
// Heuristic: we don't want to complete "System" in "package java.lang.Sys",
// so we find class of the same name as package, we exclude this package
val parent = it.getContainingDeclaration()
parent == null || parent.getMemberScope().getClassifier(it.getName()) == null
}
else {
false
}
}
return resolutionScope.getDescriptorsFiltered(JetScope.PACKAGE, nameFilter)
}
}
@@ -141,7 +141,8 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
addAllTypes()
}
else {
addReferenceVariants(JetScope.TYPE or JetScope.PACKAGE) { isPartOfTypeDeclaration(it) }
addReferenceVariants(JetScope.TYPE or JetScope.PACKAGE)
collector.addDescriptorElements(listOf(KotlinBuiltIns.getInstance().getUnit()), false)
JavaCompletionContributor.advertiseSecondCompletion(project, resultSet)
}
}
@@ -175,20 +176,6 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
private fun isOnlyKeywordCompletion()
= PsiTreeUtil.getParentOfType(position, javaClass<JetModifierList>()) != null
private fun isPartOfTypeDeclaration(descriptor: DeclarationDescriptor): Boolean {
return when (descriptor) {
is PackageViewDescriptor, is TypeParameterDescriptor -> true
is ClassDescriptor -> {
val kind = descriptor.getKind()
KotlinBuiltIns.getInstance().isUnit(descriptor.getDefaultType()) ||
kind != ClassKind.OBJECT && kind != ClassKind.CLASS_OBJECT
}
else -> false
}
}
private fun shouldRunOnlyTypeCompletion(): Boolean {
// Check that completion in the type annotation context and if there's a qualified
// expression we are at first of it
@@ -201,8 +188,8 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
return false
}
private fun addReferenceVariants(kindFilterMask: Int, filterCondition: (DeclarationDescriptor) -> Boolean = { true }) {
collector.addDescriptorElements(getReferenceVariants(kindFilterMask).filter { filterCondition(it) }, suppressAutoInsertion = false)
private fun addReferenceVariants(kindFilterMask: Int) {
collector.addDescriptorElements(getReferenceVariants(kindFilterMask), suppressAutoInsertion = false)
}
}
@@ -34,7 +34,7 @@ import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
import org.jetbrains.jet.renderer.DescriptorRenderer
import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptorImpl
class SmartCompletion(val expression: JetSimpleNameExpression,
val resolveSession: ResolveSessionForBodies,
@@ -38,7 +38,7 @@ import org.jetbrains.jet.plugin.util.makeNotNullable
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor
import org.jetbrains.jet.lang.descriptors.SamConstructorDescriptor
class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val bindingContext: BindingContext, val visibilityFilter: (DeclarationDescriptor) -> Boolean) {
public fun addToCollection(collection: MutableCollection<LookupElement>, expectedInfos: Collection<ExpectedInfo>) {