Supporting fake overrides for properties and constructors for class objects

This commit is contained in:
Andrey Breslav
2012-06-09 19:14:18 +04:00
parent f2561046bf
commit efb3df5ca2
4 changed files with 82 additions and 40 deletions
@@ -46,6 +46,7 @@ import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.CONSTRUCTOR;
/**
* @author abreslav
@@ -346,6 +347,25 @@ public class DescriptorResolver {
return typeParameterDescriptor;
}
public static ConstructorDescriptorImpl createPrimaryConstructorForObject(
@NotNull PsiElement object,
@NotNull ClassDescriptor classDescriptor,
@NotNull BindingTrace trace
) {
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(classDescriptor, Collections
.<AnnotationDescriptor>emptyList(), true);
// TODO : make the constructor private?
// TODO check set classDescriptor.getVisibility()
constructorDescriptor.initialize(Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(), Visibilities.INTERNAL);
if (object != null) {
trace.record(CONSTRUCTOR, object, constructorDescriptor);
}
return constructorDescriptor;
}
final class UpperBoundCheckerTask {
JetTypeReference upperBound;
JetType upperBoundType;
@@ -24,7 +24,6 @@ import com.intellij.psi.PsiNameIdentifierOwner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -329,17 +328,9 @@ public class TypeHierarchyResolver {
}
private void createPrimaryConstructorForObject(@Nullable PsiElement object, MutableClassDescriptor mutableClassDescriptor) {
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(mutableClassDescriptor, Collections.<AnnotationDescriptor>emptyList(), true);
// TODO check set mutableClassDescriptor.getVisibility()
constructorDescriptor.initialize(Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(), Visibilities.INTERNAL);
// TODO : make the constructor private?
ConstructorDescriptor constructorDescriptor = DescriptorResolver
.createPrimaryConstructorForObject(object, mutableClassDescriptor, trace);
mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor, trace);
if (object != null) {
trace.record(CONSTRUCTOR, object, constructorDescriptor);
}
}
private void prepareForDeferredCall(@NotNull JetScope outerScope,
@@ -356,7 +347,6 @@ public class TypeHierarchyResolver {
}
@NotNull
private static ClassKind getClassKind(@NotNull JetClass jetClass) {
if (jetClass.isTrait()) return ClassKind.TRAIT;
@@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -61,12 +62,12 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
return thisDescriptor.getScopeForMemberDeclarationResolution();
}
@Override
protected void getNonDeclaredFunctions(@NotNull Name name, @NotNull final Set<FunctionDescriptor> result) {
Collection<FunctionDescriptor> fromSupertypes = Lists.newArrayList();
for (JetType supertype : thisDescriptor.getTypeConstructor().getSupertypes()) {
fromSupertypes.addAll(supertype.getMemberScope().getFunctions(name));
}
private <D extends CallableMemberDescriptor> void generateFakeOverrides(
@NotNull Name name,
@NotNull Collection<D> fromSupertypes,
@NotNull final Collection<D> result,
@NotNull final Class<? extends D> exactDescriptorClass
) {
OverrideResolver.generateOverridesInFunctionGroup(
name,
fromSupertypes,
@@ -75,9 +76,9 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
new OverrideResolver.DescriptorSink() {
@Override
public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
assert fakeOverride instanceof FunctionDescriptor : "A non-function overrides a function";
FunctionDescriptor functionDescriptor = (FunctionDescriptor) fakeOverride;
result.add(functionDescriptor);
assert exactDescriptorClass.isInstance(fakeOverride) : "Wrong descriptor type in an override: " + fakeOverride + " while expecting " + exactDescriptorClass.getSimpleName();
//noinspection unchecked
result.add((D) fakeOverride);
}
@Override
@@ -90,16 +91,28 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
}
}
);
}
@Override
protected void getNonDeclaredProperties(@NotNull Name name, @NotNull Set<VariableDescriptor> result) {
System.err.println("getNonDeclaredProperties() should generate fake overrides for a class");
protected void getNonDeclaredFunctions(@NotNull Name name, @NotNull final Set<FunctionDescriptor> result) {
Collection<FunctionDescriptor> fromSupertypes = Lists.newArrayList();
for (JetType supertype : thisDescriptor.getTypeConstructor().getSupertypes()) {
fromSupertypes.addAll(supertype.getMemberScope().getFunctions(name));
}
generateFakeOverrides(name, fromSupertypes, result, FunctionDescriptor.class);
}
@Override
protected void getNonDeclaredProperties(@NotNull Name name, @NotNull final Set<VariableDescriptor> result) {
System.err.println("Parameter of the primary constructor");
// Inherited fake overrides
// Parameters of the primary constructor
throw new UnsupportedOperationException(); // TODO
Collection<PropertyDescriptor> fromSupertypes = Lists.newArrayList();
for (JetType supertype : thisDescriptor.getTypeConstructor().getSupertypes()) {
fromSupertypes.addAll((Set) supertype.getMemberScope().getProperties(name));
}
generateFakeOverrides(name, fromSupertypes, (Set) result, PropertyDescriptor.class);
}
@Override
@@ -137,25 +150,35 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
@Nullable
public ConstructorDescriptor getPrimaryConstructor() {
if (!primaryConstructorResolved) {
if (EnumSet.of(ClassKind.CLASS, ClassKind.ANNOTATION_CLASS).contains(thisDescriptor.getKind())) {
if (EnumSet.of(ClassKind.CLASS, ClassKind.ANNOTATION_CLASS, ClassKind.OBJECT).contains(thisDescriptor.getKind())) {
JetClassOrObject classOrObject = declarationProvider.getOwnerClassOrObject();
if (classOrObject instanceof JetClass) {
JetClass jetClass = (JetClass) classOrObject;
ConstructorDescriptorImpl descriptor = resolveSession.getInjector().getDescriptorResolver()
ConstructorDescriptorImpl constructor = resolveSession.getInjector().getDescriptorResolver()
.resolvePrimaryConstructorDescriptor(thisDescriptor.getScopeForClassHeaderResolution(), thisDescriptor,
jetClass,
resolveSession.getTrace());
primaryConstructor = descriptor;
descriptor.setReturnType(DeferredType.create(resolveSession.getTrace(), new LazyValue<JetType>() {
@Override
protected JetType compute() {
return thisDescriptor.getDefaultType();
}
}));
primaryConstructor = constructor;
setDeferredReturnType(constructor);
}
else {
ConstructorDescriptorImpl constructor =
DescriptorResolver.createPrimaryConstructorForObject(classOrObject, thisDescriptor, resolveSession.getTrace());
setDeferredReturnType(constructor);
primaryConstructor = constructor;
}
}
primaryConstructorResolved = true;
}
return primaryConstructor;
}
private void setDeferredReturnType(@NotNull ConstructorDescriptorImpl descriptor) {
descriptor.setReturnType(DeferredType.create(resolveSession.getTrace(), new LazyValue<JetType>() {
@Override
protected JetType compute() {
return thisDescriptor.getDefaultType();
}
}));
}
}
@@ -32,6 +32,7 @@ import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.InnerClassesScopeWrapper;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import java.util.Collection;
@@ -181,13 +182,21 @@ public class ResolveSession {
}
if (parent instanceof JetClassBody) {
JetClassBody classBody = (JetClassBody) parent;
JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(classBody, JetClassOrObject.class);
ClassDescriptor classDescriptor = getClassDescriptor(classOrObject);
assert classDescriptor instanceof LazyClassDescriptor : "Trying to resolve a member of a non-lazily loaded class: " + element;
return ((LazyClassDescriptor) classDescriptor).getScopeForMemberDeclarationResolution();
return getEnclosingLazyClass(element).getScopeForMemberDeclarationResolution();
}
if (parent instanceof JetClassObject) {
return new InnerClassesScopeWrapper(getEnclosingLazyClass(element).getScopeForMemberDeclarationResolution());
}
throw new IllegalArgumentException("Unsupported PSI element: " + element);
}
private LazyClassDescriptor getEnclosingLazyClass(PsiElement element) {
JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(element.getParent(), JetClassOrObject.class);
assert classOrObject != null : "Called for an element that is not a class member: " + element;
ClassDescriptor classDescriptor = getClassDescriptor(classOrObject);
assert classDescriptor instanceof LazyClassDescriptor : "Trying to resolve a member of a non-lazily loaded class: " + element;
return (LazyClassDescriptor) classDescriptor;
}
}