JET-61 Support class objects
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user