JET-61 Support class objects
This commit is contained in:
@@ -43,7 +43,7 @@ memberDeclaration
|
|||||||
;
|
;
|
||||||
|
|
||||||
classObject
|
classObject
|
||||||
: modifiers "class" objectLiteral
|
: modifiers "class" object
|
||||||
;
|
;
|
||||||
|
|
||||||
constructor
|
constructor
|
||||||
|
|||||||
@@ -38,4 +38,7 @@ public interface ClassDescriptor extends ClassifierDescriptor {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
ClassDescriptor substitute(TypeSubstitutor substitutor);
|
ClassDescriptor substitute(TypeSubstitutor substitutor);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
JetType getClassObjectType();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,11 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
|||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType getClassObjectType() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||||
return visitor.visitClassDescriptor(this, data);
|
return visitor.visitClassDescriptor(this, data);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.jetbrains.jet.lang.descriptors;
|
package org.jetbrains.jet.lang.descriptors;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeConstructor;
|
import org.jetbrains.jet.lang.types.TypeConstructor;
|
||||||
|
|
||||||
@@ -13,4 +14,7 @@ public interface ClassifierDescriptor extends DeclarationDescriptor {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
JetType getDefaultType();
|
JetType getDefaultType();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
JetType getClassObjectType();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,6 +90,11 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
|
|||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType getClassObjectType() {
|
||||||
|
return original.getClassObjectType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||||
return visitor.visitClassDescriptor(this, data);
|
return visitor.visitClassDescriptor(this, data);
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
|||||||
private final WritableScope scopeForMemberLookup;
|
private final WritableScope scopeForMemberLookup;
|
||||||
// This scope contains type parameters but does not contain inner classes
|
// This scope contains type parameters but does not contain inner classes
|
||||||
private final WritableScope scopeForSupertypeResolution;
|
private final WritableScope scopeForSupertypeResolution;
|
||||||
|
private MutableClassDescriptor classObjectDescriptor;
|
||||||
|
private JetType classObjectType;
|
||||||
|
|
||||||
public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
|
public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
|
||||||
super(containingDeclaration);
|
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) {
|
public void setPrimaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
|
||||||
assert this.primaryConstructor == null : "Primary constructor assigned twice " + this;
|
assert this.primaryConstructor == null : "Primary constructor assigned twice " + this;
|
||||||
this.primaryConstructor = constructorDescriptor;
|
this.primaryConstructor = constructorDescriptor;
|
||||||
@@ -187,6 +199,14 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
|||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType getClassObjectType() {
|
||||||
|
if (classObjectType == null && classObjectDescriptor != null) {
|
||||||
|
classObjectType = classObjectDescriptor.getDefaultType();
|
||||||
|
}
|
||||||
|
return classObjectType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||||
return visitor.visitClassDescriptor(this, data);
|
return visitor.visitClassDescriptor(this, data);
|
||||||
|
|||||||
@@ -51,4 +51,9 @@ public class NamespaceDescriptorImpl extends AbstractNamespaceDescriptorImpl imp
|
|||||||
public void addPropertyDescriptor(@NotNull PropertyDescriptor variableDescriptor) {
|
public void addPropertyDescriptor(@NotNull PropertyDescriptor variableDescriptor) {
|
||||||
memberScope.addVariableDescriptor(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 addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor);
|
||||||
|
|
||||||
void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor);
|
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 int index;
|
||||||
private final Variance variance;
|
private final Variance variance;
|
||||||
private final Set<JetType> upperBounds;
|
private final Set<JetType> upperBounds;
|
||||||
private final TypeConstructor typeConstructor;
|
|
||||||
private JetType boundsAsType;
|
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(
|
private TypeParameterDescriptor(
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
@@ -89,7 +91,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
if (boundsAsType == null) {
|
if (boundsAsType == null) {
|
||||||
assert upperBounds != null;
|
assert upperBounds != null;
|
||||||
assert upperBounds.size() > 0;
|
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) {
|
if (boundsAsType == null) {
|
||||||
boundsAsType = JetStandardClasses.getNothingType(); // TODO : some error message?
|
boundsAsType = JetStandardClasses.getNothingType(); // TODO : some error message?
|
||||||
}
|
}
|
||||||
@@ -111,8 +113,8 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public JetType getDefaultType() {
|
public JetType getDefaultType() {
|
||||||
if (type == null) {
|
if (defaultType == null) {
|
||||||
type = new JetTypeImpl(
|
defaultType = new JetTypeImpl(
|
||||||
Collections.<Annotation>emptyList(),
|
Collections.<Annotation>emptyList(),
|
||||||
getTypeConstructor(),
|
getTypeConstructor(),
|
||||||
TypeUtils.hasNullableBound(this),
|
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() {
|
public int getIndex() {
|
||||||
|
|||||||
@@ -712,7 +712,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* classObject
|
* classObject
|
||||||
* : modifiers "class" objectLiteral
|
* : modifiers "class" object
|
||||||
* ;
|
* ;
|
||||||
*/
|
*/
|
||||||
private JetNodeType parseClassObject() {
|
private JetNodeType parseClassObject() {
|
||||||
@@ -720,8 +720,9 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
|
|
||||||
advance(); // CLASS_KEYWORD
|
advance(); // CLASS_KEYWORD
|
||||||
|
|
||||||
myExpressionParsing.parseObjectLiteral();
|
final PsiBuilder.Marker objectDeclaration = mark();
|
||||||
|
parseObject(false);
|
||||||
|
objectDeclaration.done(OBJECT_DECLARATION);
|
||||||
|
|
||||||
return CLASS_OBJECT;
|
return CLASS_OBJECT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.psi;
|
|||||||
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.JetNodeTypes;
|
import org.jetbrains.jet.JetNodeTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,8 +18,9 @@ public class JetClassObject extends JetDeclaration {
|
|||||||
visitor.visitClassObject(this);
|
visitor.visitClassObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JetObjectLiteralExpression getObject() {
|
@Nullable @IfNotParsed
|
||||||
return (JetObjectLiteralExpression) findChildByType(JetNodeTypes.OBJECT_LITERAL);
|
public JetObjectDeclaration getObjectDeclaration() {
|
||||||
|
return (JetObjectDeclaration) findChildByType(JetNodeTypes.OBJECT_DECLARATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,31 +81,36 @@ public class AnalyzingUtils {
|
|||||||
// if (false)
|
// if (false)
|
||||||
topDownAnalyzer.process(scope, new NamespaceLike.Adapter(owner) {
|
topDownAnalyzer.process(scope, new NamespaceLike.Adapter(owner) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NamespaceDescriptorImpl getNamespace(String name) {
|
public NamespaceDescriptorImpl getNamespace(String name) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
|
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
|
||||||
scope.addNamespace(namespaceDescriptor);
|
scope.addNamespace(namespaceDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
|
public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
|
||||||
scope.addClassifierDescriptor(classDescriptor);
|
scope.addClassifierDescriptor(classDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
|
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
|
||||||
scope.addFunctionDescriptor(functionDescriptor);
|
scope.addFunctionDescriptor(functionDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
|
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||||
scope.addVariableDescriptor(propertyDescriptor);
|
scope.addVariableDescriptor(propertyDescriptor);
|
||||||
}
|
}
|
||||||
}, Collections.<JetDeclaration>singletonList(namespace));
|
|
||||||
|
@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;
|
return bindingTraceContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,11 @@ public class TopDownAnalyzer {
|
|||||||
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
|
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
|
||||||
|
|
||||||
|
}
|
||||||
}, Collections.<JetDeclaration>singletonList(object));
|
}, Collections.<JetDeclaration>singletonList(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,15 +173,20 @@ public class TopDownAnalyzer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
|
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
|
||||||
|
createClassDescriptorForObject(declaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MutableClassDescriptor createClassDescriptorForObject(@NotNull JetObjectDeclaration declaration) {
|
||||||
MutableClassDescriptor mutableClassDescriptor = visitClassOrObject(declaration, (Map) objects, owner, outerScope);
|
MutableClassDescriptor mutableClassDescriptor = visitClassOrObject(declaration, (Map) objects, owner, outerScope);
|
||||||
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(mutableClassDescriptor, Collections.<Annotation>emptyList(), true);
|
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(mutableClassDescriptor, Collections.<Annotation>emptyList(), true);
|
||||||
constructorDescriptor.initialize(Collections.<ValueParameterDescriptor>emptyList());
|
constructorDescriptor.initialize(Collections.<ValueParameterDescriptor>emptyList());
|
||||||
// TODO : make the constructor private?
|
// TODO : make the constructor private?
|
||||||
mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor);
|
mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor);
|
||||||
trace.recordDeclarationResolution(declaration, mutableClassDescriptor);
|
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 mutableClassDescriptor = new MutableClassDescriptor(trace, owner, outerScope);
|
||||||
mutableClassDescriptor.setName(JetPsiUtil.safeName(declaration.getName()));
|
mutableClassDescriptor.setName(JetPsiUtil.safeName(declaration.getName()));
|
||||||
|
|
||||||
@@ -202,6 +212,11 @@ public class TopDownAnalyzer {
|
|||||||
public void visitExtension(JetExtension extension) {
|
public void visitExtension(JetExtension extension) {
|
||||||
trace.getErrorHandler().genericError(extension.getNode(), "Unsupported [TopDownAnalyzer]");
|
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
|
throw new UnsupportedOperationException(); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType getClassObjectType() {
|
||||||
|
return null; // TODO : static members as class object members
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||||
return visitor.visitClassDescriptor(this, 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");
|
trace.getErrorHandler().genericError(expression.getNode(), "This variable is not readable in this context");
|
||||||
}
|
}
|
||||||
return;
|
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);
|
trace.getErrorHandler().unresolvedReference(expression);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user