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