use the power of DescriptorPredicate in completion

This commit is contained in:
Stepan Koltsov
2012-06-16 06:44:17 +04:00
parent 010db0495b
commit 65b74a19b4
8 changed files with 139 additions and 46 deletions
@@ -32,9 +32,9 @@ import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; 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.DescriptorPredicate;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; 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.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
@@ -52,7 +52,8 @@ public final class TipsManager {
} }
@NotNull @NotNull
public static Collection<DeclarationDescriptor> getReferenceVariants(JetSimpleNameExpression expression, BindingContext context) { public static Collection<DeclarationDescriptor> getReferenceVariants(
JetSimpleNameExpression expression, BindingContext context, @NotNull NamePredicate name) {
JetExpression receiverExpression = expression.getReceiverExpression(); JetExpression receiverExpression = expression.getReceiverExpression();
if (receiverExpression != null) { if (receiverExpression != null) {
// Process as call expression // Process as call expression
@@ -74,32 +75,30 @@ public final class TipsManager {
for (ReceiverDescriptor descriptor : variantsForExplicitReceiver) { for (ReceiverDescriptor descriptor : variantsForExplicitReceiver) {
descriptors.addAll(includeExternalCallableExtensions( descriptors.addAll(includeExternalCallableExtensions(
// TODO: better predicate excludePrivateDescriptors(descriptor.getType().getMemberScope().getAllDescriptors(DescriptorPredicate.hasName(name))),
excludePrivateDescriptors(descriptor.getType().getMemberScope().getAllDescriptors(DescriptorPredicate.all())), resolutionScope, descriptor, name));
resolutionScope, descriptor));
} }
return descriptors; return descriptors;
} }
return includeExternalCallableExtensions( return includeExternalCallableExtensions(
// TODO: better predicate excludePrivateDescriptors(expressionType.getMemberScope().getAllDescriptors(DescriptorPredicate.hasName(name))),
excludePrivateDescriptors(expressionType.getMemberScope().getAllDescriptors(DescriptorPredicate.all())), resolutionScope, new ExpressionReceiver(receiverExpression, expressionType), name);
resolutionScope, new ExpressionReceiver(receiverExpression, expressionType));
} }
return Collections.emptyList(); return Collections.emptyList();
} }
else { else {
return getVariantsNoReceiver(expression, context); return getVariantsNoReceiver(expression, context, name);
} }
} }
public static Collection<DeclarationDescriptor> getVariantsNoReceiver(JetExpression expression, BindingContext context) { public static Collection<DeclarationDescriptor> getVariantsNoReceiver(
JetExpression expression, BindingContext context, @NotNull NamePredicate name) {
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression); JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
if (resolutionScope != null) { if (resolutionScope != null) {
if (expression.getParent() instanceof JetImportDirective || expression.getParent() instanceof JetNamespaceHeader) { if (expression.getParent() instanceof JetImportDirective || expression.getParent() instanceof JetNamespaceHeader) {
// TODO: better predicate return resolutionScope.getAllDescriptors(DescriptorPredicate.namespaces(name));
return excludeNonPackageDescriptors(resolutionScope.getAllDescriptors(DescriptorPredicate.all()));
} }
else { else {
Collection<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(); Collection<DeclarationDescriptor> descriptorsSet = Sets.newHashSet();
@@ -109,13 +108,11 @@ public final class TipsManager {
for (ReceiverDescriptor receiverDescriptor : result) { for (ReceiverDescriptor receiverDescriptor : result) {
JetType receiverType = receiverDescriptor.getType(); JetType receiverType = receiverDescriptor.getType();
// TODO: better predicate descriptorsSet.addAll(receiverType.getMemberScope().getAllDescriptors(DescriptorPredicate.hasName(name)));
descriptorsSet.addAll(receiverType.getMemberScope().getAllDescriptors(DescriptorPredicate.all()));
} }
// TODO: better predicate descriptorsSet.addAll(resolutionScope.getAllDescriptors(DescriptorPredicate.hasName(name)));
descriptorsSet.addAll(resolutionScope.getAllDescriptors(DescriptorPredicate.all())); return excludeNotCallableExtensions(excludePrivateDescriptors(descriptorsSet), resolutionScope, name);
return excludeNotCallableExtensions(excludePrivateDescriptors(descriptorsSet), resolutionScope);
} }
} }
return Collections.emptyList(); return Collections.emptyList();
@@ -148,7 +145,9 @@ public final class TipsManager {
} }
public static Collection<DeclarationDescriptor> excludeNotCallableExtensions( public static Collection<DeclarationDescriptor> excludeNotCallableExtensions(
@NotNull Collection<? extends DeclarationDescriptor> descriptors, @NotNull final JetScope scope @NotNull Collection<? extends DeclarationDescriptor> descriptors,
@NotNull final JetScope scope,
@NotNull NamePredicate name
) { ) {
final Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors); final Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors);
@@ -156,9 +155,10 @@ public final class TipsManager {
scope.getImplicitReceiversHierarchy(result); scope.getImplicitReceiversHierarchy(result);
descriptorsSet.removeAll( descriptorsSet.removeAll(
Collections2.filter(JetScopeUtils.getAllExtensions(scope), new Predicate<CallableDescriptor>() { Collections2.filter(scope.getAllDescriptors(DescriptorPredicate.extension(name)), new Predicate<DeclarationDescriptor>() {
@Override @Override
public boolean apply(CallableDescriptor callableDescriptor) { public boolean apply(DeclarationDescriptor declarationDescriptor) {
CallableDescriptor callableDescriptor = (CallableDescriptor) declarationDescriptor;
if (!callableDescriptor.getReceiverParameter().exists()) { if (!callableDescriptor.getReceiverParameter().exists()) {
return false; return false;
} }
@@ -187,7 +187,8 @@ public final class TipsManager {
private static Set<DeclarationDescriptor> includeExternalCallableExtensions( private static Set<DeclarationDescriptor> includeExternalCallableExtensions(
@NotNull Collection<DeclarationDescriptor> descriptors, @NotNull Collection<DeclarationDescriptor> descriptors,
@NotNull final JetScope externalScope, @NotNull final JetScope externalScope,
@NotNull final ReceiverDescriptor receiverDescriptor @NotNull final ReceiverDescriptor receiverDescriptor,
@NotNull NamePredicate name
) { ) {
// It's impossible to add extension function for namespace // It's impossible to add extension function for namespace
JetType receiverType = receiverDescriptor.getType(); JetType receiverType = receiverDescriptor.getType();
@@ -198,13 +199,13 @@ public final class TipsManager {
Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors); Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors);
descriptorsSet.addAll( descriptorsSet.addAll(
Collections2.filter(JetScopeUtils.getAllExtensions(externalScope), Collections2.filter(externalScope.getAllDescriptors(DescriptorPredicate.extension(name)),
new Predicate<CallableDescriptor>() { new Predicate<DeclarationDescriptor>() {
@Override @Override
public boolean apply(CallableDescriptor callableDescriptor) { public boolean apply(DeclarationDescriptor callableDescriptor) {
return ExpressionTypingUtils.checkIsExtensionCallable(receiverDescriptor, callableDescriptor); return ExpressionTypingUtils.checkIsExtensionCallable(receiverDescriptor, (CallableDescriptor) callableDescriptor);
} }
})); }));
return descriptorsSet; return descriptorsSet;
} }
@@ -128,9 +128,9 @@ public abstract class DescriptorPredicate {
private static class HasName extends DescriptorPredicate { private static class HasName extends DescriptorPredicate {
@NotNull @NotNull
private final Name required; private final NamePredicate required;
private HasName(@NotNull Name required) { private HasName(@NotNull NamePredicate required) {
this.required = required; this.required = required;
} }
@@ -151,18 +151,24 @@ public abstract class DescriptorPredicate {
@Override @Override
public boolean includeName(@NotNull Name name) { public boolean includeName(@NotNull Name name) {
return required.equals(name); return required.matches(name);
} }
} }
public static DescriptorPredicate hasName(@NotNull Name name) { public static DescriptorPredicate hasName(@NotNull NamePredicate required) {
return new HasName(name); return new HasName(required);
} }
private static class CallableMembers extends DescriptorPredicate { private static class MembersOfType extends DescriptorPredicate {
public static final CallableMembers instance = new CallableMembers();
@NotNull
private final DescriptorKind required;
private MembersOfType(@NotNull DescriptorKind required) {
this.required = required;
}
@Override @Override
public boolean includeName(@NotNull Name name) { public boolean includeName(@NotNull Name name) {
@@ -176,24 +182,71 @@ public abstract class DescriptorPredicate {
@Override @Override
public boolean include(@NotNull DeclarationDescriptor descriptor) { public boolean include(@NotNull DeclarationDescriptor descriptor) {
return descriptor instanceof CallableMemberDescriptor; return descriptorKind(descriptor) == required;
} }
@Override @Override
public boolean includeKind(@NotNull DescriptorKind kind) { 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() { 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 static final Extension instance = new Extension();
private Extension() {
super(DescriptorKind.CALLABLE_MEMBER);
}
@Override @Override
public boolean includeExtension(boolean extension) { public boolean includeExtension(boolean extension) {
return 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<DeclarationDescriptor> asGuavaPredicate() { public Predicate<DeclarationDescriptor> asGuavaPredicate() {
return new Predicate<DeclarationDescriptor>() { return new Predicate<DeclarationDescriptor>() {
@Override @Override
@@ -158,7 +158,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
if (!allDescriptorsDone) { if (!allDescriptorsDone) {
if (!predicate.includeAll()) { if (!predicate.includeAll()) {
// super-optimized version // super-optimized version
return concat(allDescriptors, getInheritedDescriptors(predicate)); return concat(DescriptorPredicateUtils.filter(allDescriptors, predicate), getInheritedDescriptors(predicate));
} }
allDescriptorsDone = true; allDescriptorsDone = true;
@@ -35,6 +35,8 @@ import org.jetbrains.jet.cli.jvm.compiler.TipsManager;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; 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.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.caches.JetCacheManager; import org.jetbrains.jet.plugin.caches.JetCacheManager;
@@ -347,7 +349,15 @@ public class JetCompletionContributor extends CompletionContributor {
(JetFile)reference.getExpression().getContainingFile()) (JetFile)reference.getExpression().getContainingFile())
.getBindingContext(); .getBindingContext();
Collection<DeclarationDescriptor> descriptors = TipsManager.getReferenceVariants(reference.getExpression(), bindingContext); class PrefixMatcherNamePredicate extends NamePredicate {
@Override
public boolean matches(@NotNull Name name) {
return result.getPrefixMatcher().prefixMatches(name.getName());
}
}
Collection<DeclarationDescriptor> descriptors = TipsManager.getReferenceVariants(
reference.getExpression(), bindingContext, new PrefixMatcherNamePredicate());
Collection<DeclarationDescriptor> checkedDescriptors = Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() { Collection<DeclarationDescriptor> checkedDescriptors = Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() {
@Override @Override
@@ -356,7 +366,7 @@ public class JetCompletionContributor extends CompletionContributor {
return false; return false;
} }
return result.getPrefixMatcher().prefixMatches(descriptor.getName().getName()) && isVisibleDescriptor(descriptor, session); return isVisibleDescriptor(descriptor, session);
} }
}); });
@@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils; 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.DescriptorPredicate;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
@@ -84,7 +85,7 @@ public abstract class BaseJetVariableMacro extends Macro {
} }
List<JetNamedDeclaration> declarations = new ArrayList<JetNamedDeclaration>(); List<JetNamedDeclaration> declarations = new ArrayList<JetNamedDeclaration>();
for (DeclarationDescriptor declarationDescriptor : TipsManager.excludeNotCallableExtensions(filteredDescriptors, scope)) { for (DeclarationDescriptor declarationDescriptor : TipsManager.excludeNotCallableExtensions(filteredDescriptors, scope, NamePredicate.all())) {
PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bc, declarationDescriptor); PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bc, declarationDescriptor);
assert declaration == null || declaration instanceof PsiNamedElement; assert declaration == null || declaration instanceof PsiNamedElement;
@@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.JetVisibilityChecker; import org.jetbrains.jet.lang.resolve.JetVisibilityChecker;
import org.jetbrains.jet.lang.resolve.name.Name; 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.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -355,7 +356,7 @@ public class JetFunctionParameterInfoHandler implements
if (scope != null) { if (scope != null) {
placeDescriptor = scope.getContainingDeclaration(); placeDescriptor = scope.getContainingDeclaration();
} }
Collection<DeclarationDescriptor> variants = TipsManager.getReferenceVariants(refExpression, bindingContext); Collection<DeclarationDescriptor> variants = TipsManager.getReferenceVariants(refExpression, bindingContext, NamePredicate.all());
Name refName = refExpression.getReferencedNameAsName(); Name refName = refExpression.getReferencedNameAsName();
PsiReference[] references = refExpression.getReferences(); PsiReference[] references = refExpression.getReferences();
if (references.length == 0) return null; if (references.length == 0) return null;
@@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetVisitorVoid; import org.jetbrains.jet.lang.psi.JetVisitorVoid;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.name.NamePredicate;
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
import java.util.Collection; import java.util.Collection;
@@ -106,7 +107,7 @@ public class JetNameValidatorImpl implements JetNameValidator {
@Override @Override
public void visitExpression(JetExpression expression) { public void visitExpression(JetExpression expression) {
Collection<DeclarationDescriptor> variants = Collection<DeclarationDescriptor> variants =
TipsManager.getVariantsNoReceiver(expression, myBindingContext); TipsManager.getVariantsNoReceiver(expression, myBindingContext, NamePredicate.all());
for (DeclarationDescriptor variant : variants) { for (DeclarationDescriptor variant : variants) {
if (variant.getName().getName().equals(name) && variant instanceof VariableDescriptor) { if (variant.getName().getName().equals(name) && variant instanceof VariableDescriptor) {
result.set(false); result.set(false);
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; 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.completion.DescriptorLookupConverter;
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
@@ -66,7 +67,7 @@ public class JetSimpleNameReference extends JetPsiReference {
.getBindingContext(); .getBindingContext();
return DescriptorLookupConverter.collectLookupElements( return DescriptorLookupConverter.collectLookupElements(
bindingContext, TipsManager.getReferenceVariants(myExpression, bindingContext)); bindingContext, TipsManager.getReferenceVariants(myExpression, bindingContext, NamePredicate.all()));
} }
@Override @Override