merge Alex' work with mine, move internal classes to internal subpackage

This commit is contained in:
Stepan Koltsov
2011-12-14 22:30:34 +04:00
parent 7a909ff4b9
commit 7ddfa09be0
15 changed files with 922 additions and 849 deletions
@@ -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('>');
}
}
@@ -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;
+1 -1
View File
@@ -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();
}
+13 -630
View File
@@ -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);
}