Supporting fake overrides for properties and constructors for class objects
This commit is contained in:
@@ -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;
|
||||
|
||||
+46
-23
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user