merge Alex' work with mine, move internal classes to internal subpackage
This commit is contained in:
@@ -52,6 +52,7 @@ public class BothSignatureWriter {
|
||||
|
||||
private JetSignatureWriter jetSignatureWriter;
|
||||
|
||||
private String kotlinClassParameters;
|
||||
private String kotlinClassSignature;
|
||||
|
||||
private List<String> kotlinParameterTypes = new ArrayList<String>();
|
||||
@@ -207,7 +208,16 @@ public class BothSignatureWriter {
|
||||
}
|
||||
|
||||
public void writeFormalTypeParametersEnd() {
|
||||
jetSignatureWriter.visitSuperclass(); // just to call endFormals
|
||||
|
||||
kotlinClassParameters = jetSignatureWriter.toString();
|
||||
|
||||
jetSignatureWriter = null;
|
||||
|
||||
if (DEBUG_SIGNATURE_WRITER) {
|
||||
new JetSignatureReader(kotlinClassParameters).acceptFormalTypeParametersOnly(new JetSignatureAdapter());
|
||||
}
|
||||
|
||||
checkState(State.TYPE_PARAMETERS);
|
||||
}
|
||||
|
||||
@@ -285,6 +295,11 @@ public class BothSignatureWriter {
|
||||
public void writeSupersEnd() {
|
||||
kotlinClassSignature = jetSignatureWriter.toString();
|
||||
jetSignatureWriter = null;
|
||||
|
||||
if (DEBUG_SIGNATURE_WRITER) {
|
||||
new JetSignatureReader(kotlinClassSignature).accept(new JetSignatureAdapter());
|
||||
}
|
||||
|
||||
transitionState(State.SUPERS, State.CLASS_END);
|
||||
}
|
||||
|
||||
@@ -344,7 +359,13 @@ public class BothSignatureWriter {
|
||||
@Nullable
|
||||
public String makeKotlinClassSignature() {
|
||||
checkState(State.CLASS_END);
|
||||
return kotlinClassSignature;
|
||||
if (kotlinClassParameters == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (kotlinClassSignature == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return kotlinClassParameters + kotlinClassSignature;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -71,9 +71,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
v.visitOuterClass(typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null);
|
||||
}
|
||||
|
||||
if(myClass instanceof JetClass) {
|
||||
if(myClass instanceof JetClass && signature.getKotlinGenericSignature() != null) {
|
||||
AnnotationVisitor annotationVisitor = v.newAnnotation(myClass, "Ljet/typeinfo/JetSignature;", true);
|
||||
annotationVisitor.visit("value", SignatureUtil.classToSignature((JetClass)myClass, bindingContext, typeMapper));
|
||||
//annotationVisitor.visit("value", SignatureUtil.classToSignature((JetClass)myClass, bindingContext, typeMapper));
|
||||
annotationVisitor.visit("value", signature.getKotlinGenericSignature());
|
||||
annotationVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeParameter;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeReference;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class SignatureUtil {
|
||||
private SignatureUtil() {
|
||||
}
|
||||
|
||||
public static String classToSignature(JetClass type, BindingContext bindingContext, JetTypeMapper typeMapper) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
genTypeParams(type, sb);
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = type.getDelegationSpecifiers();
|
||||
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||
JetTypeReference typeReference = specifier.getTypeReference();
|
||||
JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
|
||||
genJetType(sb, jetType, typeMapper);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static void genJetType(StringBuilder sb, JetType jetType, JetTypeMapper typeMapper) {
|
||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if(descriptor instanceof ClassDescriptor) {
|
||||
JetType defaultType = ((ClassDescriptor) descriptor).getDefaultType();
|
||||
Type type = typeMapper.mapType(defaultType, OwnerKind.IMPLEMENTATION);
|
||||
if(JetTypeMapper.isPrimitive(type)) {
|
||||
type = JetTypeMapper.boxType(type);
|
||||
}
|
||||
sb.append(type.getDescriptor());
|
||||
}
|
||||
else {
|
||||
sb.append("T");
|
||||
JetType defaultType = ((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType();
|
||||
Type type = typeMapper.mapType(defaultType, OwnerKind.IMPLEMENTATION);
|
||||
sb.append(type.getDescriptor());
|
||||
sb.append(descriptor.getName());
|
||||
sb.append(";");
|
||||
}
|
||||
if(!jetType.getArguments().isEmpty()) {
|
||||
sb.append("<");
|
||||
for (TypeProjection typeProjection : jetType.getArguments()) {
|
||||
if(typeProjection.getProjectionKind() == Variance.IN_VARIANCE)
|
||||
sb.append("in ");
|
||||
if(typeProjection.getProjectionKind() == Variance.OUT_VARIANCE)
|
||||
sb.append("out ");
|
||||
genJetType(sb, typeProjection.getType(), typeMapper);
|
||||
}
|
||||
sb.append(">");
|
||||
}
|
||||
if(jetType.isNullable())
|
||||
sb.append("?");
|
||||
}
|
||||
|
||||
private static void genTypeParams(JetClass type, StringBuilder sb) {
|
||||
List<JetTypeParameter> parameters = type.getTypeParameterList().getParameters();
|
||||
if (parameters.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
sb.append('<');
|
||||
for(JetTypeParameter param : parameters) {
|
||||
Variance variance = param.getVariance();
|
||||
if(variance == Variance.IN_VARIANCE)
|
||||
sb.append("in ");
|
||||
else if(variance == Variance.OUT_VARIANCE)
|
||||
sb.append("out ");
|
||||
sb.append(param.getName());
|
||||
sb.append(";");
|
||||
}
|
||||
sb.append('>');
|
||||
}
|
||||
}
|
||||
+3
-62
@@ -1,6 +1,8 @@
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import jet.typeinfo.TypeInfoVariance;
|
||||
import jet.typeinfo.internal.signature.JetSignatureAdapter;
|
||||
import jet.typeinfo.internal.signature.JetSignatureExceptionsAdapter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
@@ -20,7 +22,7 @@ import java.util.List;
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
public abstract class JetTypeJetSignatureReader implements JetSignatureVisitor {
|
||||
public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAdapter {
|
||||
|
||||
private final JavaDescriptorResolver javaDescriptorResolver;
|
||||
private final JetStandardLibrary jetStandardLibrary;
|
||||
@@ -31,47 +33,6 @@ public abstract class JetTypeJetSignatureReader implements JetSignatureVisitor {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void visitFormalTypeParameter(String name, TypeInfoVariance variance) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitClassBound() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitInterfaceBound() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitSuperclass() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitInterface() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitParameterType() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitReturnType() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitExceptionType() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
private JetType getPrimitiveType(char descriptor, boolean nullable) {
|
||||
if (!nullable) {
|
||||
switch (descriptor) {
|
||||
@@ -124,16 +85,6 @@ public abstract class JetTypeJetSignatureReader implements JetSignatureVisitor {
|
||||
done(getPrimitiveType(descriptor, nullable));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeVariable(String name, boolean nullable) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitArrayType(boolean nullable) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
|
||||
private ClassDescriptor classDescriptor;
|
||||
private boolean nullable;
|
||||
@@ -150,16 +101,6 @@ public abstract class JetTypeJetSignatureReader implements JetSignatureVisitor {
|
||||
this.typeArguments = new ArrayList<TypeProjection>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClassType(String name, boolean nullable) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeArgument() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
private static Variance parseVariance(char wildcard) {
|
||||
switch (wildcard) {
|
||||
case '=': return Variance.INVARIANT;
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.*;
|
||||
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface JetSignature {
|
||||
public @interface JetSignature {
|
||||
String value();
|
||||
|
||||
}
|
||||
|
||||
@@ -2,12 +2,8 @@ package jet.typeinfo;
|
||||
|
||||
import jet.JetObject;
|
||||
import jet.Tuple0;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import jet.typeinfo.internal.TypeInfoImpl;
|
||||
import jet.typeinfo.internal.TypeInfoProjectionImpl;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -15,7 +11,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public abstract class TypeInfo<T> implements JetObject {
|
||||
private final static TypeInfoProjection[] EMPTY = new TypeInfoProjection[0];
|
||||
|
||||
public static final TypeInfo<Byte> BYTE_TYPE_INFO = getTypeInfo(Byte.class, false);
|
||||
public static final TypeInfo<Short> SHORT_TYPE_INFO = getTypeInfo(Short.class, false);
|
||||
@@ -56,7 +51,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
}
|
||||
|
||||
public static <T> TypeInfoProjection inProjection(TypeInfo<T> typeInfo) {
|
||||
return new TypeInfoProjection.TypeInfoProjectionImpl(typeInfo) {
|
||||
return new TypeInfoProjectionImpl(typeInfo) {
|
||||
// @NotNull
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
@@ -66,7 +61,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
}
|
||||
|
||||
public static <T> TypeInfoProjection outProjection(TypeInfo<T> typeInfo) {
|
||||
return new TypeInfoProjection.TypeInfoProjectionImpl(typeInfo) {
|
||||
return new TypeInfoProjectionImpl(typeInfo) {
|
||||
// @NotNull
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
@@ -75,6 +70,15 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
};
|
||||
}
|
||||
|
||||
private static <T> TypeInfoProjection projection(TypeInfo<T> typeInfo, TypeInfoVariance variance) {
|
||||
switch (variance) {
|
||||
case IN: return inProjection(typeInfo);
|
||||
case OUT: return outProjection(typeInfo);
|
||||
case INVARIANT: return invariantProjection(typeInfo);
|
||||
default: throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> TypeInfo<T> getTypeInfo(Class<T> klazz, boolean nullable) {
|
||||
return new TypeInfoImpl<T>(klazz, nullable);
|
||||
}
|
||||
@@ -94,626 +98,5 @@ public abstract class TypeInfo<T> implements JetObject {
|
||||
public abstract TypeInfoProjection getProjection(int index);
|
||||
|
||||
public abstract TypeInfo getArgumentType(Class klass, int index);
|
||||
|
||||
protected abstract TypeInfo substitute(List<TypeInfo> myVars);
|
||||
|
||||
protected abstract TypeInfo substitute(TypeInfoProjection[] projections);
|
||||
|
||||
private static class TypeInfoVar<T> extends TypeInfo<T> {
|
||||
final int varIndex;
|
||||
final Signature signature;
|
||||
final boolean nullable;
|
||||
|
||||
private TypeInfoVar(Signature signature, Integer varIndex) {
|
||||
this.signature = signature;
|
||||
this.varIndex = varIndex;
|
||||
nullable = false;
|
||||
}
|
||||
|
||||
public TypeInfoVar(Signature signature, boolean nullable, int varIndex) {
|
||||
this.signature = signature;
|
||||
this.nullable = nullable;
|
||||
this.varIndex = varIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] newArray(int length) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getJavaClass() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getClassObject() {
|
||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInstance(Object obj) {
|
||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProjectionCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfoProjection getProjection(int index) {
|
||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getArgumentType(Class klass, int index) {
|
||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo substitute(List<TypeInfo> myVars) {
|
||||
return myVars.get(varIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeInfo substitute(TypeInfoProjection[] projections) {
|
||||
return projections[varIndex].getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo<?> getTypeInfo() {
|
||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetObject getOuterObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "T:" + signature.klazz.getName() + ":" + varIndex;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TypeInfoImpl<T> extends TypeInfo<T> implements TypeInfoProjection {
|
||||
private TypeInfo<?> typeInfo;
|
||||
private final Signature signature;
|
||||
private final boolean nullable;
|
||||
private final TypeInfoProjection[] projections;
|
||||
|
||||
private TypeInfoImpl(Class<T> theClass, boolean nullable) {
|
||||
this(theClass, nullable, EMPTY);
|
||||
}
|
||||
|
||||
private TypeInfoImpl(Class<T> theClass, boolean nullable, TypeInfoProjection[] projections) {
|
||||
this.signature = Parser.parse(theClass);
|
||||
this.nullable = nullable;
|
||||
this.projections = projections;
|
||||
if(signature.variables.size() != projections.length)
|
||||
throw new IllegalStateException("Wrong signature " + theClass.getName());
|
||||
}
|
||||
|
||||
public final TypeInfoProjection getProjection(int index) {
|
||||
return projections[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] newArray(int length) {
|
||||
return (Object[]) Array.newInstance(signature.klazz, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getJavaClass() {
|
||||
return signature.klazz;
|
||||
}
|
||||
|
||||
public final Object getClassObject() {
|
||||
try {
|
||||
final Class implClass = signature.klazz.getClassLoader().loadClass(signature.klazz.getCanonicalName());
|
||||
final Field classobj = implClass.getField("$classobj");
|
||||
return classobj.get(null);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
TypeInfo getSuperTypeInfo(Class klass) {
|
||||
return signature.superSignatures.get(klass);
|
||||
}
|
||||
|
||||
public final TypeInfo getArgumentType(Class klass, int index) {
|
||||
if(klass == this.signature.klazz)
|
||||
return projections[index].getType();
|
||||
else {
|
||||
return getSuperTypeInfo(klass).substitute(projections).getArgumentType(klass, index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo substitute(final List<TypeInfo> myVars) {
|
||||
if(projections.length == 0)
|
||||
return new TypeInfoImpl(this.signature.klazz, nullable, EMPTY);
|
||||
else {
|
||||
TypeInfoProjection [] proj = new TypeInfoProjection[projections.length];
|
||||
for(int i = 0; i != proj.length; ++i) {
|
||||
final int finalI = i;
|
||||
final TypeInfo substitute = projections[finalI].getType().substitute(myVars);
|
||||
proj[i] = new TypeInfoProjection(){
|
||||
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return projections[finalI].getVariance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return substitute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getVariance().toString() + " " + substitute;
|
||||
}
|
||||
};
|
||||
}
|
||||
return new TypeInfoImpl(this.signature.klazz, nullable, proj);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeInfo substitute(TypeInfoProjection[] prj) {
|
||||
if(projections.length == 0)
|
||||
return new TypeInfoImpl(signature.klazz, nullable, EMPTY);
|
||||
else {
|
||||
TypeInfoProjection [] proj = new TypeInfoProjection[projections.length];
|
||||
for(int i = 0; i != proj.length; ++i) {
|
||||
final int finalI = i;
|
||||
final TypeInfo substitute = projections[finalI].getType().substitute(prj);
|
||||
proj[i] = new TypeInfoProjection(){
|
||||
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return projections[finalI].getVariance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return substitute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getVariance().toString() + " " + substitute;
|
||||
}
|
||||
};
|
||||
}
|
||||
return new TypeInfoImpl(signature.klazz, nullable, proj);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
TypeInfoImpl typeInfo = (TypeInfoImpl) o;
|
||||
|
||||
if (!signature.klazz.equals(typeInfo.signature.klazz)) return false;
|
||||
if (nullable != typeInfo.nullable) return false;
|
||||
if (!Arrays.equals(projections, typeInfo.projections)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// @NotNull
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return TypeInfoVariance.INVARIANT;
|
||||
}
|
||||
|
||||
// @NotNull
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return 31 * signature.klazz.hashCode() + Arrays.hashCode(projections);
|
||||
}
|
||||
|
||||
public final boolean isInstance(Object obj) {
|
||||
if (obj == null) return nullable;
|
||||
|
||||
if (obj instanceof JetObject) {
|
||||
return ((TypeInfoImpl)((JetObject) obj).getTypeInfo()).isSubtypeOf(this);
|
||||
}
|
||||
|
||||
return signature.klazz.isAssignableFrom(obj.getClass()); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProjectionCount() {
|
||||
return projections.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
StringBuilder sb = new StringBuilder().append(signature.klazz.getName());
|
||||
if (projections.length != 0) {
|
||||
sb.append("<");
|
||||
for (int i = 0; i != projections.length - 1; ++i) {
|
||||
sb.append(projections[i].toString()).append(",");
|
||||
}
|
||||
sb.append(projections[projections.length - 1].toString()).append(">");
|
||||
}
|
||||
if (nullable)
|
||||
sb.append("?");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TypeInfo<?> getTypeInfo() {
|
||||
if (typeInfo == null) {
|
||||
// TODO: Implementation must be lazy, otherwise the result would be of an infinite size
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetObject getOuterObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final boolean isSubtypeOf(TypeInfoImpl<?> superType) {
|
||||
if (nullable && !superType.nullable) {
|
||||
return false;
|
||||
}
|
||||
if (!superType.signature.klazz.isAssignableFrom(signature.klazz)) {
|
||||
return false;
|
||||
}
|
||||
if (superType.projections == null || superType.projections.length != projections.length) {
|
||||
throw new IllegalArgumentException("inconsistent type info for the same class");
|
||||
}
|
||||
for (int i = 0; i < projections.length; i++) {
|
||||
// TODO handle variance here
|
||||
if (!projections[i].getType().equals(superType.projections[i].getType())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Signature {
|
||||
final Class klazz;
|
||||
|
||||
List<TypeInfoProjection> variables;
|
||||
Map<String,Integer> varNames;
|
||||
List<TypeInfo> superTypes;
|
||||
|
||||
final HashMap<Class,TypeInfo> superSignatures = new HashMap<Class,TypeInfo>();
|
||||
|
||||
public Signature(Class klazz) {
|
||||
this.klazz = klazz;
|
||||
}
|
||||
|
||||
protected void afterParse() {
|
||||
List<TypeInfo> myVars = variables == null ? Collections.<TypeInfo>emptyList() : new LinkedList<TypeInfo>();
|
||||
if(variables != null)
|
||||
for(int i = 0; i != variables.size(); ++i)
|
||||
myVars.add(new TypeInfoVar(this, false, i));
|
||||
|
||||
for(TypeInfo superType : superTypes) {
|
||||
if(superType instanceof TypeInfoImpl) {
|
||||
TypeInfoImpl type = (TypeInfoImpl) superType;
|
||||
Signature superSignature = Parser.parse(type.signature.klazz);
|
||||
|
||||
TypeInfo substituted = type.substitute(myVars);
|
||||
superSignatures.put(type.signature.klazz, substituted);
|
||||
|
||||
List<TypeInfo> vars = Collections.emptyList();
|
||||
if(superType.getProjectionCount() != 0) {
|
||||
vars = new LinkedList<TypeInfo>();
|
||||
for(int i=0; i != superType.getProjectionCount(); ++i) {
|
||||
TypeInfo substitute = superType.getProjection(i).getType().substitute(myVars);
|
||||
vars.add(substitute);
|
||||
}
|
||||
}
|
||||
|
||||
for(Map.Entry<Class,TypeInfo> entry : superSignature.superSignatures.entrySet()) {
|
||||
superSignatures.put(entry.getKey(), entry.getValue().substitute(vars));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Parser {
|
||||
static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
static final WeakHashMap<Class,Signature> map = new WeakHashMap<Class,Signature>();
|
||||
|
||||
int cur;
|
||||
final char [] string;
|
||||
|
||||
final ClassLoader classLoader;
|
||||
|
||||
Parser(String string, ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
this.string = string.toCharArray();
|
||||
}
|
||||
|
||||
public static Signature parse(Class klass) {
|
||||
if(klass == null)
|
||||
return null;
|
||||
|
||||
// lock.readLock().lock();
|
||||
Signature sig = map.get(klass);
|
||||
// lock.readLock().unlock();
|
||||
if (sig == null) {
|
||||
// lock.writeLock().lock();
|
||||
|
||||
sig = map.get(klass);
|
||||
if (sig == null) {
|
||||
sig = internalParse(klass);
|
||||
}
|
||||
|
||||
// lock.writeLock().unlock();
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
private static Signature internalParse(Class klass) {
|
||||
if(klass.isArray() && !klass.getComponentType().isPrimitive()) {
|
||||
Signature signature = new ArraySignature(klass);
|
||||
map.put(klass, signature);
|
||||
return signature;
|
||||
}
|
||||
|
||||
JetSignature annotation = (JetSignature) klass.getAnnotation(JetSignature.class);
|
||||
if(annotation != null) {
|
||||
String value = annotation.value();
|
||||
if(value != null) {
|
||||
Parser parser = new Parser(value, klass.getClassLoader());
|
||||
Class enclosingClass = klass.getEnclosingClass();
|
||||
Signature signature = new Signature(klass);
|
||||
map.put(klass, signature);
|
||||
parser.parseVars(signature);
|
||||
parser.parseTypes(signature);
|
||||
signature.afterParse();
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
return getGenericSignature(klass);
|
||||
}
|
||||
|
||||
private static Signature getGenericSignature(Class klass) {
|
||||
// todo complete impl
|
||||
|
||||
java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass();
|
||||
Signature signature = new Signature(klass);
|
||||
|
||||
TypeVariable[] typeParameters = klass.getTypeParameters();
|
||||
if(typeParameters == null || typeParameters.length == 0) {
|
||||
signature.varNames = Collections.emptyMap();
|
||||
signature.variables = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
signature.varNames = new HashMap<String, Integer>();
|
||||
signature.variables = new LinkedList<TypeInfoProjection>();
|
||||
}
|
||||
|
||||
if (typeParameters != null && typeParameters.length != 0) {
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
TypeVariable typeParameter = typeParameters[i];
|
||||
signature.varNames.put(typeParameter.getName(), i);
|
||||
final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, false, i);
|
||||
signature.variables.add(new TypeInfoProjection(){
|
||||
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return TypeInfoVariance.INVARIANT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return typeInfoVar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return typeInfoVar.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void parseVars(Signature signature) {
|
||||
if (cur < string.length && string[cur] == '<') {
|
||||
cur++;
|
||||
while(cur < string.length && string[cur] != '>') {
|
||||
if(signature.variables == null) {
|
||||
signature.variables = new LinkedList<TypeInfoProjection>();
|
||||
signature.varNames = new HashMap<String, Integer>();
|
||||
}
|
||||
signature.variables.add(parseVar(signature));
|
||||
}
|
||||
cur++;
|
||||
}
|
||||
signature.variables = signature.variables == null ? Collections.<TypeInfoProjection>emptyList() : signature.variables;
|
||||
signature.varNames = signature.varNames == null ? Collections.<String,Integer>emptyMap() : signature.varNames;
|
||||
}
|
||||
|
||||
private TypeInfoProjection parseVar(Signature signature) {
|
||||
final TypeInfoVariance variance = parseVariance();
|
||||
String name = parseName();
|
||||
final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, signature.variables.size());
|
||||
signature.varNames.put(name, signature.variables.size());
|
||||
return new TypeInfoProjection(){
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return variance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return typeInfoVar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return typeInfoVar.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private String parseName() {
|
||||
int c = cur;
|
||||
while (string[c] != ';') {
|
||||
c++;
|
||||
}
|
||||
String name = new String(string, cur, c - cur);
|
||||
cur = c+1;
|
||||
return name;
|
||||
}
|
||||
|
||||
private TypeInfoVariance parseVariance() {
|
||||
if(string[cur] == 'i' && string[cur+1] == 'n' && string[cur+2] == ' ' ) {
|
||||
cur += 3;
|
||||
return TypeInfoVariance.IN;
|
||||
}
|
||||
else if (string[cur] == 'o' && string[cur+1] == 'u' && string[cur+2] == 't' && string[cur+3] == ' ') {
|
||||
cur += 4;
|
||||
return TypeInfoVariance.OUT;
|
||||
}
|
||||
else {
|
||||
return TypeInfoVariance.INVARIANT;
|
||||
}
|
||||
}
|
||||
|
||||
public void parseTypes(Signature signature) {
|
||||
List<TypeInfo> types = null;
|
||||
while(cur != string.length) {
|
||||
if(types == null) {
|
||||
types = new LinkedList<TypeInfo>();
|
||||
}
|
||||
types.add(parseType(signature));
|
||||
}
|
||||
signature.superTypes = types == null ? Collections.<TypeInfo>emptyList() : types;
|
||||
}
|
||||
|
||||
private TypeInfo parseType(Signature signature) {
|
||||
switch (string[cur]) {
|
||||
case 'L':
|
||||
cur++;
|
||||
String name = parseName();
|
||||
Class<?> aClass;
|
||||
try {
|
||||
aClass = classLoader.loadClass(name.replace('/','.'));
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
List<TypeInfoProjection> proj = null;
|
||||
boolean nullable = false;
|
||||
if(cur != string.length && string[cur] == '<') {
|
||||
cur++;
|
||||
while(string[cur] != '>') {
|
||||
if(proj == null)
|
||||
proj = new LinkedList<TypeInfoProjection>();
|
||||
proj.add(parseProjection(signature));
|
||||
}
|
||||
cur++;
|
||||
}
|
||||
if(cur != string.length && string[cur] == '?') {
|
||||
cur++;
|
||||
nullable = true;
|
||||
}
|
||||
if(proj == null)
|
||||
proj = Collections.emptyList();
|
||||
return new TypeInfoImpl(aClass, nullable,proj.toArray(new TypeInfoProjection[proj.size()]));
|
||||
|
||||
case 'T':
|
||||
cur++;
|
||||
return parseTypeVar(signature);
|
||||
|
||||
default:
|
||||
throw new IllegalStateException(new String(string));
|
||||
}
|
||||
}
|
||||
|
||||
private TypeInfo parseTypeVar(Signature signature) {
|
||||
TypeInfoVariance variance = parseVariance();
|
||||
assert string[cur] == 'L';
|
||||
cur++;
|
||||
String klazz = parseName().replace('/','.');
|
||||
String name = parseName();
|
||||
boolean nullable = false;
|
||||
if(string[cur] == '?') {
|
||||
nullable = true;
|
||||
cur++;
|
||||
}
|
||||
|
||||
if(klazz.equals(signature.klazz.getName()))
|
||||
return new TypeInfoVar(signature, nullable, signature.varNames.get(name));
|
||||
else {
|
||||
// Signature sig = signature;
|
||||
// while(!klazz.equals(sig.klazz.getName())) {
|
||||
// sig = sig.outer;
|
||||
// if(sig == null)
|
||||
// throw new IllegalStateException();
|
||||
// }
|
||||
|
||||
throw new UnsupportedOperationException("outer type info does not supported");
|
||||
}
|
||||
}
|
||||
|
||||
private TypeInfoProjection parseProjection(Signature signature) {
|
||||
final TypeInfoVariance variance = parseVariance();
|
||||
final TypeInfo type = parseType(signature);
|
||||
return new TypeInfoProjection(){
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return variance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class ArraySignature extends Signature {
|
||||
public ArraySignature(Class klass) {
|
||||
super(klass);
|
||||
variables = new LinkedList<TypeInfoProjection>();
|
||||
varNames = new HashMap<String, Integer>();
|
||||
varNames.put("T", 0);
|
||||
final TypeInfoVar typeInfoVar = new TypeInfoVar(this, 0);
|
||||
variables.add(new TypeInfoProjection(){
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return TypeInfoVariance.INVARIANT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return typeInfoVar;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,38 +12,4 @@ public interface TypeInfoProjection {
|
||||
|
||||
TypeInfo getType();
|
||||
|
||||
abstract class TypeInfoProjectionImpl implements TypeInfoProjection {
|
||||
private final TypeInfo type;
|
||||
|
||||
TypeInfoProjectionImpl(TypeInfo typeInfo) {
|
||||
this.type = typeInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
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,60 @@
|
||||
package jet.typeinfo.internal;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import jet.typeinfo.TypeInfoProjection;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
class Signature {
|
||||
|
||||
// TODO: make all these fields private
|
||||
|
||||
final Class klazz;
|
||||
|
||||
List<TypeInfoProjection> variables;
|
||||
Map<String,Integer> varNames;
|
||||
List<TypeInfo> superTypes;
|
||||
|
||||
HashMap<Class,TypeInfo> superSignatures = new HashMap<Class,TypeInfo>();
|
||||
|
||||
Signature(Class klazz) {
|
||||
this.klazz = klazz;
|
||||
}
|
||||
|
||||
void afterParse() {
|
||||
List<TypeInfo> myVars = variables == null ? Collections.<TypeInfo>emptyList() : new LinkedList<TypeInfo>();
|
||||
if(variables != null)
|
||||
for(int i = 0; i != variables.size(); ++i)
|
||||
myVars.add(new TypeInfoVar(this, false, i));
|
||||
|
||||
for(TypeInfo superType : superTypes) {
|
||||
if(superType instanceof TypeInfoImpl) {
|
||||
TypeInfoImpl type = (TypeInfoImpl) superType;
|
||||
Signature superSignature = TypeInfoParser.parse(type.signature.klazz);
|
||||
|
||||
TypeInfo substituted = TypeInfoUtils.substitute(type, myVars);
|
||||
superSignatures.put(type.signature.klazz, substituted);
|
||||
|
||||
List<TypeInfo> vars = Collections.emptyList();
|
||||
if(superType.getProjectionCount() != 0) {
|
||||
vars = new LinkedList<TypeInfo>();
|
||||
for(int i=0; i != superType.getProjectionCount(); ++i) {
|
||||
TypeInfo substitute = TypeInfoUtils.substitute(superType.getProjection(i).getType(), myVars);
|
||||
vars.add(substitute);
|
||||
}
|
||||
}
|
||||
|
||||
for(Map.Entry<Class,TypeInfo> entry : superSignature.superSignatures.entrySet()) {
|
||||
superSignatures.put(entry.getKey(), TypeInfoUtils.substitute(entry.getValue(), vars));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
package jet.typeinfo.internal;
|
||||
|
||||
import jet.JetObject;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import jet.typeinfo.TypeInfoProjection;
|
||||
import jet.typeinfo.TypeInfoVariance;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
* @author yole
|
||||
* @author alex.tkachman
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
public class TypeInfoImpl<T> extends TypeInfo<T> implements TypeInfoProjection {
|
||||
private final static TypeInfoProjection[] EMPTY = new TypeInfoProjection[0];
|
||||
|
||||
private TypeInfo<?> typeInfo;
|
||||
public final Signature signature;
|
||||
private final boolean nullable;
|
||||
private final TypeInfoProjection[] projections;
|
||||
|
||||
public TypeInfoImpl(Class<T> theClass, boolean nullable) {
|
||||
this(theClass, nullable, EMPTY);
|
||||
}
|
||||
|
||||
public TypeInfoImpl(Class<T> theClass, boolean nullable, TypeInfoProjection[] projections) {
|
||||
this.signature = TypeInfoParser.parse(theClass);
|
||||
this.nullable = nullable;
|
||||
this.projections = projections;
|
||||
if(signature.variables.size() != projections.length)
|
||||
throw new IllegalStateException("Wrong signature " + theClass.getName());
|
||||
}
|
||||
|
||||
public final TypeInfoProjection getProjection(int index) {
|
||||
return projections[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] newArray(int length) {
|
||||
return (Object[]) Array.newInstance(signature.klazz, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getJavaClass() {
|
||||
return signature.klazz;
|
||||
}
|
||||
|
||||
public final Object getClassObject() {
|
||||
try {
|
||||
final Class implClass = signature.klazz.getClassLoader().loadClass(signature.klazz.getCanonicalName());
|
||||
final Field classobj = implClass.getField("$classobj");
|
||||
return classobj.get(null);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
TypeInfo getSuperTypeInfo(Class klass) {
|
||||
return signature.superSignatures.get(klass);
|
||||
}
|
||||
|
||||
public final TypeInfo getArgumentType(Class klass, int index) {
|
||||
if(klass == this.signature.klazz)
|
||||
return projections[index].getType();
|
||||
else {
|
||||
return TypeInfoUtils.substitute(getSuperTypeInfo(klass), projections).getArgumentType(klass, index);
|
||||
}
|
||||
}
|
||||
|
||||
TypeInfo substitute(final List<TypeInfo> myVars) {
|
||||
if(projections.length == 0)
|
||||
return new TypeInfoImpl(this.signature.klazz, nullable, EMPTY);
|
||||
else {
|
||||
TypeInfoProjection [] proj = new TypeInfoProjection[projections.length];
|
||||
for(int i = 0; i != proj.length; ++i) {
|
||||
final int finalI = i;
|
||||
final TypeInfo substitute = TypeInfoUtils.substitute(projections[finalI].getType(), myVars);
|
||||
proj[i] = new TypeInfoProjection(){
|
||||
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return projections[finalI].getVariance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return substitute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getVariance().toString() + " " + substitute;
|
||||
}
|
||||
};
|
||||
}
|
||||
return new TypeInfoImpl(this.signature.klazz, nullable, proj);
|
||||
}
|
||||
}
|
||||
|
||||
TypeInfo substitute(TypeInfoProjection[] prj) {
|
||||
if(projections.length == 0)
|
||||
return new TypeInfoImpl(signature.klazz, nullable, EMPTY);
|
||||
else {
|
||||
TypeInfoProjection [] proj = new TypeInfoProjection[projections.length];
|
||||
for(int i = 0; i != proj.length; ++i) {
|
||||
final int finalI = i;
|
||||
final TypeInfo substitute = TypeInfoUtils.substitute(projections[finalI].getType(), prj);
|
||||
proj[i] = new TypeInfoProjection(){
|
||||
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return projections[finalI].getVariance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return substitute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getVariance().toString() + " " + substitute;
|
||||
}
|
||||
};
|
||||
}
|
||||
return new TypeInfoImpl(signature.klazz, nullable, proj);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
TypeInfoImpl typeInfo = (TypeInfoImpl) o;
|
||||
|
||||
if (!signature.klazz.equals(typeInfo.signature.klazz)) return false;
|
||||
if (nullable != typeInfo.nullable) return false;
|
||||
if (!Arrays.equals(projections, typeInfo.projections)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// @NotNull
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return TypeInfoVariance.INVARIANT;
|
||||
}
|
||||
|
||||
// @NotNull
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return 31 * signature.klazz.hashCode() + Arrays.hashCode(projections);
|
||||
}
|
||||
|
||||
public final boolean isInstance(Object obj) {
|
||||
if (obj == null) return nullable;
|
||||
|
||||
if (obj instanceof JetObject) {
|
||||
return ((TypeInfoImpl)((JetObject) obj).getTypeInfo()).isSubtypeOf(this);
|
||||
}
|
||||
|
||||
return signature.klazz.isAssignableFrom(obj.getClass()); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProjectionCount() {
|
||||
return projections.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
StringBuilder sb = new StringBuilder().append(signature.klazz.getName());
|
||||
if (projections.length != 0) {
|
||||
sb.append("<");
|
||||
for (int i = 0; i != projections.length - 1; ++i) {
|
||||
sb.append(projections[i].toString()).append(",");
|
||||
}
|
||||
sb.append(projections[projections.length - 1].toString()).append(">");
|
||||
}
|
||||
if (nullable)
|
||||
sb.append("?");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TypeInfo<?> getTypeInfo() {
|
||||
if (typeInfo == null) {
|
||||
// TODO: Implementation must be lazy, otherwise the result would be of an infinite size
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetObject getOuterObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final boolean isSubtypeOf(TypeInfoImpl<?> superType) {
|
||||
if (nullable && !superType.nullable) {
|
||||
return false;
|
||||
}
|
||||
if (!superType.signature.klazz.isAssignableFrom(signature.klazz)) {
|
||||
return false;
|
||||
}
|
||||
if (superType.projections == null || superType.projections.length != projections.length) {
|
||||
throw new IllegalArgumentException("inconsistent type info for the same class");
|
||||
}
|
||||
for (int i = 0; i < projections.length; i++) {
|
||||
// TODO handle variance here
|
||||
if (!projections[i].getType().equals(superType.projections[i].getType())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
package jet.typeinfo.internal;
|
||||
|
||||
import jet.typeinfo.JetSignature;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import jet.typeinfo.TypeInfoProjection;
|
||||
import jet.typeinfo.TypeInfoVariance;
|
||||
import jet.typeinfo.internal.signature.JetSignatureExceptionsAdapter;
|
||||
import jet.typeinfo.internal.signature.JetSignatureReader;
|
||||
import jet.typeinfo.internal.signature.JetSignatureVisitor;
|
||||
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
class TypeInfoParser {
|
||||
static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
static final WeakHashMap<Class,Signature> map = new WeakHashMap<Class,Signature>();
|
||||
|
||||
public static Signature parse(Class klass) {
|
||||
if(klass == null)
|
||||
return null;
|
||||
|
||||
// lock.readLock().lock();
|
||||
Signature sig = map.get(klass);
|
||||
// lock.readLock().unlock();
|
||||
if (sig == null) {
|
||||
// lock.writeLock().lock();
|
||||
|
||||
sig = map.get(klass);
|
||||
if (sig == null) {
|
||||
sig = internalParse(klass);
|
||||
}
|
||||
|
||||
// lock.writeLock().unlock();
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
private static Signature internalParse(Class klass) {
|
||||
if(klass.isArray() && !klass.getComponentType().isPrimitive()) {
|
||||
Signature signature = new ArraySignature(klass);
|
||||
map.put(klass, signature);
|
||||
return signature;
|
||||
}
|
||||
|
||||
JetSignature annotation = (JetSignature) klass.getAnnotation(JetSignature.class);
|
||||
if(annotation != null) {
|
||||
String value = annotation.value();
|
||||
if(value != null) {
|
||||
Class enclosingClass = klass.getEnclosingClass();
|
||||
Signature signature = new Signature(klass);
|
||||
map.put(klass, signature);
|
||||
parse(value, signature);
|
||||
signature.afterParse();
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
return getGenericSignature(klass);
|
||||
}
|
||||
|
||||
private static void parse(String annotationValue, final Signature signature) {
|
||||
signature.variables = new ArrayList<TypeInfoProjection>();
|
||||
signature.varNames = new HashMap<String, Integer>();
|
||||
signature.superTypes = new ArrayList<TypeInfo>();
|
||||
new JetSignatureReader(annotationValue).accept(new JetSignatureExceptionsAdapter() {
|
||||
int varIndex = 0;
|
||||
|
||||
@Override
|
||||
public void visitFormalTypeParameter(String name, final TypeInfoVariance variance) {
|
||||
|
||||
final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, signature.variables.size());
|
||||
|
||||
signature.varNames.put(name, signature.variables.size());
|
||||
TypeInfoProjection typeInfoProjection = new TypeInfoProjection() {
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return variance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return typeInfoVar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return typeInfoVar.toString();
|
||||
}
|
||||
};
|
||||
|
||||
signature.variables.add(typeInfoProjection);
|
||||
// TODO: supers
|
||||
// TODO: nullability
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitClassBound() {
|
||||
return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) {
|
||||
@Override
|
||||
protected void done(TypeInfo typeInfo) {
|
||||
// TODO
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitInterfaceBound() {
|
||||
return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) {
|
||||
@Override
|
||||
protected void done(TypeInfo typeInfo) {
|
||||
// TODO
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitSuperclass() {
|
||||
return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) {
|
||||
@Override
|
||||
protected void done(TypeInfo typeInfo) {
|
||||
signature.superTypes.add(typeInfo);
|
||||
signature.superSignatures.put(typeInfo.getJavaClass(), typeInfo);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitInterface() {
|
||||
return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) {
|
||||
@Override
|
||||
protected void done(TypeInfo typeInfo) {
|
||||
signature.superTypes.add(typeInfo);
|
||||
signature.superSignatures.put(typeInfo.getJavaClass(), typeInfo);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static abstract class SignatureParserJetSignatureAdapter extends JetSignatureExceptionsAdapter {
|
||||
private final ClassLoader classLoader;
|
||||
private final Signature signature;
|
||||
|
||||
protected SignatureParserJetSignatureAdapter(ClassLoader classLoader, Signature signature) {
|
||||
this.classLoader = classLoader;
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
protected abstract void done(TypeInfo typeInfo);
|
||||
|
||||
private Class<?> klass;
|
||||
private boolean nullable;
|
||||
private List<TypeInfoProjection> projections;
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name, boolean nullable) {
|
||||
try {
|
||||
klass = classLoader.loadClass(name.replace('/', '.'));
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
this.nullable = nullable;
|
||||
this.projections = new ArrayList<TypeInfoProjection>();
|
||||
}
|
||||
|
||||
private static TypeInfoVariance parseVariance(char wildcard) {
|
||||
switch (wildcard) {
|
||||
case '=': return TypeInfoVariance.INVARIANT;
|
||||
case '+': return TypeInfoVariance.OUT;
|
||||
case '-': return TypeInfoVariance.IN;
|
||||
default: throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitTypeArgument(final char wildcard) {
|
||||
final TypeInfoVariance variance = parseVariance(wildcard);
|
||||
return new SignatureParserJetSignatureAdapter(classLoader, signature) {
|
||||
@Override
|
||||
protected void done(TypeInfo typeInfo) {
|
||||
projections.add(new TypeInfoProjectionImpl(typeInfo) {
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return variance;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeVariable(String name, boolean nullable) {
|
||||
Integer varIndex = signature.varNames.get(name);
|
||||
if (varIndex == null) {
|
||||
throw new IllegalStateException("unresolved type variable: " + name);
|
||||
}
|
||||
TypeInfoVar typeInfo = new TypeInfoVar(signature, nullable, varIndex);
|
||||
done(typeInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
done(new TypeInfoImpl(klass, nullable, projections.toArray(new TypeInfoProjection[0])));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Signature getGenericSignature(Class klass) {
|
||||
// todo complete impl
|
||||
|
||||
java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass();
|
||||
Signature signature = new Signature(klass);
|
||||
|
||||
TypeVariable[] typeParameters = klass.getTypeParameters();
|
||||
if(typeParameters == null || typeParameters.length == 0) {
|
||||
signature.varNames = Collections.emptyMap();
|
||||
signature.variables = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
signature.varNames = new HashMap<String, Integer>();
|
||||
signature.variables = new LinkedList<TypeInfoProjection>();
|
||||
}
|
||||
|
||||
if (typeParameters != null && typeParameters.length != 0) {
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
TypeVariable typeParameter = typeParameters[i];
|
||||
signature.varNames.put(typeParameter.getName(), i);
|
||||
final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, false, i);
|
||||
signature.variables.add(new TypeInfoProjection(){
|
||||
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return TypeInfoVariance.INVARIANT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return typeInfoVar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return typeInfoVar.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
private static class ArraySignature extends Signature {
|
||||
public ArraySignature(Class klass) {
|
||||
super(klass);
|
||||
variables = new LinkedList<TypeInfoProjection>();
|
||||
varNames = new HashMap<String, Integer>();
|
||||
varNames.put("T", 0);
|
||||
final TypeInfoVar typeInfoVar = new TypeInfoVar(this, 0);
|
||||
variables.add(new TypeInfoProjection() {
|
||||
@Override
|
||||
public TypeInfoVariance getVariance() {
|
||||
return TypeInfoVariance.INVARIANT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getType() {
|
||||
return typeInfoVar;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package jet.typeinfo.internal;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import jet.typeinfo.TypeInfoProjection;
|
||||
import jet.typeinfo.TypeInfoVariance;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
* @author yole
|
||||
* @author alex.tkachman
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
public abstract class TypeInfoProjectionImpl implements TypeInfoProjection {
|
||||
private final TypeInfo type;
|
||||
|
||||
public TypeInfoProjectionImpl(TypeInfo typeInfo) {
|
||||
this.type = typeInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
|
||||
jet.typeinfo.internal.TypeInfoProjectionImpl that = (jet.typeinfo.internal.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,40 @@
|
||||
package jet.typeinfo.internal;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import jet.typeinfo.TypeInfoProjection;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
* @author yole
|
||||
* @author alex.tkachman
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
class TypeInfoUtils {
|
||||
|
||||
static TypeInfo<?> substitute(TypeInfo<?> typeInfo, TypeInfoProjection[] projections) {
|
||||
if (typeInfo instanceof TypeInfoImpl<?>) {
|
||||
TypeInfoImpl<?> typeInfoImpl = (TypeInfoImpl<?>) typeInfo;
|
||||
return typeInfoImpl.substitute(projections);
|
||||
} else if (typeInfo instanceof TypeInfoVar<?>) {
|
||||
TypeInfoVar<?> typeInfoVar = (TypeInfoVar<?>) typeInfo;
|
||||
return typeInfoVar.substitute(projections);
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
static TypeInfo<?> substitute(TypeInfo<?> typeInfo, List<TypeInfo> myVars) {
|
||||
if (typeInfo instanceof TypeInfoImpl<?>) {
|
||||
TypeInfoImpl<?> typeInfoImpl = (TypeInfoImpl<?>) typeInfo;
|
||||
return typeInfoImpl.substitute(myVars);
|
||||
} else if (typeInfo instanceof TypeInfoVar<?>) {
|
||||
TypeInfoVar<?> typeInfoVar = (TypeInfoVar<?>) typeInfo;
|
||||
return typeInfoVar.substitute(myVars);
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package jet.typeinfo.internal;
|
||||
|
||||
import jet.JetObject;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import jet.typeinfo.TypeInfoProjection;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
* @author yole
|
||||
* @author alex.tkachman
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
class TypeInfoVar<T> extends TypeInfo<T> {
|
||||
final int varIndex;
|
||||
final Signature signature;
|
||||
final boolean nullable;
|
||||
|
||||
public TypeInfoVar(Signature signature, Integer varIndex) {
|
||||
this.signature = signature;
|
||||
this.varIndex = varIndex;
|
||||
nullable = false;
|
||||
}
|
||||
|
||||
public TypeInfoVar(Signature signature, boolean nullable, int varIndex) {
|
||||
this.signature = signature;
|
||||
this.nullable = nullable;
|
||||
this.varIndex = varIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] newArray(int length) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getJavaClass() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getClassObject() {
|
||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInstance(Object obj) {
|
||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProjectionCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfoProjection getProjection(int index) {
|
||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo getArgumentType(Class klass, int index) {
|
||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||
}
|
||||
|
||||
TypeInfo substitute(List<TypeInfo> myVars) {
|
||||
return myVars.get(varIndex);
|
||||
}
|
||||
|
||||
TypeInfo substitute(TypeInfoProjection[] projections) {
|
||||
return projections[varIndex].getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInfo<?> getTypeInfo() {
|
||||
throw new UnsupportedOperationException("Abstract TypeInfo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetObject getOuterObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "T:" + signature.klazz.getName() + ":" + varIndex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package jet.typeinfo.internal.signature;
|
||||
|
||||
import jet.typeinfo.TypeInfoVariance;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
public class JetSignatureExceptionsAdapter implements JetSignatureVisitor {
|
||||
@Override
|
||||
public void visitFormalTypeParameter(String name, TypeInfoVariance variance) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitClassBound() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitInterfaceBound() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitSuperclass() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitInterface() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitParameterType() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitReturnType() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitExceptionType() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor, boolean nullable) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeVariable(String name, boolean nullable) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitArrayType(boolean nullable) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name, boolean nullable) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClassType(String name, boolean nullable) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeArgument() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitTypeArgument(char wildcard) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
@@ -19,39 +19,7 @@ public class JetSignatureReader {
|
||||
public void accept(final JetSignatureVisitor v) {
|
||||
String signature = this.signature;
|
||||
int len = signature.length();
|
||||
int pos;
|
||||
char c;
|
||||
|
||||
if (signature.charAt(0) == '<') {
|
||||
pos = 2;
|
||||
do {
|
||||
TypeInfoVariance variance;
|
||||
if (signature.substring(pos).startsWith("in ")) {
|
||||
variance = TypeInfoVariance.IN;
|
||||
pos += "in ".length();
|
||||
} else if (signature.substring(pos).startsWith("out ")) {
|
||||
variance = TypeInfoVariance.OUT;
|
||||
pos += "out ".length();
|
||||
} else {
|
||||
variance = TypeInfoVariance.INVARIANT;
|
||||
pos += "".length();
|
||||
}
|
||||
int end = signature.indexOf(':', pos);
|
||||
v.visitFormalTypeParameter(signature.substring(pos - 1, end), variance);
|
||||
pos = end + 1;
|
||||
|
||||
c = signature.charAt(pos);
|
||||
if (c == 'L' || c == '[' || c == 'T') {
|
||||
pos = parseType(signature, pos, v.visitClassBound());
|
||||
}
|
||||
|
||||
while ((c = signature.charAt(pos++)) == ':') {
|
||||
pos = parseType(signature, pos, v.visitInterfaceBound());
|
||||
}
|
||||
} while (c != '>');
|
||||
} else {
|
||||
pos = 0;
|
||||
}
|
||||
int pos = acceptFormalTypeParameters(v);
|
||||
|
||||
if (signature.charAt(pos) == '(') {
|
||||
pos++;
|
||||
@@ -70,6 +38,52 @@ public class JetSignatureReader {
|
||||
}
|
||||
}
|
||||
|
||||
public int acceptFormalTypeParameters(JetSignatureVisitor v) {
|
||||
int pos;
|
||||
char c;
|
||||
if (signature.length() > 0 && signature.charAt(0) == '<') {
|
||||
pos = 1;
|
||||
do {
|
||||
TypeInfoVariance variance;
|
||||
if (signature.substring(pos).startsWith("in ")) {
|
||||
variance = TypeInfoVariance.IN;
|
||||
pos += "in ".length();
|
||||
} else if (signature.substring(pos).startsWith("out ")) {
|
||||
variance = TypeInfoVariance.OUT;
|
||||
pos += "out ".length();
|
||||
} else {
|
||||
variance = TypeInfoVariance.INVARIANT;
|
||||
pos += "".length();
|
||||
}
|
||||
int end = signature.indexOf(':', pos);
|
||||
if (end < 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
v.visitFormalTypeParameter(signature.substring(pos, end), variance);
|
||||
pos = end + 1;
|
||||
|
||||
c = signature.charAt(pos);
|
||||
if (c == 'L' || c == '[' || c == 'T' || c == '?') {
|
||||
pos = parseType(signature, pos, v.visitClassBound());
|
||||
}
|
||||
|
||||
while ((c = signature.charAt(pos++)) == ':') {
|
||||
pos = parseType(signature, pos, v.visitInterfaceBound());
|
||||
}
|
||||
} while (c != '>');
|
||||
} else {
|
||||
pos = 0;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
public void acceptFormalTypeParametersOnly(JetSignatureVisitor v) {
|
||||
int r = acceptFormalTypeParameters(v);
|
||||
if (r != signature.length()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
public int acceptType(JetSignatureVisitor v) {
|
||||
return parseType(this.signature, 0, v);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user