JET-61 Support class objects
JET-83 Interpret Java static methods as class objects' members
This commit is contained in:
@@ -6,6 +6,7 @@ import org.jetbrains.jet.lang.resolve.JetScope;
|
|||||||
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
|
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
|
|||||||
|
|
||||||
private TypeConstructor typeConstructor;
|
private TypeConstructor typeConstructor;
|
||||||
private JavaClassMembersScope unsubstitutedMemberScope;
|
private JavaClassMembersScope unsubstitutedMemberScope;
|
||||||
|
private JetType classObjectType;
|
||||||
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
|
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
|
||||||
|
|
||||||
public JavaClassDescriptor(DeclarationDescriptor containingDeclaration) {
|
public JavaClassDescriptor(DeclarationDescriptor containingDeclaration) {
|
||||||
@@ -30,6 +32,20 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
|
|||||||
this.unsubstitutedMemberScope = memberScope;
|
this.unsubstitutedMemberScope = memberScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setClassObjectMemberScope(JavaClassMembersScope memberScope) {
|
||||||
|
classObjectType = new JetTypeImpl(
|
||||||
|
new TypeConstructorImpl(
|
||||||
|
JavaDescriptorResolver.JAVA_CLASS_OBJECT,
|
||||||
|
Collections.<Annotation>emptyList(),
|
||||||
|
true,
|
||||||
|
"Class object emulation for " + getName(),
|
||||||
|
Collections.<TypeParameterDescriptor>emptyList(),
|
||||||
|
Collections.<JetType>emptyList()
|
||||||
|
),
|
||||||
|
memberScope
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public void addConstructor(ConstructorDescriptor constructorDescriptor) {
|
public void addConstructor(ConstructorDescriptor constructorDescriptor) {
|
||||||
this.constructors.addFunction(constructorDescriptor);
|
this.constructors.addFunction(constructorDescriptor);
|
||||||
}
|
}
|
||||||
@@ -89,7 +105,7 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType getClassObjectType() {
|
public JetType getClassObjectType() {
|
||||||
return null; // TODO : static members as class object members
|
return classObjectType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -30,6 +30,19 @@ public class JavaDescriptorResolver {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*package*/ static final DeclarationDescriptor JAVA_CLASS_OBJECT = new DeclarationDescriptorImpl(null, Collections.<Annotation>emptyList(), "<java_class_object_emulation>") {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public DeclarationDescriptor substitute(TypeSubstitutor substitutor) {
|
||||||
|
throw new UnsupportedOperationException(); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||||
|
return visitor.visitDeclarationDescriptor(this, data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
protected final Map<String, ClassDescriptor> classDescriptorCache = new HashMap<String, ClassDescriptor>();
|
protected final Map<String, ClassDescriptor> classDescriptorCache = new HashMap<String, ClassDescriptor>();
|
||||||
protected final Map<PsiTypeParameter, TypeParameterDescriptor> typeParameterDescriptorCache = Maps.newHashMap();
|
protected final Map<PsiTypeParameter, TypeParameterDescriptor> typeParameterDescriptorCache = Maps.newHashMap();
|
||||||
protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap();
|
protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap();
|
||||||
@@ -91,6 +104,7 @@ public class JavaDescriptorResolver {
|
|||||||
));
|
));
|
||||||
classDescriptorCache.put(psiClass.getQualifiedName(), classDescriptor);
|
classDescriptorCache.put(psiClass.getQualifiedName(), classDescriptor);
|
||||||
classDescriptor.setUnsubstitutedMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false));
|
classDescriptor.setUnsubstitutedMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false));
|
||||||
|
classDescriptor.setClassObjectMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, true));
|
||||||
// UGLY HACK
|
// UGLY HACK
|
||||||
supertypes.addAll(getSupertypes(psiClass));
|
supertypes.addAll(getSupertypes(psiClass));
|
||||||
|
|
||||||
|
|||||||
@@ -713,7 +713,7 @@ public class JetTypeInferrer {
|
|||||||
result = classObjectType;
|
result = classObjectType;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace.getErrorHandler().genericError(expression.getNode(), "This class does not have a class object");
|
trace.getErrorHandler().genericError(expression.getNode(), "Classifier " + classifier.getName() + " does not have a class object");
|
||||||
}
|
}
|
||||||
trace.recordReferenceResolution(expression, classifier);
|
trace.recordReferenceResolution(expression, classifier);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -171,7 +171,6 @@ JetFile: SimpleClassMembers.jet
|
|||||||
CLASS_OBJECT
|
CLASS_OBJECT
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -186,7 +185,6 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -201,7 +199,6 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -225,7 +222,6 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -261,7 +257,6 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -535,7 +530,6 @@ JetFile: SimpleClassMembers.jet
|
|||||||
CLASS_OBJECT
|
CLASS_OBJECT
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -550,7 +544,6 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -565,7 +558,6 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -589,7 +581,6 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -625,7 +616,6 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
|
|||||||
@@ -134,7 +134,6 @@ JetFile: PolymorphicClassObjects.jet
|
|||||||
CLASS_OBJECT
|
CLASS_OBJECT
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ JetFile: UpdateOperation.jet
|
|||||||
CLASS_OBJECT
|
CLASS_OBJECT
|
||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
OBJECT_LITERAL
|
|
||||||
OBJECT_DECLARATION
|
OBJECT_DECLARATION
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testCondJumpOnStack() throws Exception {
|
public void testCondJumpOnStack() throws Exception {
|
||||||
loadText("fun foo(a: String): Int = if (Boolean.parseBoolean(a)) 5 else 10");
|
loadText("fun foo(a: String): Int = if (java.lang.Boolean.parseBoolean(a)) 5 else 10");
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
assertEquals(5, main.invoke(null, "true"));
|
assertEquals(5, main.invoke(null, "true"));
|
||||||
assertEquals(10, main.invoke(null, "false"));
|
assertEquals(10, main.invoke(null, "false"));
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ public class PrimitiveTypesTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testDoubleToJava() throws Exception {
|
public void testDoubleToJava() throws Exception {
|
||||||
loadText("fun foo(d: Double): String? = Double.toString(d)");
|
loadText("fun foo(d: Double): String? = java.lang.Double.toString(d)");
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
assertEquals("1.0", main.invoke(null, 1.0));
|
assertEquals("1.0", main.invoke(null, 1.0));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user