resolve of import all members from objects and variables

This commit is contained in:
svtk
2011-12-27 17:00:43 +04:00
parent 084472aa4f
commit 979dfdcd1e
5 changed files with 211 additions and 19 deletions
@@ -12,22 +12,22 @@ import java.util.Set;
/**
* @author svtk
*/
public class FunctionDescriptorWithImplicitReceiver implements FunctionDescriptor {
public class FunctionDescriptorBoundToReceiver implements FunctionDescriptor {
private FunctionDescriptor functionDescriptor;
private DeclarationDescriptor implicitReceiver;
private DeclarationDescriptor receiver;
public FunctionDescriptorWithImplicitReceiver(@NotNull FunctionDescriptor functionDescriptor, @NotNull DeclarationDescriptor implicitReceiver) {
public FunctionDescriptorBoundToReceiver(@NotNull FunctionDescriptor functionDescriptor, @NotNull DeclarationDescriptor receiver) {
this.functionDescriptor = functionDescriptor;
this.implicitReceiver = implicitReceiver;
this.receiver = receiver;
}
public FunctionDescriptor getFunctionDescriptor() {
return functionDescriptor;
}
public DeclarationDescriptor getImplicitReceiver() {
return implicitReceiver;
public DeclarationDescriptor getReceiver() {
return receiver;
}
@NotNull
@@ -12,21 +12,21 @@ import java.util.Set;
/**
* @author svtk
*/
public class VariableDescriptorWithImplicitReceiver implements VariableDescriptor {
public class VariableDescriptorBoundToReceiver implements VariableDescriptor {
private VariableDescriptor variableDescriptor;
private DeclarationDescriptor implicitReceiver;
private DeclarationDescriptor receiver;
public VariableDescriptorWithImplicitReceiver(VariableDescriptor variableDescriptor, DeclarationDescriptor implicitReceiver) {
public VariableDescriptorBoundToReceiver(VariableDescriptor variableDescriptor, DeclarationDescriptor receiver) {
this.variableDescriptor = variableDescriptor;
this.implicitReceiver = implicitReceiver;
this.receiver = receiver;
}
public VariableDescriptor getVariableDescriptor() {
return variableDescriptor;
}
public DeclarationDescriptor getImplicitReceiver() {
return implicitReceiver;
public DeclarationDescriptor getReceiver() {
return receiver;
}
@Override
@@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.ScopeBoundToReceiver;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.JetType;
@@ -77,12 +78,21 @@ public class ImportsResolver {
descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope);
}
if (importDirective.isAllUnder()) {
if (firstPhase) {
for (DeclarationDescriptor descriptor : descriptors) {
for (DeclarationDescriptor descriptor : descriptors) {
if (firstPhase) {
if (descriptor instanceof NamespaceDescriptor) {
namespaceScope.importScope(((NamespaceDescriptor) descriptor).getMemberScope());
}
}
else if (descriptor instanceof VariableDescriptor) {
JetType type = ((VariableDescriptor) descriptor).getOutType();
if (type != null) {
namespaceScope.importScope(ScopeBoundToReceiver.create(descriptor, type.getMemberScope()));
}
}
else if (descriptor instanceof ClassDescriptor) {
namespaceScope.importScope(ScopeBoundToReceiver.create(descriptor, ((ClassDescriptor) descriptor).getDefaultType().getMemberScope()));
}
}
return;
}
@@ -167,7 +177,7 @@ public class ImportsResolver {
trace.report(NO_CLASS_OBJECT.on(classReference, classDescriptor));
return Collections.emptyList();
}
return addImplicitReceiver(lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope()), classDescriptor);
return addBoundToReceiver(lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope()), classDescriptor);
}
@NotNull
@@ -176,19 +186,19 @@ public class ImportsResolver {
JetType variableType = variableDescriptor.getReturnType();
if (variableType == null) return Collections.emptyList();
return addImplicitReceiver(lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope()), variableDescriptor);
return addBoundToReceiver(lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope()), variableDescriptor);
}
@NotNull
private static Collection<DeclarationDescriptor> addImplicitReceiver(@NotNull Collection<DeclarationDescriptor> descriptors, @NotNull final DeclarationDescriptor implicitReceiver) {
private static Collection<DeclarationDescriptor> addBoundToReceiver(@NotNull Collection<DeclarationDescriptor> descriptors, @NotNull final DeclarationDescriptor implicitReceiver) {
return Collections2.transform(descriptors, new Function<DeclarationDescriptor, DeclarationDescriptor>() {
@Override
public DeclarationDescriptor apply(@Nullable DeclarationDescriptor descriptor) {
if (descriptor instanceof FunctionDescriptor) {
return new FunctionDescriptorWithImplicitReceiver((FunctionDescriptor) descriptor, implicitReceiver);
return new FunctionDescriptorBoundToReceiver((FunctionDescriptor) descriptor, implicitReceiver);
}
if (descriptor instanceof VariableDescriptor) {
return new VariableDescriptorWithImplicitReceiver((VariableDescriptor) descriptor, implicitReceiver);
return new VariableDescriptorBoundToReceiver((VariableDescriptor) descriptor, implicitReceiver);
}
return descriptor;
}
@@ -0,0 +1,167 @@
package org.jetbrains.jet.lang.resolve.scopes;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.SetMultimap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.util.CommonSuppliers;
import java.util.*;
/**
* @author svtk
*/
public class ScopeBoundToReceiver implements JetScope {
private final DeclarationDescriptor receiver;
private final JetScope scope;
private SetMultimap<String, VariableDescriptor> propertiesMap;
private SetMultimap<String, FunctionDescriptor> functionsMap;
private Map<DeclarationDescriptor, DeclarationDescriptor> descriptorsBoundToReceiver;
public static ScopeBoundToReceiver create(DeclarationDescriptor implicitReceiver, JetScope memberScope) {
return new ScopeBoundToReceiver(implicitReceiver, memberScope);
}
private ScopeBoundToReceiver(DeclarationDescriptor receiver, JetScope scope) {
this.receiver = receiver;
this.scope = scope;
}
public DeclarationDescriptor getReceiver() {
return receiver;
}
private SetMultimap<String, VariableDescriptor> getPropertiesMap() {
if (propertiesMap == null) {
propertiesMap = CommonSuppliers.newLinkedHashSetHashSetMultimap();
}
return propertiesMap;
}
private SetMultimap<String, FunctionDescriptor> getFunctionsMap() {
if (functionsMap == null) {
functionsMap = CommonSuppliers.newLinkedHashSetHashSetMultimap();
}
return functionsMap;
}
private Map<DeclarationDescriptor, DeclarationDescriptor> getDescriptorsBoundToReceiver() {
if (descriptorsBoundToReceiver == null) {
descriptorsBoundToReceiver = Maps.newHashMap();
}
return descriptorsBoundToReceiver;
}
@Nullable
@Override
public ClassifierDescriptor getClassifier(@NotNull String name) {
return scope.getClassifier(name);
}
@Nullable
@Override
public NamespaceDescriptor getNamespace(@NotNull String name) {
return scope.getNamespace(name);
}
@NotNull
@Override
public Set<VariableDescriptor> getProperties(@NotNull String name) {
if (getPropertiesMap().containsKey(name)) {
return getPropertiesMap().get(name);
}
return getMembersBoundToReceiver(name, getPropertiesMap(), scope.getProperties(name), new Function<VariableDescriptor, VariableDescriptor>() {
@Override
public VariableDescriptor apply(VariableDescriptor property) {
return new VariableDescriptorBoundToReceiver(property, receiver);
}
});
}
@Nullable
@Override
public VariableDescriptor getLocalVariable(@NotNull String name) {
return scope.getLocalVariable(name);
}
private <D extends DeclarationDescriptor> Set<D> getMembersBoundToReceiver(String name, SetMultimap<String, D> cache, Set<D> oldMembers, Function<D, D> transformation) {
for (D oldMember : oldMembers) {
cache.put(name, transformation.apply(oldMember));
}
return cache.get(name);
}
@NotNull
@Override
public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
if (getFunctionsMap().containsKey(name)) {
return getFunctionsMap().get(name);
}
return getMembersBoundToReceiver(name, getFunctionsMap(), scope.getFunctions(name), new Function<FunctionDescriptor, FunctionDescriptor>() {
@Override
public FunctionDescriptor apply(FunctionDescriptor function) {
return new FunctionDescriptorBoundToReceiver(function, receiver);
}
});
}
@NotNull
@Override
public DeclarationDescriptor getContainingDeclaration() {
return scope.getContainingDeclaration();
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getDeclarationsByLabel(String labelName) {
return scope.getDeclarationsByLabel(labelName);
}
@Nullable
@Override
public PropertyDescriptor getPropertyByFieldReference(@NotNull String fieldName) {
return scope.getPropertyByFieldReference(fieldName);
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
Collection<DeclarationDescriptor> result = Lists.newArrayList();
Collection<DeclarationDescriptor> allDescriptors = scope.getAllDescriptors();
for (DeclarationDescriptor descriptor : allDescriptors) {
if (getDescriptorsBoundToReceiver().containsKey(descriptor)) {
result.add(getDescriptorsBoundToReceiver().get(descriptor));
continue;
}
if (descriptor instanceof FunctionDescriptor) {
getFunctions(descriptor.getName());
}
else if (descriptor instanceof VariableDescriptor) {
getProperties(descriptor.getName());
}
else {
result.add(descriptor);
continue;
}
if (getDescriptorsBoundToReceiver().containsKey(descriptor)) {
result.add(getDescriptorsBoundToReceiver().get(descriptor));
}
}
return result;
}
@NotNull
@Override
public ReceiverDescriptor getImplicitReceiver() {
return ReceiverDescriptor.NO_RECEIVER;
}
@Override
public void getImplicitReceiversHierarchy(@NotNull List<ReceiverDescriptor> result) {
}
}
@@ -56,4 +56,19 @@ class E() {
class F() {
fun f() {}
}
//FILE:c.kt
package c
import C.*
object C {
fun a() {
}
val b = 3
}
fun foo() {
if (b == 3) a()
}