Properly load objects nested into class objects from Java

This commit is contained in:
Andrey Breslav
2013-06-07 17:47:40 +04:00
parent 56f040608a
commit 3e8031acbd
9 changed files with 76 additions and 11 deletions
@@ -149,7 +149,7 @@ public final class JavaClassObjectResolver {
classObjectDescriptor.createTypeConstructor();
JavaClassNonStaticMembersScope classMembersScope = new JavaClassNonStaticMembersScope(classObjectDescriptor, data, semanticServices);
WritableScopeImpl writableScope =
new WritableScopeImpl(classMembersScope, classObjectDescriptor, RedeclarationHandler.THROW_EXCEPTION, fqName.toString());
new WritableScopeImpl(classMembersScope, classObjectDescriptor, RedeclarationHandler.THROW_EXCEPTION, "Member lookup scope");
writableScope.changeLockLevel(WritableScope.LockLevel.BOTH);
classObjectDescriptor.setScopeForMemberLookup(writableScope);
classObjectDescriptor.setScopeForConstructorResolve(classMembersScope);
@@ -20,7 +20,9 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiElement;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
@@ -33,10 +35,7 @@ import org.jetbrains.jet.lang.resolve.java.provider.PsiDeclarationProvider;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.*;
public abstract class JavaBaseScope extends JetScopeImpl {
@@ -50,6 +49,8 @@ public abstract class JavaBaseScope extends JetScopeImpl {
private final Map<Name, Set<VariableDescriptor>> propertyDescriptors = Maps.newHashMap();
@Nullable
private Collection<DeclarationDescriptor> allDescriptors = null;
@Nullable
private Set<ClassDescriptor> objectDescriptors = null;
@NotNull
protected final ClassOrNamespaceDescriptor descriptor;
@@ -130,10 +131,19 @@ public abstract class JavaBaseScope extends JetScopeImpl {
protected Collection<DeclarationDescriptor> computeAllDescriptors() {
Collection<DeclarationDescriptor> result = Sets.newHashSet();
result.addAll(computeFieldAndFunctionDescriptors());
result.addAll(getInnerClasses());
result.addAll(filterObjects(getInnerClasses(), false));
return result;
}
@NotNull
@Override
public Set<ClassDescriptor> getObjectDescriptors() {
if (objectDescriptors == null) {
objectDescriptors = new HashSet<ClassDescriptor>(filterObjects(getInnerClasses(), true));
}
return objectDescriptors;
}
@NotNull
protected abstract Collection<ClassDescriptor> computeInnerClasses();
@@ -174,4 +184,13 @@ public abstract class JavaBaseScope extends JetScopeImpl {
}
return innerClasses;
}
private static <T extends ClassDescriptor> Collection<T> filterObjects(Collection<T> classes, final boolean objects) {
return ContainerUtil.filter(classes, new Condition<T>() {
@Override
public boolean value(T classDescriptor) {
return classDescriptor.getKind().isObject() == objects;
}
});
}
}
@@ -33,6 +33,8 @@ public class WritableScopeImpl extends WritableScopeWithImports {
private final Multimap<Name, DeclarationDescriptor> declaredDescriptorsAccessibleBySimpleName = HashMultimap.create();
private boolean allDescriptorsDone = false;
private Set<ClassDescriptor> allObjectDescriptors = null;
@NotNull
private final DeclarationDescriptor ownerDeclarationDescriptor;
@@ -401,13 +403,26 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@Override
public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
return getObjectDescriptorsMap().get(name);
ClassDescriptor descriptor = getObjectDescriptorsMap().get(name);
if (descriptor != null) return descriptor;
ClassDescriptor fromWorker = getWorkerScope().getObjectDescriptor(name);
if (fromWorker != null) return fromWorker;
return super.getObjectDescriptor(name);
}
@NotNull
@Override
public Set<ClassDescriptor> getObjectDescriptors() {
return Sets.newHashSet(getObjectDescriptorsMap().values());
if (allObjectDescriptors == null) {
allObjectDescriptors = Sets.newHashSet(getObjectDescriptorsMap().values());
allObjectDescriptors.addAll(getWorkerScope().getObjectDescriptors());
for (JetScope imported : getImports()) {
allObjectDescriptors.addAll(imported.getObjectDescriptors());
}
}
return allObjectDescriptors;
}
@Override
@@ -14,7 +14,7 @@ package toplevelObjectDeclarations
}
}
object B : <!UNRESOLVED_REFERENCE!>A<!> {}
object B : <!SUPERTYPE_NOT_INITIALIZED, FINAL_SUPERTYPE!>A<!> {}
val x = A.foo()
@@ -26,4 +26,4 @@ package toplevelObjectDeclarations
override fun foo() : Int = 1
}
val z = y.foo()
val z = y.foo()
@@ -3,4 +3,4 @@ package toplevelObjectDeclarations
object CObj {}
object DOjb : <!UNRESOLVED_REFERENCE!>CObj<!> {}
object DOjb : <!SUPERTYPE_NOT_INITIALIZED, FINAL_SUPERTYPE!>CObj<!> {}
@@ -0,0 +1,8 @@
package test
public class Outer {
public object Obj {
public val v: String = "val"
public fun f(): String = "fun"
}
}
@@ -0,0 +1,13 @@
package test
public final class Outer {
/*primary*/ public constructor Outer()
public final val Obj: test.Outer.Obj
public object Obj {
/*primary*/ private constructor Obj()
public final val v: jet.String
public final fun <get-v>(): jet.String
public final fun f(): jet.String
}
}
@@ -158,6 +158,11 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT
doTestWithAccessors("compiler/testData/loadKotlin/class/NamedObject.kt");
}
@TestMetadata("NamedObjectInClass.kt")
public void testNamedObjectInClass() throws Exception {
doTestWithAccessors("compiler/testData/loadKotlin/class/NamedObjectInClass.kt");
}
@TestMetadata("NamedObjectInClassObject.kt")
public void testNamedObjectInClassObject() throws Exception {
doTestWithAccessors("compiler/testData/loadKotlin/class/NamedObjectInClassObject.kt");
@@ -160,6 +160,11 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/NamedObject.kt");
}
@TestMetadata("NamedObjectInClass.kt")
public void testNamedObjectInClass() throws Exception {
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/NamedObjectInClass.kt");
}
@TestMetadata("NamedObjectInClassObject.kt")
public void testNamedObjectInClassObject() throws Exception {
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/NamedObjectInClassObject.kt");