From 65b74a19b4a94fa2d0119901b0f04b39bc412095 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Sat, 16 Jun 2012 06:44:17 +0400 Subject: [PATCH] use the power of DescriptorPredicate in completion --- .../jet/cli/jvm/compiler/TipsManager.java | 57 +++++----- .../resolve/scopes/DescriptorPredicate.java | 100 ++++++++++++++++-- .../resolve/scopes/WritableScopeImpl.java | 2 +- .../completion/JetCompletionContributor.java | 14 ++- .../macro/BaseJetVariableMacro.java | 3 +- .../JetFunctionParameterInfoHandler.java | 3 +- .../refactoring/JetNameValidatorImpl.java | 3 +- .../references/JetSimpleNameReference.java | 3 +- 8 files changed, 139 insertions(+), 46 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/cli/jvm/compiler/TipsManager.java b/compiler/backend/src/org/jetbrains/jet/cli/jvm/compiler/TipsManager.java index ba8bf37734c..9abda767899 100644 --- a/compiler/backend/src/org/jetbrains/jet/cli/jvm/compiler/TipsManager.java +++ b/compiler/backend/src/org/jetbrains/jet/cli/jvm/compiler/TipsManager.java @@ -32,9 +32,9 @@ import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; +import org.jetbrains.jet.lang.resolve.name.NamePredicate; import org.jetbrains.jet.lang.resolve.scopes.DescriptorPredicate; 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.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; @@ -52,7 +52,8 @@ public final class TipsManager { } @NotNull - public static Collection getReferenceVariants(JetSimpleNameExpression expression, BindingContext context) { + public static Collection getReferenceVariants( + JetSimpleNameExpression expression, BindingContext context, @NotNull NamePredicate name) { JetExpression receiverExpression = expression.getReceiverExpression(); if (receiverExpression != null) { // Process as call expression @@ -74,32 +75,30 @@ public final class TipsManager { for (ReceiverDescriptor descriptor : variantsForExplicitReceiver) { descriptors.addAll(includeExternalCallableExtensions( - // TODO: better predicate - excludePrivateDescriptors(descriptor.getType().getMemberScope().getAllDescriptors(DescriptorPredicate.all())), - resolutionScope, descriptor)); + excludePrivateDescriptors(descriptor.getType().getMemberScope().getAllDescriptors(DescriptorPredicate.hasName(name))), + resolutionScope, descriptor, name)); } return descriptors; } return includeExternalCallableExtensions( - // TODO: better predicate - excludePrivateDescriptors(expressionType.getMemberScope().getAllDescriptors(DescriptorPredicate.all())), - resolutionScope, new ExpressionReceiver(receiverExpression, expressionType)); + excludePrivateDescriptors(expressionType.getMemberScope().getAllDescriptors(DescriptorPredicate.hasName(name))), + resolutionScope, new ExpressionReceiver(receiverExpression, expressionType), name); } return Collections.emptyList(); } else { - return getVariantsNoReceiver(expression, context); + return getVariantsNoReceiver(expression, context, name); } } - public static Collection getVariantsNoReceiver(JetExpression expression, BindingContext context) { + public static Collection getVariantsNoReceiver( + JetExpression expression, BindingContext context, @NotNull NamePredicate name) { JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression); if (resolutionScope != null) { if (expression.getParent() instanceof JetImportDirective || expression.getParent() instanceof JetNamespaceHeader) { - // TODO: better predicate - return excludeNonPackageDescriptors(resolutionScope.getAllDescriptors(DescriptorPredicate.all())); + return resolutionScope.getAllDescriptors(DescriptorPredicate.namespaces(name)); } else { Collection descriptorsSet = Sets.newHashSet(); @@ -109,13 +108,11 @@ public final class TipsManager { for (ReceiverDescriptor receiverDescriptor : result) { JetType receiverType = receiverDescriptor.getType(); - // TODO: better predicate - descriptorsSet.addAll(receiverType.getMemberScope().getAllDescriptors(DescriptorPredicate.all())); + descriptorsSet.addAll(receiverType.getMemberScope().getAllDescriptors(DescriptorPredicate.hasName(name))); } - // TODO: better predicate - descriptorsSet.addAll(resolutionScope.getAllDescriptors(DescriptorPredicate.all())); - return excludeNotCallableExtensions(excludePrivateDescriptors(descriptorsSet), resolutionScope); + descriptorsSet.addAll(resolutionScope.getAllDescriptors(DescriptorPredicate.hasName(name))); + return excludeNotCallableExtensions(excludePrivateDescriptors(descriptorsSet), resolutionScope, name); } } return Collections.emptyList(); @@ -148,7 +145,9 @@ public final class TipsManager { } public static Collection excludeNotCallableExtensions( - @NotNull Collection descriptors, @NotNull final JetScope scope + @NotNull Collection descriptors, + @NotNull final JetScope scope, + @NotNull NamePredicate name ) { final Set descriptorsSet = Sets.newHashSet(descriptors); @@ -156,9 +155,10 @@ public final class TipsManager { scope.getImplicitReceiversHierarchy(result); descriptorsSet.removeAll( - Collections2.filter(JetScopeUtils.getAllExtensions(scope), new Predicate() { + Collections2.filter(scope.getAllDescriptors(DescriptorPredicate.extension(name)), new Predicate() { @Override - public boolean apply(CallableDescriptor callableDescriptor) { + public boolean apply(DeclarationDescriptor declarationDescriptor) { + CallableDescriptor callableDescriptor = (CallableDescriptor) declarationDescriptor; if (!callableDescriptor.getReceiverParameter().exists()) { return false; } @@ -187,7 +187,8 @@ public final class TipsManager { private static Set includeExternalCallableExtensions( @NotNull Collection descriptors, @NotNull final JetScope externalScope, - @NotNull final ReceiverDescriptor receiverDescriptor + @NotNull final ReceiverDescriptor receiverDescriptor, + @NotNull NamePredicate name ) { // It's impossible to add extension function for namespace JetType receiverType = receiverDescriptor.getType(); @@ -198,13 +199,13 @@ public final class TipsManager { Set descriptorsSet = Sets.newHashSet(descriptors); descriptorsSet.addAll( - Collections2.filter(JetScopeUtils.getAllExtensions(externalScope), - new Predicate() { - @Override - public boolean apply(CallableDescriptor callableDescriptor) { - return ExpressionTypingUtils.checkIsExtensionCallable(receiverDescriptor, callableDescriptor); - } - })); + Collections2.filter(externalScope.getAllDescriptors(DescriptorPredicate.extension(name)), + new Predicate() { + @Override + public boolean apply(DeclarationDescriptor callableDescriptor) { + return ExpressionTypingUtils.checkIsExtensionCallable(receiverDescriptor, (CallableDescriptor) callableDescriptor); + } + })); return descriptorsSet; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/DescriptorPredicate.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/DescriptorPredicate.java index c1001099302..8a6ff5c1a29 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/DescriptorPredicate.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/DescriptorPredicate.java @@ -128,9 +128,9 @@ public abstract class DescriptorPredicate { private static class HasName extends DescriptorPredicate { @NotNull - private final Name required; + private final NamePredicate required; - private HasName(@NotNull Name required) { + private HasName(@NotNull NamePredicate required) { this.required = required; } @@ -151,18 +151,24 @@ public abstract class DescriptorPredicate { @Override public boolean includeName(@NotNull Name name) { - return required.equals(name); + return required.matches(name); } } - public static DescriptorPredicate hasName(@NotNull Name name) { - return new HasName(name); + public static DescriptorPredicate hasName(@NotNull NamePredicate required) { + return new HasName(required); } - private static class CallableMembers extends DescriptorPredicate { - public static final CallableMembers instance = new CallableMembers(); + private static class MembersOfType extends DescriptorPredicate { + + @NotNull + private final DescriptorKind required; + + private MembersOfType(@NotNull DescriptorKind required) { + this.required = required; + } @Override public boolean includeName(@NotNull Name name) { @@ -176,24 +182,71 @@ public abstract class DescriptorPredicate { @Override public boolean include(@NotNull DeclarationDescriptor descriptor) { - return descriptor instanceof CallableMemberDescriptor; + return descriptorKind(descriptor) == required; } @Override public boolean includeKind(@NotNull DescriptorKind kind) { - return kind == DescriptorKind.CALLABLE_MEMBER; + return kind == required; } } + + private static final DescriptorPredicate callableMembers = new MembersOfType(DescriptorKind.CALLABLE_MEMBER); + public static DescriptorPredicate callableMembers() { - return CallableMembers.instance; + return callableMembers; + } + + private static final DescriptorPredicate namespaces = new MembersOfType(DescriptorKind.NAMESPACE); + + public static DescriptorPredicate namespaces() { + return namespaces; } - private static class Extension extends CallableMembers { + private static class MembersOrTypeWithName extends MembersOfType { + @NotNull + private final NamePredicate required; + + private MembersOrTypeWithName(@NotNull DescriptorKind descriptorKind, @NotNull NamePredicate required) { + super(descriptorKind); + this.required = required; + } + + @Override + public boolean includeName(@NotNull Name name) { + return required.matches(name); + } + } + + public static DescriptorPredicate callableMembers(@NotNull NamePredicate required) { + if (required.isAll()) { + return callableMembers(); + } + else { + return new MembersOrTypeWithName(DescriptorKind.CALLABLE_MEMBER, required); + } + } + + public static DescriptorPredicate namespaces(@NotNull NamePredicate required) { + if (required.isAll()) { + return namespaces(); + } + else { + return new MembersOrTypeWithName(DescriptorKind.NAMESPACE, required); + } + } + + + private static class Extension extends MembersOfType { private static final Extension instance = new Extension(); + private Extension() { + super(DescriptorKind.CALLABLE_MEMBER); + } + @Override public boolean includeExtension(boolean extension) { return extension; @@ -205,6 +258,31 @@ public abstract class DescriptorPredicate { } + + private static class ExtensionWithName extends Extension { + @NotNull + private final NamePredicate required; + + private ExtensionWithName(@NotNull NamePredicate required) { + this.required = required; + } + + @Override + public boolean includeName(@NotNull Name name) { + return required.matches(name); + } + } + + public static DescriptorPredicate extension(@NotNull NamePredicate required) { + if (required.isAll()) { + return extension(); + } + else { + return new ExtensionWithName(required); + } + } + + public Predicate asGuavaPredicate() { return new Predicate() { @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java index fb0d02d18c2..9e5a6305182 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java @@ -158,7 +158,7 @@ public class WritableScopeImpl extends WritableScopeWithImports { if (!allDescriptorsDone) { if (!predicate.includeAll()) { // super-optimized version - return concat(allDescriptors, getInheritedDescriptors(predicate)); + return concat(DescriptorPredicateUtils.filter(allDescriptors, predicate), getInheritedDescriptors(predicate)); } allDescriptorsDone = true; diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java index c70ca9b9fa2..172bf2ea97c 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java @@ -35,6 +35,8 @@ import org.jetbrains.jet.cli.jvm.compiler.TipsManager; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.name.NamePredicate; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.caches.JetCacheManager; @@ -347,7 +349,15 @@ public class JetCompletionContributor extends CompletionContributor { (JetFile)reference.getExpression().getContainingFile()) .getBindingContext(); - Collection descriptors = TipsManager.getReferenceVariants(reference.getExpression(), bindingContext); + class PrefixMatcherNamePredicate extends NamePredicate { + @Override + public boolean matches(@NotNull Name name) { + return result.getPrefixMatcher().prefixMatches(name.getName()); + } + } + + Collection descriptors = TipsManager.getReferenceVariants( + reference.getExpression(), bindingContext, new PrefixMatcherNamePredicate()); Collection checkedDescriptors = Collections2.filter(descriptors, new Predicate() { @Override @@ -356,7 +366,7 @@ public class JetCompletionContributor extends CompletionContributor { return false; } - return result.getPrefixMatcher().prefixMatches(descriptor.getName().getName()) && isVisibleDescriptor(descriptor, session); + return isVisibleDescriptor(descriptor, session); } }); 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 6250c8390ad..5038012f467 100644 --- a/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/BaseJetVariableMacro.java +++ b/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/BaseJetVariableMacro.java @@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.name.NamePredicate; import org.jetbrains.jet.lang.resolve.scopes.DescriptorPredicate; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; @@ -84,7 +85,7 @@ public abstract class BaseJetVariableMacro extends Macro { } List declarations = new ArrayList(); - for (DeclarationDescriptor declarationDescriptor : TipsManager.excludeNotCallableExtensions(filteredDescriptors, scope)) { + for (DeclarationDescriptor declarationDescriptor : TipsManager.excludeNotCallableExtensions(filteredDescriptors, scope, NamePredicate.all())) { PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bc, 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 48a65c827d5..9ead989d8f4 100644 --- a/idea/src/org/jetbrains/jet/plugin/parameterInfo/JetFunctionParameterInfoHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/parameterInfo/JetFunctionParameterInfoHandler.java @@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.JetVisibilityChecker; import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.name.NamePredicate; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; @@ -355,7 +356,7 @@ public class JetFunctionParameterInfoHandler implements if (scope != null) { placeDescriptor = scope.getContainingDeclaration(); } - Collection variants = TipsManager.getReferenceVariants(refExpression, bindingContext); + Collection variants = TipsManager.getReferenceVariants(refExpression, bindingContext, NamePredicate.all()); Name refName = refExpression.getReferencedNameAsName(); PsiReference[] references = refExpression.getReferences(); if (references.length == 0) return null; diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/JetNameValidatorImpl.java b/idea/src/org/jetbrains/jet/plugin/refactoring/JetNameValidatorImpl.java index 2448ffb3496..e009fe7ab1a 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/JetNameValidatorImpl.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/JetNameValidatorImpl.java @@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetVisitorVoid; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.name.NamePredicate; import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; import java.util.Collection; @@ -106,7 +107,7 @@ public class JetNameValidatorImpl implements JetNameValidator { @Override public void visitExpression(JetExpression expression) { Collection variants = - TipsManager.getVariantsNoReceiver(expression, myBindingContext); + TipsManager.getVariantsNoReceiver(expression, myBindingContext, NamePredicate.all()); for (DeclarationDescriptor variant : variants) { if (variant.getName().getName().equals(name) && variant instanceof VariableDescriptor) { result.set(false); diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java index 6be592e32e9..d3142056acc 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java @@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.name.NamePredicate; import org.jetbrains.jet.plugin.completion.DescriptorLookupConverter; import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; @@ -66,7 +67,7 @@ public class JetSimpleNameReference extends JetPsiReference { .getBindingContext(); return DescriptorLookupConverter.collectLookupElements( - bindingContext, TipsManager.getReferenceVariants(myExpression, bindingContext)); + bindingContext, TipsManager.getReferenceVariants(myExpression, bindingContext, NamePredicate.all())); } @Override