Correctly resolving all references in library source.

Added test with stdlib.

Ignoring top-level members from library source to avoid ambiguity. Resolving classes from source when deserializing descriptors (for unification).
This commit is contained in:
Evgeny Gerashchenko
2013-09-11 16:53:35 +04:00
parent e4d8e4d61b
commit 53c832d88c
11 changed files with 241 additions and 31 deletions
@@ -0,0 +1,66 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import java.util.Collection;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
public class LibrarySourceHacks {
private LibrarySourceHacks() {
}
public static final Key<Boolean> SKIP_TOP_LEVEL_MEMBERS = Key.create("SKIP_TOP_LEVEL_MEMBERS"); // used when analyzing library source
public static <D extends CallableDescriptor> List<D> filterOutMembersFromLibrarySource(Collection<D> members, BindingTrace trace) {
List<D> filteredMembers = Lists.newArrayList();
for (D member : members) {
if (!shouldSkip(member, trace)) {
filteredMembers.add(member);
}
}
return filteredMembers;
}
private static boolean shouldSkip(CallableDescriptor member, BindingTrace trace) {
CallableDescriptor original = member.getOriginal();
if (!(original instanceof CallableMemberDescriptor)) {
return false;
}
if (!(original.getContainingDeclaration() instanceof NamespaceDescriptor)) {
return false;
}
PsiElement declaration = callableDescriptorToDeclaration(trace.getBindingContext(),
(CallableMemberDescriptor) original);
if (declaration == null) {
return false;
}
PsiFile file = declaration.getContainingFile();
return file != null && Boolean.TRUE.equals(file.getUserData(SKIP_TOP_LEVEL_MEMBERS));
}
}
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.calls.tasks;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
@@ -26,11 +27,11 @@ import java.util.Collection;
public interface CallableDescriptorCollector<D extends CallableDescriptor> {
@NotNull
Collection<D> getNonExtensionsByName(JetScope scope, Name name);
Collection<D> getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace);
@NotNull
Collection<D> getMembersByName(@NotNull JetType receiver, Name name);
Collection<D> getMembersByName(@NotNull JetType receiver, Name name, @NotNull BindingTrace bindingTrace);
@NotNull
Collection<D> getNonMembersByName(JetScope scope, Name name);
Collection<D> getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace);
}
@@ -20,6 +20,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.ErrorUtils;
@@ -27,10 +28,15 @@ import org.jetbrains.jet.lang.types.JetType;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.LibrarySourceHacks.filterOutMembersFromLibrarySource;
public class CallableDescriptorCollectors {
public static CallableDescriptorCollector<FunctionDescriptor> FUNCTIONS = new FunctionCollector();
public static CallableDescriptorCollector<VariableDescriptor> VARIABLES = new VariableCollector();
public static CallableDescriptorCollector<VariableDescriptor> PROPERTIES = new PropertyCollector();
public static CallableDescriptorCollector<FunctionDescriptor> FUNCTIONS =
new FilteredCollector<FunctionDescriptor>(new FunctionCollector());
public static CallableDescriptorCollector<VariableDescriptor> VARIABLES =
new FilteredCollector<VariableDescriptor>(new VariableCollector());
public static CallableDescriptorCollector<VariableDescriptor> PROPERTIES =
new FilteredCollector<VariableDescriptor>(new PropertyCollector());
public static List<CallableDescriptorCollector<? extends CallableDescriptor>> FUNCTIONS_AND_VARIABLES =
Lists.newArrayList(FUNCTIONS, VARIABLES);
@@ -38,7 +44,7 @@ public class CallableDescriptorCollectors {
@NotNull
@Override
public Collection<FunctionDescriptor> getNonExtensionsByName(JetScope scope, Name name) {
public Collection<FunctionDescriptor> getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
Set<FunctionDescriptor> functions = Sets.newLinkedHashSet();
for (FunctionDescriptor function : scope.getFunctions(name)) {
if (function.getReceiverParameter() == null) {
@@ -51,7 +57,7 @@ public class CallableDescriptorCollectors {
@NotNull
@Override
public Collection<FunctionDescriptor> getMembersByName(@NotNull JetType receiverType, Name name) {
public Collection<FunctionDescriptor> getMembersByName(@NotNull JetType receiverType, Name name, @NotNull BindingTrace bindingTrace) {
JetScope receiverScope = receiverType.getMemberScope();
Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctions(name));
addConstructors(receiverScope, name, members);
@@ -60,7 +66,7 @@ public class CallableDescriptorCollectors {
@NotNull
@Override
public Collection<FunctionDescriptor> getNonMembersByName(JetScope scope, Name name) {
public Collection<FunctionDescriptor> getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
return scope.getFunctions(name);
}
@@ -82,7 +88,7 @@ public class CallableDescriptorCollectors {
@NotNull
@Override
public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, Name name) {
public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
VariableDescriptor localVariable = scope.getLocalVariable(name);
if (localVariable != null) {
return Collections.singleton(localVariable);
@@ -99,13 +105,13 @@ public class CallableDescriptorCollectors {
@NotNull
@Override
public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiverType, Name name) {
public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiverType, Name name, @NotNull BindingTrace bindingTrace) {
return receiverType.getMemberScope().getProperties(name);
}
@NotNull
@Override
public Collection<VariableDescriptor> getNonMembersByName(JetScope scope, Name name) {
public Collection<VariableDescriptor> getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
Collection<VariableDescriptor> result = Sets.newLinkedHashSet();
VariableDescriptor localVariable = scope.getLocalVariable(name);
@@ -135,20 +141,20 @@ public class CallableDescriptorCollectors {
@NotNull
@Override
public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, Name name) {
return filterProperties(VARIABLES.getNonExtensionsByName(scope, name));
public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
return filterProperties(VARIABLES.getNonExtensionsByName(scope, name, bindingTrace));
}
@NotNull
@Override
public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiver, Name name) {
return filterProperties(VARIABLES.getMembersByName(receiver, name));
public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiver, Name name, @NotNull BindingTrace bindingTrace) {
return filterProperties(VARIABLES.getMembersByName(receiver, name, bindingTrace));
}
@NotNull
@Override
public Collection<VariableDescriptor> getNonMembersByName(JetScope scope, Name name) {
return filterProperties(VARIABLES.getNonMembersByName(scope, name));
public Collection<VariableDescriptor> getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
return filterProperties(VARIABLES.getNonMembersByName(scope, name, bindingTrace));
}
@Override
@@ -156,6 +162,37 @@ public class CallableDescriptorCollectors {
return "PROPERTIES";
}
}
private static class FilteredCollector<D extends CallableDescriptor> implements CallableDescriptorCollector<D> {
private final CallableDescriptorCollector<D> delegate;
private FilteredCollector(CallableDescriptorCollector<D> delegate) {
this.delegate = delegate;
}
@NotNull
@Override
public Collection<D> getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
return filterOutMembersFromLibrarySource(delegate.getNonExtensionsByName(scope, name, bindingTrace), bindingTrace);
}
@NotNull
@Override
public Collection<D> getMembersByName(@NotNull JetType receiver, Name name, @NotNull BindingTrace bindingTrace) {
return filterOutMembersFromLibrarySource(delegate.getMembersByName(receiver, name, bindingTrace), bindingTrace);
}
@NotNull
@Override
public Collection<D> getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
return filterOutMembersFromLibrarySource(delegate.getNonMembersByName(scope, name, bindingTrace), bindingTrace);
}
@Override
public String toString() {
return delegate.toString();
}
}
private CallableDescriptorCollectors() {
}
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.psi.JetSuperExpression;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.LibrarySourceHacks;
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -41,7 +42,7 @@ import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.*;
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.isOrOverridesSynthesized;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
public class TaskPrioritizer {
@@ -130,7 +131,8 @@ public class TaskPrioritizer {
for (CallableDescriptorCollector<? extends D> callableDescriptorCollector : c.callableDescriptorCollectors) {
Collection<ResolutionCandidate<D>> members = Lists.newArrayList();
for (ReceiverValue variant : variantsForExplicitReceiver) {
Collection<? extends D> membersForThisVariant = callableDescriptorCollector.getMembersByName(variant.getType(), c.name);
Collection<? extends D> membersForThisVariant =
callableDescriptorCollector.getMembersByName(variant.getType(), c.name, c.context.trace);
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant),
Collections.singletonList(NO_RECEIVER), members, resolveInvoke);
}
@@ -144,9 +146,9 @@ public class TaskPrioritizer {
callableDescriptorCollector, c, resolveInvoke);
}
//extensions
Collection<ResolutionCandidate<D>> extensionFunctions = convertWithImpliedThis(
c.scope, variantsForExplicitReceiver, callableDescriptorCollector.getNonMembersByName(c.scope, c.name));
c.result.addCandidates(extensionFunctions);
Collection<ResolutionCandidate<D>> extensions = convertWithImpliedThis(
c.scope, variantsForExplicitReceiver, callableDescriptorCollector.getNonMembersByName(c.scope, c.name, c.context.trace));
c.result.addCandidates(extensions);
}
}
@@ -157,7 +159,7 @@ public class TaskPrioritizer {
boolean resolveInvoke
) {
Collection<? extends D> memberExtensions = callableDescriptorCollector.getNonMembersByName(
implicitReceiver.getType().getMemberScope(), c.name);
implicitReceiver.getType().getMemberScope(), c.name, c.context.trace);
List<ReceiverValue> variantsForImplicitReceiver = c.autoCastService.getVariantsForReceiver(implicitReceiver);
c.result.addCandidates(convertWithReceivers(memberExtensions, variantsForImplicitReceiver,
variantsForExplicitReceiver, resolveInvoke));
@@ -173,7 +175,7 @@ public class TaskPrioritizer {
Collection<ResolutionCandidate<D>> members =
convertWithImpliedThis(c.scope, Collections.singletonList(NO_RECEIVER), callableDescriptorCollector
.getNonExtensionsByName(c.scope, c.name));
.getNonExtensionsByName(c.scope, c.name, c.context.trace));
List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList();
List<ResolutionCandidate<D>> locals = Lists.newArrayList();