diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java index d6dd919c665..99ca5dd9081 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java @@ -19,11 +19,12 @@ package org.jetbrains.jet.lang.resolve.scopes; import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.TraceBasedRedeclarationHandler; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; @@ -31,7 +32,6 @@ import org.jetbrains.jet.utils.Printer; import java.util.Collection; import java.util.List; -import java.util.Set; public final class JetScopeUtils { private JetScopeUtils() {} @@ -51,28 +51,6 @@ public final class JetScopeUtils { ); } - /** - * Get all extension descriptors among visible descriptors for current scope. - * - * @param scope Scope for query extensions. - * @return extension descriptors. - */ - @NotNull - public static Collection getAllExtensions(@NotNull JetScope scope) { - Set result = Sets.newHashSet(); - - for (DeclarationDescriptor descriptor : scope.getDescriptors(JetScope.EXTENSIONS_MASK, JetScope.ALL_NAME_FILTER)) { - if (descriptor instanceof CallableDescriptor) { - CallableDescriptor callDescriptor = (CallableDescriptor) descriptor; - if (callDescriptor.getExtensionReceiverParameter() != null) { - result.add(callDescriptor); - } - } - } - - return result; - } - public static JetScope makeScopeForPropertyAccessor( @NotNull PropertyDescriptor propertyDescriptor, @NotNull JetScope parentScope, diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.kt b/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.kt index b56510d22c9..1f7a90e8102 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.kt +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.kt @@ -23,7 +23,6 @@ import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.jet.lang.resolve.scopes.JetScope -import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils @@ -31,18 +30,21 @@ 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 public object TipsManager{ public fun getReferenceVariants(expression: JetSimpleNameExpression, context: BindingContext, + kindFilterMask: Int, nameFilter: (Name) -> Boolean, visibilityFilter: (DeclarationDescriptor) -> Boolean): Collection { - return getReferenceVariants(expression, context, nameFilter).filter(visibilityFilter) + return getReferenceVariants(expression, context, kindFilterMask, nameFilter).filter(visibilityFilter) } private fun getReferenceVariants(expression: JetSimpleNameExpression, context: BindingContext, + kindFilterMask: Int, nameFilter: (Name) -> Boolean): Collection { val receiverExpression = expression.getReceiverExpression() val parent = expression.getParent() @@ -64,7 +66,7 @@ public object TipsManager{ 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(JetScope.NON_EXTENSIONS_MASK, nameFilter).filterTo(descriptors, ::filterIfInfix) + qualifier.scope.getDescriptors(kindFilterMask and JetScope.NON_EXTENSIONS_MASK, nameFilter).filterTo(descriptors, ::filterIfInfix) } val expressionType = context[BindingContext.EXPRESSION_TYPE, receiverExpression] @@ -74,12 +76,10 @@ public object TipsManager{ for (variant in SmartCastUtils.getSmartCastVariants(receiverValue, context, dataFlowInfo)) { //TODO: filter out nested classes! - variant.getMemberScope().getDescriptors().filterTo(descriptors) { filterIfInfix(it) && !it.isExtension } + variant.getMemberScope().getDescriptors(kindFilterMask, nameFilter).filterTo(descriptors) { filterIfInfix(it) && !it.isExtension } } - JetScopeUtils.getAllExtensions(resolutionScope).filterTo(descriptors) { - ExpressionTypingUtils.checkIsExtensionCallable(receiverValue, it, isInfixCall, context, dataFlowInfo) - } + descriptors.addAll(getCallableExtensions(resolutionScope, listOf(receiverValue), context, dataFlowInfo, isInfixCall, kindFilterMask, nameFilter)) } return descriptors @@ -87,23 +87,60 @@ public object TipsManager{ } if (parent is JetImportDirective || parent is JetPackageDirective) { - return excludeNonPackageDescriptors(resolutionScope.getDescriptors(JetScope.PACKAGE, nameFilter)) + return excludeNonPackageDescriptors(resolutionScope.getDescriptors(kindFilterMask and JetScope.PACKAGE, nameFilter)) } else { val descriptorsSet = HashSet() - for (receiverDescriptor in resolutionScope.getImplicitReceiversHierarchy()) { - receiverDescriptor.getType().getMemberScope().getDescriptors().filterTo(descriptorsSet) { !it.isExtension } + val receivers = resolutionScope.getImplicitReceiversHierarchy() + for (receiver in receivers) { + receiver.getType().getMemberScope().getDescriptors(kindFilterMask and JetScope.NON_EXTENSIONS_MASK, nameFilter) + .filterTo(descriptorsSet) { !it.isExtension } } - descriptorsSet.addAll(resolutionScope.getDescriptors(JetScope.ALL_KINDS_MASK, nameFilter)) + val dataFlowInfo = context.getDataFlowInfo(expression) + val receiverValues = receivers.map { it.getValue() } - descriptorsSet.excludeNotCallableExtensions(resolutionScope, context, context.getDataFlowInfo(expression)) + resolutionScope.getDescriptors(kindFilterMask, nameFilter).filterTo(descriptorsSet) { + if (it is CallableDescriptor && it.getExtensionReceiverParameter() != null) { + it.isExtensionCallable(receiverValues, context, dataFlowInfo, false) + } + else + true + } return descriptorsSet } } + public fun getCallableExtensions( + resolutionScope: JetScope, + receivers: Collection, + context: BindingContext, + dataFlowInfo: DataFlowInfo, + isInfixCall: Boolean, + kindFilterMask: Int, + nameFilter: (Name) -> Boolean): Collection { + val mask = kindFilterMask and JetScope.EXTENSIONS_MASK + if (mask == 0) return listOf() + return resolutionScope.getDescriptors(mask, nameFilter) + .stream() + .filterIsInstance(javaClass()) + .filter { + it.getExtensionReceiverParameter() != null && it.isExtensionCallable(receivers, context, dataFlowInfo, isInfixCall) + } + .toList() + } + + public fun CallableDescriptor.isExtensionCallable(receivers: Collection, + context: BindingContext, + dataFlowInfo: DataFlowInfo, + isInfixCall: Boolean): Boolean + = receivers.any { ExpressionTypingUtils.checkIsExtensionCallable(it, this, isInfixCall, context, dataFlowInfo) } + + public fun CallableDescriptor.isExtensionCallableWithImplicitReceiver(scope: JetScope, context: BindingContext, dataFlowInfo: DataFlowInfo): Boolean + = isExtensionCallable(scope.getImplicitReceiversHierarchy().map { it.getValue() }, context, dataFlowInfo, false) + public fun getPackageReferenceVariants(expression: JetSimpleNameExpression, context: BindingContext, nameFilter: (Name) -> Boolean): Collection { @@ -111,24 +148,6 @@ public object TipsManager{ return excludeNonPackageDescriptors(resolutionScope.getDescriptors(JetScope.PACKAGE, nameFilter)) } - public fun excludeNotCallableExtensions(descriptors: Collection, - scope: JetScope, - context: BindingContext, - dataFlowInfo: DataFlowInfo): Collection { - val set = HashSet(descriptors) - set.excludeNotCallableExtensions(scope, context, dataFlowInfo) - return set - } - - private fun MutableSet.excludeNotCallableExtensions(scope: JetScope, - context: BindingContext, - dataFlowInfo: DataFlowInfo) { - val implicitReceivers = scope.getImplicitReceiversHierarchy() - removeAll(JetScopeUtils.getAllExtensions(scope).filter { callable -> - implicitReceivers.none { ExpressionTypingUtils.checkIsExtensionCallable(it.getValue(), callable, false, context, dataFlowInfo) } - }) - } - private fun excludeNonPackageDescriptors(descriptors: Collection): Collection { return descriptors.filter{ if (it is PackageViewDescriptor) { diff --git a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt index 50a60f220bb..9b9f8bf612c 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt @@ -32,6 +32,7 @@ import org.jetbrains.jet.plugin.references.JetSimpleNameReference import org.jetbrains.jet.plugin.project.ResolveSessionForBodies import org.jetbrains.jet.plugin.caches.KotlinIndicesHelper import com.intellij.openapi.project.Project +import org.jetbrains.jet.lang.resolve.scopes.JetScope class CompletionSessionConfiguration( val completeNonImportedDeclarations: Boolean, @@ -86,8 +87,12 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess protected abstract fun doComplete() - protected fun getReferenceVariants(): Collection { - return TipsManager.getReferenceVariants(jetReference!!.expression, bindingContext!!, prefixMatcher.asNameFilter(), { isVisibleDescriptor(it) }) + protected fun getReferenceVariants(kindFilterMask: Int): Collection { + return TipsManager.getReferenceVariants(jetReference!!.expression, + bindingContext!!, + kindFilterMask, + prefixMatcher.asNameFilter(), + { isVisibleDescriptor(it) }) } protected fun shouldRunTopLevelCompletion(): Boolean { @@ -136,12 +141,12 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, addAllTypes() } else { - addReferenceVariants { isPartOfTypeDeclaration(it) } + addReferenceVariants(JetScope.TYPE or JetScope.PACKAGE) { isPartOfTypeDeclaration(it) } JavaCompletionContributor.advertiseSecondCompletion(project, resultSet) } } else { - addReferenceVariants() + addReferenceVariants(JetScope.ALL_KINDS_MASK) } } @@ -196,14 +201,20 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, return false } - private fun addReferenceVariants(filterCondition: (DeclarationDescriptor) -> Boolean = { true }) { - collector.addDescriptorElements(getReferenceVariants().filter { filterCondition(it) }, suppressAutoInsertion = false) + private fun addReferenceVariants(kindFilterMask: Int, filterCondition: (DeclarationDescriptor) -> Boolean = { true }) { + collector.addDescriptorElements(getReferenceVariants(kindFilterMask).filter { filterCondition(it) }, suppressAutoInsertion = false) } } class SmartCompletionSession(configuration: CompletionSessionConfiguration, parameters: CompletionParameters, resultSet: CompletionResultSet) : CompletionSessionBase(configuration, parameters, resultSet) { + // we do not include SAM-constructors because they are handled separately and adding them requires iterating of java classes + private val DESCRIPTOR_KIND_MASK = JetScope.ORDINARY_FUNCTION or + JetScope.EXTENSION_FUNCTION or + JetScope.VARIABLES_AND_PROPERTIES_MASK or + JetScope.ENUM_ENTRY + override fun doComplete() { if (jetReference != null) { val completion = SmartCompletion(jetReference.expression, resolveSession, { isVisibleDescriptor(it) }, parameters.getOriginalFile() as JetFile) @@ -213,7 +224,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para val filter = result.declarationFilter if (filter != null) { - getReferenceVariants().forEach { + getReferenceVariants(DESCRIPTOR_KIND_MASK).forEach { if (prefixMatcher.prefixMatches(it.getName().asString())) { collector.addElements(filter(it)) } diff --git a/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/BaseJetVariableMacro.java b/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/BaseJetVariableMacro.java index c3f86013648..9655681b630 100644 --- a/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/BaseJetVariableMacro.java +++ b/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/BaseJetVariableMacro.java @@ -74,20 +74,25 @@ public abstract class BaseJetVariableMacro extends Macro { ExpressionTypingComponents components = new InjectorForMacros(project, resolveSession.getModuleDescriptor()).getExpressionTypingComponents(); + DataFlowInfo dataFlowInfo = getDataFlowInfo(bindingContext, contextExpression); + List filteredDescriptors = new ArrayList(); for (DeclarationDescriptor declarationDescriptor : scope.getDescriptors(JetScope.VARIABLES_AND_PROPERTIES_MASK, JetScope.ALL_NAME_FILTER)) { if (declarationDescriptor instanceof VariableDescriptor) { VariableDescriptor variableDescriptor = (VariableDescriptor) declarationDescriptor; + + if (variableDescriptor.getExtensionReceiverParameter() != null + && !TipsManager.INSTANCE$.isExtensionCallableWithImplicitReceiver(variableDescriptor, scope, bindingContext, dataFlowInfo)) continue; + if (isSuitable(variableDescriptor, scope, project, components)) { filteredDescriptors.add(variableDescriptor); } } } - DataFlowInfo dataFlowInfo = getDataFlowInfo(bindingContext, contextExpression); List declarations = new ArrayList(); - for (DeclarationDescriptor declarationDescriptor : TipsManager.INSTANCE$.excludeNotCallableExtensions(filteredDescriptors, scope, bindingContext, dataFlowInfo)) { + for (DeclarationDescriptor declarationDescriptor : filteredDescriptors) { PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(declarationDescriptor); assert declaration == null || declaration instanceof PsiNamedElement; diff --git a/idea/src/org/jetbrains/jet/plugin/parameterInfo/JetFunctionParameterInfoHandler.java b/idea/src/org/jetbrains/jet/plugin/parameterInfo/JetFunctionParameterInfoHandler.java index bb6c84ba258..e737ae9da51 100644 --- a/idea/src/org/jetbrains/jet/plugin/parameterInfo/JetFunctionParameterInfoHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/parameterInfo/JetFunctionParameterInfoHandler.java @@ -407,7 +407,8 @@ public class JetFunctionParameterInfoHandler implements ParameterInfoHandlerWith return name.equals(refName); } }; - Collection variants = TipsManager.INSTANCE$.getReferenceVariants(callNameExpression, bindingContext, nameFilter, visibilityFilter); + Collection variants = TipsManager.INSTANCE$.getReferenceVariants( + callNameExpression, bindingContext, JetScope.FUNCTIONS_MASK | JetScope.TYPE, nameFilter, visibilityFilter); Collection> itemsToShow = new ArrayList>(); for (DeclarationDescriptor variant : variants) {