JET-61 Support class objects

This commit is contained in:
Andrey Breslav
2011-06-03 18:37:47 +04:00
parent 2350a8a731
commit 4884af389f
15 changed files with 136 additions and 36 deletions
+1 -1
View File
@@ -43,7 +43,7 @@ memberDeclaration
;
classObject
: modifiers "class" objectLiteral
: modifiers "class" object
;
constructor
@@ -38,4 +38,7 @@ public interface ClassDescriptor extends ClassifierDescriptor {
@NotNull
@Override
ClassDescriptor substitute(TypeSubstitutor substitutor);
@Nullable
JetType getClassObjectType();
}
@@ -81,6 +81,11 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
throw new UnsupportedOperationException(); // TODO
}
@Override
public JetType getClassObjectType() {
return null;
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitClassDescriptor(this, data);
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
@@ -13,4 +14,7 @@ public interface ClassifierDescriptor extends DeclarationDescriptor {
@NotNull
JetType getDefaultType();
@Nullable
JetType getClassObjectType();
}
@@ -90,6 +90,11 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
throw new UnsupportedOperationException(); // TODO
}
@Override
public JetType getClassObjectType() {
return original.getClassObjectType();
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitClassDescriptor(this, data);
@@ -27,6 +27,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
private final WritableScope scopeForMemberLookup;
// This scope contains type parameters but does not contain inner classes
private final WritableScope scopeForSupertypeResolution;
private MutableClassDescriptor classObjectDescriptor;
private JetType classObjectType;
public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
super(containingDeclaration);
@@ -37,6 +39,16 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
this.classObjectDescriptor = classObjectDescriptor;
}
@Nullable
public MutableClassDescriptor getClassObjectDescriptor() {
return classObjectDescriptor;
}
public void setPrimaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
assert this.primaryConstructor == null : "Primary constructor assigned twice " + this;
this.primaryConstructor = constructorDescriptor;
@@ -187,6 +199,14 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
throw new UnsupportedOperationException(); // TODO
}
@Override
public JetType getClassObjectType() {
if (classObjectType == null && classObjectDescriptor != null) {
classObjectType = classObjectDescriptor.getDefaultType();
}
return classObjectType;
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitClassDescriptor(this, data);
@@ -51,4 +51,9 @@ public class NamespaceDescriptorImpl extends AbstractNamespaceDescriptorImpl imp
public void addPropertyDescriptor(@NotNull PropertyDescriptor variableDescriptor) {
memberScope.addVariableDescriptor(variableDescriptor);
}
@Override
public void setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
throw new IllegalStateException("Must be guaranteed not to happen by the parser");
}
}
@@ -67,4 +67,6 @@ public interface NamespaceLike extends DeclarationDescriptor {
void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor);
void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor);
void setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor);
}
@@ -37,9 +37,11 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
private final int index;
private final Variance variance;
private final Set<JetType> upperBounds;
private final TypeConstructor typeConstructor;
private JetType boundsAsType;
private JetType type;
private final TypeConstructor typeConstructor;
private JetType defaultType;
private final Set<JetType> classObjectUpperBounds = Sets.newLinkedHashSet();
private JetType classObjectBoundsAsType;
private TypeParameterDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@@ -89,7 +91,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
if (boundsAsType == null) {
assert upperBounds != null;
assert upperBounds.size() > 0;
boundsAsType = upperBounds.size() == 1 ? upperBounds.iterator().next() : TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
boundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
if (boundsAsType == null) {
boundsAsType = JetStandardClasses.getNothingType(); // TODO : some error message?
}
@@ -111,8 +113,8 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
@NotNull
@Override
public JetType getDefaultType() {
if (type == null) {
type = new JetTypeImpl(
if (defaultType == null) {
defaultType = new JetTypeImpl(
Collections.<Annotation>emptyList(),
getTypeConstructor(),
TypeUtils.hasNullableBound(this),
@@ -124,7 +126,18 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
}
}));
}
return type;
return defaultType;
}
@Override
public JetType getClassObjectType() {
if (classObjectUpperBounds.isEmpty()) return null;
if (classObjectBoundsAsType == null) {
classObjectBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, classObjectUpperBounds);
assert classObjectBoundsAsType != null; // TODO : Error message
}
return classObjectBoundsAsType;
}
public int getIndex() {
@@ -712,7 +712,7 @@ public class JetParsing extends AbstractJetParsing {
/*
* classObject
* : modifiers "class" objectLiteral
* : modifiers "class" object
* ;
*/
private JetNodeType parseClassObject() {
@@ -720,8 +720,9 @@ public class JetParsing extends AbstractJetParsing {
advance(); // CLASS_KEYWORD
myExpressionParsing.parseObjectLiteral();
final PsiBuilder.Marker objectDeclaration = mark();
parseObject(false);
objectDeclaration.done(OBJECT_DECLARATION);
return CLASS_OBJECT;
}
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
/**
@@ -17,8 +18,9 @@ public class JetClassObject extends JetDeclaration {
visitor.visitClassObject(this);
}
public JetObjectLiteralExpression getObject() {
return (JetObjectLiteralExpression) findChildByType(JetNodeTypes.OBJECT_LITERAL);
@Nullable @IfNotParsed
public JetObjectDeclaration getObjectDeclaration() {
return (JetObjectDeclaration) findChildByType(JetNodeTypes.OBJECT_DECLARATION);
}
}
@@ -81,31 +81,36 @@ public class AnalyzingUtils {
// if (false)
topDownAnalyzer.process(scope, new NamespaceLike.Adapter(owner) {
@Override
public NamespaceDescriptorImpl getNamespace(String name) {
return null;
}
@Override
public NamespaceDescriptorImpl getNamespace(String name) {
return null;
}
@Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
scope.addNamespace(namespaceDescriptor);
}
@Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
scope.addNamespace(namespaceDescriptor);
}
@Override
public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
scope.addClassifierDescriptor(classDescriptor);
}
@Override
public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
scope.addClassifierDescriptor(classDescriptor);
}
@Override
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
scope.addFunctionDescriptor(functionDescriptor);
}
@Override
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
scope.addFunctionDescriptor(functionDescriptor);
}
@Override
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
scope.addVariableDescriptor(propertyDescriptor);
}
}, Collections.<JetDeclaration>singletonList(namespace));
@Override
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
scope.addVariableDescriptor(propertyDescriptor);
}
@Override
public void setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
throw new IllegalStateException("Must be guaranteed not to happen by the parser");
}
}, Collections.<JetDeclaration>singletonList(namespace));
return bindingTraceContext;
}
@@ -112,6 +112,11 @@ public class TopDownAnalyzer {
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
}
@Override
public void setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
}
}, Collections.<JetDeclaration>singletonList(object));
}
@@ -168,15 +173,20 @@ public class TopDownAnalyzer {
@Override
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
createClassDescriptorForObject(declaration);
}
private MutableClassDescriptor createClassDescriptorForObject(@NotNull JetObjectDeclaration declaration) {
MutableClassDescriptor mutableClassDescriptor = visitClassOrObject(declaration, (Map) objects, owner, outerScope);
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(mutableClassDescriptor, Collections.<Annotation>emptyList(), true);
constructorDescriptor.initialize(Collections.<ValueParameterDescriptor>emptyList());
// TODO : make the constructor private?
mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor);
trace.recordDeclarationResolution(declaration, mutableClassDescriptor);
return mutableClassDescriptor;
}
private MutableClassDescriptor visitClassOrObject(JetClassOrObject declaration, Map<JetClassOrObject, MutableClassDescriptor> map, NamespaceLike owner, JetScope outerScope) {
private MutableClassDescriptor visitClassOrObject(@NotNull JetClassOrObject declaration, Map<JetClassOrObject, MutableClassDescriptor> map, NamespaceLike owner, JetScope outerScope) {
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(trace, owner, outerScope);
mutableClassDescriptor.setName(JetPsiUtil.safeName(declaration.getName()));
@@ -202,6 +212,11 @@ public class TopDownAnalyzer {
public void visitExtension(JetExtension extension) {
trace.getErrorHandler().genericError(extension.getNode(), "Unsupported [TopDownAnalyzer]");
}
@Override
public void visitClassObject(JetClassObject classObject) {
owner.setClassObjectDescriptor(createClassDescriptorForObject(classObject.getObjectDeclaration()));
}
});
}
}
@@ -87,6 +87,11 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
throw new UnsupportedOperationException(); // TODO
}
@Override
public JetType getClassObjectType() {
return null; // TODO : static members as class object members
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitClassDescriptor(this, data);
@@ -704,8 +704,23 @@ public class JetTypeInferrer {
trace.getErrorHandler().genericError(expression.getNode(), "This variable is not readable in this context");
}
return;
} else if (furtherNameLookup(expression, referencedName)) {
return;
}
else {
ClassifierDescriptor classifier = scope.getClassifier(referencedName);
if (classifier != null) {
JetType classObjectType = classifier.getClassObjectType();
if (classObjectType != null) {
result = classObjectType;
}
else {
trace.getErrorHandler().genericError(expression.getNode(), "This class does not have a class object");
}
trace.recordReferenceResolution(expression, classifier);
return;
}
else if (furtherNameLookup(expression, referencedName)) {
return;
}
}
trace.getErrorHandler().unresolvedReference(expression);
}