TypeInfo based on projections instead of other TypeInfo's
This commit is contained in:
@@ -56,10 +56,8 @@ public class ClassCodegen {
|
|||||||
|
|
||||||
|
|
||||||
public static void newTypeInfo(InstructionAdapter v, boolean isNullable, Type asmType) {
|
public static void newTypeInfo(InstructionAdapter v, boolean isNullable, Type asmType) {
|
||||||
v.anew(JetTypeMapper.TYPE_TYPEINFO);
|
|
||||||
v.dup();
|
|
||||||
v.aconst(asmType);
|
v.aconst(asmType);
|
||||||
v.iconst(isNullable?1:0);
|
v.iconst(isNullable?1:0);
|
||||||
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;Z)V");
|
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
|
|||||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||||
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
@@ -1948,29 +1949,39 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
v.anew(JetTypeMapper.TYPE_TYPEINFO);
|
|
||||||
v.dup();
|
|
||||||
v.aconst(jvmType);
|
v.aconst(jvmType);
|
||||||
v.iconst(jetType.isNullable()?1:0);
|
v.iconst(jetType.isNullable()?1:0);
|
||||||
List<TypeProjection> arguments = jetType.getArguments();
|
List<TypeProjection> arguments = jetType.getArguments();
|
||||||
if (arguments.size() > 0) {
|
if (arguments.size() > 0) {
|
||||||
v.iconst(arguments.size());
|
v.iconst(arguments.size());
|
||||||
v.newarray(JetTypeMapper.TYPE_TYPEINFO);
|
v.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
||||||
|
|
||||||
for (int i = 0, argumentsSize = arguments.size(); i < argumentsSize; i++) {
|
for (int i = 0, argumentsSize = arguments.size(); i < argumentsSize; i++) {
|
||||||
TypeProjection argument = arguments.get(i);
|
TypeProjection argument = arguments.get(i);
|
||||||
v.dup();
|
v.dup();
|
||||||
v.iconst(i);
|
v.iconst(i);
|
||||||
generateTypeInfo(argument.getType());
|
generateTypeInfo(argument.getType());
|
||||||
|
genTypeInfoToProjection(v, argument.getProjectionKind());
|
||||||
v.astore(JetTypeMapper.TYPE_OBJECT);
|
v.astore(JetTypeMapper.TYPE_OBJECT);
|
||||||
}
|
}
|
||||||
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfo;)V");
|
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;Z)V");
|
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void genTypeInfoToProjection(InstructionAdapter v, Variance variance) {
|
||||||
|
if(variance == Variance.INVARIANT)
|
||||||
|
v.invokestatic("jet/typeinfo/TypeInfo", "invariantProjection", "(Ljet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfoProjection;");
|
||||||
|
else if(variance == Variance.IN_VARIANCE)
|
||||||
|
v.invokestatic("jet/typeinfo/TypeInfo", "inProjection", "(Ljet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfoProjection;");
|
||||||
|
else if(variance == Variance.OUT_VARIANCE)
|
||||||
|
v.invokestatic("jet/typeinfo/TypeInfo", "outProjection", "(Ljet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfoProjection;");
|
||||||
|
else
|
||||||
|
throw new UnsupportedOperationException(variance.toString());
|
||||||
|
}
|
||||||
|
|
||||||
private void loadTypeParameterTypeInfo(TypeParameterDescriptor typeParameterDescriptor) {
|
private void loadTypeParameterTypeInfo(TypeParameterDescriptor typeParameterDescriptor) {
|
||||||
final StackValue value = typeParameterExpressions.get(typeParameterDescriptor);
|
final StackValue value = typeParameterExpressions.get(typeParameterDescriptor);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@@ -1981,7 +1992,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
if (containingDeclaration == contextType() && contextType() instanceof ClassDescriptor) {
|
if (containingDeclaration == contextType() && contextType() instanceof ClassDescriptor) {
|
||||||
loadTypeInfo(typeMapper, (ClassDescriptor) contextType(), v);
|
loadTypeInfo(typeMapper, (ClassDescriptor) contextType(), v);
|
||||||
v.iconst(typeParameterDescriptor.getIndex());
|
v.iconst(typeParameterDescriptor.getIndex());
|
||||||
v.invokevirtual("jet/typeinfo/TypeInfo", "getTypeParameter", "(I)Ljet/typeinfo/TypeInfo;");
|
v.invokevirtual("jet/typeinfo/TypeInfo", "getArgumentType", "(I)Ljet/typeinfo/TypeInfo;");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException("don't know what this type parameter resolves to");
|
throw new UnsupportedOperationException("don't know what this type parameter resolves to");
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.psi.*;
|
|||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
@@ -389,21 +390,20 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
|
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
iv.anew(JetTypeMapper.TYPE_TYPEINFO);
|
|
||||||
iv.dup();
|
|
||||||
|
|
||||||
iv.aconst(state.getTypeMapper().jvmType(descriptor, OwnerKind.INTERFACE));
|
iv.aconst(state.getTypeMapper().jvmType(descriptor, OwnerKind.INTERFACE));
|
||||||
iv.iconst(0);
|
iv.iconst(0);
|
||||||
iv.iconst(typeParamCount);
|
iv.iconst(typeParamCount);
|
||||||
iv.newarray(JetTypeMapper.TYPE_TYPEINFO);
|
iv.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
||||||
|
|
||||||
for (int i = 0; i < typeParamCount; i++) {
|
for (int i = 0; i < typeParamCount; i++) {
|
||||||
iv.dup();
|
iv.dup();
|
||||||
iv.iconst(i);
|
iv.iconst(i);
|
||||||
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
|
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
ExpressionCodegen.genTypeInfoToProjection(iv, Variance.INVARIANT);
|
||||||
iv.astore(JetTypeMapper.TYPE_OBJECT);
|
iv.astore(JetTypeMapper.TYPE_OBJECT);
|
||||||
}
|
}
|
||||||
iv.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfo;)V");
|
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
||||||
iv.putfield(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
iv.putfield(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.intellij.psi.*;
|
|||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import jet.JetObject;
|
import jet.JetObject;
|
||||||
import jet.typeinfo.TypeInfo;
|
import jet.typeinfo.TypeInfo;
|
||||||
|
import jet.typeinfo.TypeInfoProjection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -23,6 +24,7 @@ import java.util.*;
|
|||||||
public class JetTypeMapper {
|
public class JetTypeMapper {
|
||||||
public static final Type TYPE_OBJECT = Type.getObjectType("java/lang/Object");
|
public static final Type TYPE_OBJECT = Type.getObjectType("java/lang/Object");
|
||||||
public static final Type TYPE_TYPEINFO = Type.getType(TypeInfo.class);
|
public static final Type TYPE_TYPEINFO = Type.getType(TypeInfo.class);
|
||||||
|
public static final Type TYPE_TYPEINFOPROJECTION = Type.getType(TypeInfoProjection.class);
|
||||||
public static final Type TYPE_JET_OBJECT = Type.getType(JetObject.class);
|
public static final Type TYPE_JET_OBJECT = Type.getType(JetObject.class);
|
||||||
public static final Type TYPE_CLASS = Type.getType(Class.class);
|
public static final Type TYPE_CLASS = Type.getType(Class.class);
|
||||||
public static final Type TYPE_NOTHING = Type.getObjectType("jet/Nothing");
|
public static final Type TYPE_NOTHING = Type.getObjectType("jet/Nothing");
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fun typeName(a: Any?) : String {
|
||||||
|
return when(a) {
|
||||||
|
is java.util.ArrayList<Int> => "array list"
|
||||||
|
else => "no idea"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
if(typeName(java.util.ArrayList<Int> ()) != "array list") return "array list failed"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -47,6 +47,12 @@ public class PatternMatchingTest extends CodegenTestCase {
|
|||||||
assertEquals("something", foo.invoke(null, 19));
|
assertEquals("something", foo.invoke(null, 19));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testIs() throws Exception {
|
||||||
|
loadFile();
|
||||||
|
blackBox();
|
||||||
|
System.out.println(generateToText());
|
||||||
|
}
|
||||||
|
|
||||||
public void testRange() throws Exception {
|
public void testRange() throws Exception {
|
||||||
loadFile();
|
loadFile();
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package jet.typeinfo;
|
package jet.typeinfo;
|
||||||
|
|
||||||
import jet.JetObject;
|
import jet.JetObject;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -8,60 +9,101 @@ import java.util.Arrays;
|
|||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
* @author yole
|
* @author yole
|
||||||
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class TypeInfo<T> implements JetObject {
|
public abstract class TypeInfo<T> implements JetObject {
|
||||||
|
public static final TypeInfo<Byte> BYTE_TYPE_INFO = getTypeInfo(Byte.class, false);
|
||||||
|
public static final TypeInfo<Short> SHORT_TYPE_INFO = getTypeInfo(Short.class, false);
|
||||||
|
public static final TypeInfo<Integer> INT_TYPE_INFO = getTypeInfo(Integer.class, false);
|
||||||
|
public static final TypeInfo<Long> LONG_TYPE_INFO = getTypeInfo(Long.class, false);
|
||||||
|
public static final TypeInfo<Character> CHAR_TYPE_INFO = getTypeInfo(Character.class, false);
|
||||||
|
public static final TypeInfo<Boolean> BOOL_TYPE_INFO = getTypeInfo(Boolean.class, false);
|
||||||
|
public static final TypeInfo<Float> FLOAT_TYPE_INFO = getTypeInfo(Float.class, false);
|
||||||
|
public static final TypeInfo<Double> DOUBLE_TYPE_INFO = getTypeInfo(Double.class, false);
|
||||||
|
|
||||||
private TypeInfo<?> typeInfo;
|
private TypeInfo<?> typeInfo;
|
||||||
private final Class<T> theClass;
|
private final Class<T> theClass;
|
||||||
private final boolean nullable;
|
private final boolean nullable;
|
||||||
private final TypeInfo[] typeParameters;
|
private final TypeInfoProjection[] projections;
|
||||||
|
|
||||||
public TypeInfo(Class<T> theClass, boolean nullable) {
|
private TypeInfo(Class<T> theClass, boolean nullable) {
|
||||||
this.theClass = theClass;
|
this.theClass = theClass;
|
||||||
this.nullable = nullable;
|
this.nullable = nullable;
|
||||||
this.typeParameters = null;
|
this.projections = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeInfo(Class<T> theClass, boolean nullable, TypeInfo[] typeParameters) {
|
private TypeInfo(Class<T> theClass, boolean nullable, TypeInfoProjection[] projections) {
|
||||||
this.theClass = theClass;
|
this.theClass = theClass;
|
||||||
this.nullable = nullable;
|
this.nullable = nullable;
|
||||||
this.typeParameters = typeParameters;
|
this.projections = projections;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getClassObject() {
|
public static <T> TypeInfoProjection invariantProjection(final TypeInfo<T> typeInfo) {
|
||||||
|
return (TypeInfoImpl) typeInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> TypeInfoProjection inProjection(TypeInfo<T> typeInfo) {
|
||||||
|
return new TypeInfoProjection.TypeInfoProjectionImpl(typeInfo) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public TypeInfoVariance getVariance() {
|
||||||
|
return TypeInfoVariance.IN_VARIANCE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> TypeInfoProjection outProjection(TypeInfo<T> typeInfo) {
|
||||||
|
return new TypeInfoProjection.TypeInfoProjectionImpl(typeInfo) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public TypeInfoVariance getVariance() {
|
||||||
|
return TypeInfoVariance.OUT_VARIANCE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> TypeInfo<T> getTypeInfo(Class<T> klazz, boolean nullable) {
|
||||||
|
return new TypeInfoImpl<T>(klazz, nullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> TypeInfo<T> getTypeInfo(Class<T> klazz, boolean nullable, TypeInfoProjection[] projections) {
|
||||||
|
return new TypeInfoImpl<T>(klazz, nullable, projections);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Object getClassObject() {
|
||||||
try {
|
try {
|
||||||
final Class implClass = theClass.getClassLoader().loadClass(theClass.getCanonicalName() + "$$Impl");
|
final Class implClass = theClass.getClassLoader().loadClass(theClass.getCanonicalName() + "$$Impl");
|
||||||
final Field classobj = implClass.getField("$classobj");
|
final Field classobj = implClass.getField("$classobj");
|
||||||
return classobj.get(null);
|
return classobj.get(null);
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch(Exception e) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInstance(Object obj) {
|
public final boolean isInstance(Object obj) {
|
||||||
if (obj instanceof JetObject) {
|
if (obj instanceof JetObject) {
|
||||||
return ((JetObject) obj).getTypeInfo().isSubtypeOf(this);
|
return ((JetObject) obj).getTypeInfo().isSubtypeOf(this);
|
||||||
}
|
}
|
||||||
if(obj == null)
|
if (obj == null)
|
||||||
return nullable;
|
return nullable;
|
||||||
|
|
||||||
return theClass.isAssignableFrom(obj.getClass()); // TODO
|
return theClass.isAssignableFrom(obj.getClass()); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSubtypeOf(TypeInfo<?> superType) {
|
public final boolean isSubtypeOf(TypeInfo<?> superType) {
|
||||||
if (!superType.theClass.isAssignableFrom(theClass)) {
|
if (!superType.theClass.isAssignableFrom(theClass)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (nullable && !superType.nullable) {
|
if (nullable && !superType.nullable) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (typeParameters != null) {
|
if (projections != null) {
|
||||||
if (superType.typeParameters == null || superType.typeParameters.length != typeParameters.length) {
|
if (superType.projections == null || superType.projections.length != projections.length) {
|
||||||
throw new IllegalArgumentException("inconsistent type infos for the same class");
|
throw new IllegalArgumentException("inconsistent type infos for the same class");
|
||||||
}
|
}
|
||||||
for (int i = 0; i < typeParameters.length; i++) {
|
for (int i = 0; i < projections.length; i++) {
|
||||||
// TODO handle variance here
|
// TODO handle variance here
|
||||||
if (!typeParameters [i].equals(superType.typeParameters [i])) {
|
if (!projections[i].equals(superType.projections[i])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,12 +111,16 @@ public class TypeInfo<T> implements JetObject {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeInfo getTypeParameter(int index) {
|
public final TypeInfoProjection getProjection(int index) {
|
||||||
return typeParameters[index];
|
return projections[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public final TypeInfo getArgumentType(int index) {
|
||||||
|
return projections[index].getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeInfo<?> getTypeInfo() {
|
public final TypeInfo<?> getTypeInfo() {
|
||||||
if (typeInfo == null) {
|
if (typeInfo == null) {
|
||||||
// TODO: Implementation must be lazy, otherwise the result would be of an infinite size
|
// TODO: Implementation must be lazy, otherwise the result would be of an infinite size
|
||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
@@ -83,7 +129,7 @@ public class TypeInfo<T> implements JetObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public final boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
@@ -91,37 +137,50 @@ public class TypeInfo<T> implements JetObject {
|
|||||||
|
|
||||||
if (!theClass.equals(typeInfo.theClass)) return false;
|
if (!theClass.equals(typeInfo.theClass)) return false;
|
||||||
if (nullable != typeInfo.nullable) return false;
|
if (nullable != typeInfo.nullable) return false;
|
||||||
if (!Arrays.equals(typeParameters, typeInfo.typeParameters)) return false;
|
if (!Arrays.equals(projections, typeInfo.projections)) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public final int hashCode() {
|
||||||
return 31 * theClass.hashCode() + (typeParameters != null ? Arrays.hashCode(typeParameters) : 0);
|
return 31 * theClass.hashCode() + (projections != null ? Arrays.hashCode(projections) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public final String toString() {
|
||||||
StringBuilder sb = new StringBuilder().append(theClass.getName());
|
StringBuilder sb = new StringBuilder().append(theClass.getName());
|
||||||
if(typeParameters != null && typeParameters.length != 0) {
|
if (projections != null && projections.length != 0) {
|
||||||
sb.append("<");
|
sb.append("<");
|
||||||
for(int i = 0; i != typeParameters.length-1; ++i) {
|
for (int i = 0; i != projections.length - 1; ++i) {
|
||||||
sb.append(typeParameters[i].toString()).append(",");
|
sb.append(projections[i].toString()).append(",");
|
||||||
}
|
}
|
||||||
sb.append(typeParameters[typeParameters.length - 1].toString()).append(">");
|
sb.append(projections[projections.length - 1].toString()).append(">");
|
||||||
}
|
}
|
||||||
if(nullable)
|
if (nullable)
|
||||||
sb.append("?");
|
sb.append("?");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final TypeInfo<Byte> BYTE_TYPE_INFO = new TypeInfo<Byte>(Byte.class, false);
|
private static class TypeInfoImpl<T> extends TypeInfo<T> implements TypeInfoProjection {
|
||||||
public static final TypeInfo<Short> SHORT_TYPE_INFO = new TypeInfo<Short>(Short.class, false);
|
TypeInfoImpl(Class<T> klazz, boolean nullable) {
|
||||||
public static final TypeInfo<Integer> INT_TYPE_INFO = new TypeInfo<Integer>(Integer.class, false);
|
super(klazz, nullable);
|
||||||
public static final TypeInfo<Long> LONG_TYPE_INFO = new TypeInfo<Long>(Long.class, false);
|
}
|
||||||
public static final TypeInfo<Character> CHAR_TYPE_INFO = new TypeInfo<Character>(Character.class, false);
|
|
||||||
public static final TypeInfo<Boolean> BOOL_TYPE_INFO = new TypeInfo<Boolean>(Boolean.class, false);
|
TypeInfoImpl(Class<T> klazz, boolean nullable, TypeInfoProjection[] projections) {
|
||||||
public static final TypeInfo<Float> FLOAT_TYPE_INFO = new TypeInfo<Float>(Float.class, false);
|
super(klazz, nullable, projections);
|
||||||
public static final TypeInfo<Double> DOUBLE_TYPE_INFO = new TypeInfo<Double>(Double.class, false);
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public TypeInfoVariance getVariance() {
|
||||||
|
return TypeInfoVariance.INVARIANT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public TypeInfo getType() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package jet.typeinfo;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author alex.tkachman
|
||||||
|
*/
|
||||||
|
public interface TypeInfoProjection {
|
||||||
|
@NotNull
|
||||||
|
TypeInfoVariance getVariance();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
TypeInfo getType();
|
||||||
|
|
||||||
|
abstract class TypeInfoProjectionImpl implements TypeInfoProjection {
|
||||||
|
@NotNull private final TypeInfo type;
|
||||||
|
|
||||||
|
TypeInfoProjectionImpl(@NotNull TypeInfo typeInfo) {
|
||||||
|
this.type = typeInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public final TypeInfo getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
TypeInfoProjectionImpl that = (TypeInfoProjectionImpl) o;
|
||||||
|
// no need to compare variance as we compared classes already
|
||||||
|
return type.equals(that.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int hashCode() {
|
||||||
|
int result = type.hashCode();
|
||||||
|
result = 31 * result + (getVariance().hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final String toString() {
|
||||||
|
return (getVariance() == TypeInfoVariance.INVARIANT ? "" : getVariance().toString() + " ") + type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package jet.typeinfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author alex.tkachman
|
||||||
|
*/
|
||||||
|
public enum TypeInfoVariance {
|
||||||
|
INVARIANT("") ,
|
||||||
|
IN_VARIANCE("in"),
|
||||||
|
OUT_VARIANCE("out");
|
||||||
|
|
||||||
|
private final String label;
|
||||||
|
|
||||||
|
TypeInfoVariance(String label) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user