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 * @author svtk
*/ */
public class FunctionDescriptorWithImplicitReceiver implements FunctionDescriptor { public class FunctionDescriptorBoundToReceiver implements FunctionDescriptor {
private FunctionDescriptor 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.functionDescriptor = functionDescriptor;
this.implicitReceiver = implicitReceiver; this.receiver = receiver;
} }
public FunctionDescriptor getFunctionDescriptor() { public FunctionDescriptor getFunctionDescriptor() {
return functionDescriptor; return functionDescriptor;
} }
public DeclarationDescriptor getImplicitReceiver() { public DeclarationDescriptor getReceiver() {
return implicitReceiver; return receiver;
} }
@NotNull @NotNull
@@ -12,21 +12,21 @@ import java.util.Set;
/** /**
* @author svtk * @author svtk
*/ */
public class VariableDescriptorWithImplicitReceiver implements VariableDescriptor { public class VariableDescriptorBoundToReceiver implements VariableDescriptor {
private VariableDescriptor 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.variableDescriptor = variableDescriptor;
this.implicitReceiver = implicitReceiver; this.receiver = receiver;
} }
public VariableDescriptor getVariableDescriptor() { public VariableDescriptor getVariableDescriptor() {
return variableDescriptor; return variableDescriptor;
} }
public DeclarationDescriptor getImplicitReceiver() { public DeclarationDescriptor getReceiver() {
return implicitReceiver; return receiver;
} }
@Override @Override
@@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable;
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.scopes.JetScope; 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.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
@@ -77,12 +78,21 @@ public class ImportsResolver {
descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope); descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope);
} }
if (importDirective.isAllUnder()) { if (importDirective.isAllUnder()) {
if (firstPhase) { for (DeclarationDescriptor descriptor : descriptors) {
for (DeclarationDescriptor descriptor : descriptors) { if (firstPhase) {
if (descriptor instanceof NamespaceDescriptor) { if (descriptor instanceof NamespaceDescriptor) {
namespaceScope.importScope(((NamespaceDescriptor) descriptor).getMemberScope()); 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; return;
} }
@@ -167,7 +177,7 @@ public class ImportsResolver {
trace.report(NO_CLASS_OBJECT.on(classReference, classDescriptor)); trace.report(NO_CLASS_OBJECT.on(classReference, classDescriptor));
return Collections.emptyList(); return Collections.emptyList();
} }
return addImplicitReceiver(lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope()), classDescriptor); return addBoundToReceiver(lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope()), classDescriptor);
} }
@NotNull @NotNull
@@ -176,19 +186,19 @@ public class ImportsResolver {
JetType variableType = variableDescriptor.getReturnType(); JetType variableType = variableDescriptor.getReturnType();
if (variableType == null) return Collections.emptyList(); if (variableType == null) return Collections.emptyList();
return addImplicitReceiver(lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope()), variableDescriptor); return addBoundToReceiver(lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope()), variableDescriptor);
} }
@NotNull @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>() { return Collections2.transform(descriptors, new Function<DeclarationDescriptor, DeclarationDescriptor>() {
@Override @Override
public DeclarationDescriptor apply(@Nullable DeclarationDescriptor descriptor) { public DeclarationDescriptor apply(@Nullable DeclarationDescriptor descriptor) {
if (descriptor instanceof FunctionDescriptor) { if (descriptor instanceof FunctionDescriptor) {
return new FunctionDescriptorWithImplicitReceiver((FunctionDescriptor) descriptor, implicitReceiver); return new FunctionDescriptorBoundToReceiver((FunctionDescriptor) descriptor, implicitReceiver);
} }
if (descriptor instanceof VariableDescriptor) { if (descriptor instanceof VariableDescriptor) {
return new VariableDescriptorWithImplicitReceiver((VariableDescriptor) descriptor, implicitReceiver); return new VariableDescriptorBoundToReceiver((VariableDescriptor) descriptor, implicitReceiver);
} }
return descriptor; 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() { class F() {
fun f() {} fun f() {}
}
//FILE:c.kt
package c
import C.*
object C {
fun a() {
}
val b = 3
}
fun foo() {
if (b == 3) a()
} }