writing my signatures
This commit is contained in:
+25
-2
@@ -360,6 +360,7 @@ public class JavaDescriptorResolver {
|
||||
|
||||
boolean changeNullable = false;
|
||||
boolean nullable = true;
|
||||
String typeFromAnnotation = null;
|
||||
|
||||
// TODO: must be very slow, make it lazy?
|
||||
String name = parameter.getName() != null ? parameter.getName() : "p" + i;
|
||||
@@ -383,10 +384,20 @@ public class JavaDescriptorResolver {
|
||||
nullable = false;
|
||||
changeNullable = true;
|
||||
}
|
||||
|
||||
PsiLiteralExpression signatureExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_VALUE_PARAMETER_TYPE_FIELD);
|
||||
if (signatureExpression != null) {
|
||||
typeFromAnnotation = (String) signatureExpression.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JetType outType = semanticServices.getTypeTransformer().transformToType(psiType);
|
||||
JetType outType;
|
||||
if (typeFromAnnotation != null) {
|
||||
outType = semanticServices.getTypeTransformer().transformToType(typeFromAnnotation);
|
||||
} else {
|
||||
outType = semanticServices.getTypeTransformer().transformToType(psiType);
|
||||
}
|
||||
return new ValueParameterDescriptorImpl(
|
||||
containingDeclaration,
|
||||
i,
|
||||
@@ -509,6 +520,8 @@ public class JavaDescriptorResolver {
|
||||
private JetType makeReturnType(PsiType returnType, PsiMethod method) {
|
||||
boolean changeNullable = false;
|
||||
boolean nullable = true;
|
||||
|
||||
String returnTypeFromAnnotation = null;
|
||||
|
||||
for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) {
|
||||
if (annotation.getQualifiedName().equals(StdlibNames.JET_METHOD_CLASS)) {
|
||||
@@ -520,9 +533,19 @@ public class JavaDescriptorResolver {
|
||||
nullable = false;
|
||||
changeNullable = true;
|
||||
}
|
||||
|
||||
PsiLiteralExpression returnTypeExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_METHOD_RETURN_TYPE_FIELD);
|
||||
if (returnTypeExpression != null) {
|
||||
returnTypeFromAnnotation = (String) returnTypeExpression.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
JetType transformedType = semanticServices.getTypeTransformer().transformToType(returnType);
|
||||
JetType transformedType;
|
||||
if (returnTypeFromAnnotation != null) {
|
||||
transformedType = semanticServices.getTypeTransformer().transformToType(returnTypeFromAnnotation);
|
||||
} else {
|
||||
transformedType = semanticServices.getTypeTransformer().transformToType(returnType);
|
||||
}
|
||||
if (changeNullable) {
|
||||
return TypeUtils.makeNullableAsSpecified(transformedType, nullable);
|
||||
} else {
|
||||
|
||||
+15
@@ -6,6 +6,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureReader;
|
||||
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureVisitor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -57,6 +59,19 @@ public class JavaTypeTransformer {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetType transformToType(@NotNull String kotlinSignature) {
|
||||
final JetType[] r = new JetType[1];
|
||||
JetTypeJetSignatureReader reader = new JetTypeJetSignatureReader(resolver, standardLibrary) {
|
||||
@Override
|
||||
protected void done(@NotNull JetType jetType) {
|
||||
r[0] = jetType;
|
||||
}
|
||||
};
|
||||
new JetSignatureReader(kotlinSignature).acceptType(reader);
|
||||
return r[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetType transformToType(@NotNull PsiType javaType) {
|
||||
return javaType.accept(new PsiTypeVisitor<JetType>() {
|
||||
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureReader;
|
||||
import org.jetbrains.jet.lang.resolve.java.signature.JetSignatureVisitor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeImpl;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
public abstract class JetTypeJetSignatureReader implements JetSignatureVisitor {
|
||||
|
||||
private final JavaDescriptorResolver javaDescriptorResolver;
|
||||
private final JetStandardLibrary jetStandardLibrary;
|
||||
|
||||
public JetTypeJetSignatureReader(JavaDescriptorResolver javaDescriptorResolver, JetStandardLibrary jetStandardLibrary) {
|
||||
this.javaDescriptorResolver = javaDescriptorResolver;
|
||||
this.jetStandardLibrary = jetStandardLibrary;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void visitFormalTypeParameter(String name) {
|
||||
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) {
|
||||
case 'Z':
|
||||
return jetStandardLibrary.getBooleanType();
|
||||
case 'C':
|
||||
return jetStandardLibrary.getCharType();
|
||||
case 'B':
|
||||
return jetStandardLibrary.getByteType();
|
||||
case 'S':
|
||||
return jetStandardLibrary.getShortType();
|
||||
case 'I':
|
||||
return jetStandardLibrary.getIntType();
|
||||
case 'F':
|
||||
return jetStandardLibrary.getFloatType();
|
||||
case 'J':
|
||||
return jetStandardLibrary.getLongType();
|
||||
case 'D':
|
||||
return jetStandardLibrary.getDoubleType();
|
||||
case 'V':
|
||||
return JetStandardClasses.getUnitType();
|
||||
}
|
||||
} else {
|
||||
switch (descriptor) {
|
||||
case 'Z':
|
||||
return jetStandardLibrary.getNullableBooleanType();
|
||||
case 'C':
|
||||
return jetStandardLibrary.getNullableCharType();
|
||||
case 'B':
|
||||
return jetStandardLibrary.getNullableByteType();
|
||||
case 'S':
|
||||
return jetStandardLibrary.getNullableShortType();
|
||||
case 'I':
|
||||
return jetStandardLibrary.getNullableIntType();
|
||||
case 'F':
|
||||
return jetStandardLibrary.getNullableFloatType();
|
||||
case 'J':
|
||||
return jetStandardLibrary.getNullableLongType();
|
||||
case 'D':
|
||||
return jetStandardLibrary.getNullableDoubleType();
|
||||
case 'V':
|
||||
throw new IllegalStateException("incorrect signature: nullable void");
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("incorrect signature");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor, boolean nullable) {
|
||||
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;
|
||||
private List<TypeProjection> typeArguments;
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name, boolean nullable) {
|
||||
String ourName = name.replace('/', '.');
|
||||
this.classDescriptor = javaDescriptorResolver.resolveClass(ourName);
|
||||
if (this.classDescriptor == null) {
|
||||
throw new IllegalStateException("class not found by name: " + ourName); // TODO: wrong exception
|
||||
}
|
||||
this.nullable = nullable;
|
||||
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;
|
||||
case '+': return Variance.OUT_VARIANCE;
|
||||
case '-': return Variance.IN_VARIANCE;
|
||||
default: throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitTypeArgument(final char wildcard) {
|
||||
return new JetTypeJetSignatureReader(javaDescriptorResolver, jetStandardLibrary) {
|
||||
|
||||
@Override
|
||||
protected void done(@NotNull JetType jetType) {
|
||||
typeArguments.add(new TypeProjection(parseVariance(wildcard), jetType));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
JetType jetType = new JetTypeImpl(
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
classDescriptor.getTypeConstructor(),
|
||||
nullable,
|
||||
typeArguments,
|
||||
ErrorUtils.getErrorScope());
|
||||
done(jetType);
|
||||
}
|
||||
|
||||
protected abstract void done(@NotNull JetType jetType);
|
||||
}
|
||||
@@ -13,6 +13,7 @@ public class StdlibNames {
|
||||
public static final String JET_VALUE_PARAMETER_NAME_FIELD = "name";
|
||||
public static final String JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD = "hasDefaultValue";
|
||||
public static final String JET_VALUE_PARAMETER_NULLABLE_FIELD = "nullable";
|
||||
public static final String JET_VALUE_PARAMETER_TYPE_FIELD = "type";
|
||||
|
||||
|
||||
public static final String JET_TYPE_PARAMETER_CLASS = "jet.typeinfo.JetTypeParameter";
|
||||
@@ -25,6 +26,7 @@ public class StdlibNames {
|
||||
public static final String JET_METHOD_DESCRIPTOR = "Ljet/typeinfo/JetMethod;";
|
||||
|
||||
public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType";
|
||||
public static final String JET_METHOD_RETURN_TYPE_FIELD = "returnType";
|
||||
|
||||
|
||||
public static final String JET_OBJECT_INTERNAL = "jet/JetObject";
|
||||
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package org.jetbrains.jet.lang.resolve.java.signature;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
public class JetSignatureAdapter implements JetSignatureVisitor {
|
||||
@Override
|
||||
public void visitFormalTypeParameter(String name) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitClassBound() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitInterfaceBound() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitSuperclass() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitInterface() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitParameterType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitReturnType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitExceptionType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor, boolean nullable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeVariable(String name, boolean nullable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitArrayType(boolean nullable) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name, boolean nullable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClassType(String name, boolean nullable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeArgument() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitTypeArgument(char wildcard) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
}
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
package org.jetbrains.jet.lang.resolve.java.signature;
|
||||
|
||||
import org.objectweb.asm.signature.SignatureReader;
|
||||
import org.objectweb.asm.signature.SignatureVisitor;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*
|
||||
* @see SignatureReader
|
||||
*/
|
||||
public class JetSignatureReader {
|
||||
|
||||
private final String signature;
|
||||
|
||||
public JetSignatureReader(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
|
||||
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 {
|
||||
int end = signature.indexOf(':', pos);
|
||||
v.visitFormalTypeParameter(signature.substring(pos - 1, end));
|
||||
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;
|
||||
}
|
||||
|
||||
if (signature.charAt(pos) == '(') {
|
||||
pos++;
|
||||
while (signature.charAt(pos) != ')') {
|
||||
pos = parseType(signature, pos, v.visitParameterType());
|
||||
}
|
||||
pos = parseType(signature, pos + 1, v.visitReturnType());
|
||||
while (pos < len) {
|
||||
pos = parseType(signature, pos + 1, v.visitExceptionType());
|
||||
}
|
||||
} else {
|
||||
pos = parseType(signature, pos, v.visitSuperclass());
|
||||
while (pos < len) {
|
||||
pos = parseType(signature, pos, v.visitInterface());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int acceptType(JetSignatureVisitor v) {
|
||||
return parseType(this.signature, 0, v);
|
||||
}
|
||||
|
||||
public void acceptTypeOnly(JetSignatureVisitor v) {
|
||||
int r = acceptType(v);
|
||||
if (r != signature.length()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int parseType(
|
||||
final String signature,
|
||||
int pos,
|
||||
final JetSignatureVisitor v)
|
||||
{
|
||||
char c;
|
||||
int start, end;
|
||||
boolean visited, inner;
|
||||
String name;
|
||||
|
||||
boolean nullable = false;
|
||||
if (signature.charAt(pos) == '?') {
|
||||
nullable = true;
|
||||
pos++;
|
||||
}
|
||||
|
||||
switch (c = signature.charAt(pos++)) {
|
||||
case 'Z':
|
||||
case 'C':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'I':
|
||||
case 'F':
|
||||
case 'J':
|
||||
case 'D':
|
||||
case 'V':
|
||||
v.visitBaseType(c, nullable);
|
||||
return pos;
|
||||
|
||||
case '[':
|
||||
return parseType(signature, pos, v.visitArrayType(nullable));
|
||||
|
||||
case 'T':
|
||||
end = signature.indexOf(';', pos);
|
||||
v.visitTypeVariable(signature.substring(pos, end), nullable);
|
||||
return end + 1;
|
||||
|
||||
default: // case 'L':
|
||||
start = pos;
|
||||
visited = false;
|
||||
inner = false;
|
||||
for (;;) {
|
||||
switch (c = signature.charAt(pos++)) {
|
||||
case '.':
|
||||
case ';':
|
||||
if (!visited) {
|
||||
name = signature.substring(start, pos - 1);
|
||||
if (inner) {
|
||||
v.visitInnerClassType(name, nullable);
|
||||
} else {
|
||||
v.visitClassType(name, nullable);
|
||||
}
|
||||
}
|
||||
if (c == ';') {
|
||||
v.visitEnd();
|
||||
return pos;
|
||||
}
|
||||
start = pos;
|
||||
visited = false;
|
||||
inner = true;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
name = signature.substring(start, pos - 1);
|
||||
if (inner) {
|
||||
v.visitInnerClassType(name, nullable);
|
||||
} else {
|
||||
v.visitClassType(name, nullable);
|
||||
}
|
||||
visited = true;
|
||||
top: for (;;) {
|
||||
switch (c = signature.charAt(pos)) {
|
||||
case '>':
|
||||
break top;
|
||||
case '*':
|
||||
++pos;
|
||||
v.visitTypeArgument();
|
||||
break;
|
||||
case '+':
|
||||
case '-':
|
||||
pos = parseType(signature,
|
||||
pos + 1,
|
||||
v.visitTypeArgument(c));
|
||||
break;
|
||||
default:
|
||||
pos = parseType(signature,
|
||||
pos,
|
||||
v.visitTypeArgument('='));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
package org.jetbrains.jet.lang.resolve.java.signature;
|
||||
|
||||
import org.objectweb.asm.signature.SignatureVisitor;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*
|
||||
* @see SignatureVisitor
|
||||
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
|
||||
*/
|
||||
public interface JetSignatureVisitor {
|
||||
|
||||
/**
|
||||
* Wildcard for an "extends" type argument.
|
||||
*/
|
||||
char EXTENDS = '+';
|
||||
|
||||
/**
|
||||
* Wildcard for a "super" type argument.
|
||||
*/
|
||||
char SUPER = '-';
|
||||
|
||||
/**
|
||||
* Wildcard for a normal type argument.
|
||||
*/
|
||||
char INSTANCEOF = '=';
|
||||
|
||||
/**
|
||||
* Visits a formal type parameter.
|
||||
*
|
||||
* @param name the name of the formal parameter.
|
||||
*/
|
||||
void visitFormalTypeParameter(String name);
|
||||
|
||||
/**
|
||||
* Visits the class bound of the last visited formal type parameter.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the class bound.
|
||||
*/
|
||||
JetSignatureVisitor visitClassBound();
|
||||
|
||||
/**
|
||||
* Visits an interface bound of the last visited formal type parameter.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the interface bound.
|
||||
*/
|
||||
JetSignatureVisitor visitInterfaceBound();
|
||||
|
||||
/**
|
||||
* Visits the type of the super class.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the super class
|
||||
* type.
|
||||
*/
|
||||
JetSignatureVisitor visitSuperclass();
|
||||
|
||||
/**
|
||||
* Visits the type of an interface implemented by the class.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the interface type.
|
||||
*/
|
||||
JetSignatureVisitor visitInterface();
|
||||
|
||||
/**
|
||||
* Visits the type of a method parameter.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the parameter type.
|
||||
*/
|
||||
JetSignatureVisitor visitParameterType();
|
||||
|
||||
/**
|
||||
* Visits the return type of the method.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the return type.
|
||||
*/
|
||||
JetSignatureVisitor visitReturnType();
|
||||
|
||||
/**
|
||||
* Visits the type of a method exception.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the exception type.
|
||||
*/
|
||||
JetSignatureVisitor visitExceptionType();
|
||||
|
||||
/**
|
||||
* Visits a signature corresponding to a primitive type.
|
||||
*
|
||||
* @param descriptor the descriptor of the primitive type, or 'V' for
|
||||
* <tt>void</tt>.
|
||||
*/
|
||||
void visitBaseType(char descriptor, boolean nullable);
|
||||
|
||||
/**
|
||||
* Visits a signature corresponding to a type variable.
|
||||
*
|
||||
* @param name the name of the type variable.
|
||||
*/
|
||||
void visitTypeVariable(String name, boolean nullable);
|
||||
|
||||
/**
|
||||
* Visits a signature corresponding to an array type.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the array element
|
||||
* type.
|
||||
*/
|
||||
JetSignatureVisitor visitArrayType(boolean nullable);
|
||||
|
||||
/**
|
||||
* Starts the visit of a signature corresponding to a class or interface
|
||||
* type.
|
||||
*
|
||||
* @param name the internal name of the class or interface.
|
||||
*/
|
||||
void visitClassType(String name, boolean nullable);
|
||||
|
||||
/**
|
||||
* Visits an inner class.
|
||||
*
|
||||
* @param name the local name of the inner class in its enclosing class.
|
||||
*/
|
||||
void visitInnerClassType(String name, boolean nullable);
|
||||
|
||||
/**
|
||||
* Visits an unbounded type argument of the last visited class or inner
|
||||
* class type.
|
||||
*/
|
||||
void visitTypeArgument();
|
||||
|
||||
/**
|
||||
* Visits a type argument of the last visited class or inner class type.
|
||||
*
|
||||
* @param wildcard '+', '-' or '='.
|
||||
* @return a non null visitor to visit the signature of the type argument.
|
||||
*/
|
||||
JetSignatureVisitor visitTypeArgument(char wildcard);
|
||||
|
||||
/**
|
||||
* Ends the visit of a signature corresponding to a class or interface type.
|
||||
*/
|
||||
void visitEnd();
|
||||
}
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
package org.jetbrains.jet.lang.resolve.java.signature;
|
||||
|
||||
import org.objectweb.asm.signature.SignatureWriter;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*
|
||||
* @see SignatureWriter
|
||||
*/
|
||||
public class JetSignatureWriter implements JetSignatureVisitor {
|
||||
|
||||
/**
|
||||
* Buffer used to construct the signature.
|
||||
*/
|
||||
private final StringBuffer buf = new StringBuffer();
|
||||
|
||||
/**
|
||||
* Indicates if the signature contains formal type parameters.
|
||||
*/
|
||||
private boolean hasFormals;
|
||||
|
||||
/**
|
||||
* Indicates if the signature contains method parameter types.
|
||||
*/
|
||||
private boolean hasParameters;
|
||||
|
||||
/**
|
||||
* Stack used to keep track of class types that have arguments. Each element
|
||||
* of this stack is a boolean encoded in one bit. The top of the stack is
|
||||
* the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
|
||||
* /2.
|
||||
*/
|
||||
private int argumentStack;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link SignatureWriter} object.
|
||||
*/
|
||||
public JetSignatureWriter() {
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Implementation of the SignatureVisitor interface
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void visitFormalTypeParameter(final String name) {
|
||||
if (!hasFormals) {
|
||||
hasFormals = true;
|
||||
buf.append('<');
|
||||
}
|
||||
buf.append(name);
|
||||
buf.append(':');
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureWriter visitClassBound() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureWriter visitInterfaceBound() {
|
||||
buf.append(':');
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureWriter visitSuperclass() {
|
||||
endFormals();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureWriter visitInterface() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureWriter visitParameterType() {
|
||||
endFormals();
|
||||
if (!hasParameters) {
|
||||
hasParameters = true;
|
||||
buf.append('(');
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureWriter visitReturnType() {
|
||||
endFormals();
|
||||
if (!hasParameters) {
|
||||
buf.append('(');
|
||||
}
|
||||
buf.append(')');
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureWriter visitExceptionType() {
|
||||
buf.append('^');
|
||||
return this;
|
||||
}
|
||||
|
||||
private void visitNullabe(boolean nullable) {
|
||||
if (nullable) {
|
||||
buf.append('?');
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(final char descriptor, boolean nullable) {
|
||||
visitNullabe(nullable);
|
||||
buf.append(descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeVariable(final String name, boolean nullable) {
|
||||
visitNullabe(nullable);
|
||||
buf.append('T');
|
||||
buf.append(name);
|
||||
buf.append(';');
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureWriter visitArrayType(boolean nullable) {
|
||||
visitNullabe(nullable);
|
||||
buf.append('[');
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(final String name, boolean nullable) {
|
||||
visitNullabe(nullable);
|
||||
buf.append('L');
|
||||
buf.append(name);
|
||||
argumentStack *= 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClassType(final String name, boolean nullable) {
|
||||
endArguments();
|
||||
visitNullabe(nullable);
|
||||
buf.append('.');
|
||||
buf.append(name);
|
||||
argumentStack *= 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeArgument() {
|
||||
if (argumentStack % 2 == 0) {
|
||||
++argumentStack;
|
||||
buf.append('<');
|
||||
}
|
||||
buf.append('*');
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureWriter visitTypeArgument(final char wildcard) {
|
||||
if (argumentStack % 2 == 0) {
|
||||
++argumentStack;
|
||||
buf.append('<');
|
||||
}
|
||||
if (wildcard != '=') {
|
||||
buf.append(wildcard);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
endArguments();
|
||||
buf.append(';');
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Utility methods
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Ends the formal type parameters section of the signature.
|
||||
*/
|
||||
private void endFormals() {
|
||||
if (hasFormals) {
|
||||
hasFormals = false;
|
||||
buf.append('>');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the type arguments of a class or inner class type.
|
||||
*/
|
||||
private void endArguments() {
|
||||
if (argumentStack % 2 != 0) {
|
||||
buf.append('>');
|
||||
}
|
||||
argumentStack /= 2;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user