diff --git a/src/main/java/io/quarkus/gizmo/ClassSignatureBuilderImpl.java b/src/main/java/io/quarkus/gizmo/ClassSignatureBuilderImpl.java index 3b2286e..ef21694 100644 --- a/src/main/java/io/quarkus/gizmo/ClassSignatureBuilderImpl.java +++ b/src/main/java/io/quarkus/gizmo/ClassSignatureBuilderImpl.java @@ -3,17 +3,14 @@ import java.util.ArrayList; import java.util.List; -import org.jboss.jandex.DotName; - import io.quarkus.gizmo.SignatureBuilder.ClassSignatureBuilder; import io.quarkus.gizmo.Type.ClassType; import io.quarkus.gizmo.Type.ParameterizedType; import io.quarkus.gizmo.Type.TypeVariable; class ClassSignatureBuilderImpl implements ClassSignatureBuilder { - - private Type superClass = Type.classType(DotName.OBJECT_NAME); private List typeParameters = new ArrayList<>(); + private Type superClass = ClassType.OBJECT; private List superInterfaces = new ArrayList<>(); @Override @@ -30,12 +27,12 @@ public String build() { } // superclass - signature.append(superClass.toSignature()); + superClass.appendToSignature(signature); // interfaces if (!superInterfaces.isEmpty()) { for (Type superInterface : superInterfaces) { - signature.append(superInterface.toSignature()); + superInterface.appendToSignature(signature); } } return signature.toString(); @@ -58,6 +55,7 @@ public ClassSignatureBuilder setSuperClass(ParameterizedType superClass) { if (containsWildcard(superClass)) { throw new IllegalArgumentException("A super type may not specify a wilcard"); } + this.superClass = superClass; return this; } @@ -81,7 +79,7 @@ private boolean containsWildcard(Type type) { if (type.isWildcard()) { return true; } else if (type.isParameterizedType()) { - for (Type typeArgument : type.asParameterizedType().typeArguments) { + for (Type typeArgument : type.asParameterizedType().getTypeArguments()) { if (containsWildcard(typeArgument)) { return true; } @@ -89,5 +87,4 @@ private boolean containsWildcard(Type type) { } return false; } - -} \ No newline at end of file +} diff --git a/src/main/java/io/quarkus/gizmo/FieldSignatureBuilderImpl.java b/src/main/java/io/quarkus/gizmo/FieldSignatureBuilderImpl.java index d26342e..8364a1d 100644 --- a/src/main/java/io/quarkus/gizmo/FieldSignatureBuilderImpl.java +++ b/src/main/java/io/quarkus/gizmo/FieldSignatureBuilderImpl.java @@ -5,12 +5,13 @@ import io.quarkus.gizmo.SignatureBuilder.FieldSignatureBuilder; class FieldSignatureBuilderImpl implements FieldSignatureBuilder { - private Type type; @Override public String build() { - return type.toSignature(); + StringBuilder signature = new StringBuilder(); + type.appendToSignature(signature); + return signature.toString(); } @Override @@ -18,5 +19,4 @@ public FieldSignatureBuilder setType(Type type) { this.type = Objects.requireNonNull(type); return this; } - -} \ No newline at end of file +} diff --git a/src/main/java/io/quarkus/gizmo/MethodSignatureBuilderImpl.java b/src/main/java/io/quarkus/gizmo/MethodSignatureBuilderImpl.java index b184928..78d4f0b 100644 --- a/src/main/java/io/quarkus/gizmo/MethodSignatureBuilderImpl.java +++ b/src/main/java/io/quarkus/gizmo/MethodSignatureBuilderImpl.java @@ -7,12 +7,12 @@ import io.quarkus.gizmo.SignatureBuilder.MethodSignatureBuilder; import io.quarkus.gizmo.Type.ClassType; import io.quarkus.gizmo.Type.TypeVariable; +import io.quarkus.gizmo.Type.VoidType; class MethodSignatureBuilderImpl implements MethodSignatureBuilder { - - private Type returnType = Type.voidType(); - private List parameterTypes = new ArrayList<>(); private List typeParameters = new ArrayList<>(); + private Type returnType = VoidType.INSTANCE; + private List parameterTypes = new ArrayList<>(); private List exceptions = new ArrayList<>(); @Override @@ -28,22 +28,24 @@ public String build() { signature.append('>'); } - // params + // param types signature.append('('); for (Type parameterType : parameterTypes) { - signature.append(parameterType.toSignature()); + parameterType.appendToSignature(signature); } signature.append(')'); // return type - signature.append(returnType.toSignature()); + returnType.appendToSignature(signature); - // exceptions + // exception types if (!exceptions.isEmpty()) { for (Type exceptionType : exceptions) { - signature.append('^').append(exceptionType.toSignature()); + signature.append('^'); + exceptionType.appendToSignature(signature); } } + return signature.toString(); } @@ -60,7 +62,7 @@ public MethodSignatureBuilder setReturnType(Type returnType) { } @Override - public MethodSignatureBuilder addParameter(Type parameterType) { + public MethodSignatureBuilder addParameterType(Type parameterType) { this.parameterTypes.add(Objects.requireNonNull(parameterType)); return this; } @@ -76,5 +78,4 @@ public MethodSignatureBuilder addException(TypeVariable exceptionType) { this.exceptions.add(Objects.requireNonNull(exceptionType)); return this; } - -} \ No newline at end of file +} diff --git a/src/main/java/io/quarkus/gizmo/SignatureBuilder.java b/src/main/java/io/quarkus/gizmo/SignatureBuilder.java index 6c99d5a..d90f3c2 100644 --- a/src/main/java/io/quarkus/gizmo/SignatureBuilder.java +++ b/src/main/java/io/quarkus/gizmo/SignatureBuilder.java @@ -5,12 +5,11 @@ import io.quarkus.gizmo.Type.TypeVariable; /** - * Builds a signature as defined in JVMS 17, chapter "4.7.9.1. Signatures". + * Builds a generic signature as defined in JVMS 17, chapter "4.7.9.1. Signatures". * * @see SignatureElement#setSignature(String) */ public interface SignatureBuilder { - static ClassSignatureBuilder forClass() { return new ClassSignatureBuilderImpl(); } @@ -24,12 +23,14 @@ static FieldSignatureBuilder forField() { } /** - * @return the signature + * @return the generic signature */ String build(); + /** + * Builds a generic signature of a class (including interfaces). + */ interface ClassSignatureBuilder extends SignatureBuilder { - ClassSignatureBuilder addTypeParameter(TypeVariable typeParameter); ClassSignatureBuilder setSuperClass(ClassType superClass); @@ -41,22 +42,25 @@ interface ClassSignatureBuilder extends SignatureBuilder { ClassSignatureBuilder addSuperInterface(ParameterizedType interfaceType); } + /** + * Builds a generic signature of a method (including constructors). + */ interface MethodSignatureBuilder extends SignatureBuilder { - MethodSignatureBuilder addTypeParameter(TypeVariable typeParameter); MethodSignatureBuilder setReturnType(Type returnType); - MethodSignatureBuilder addParameter(Type parameter); + MethodSignatureBuilder addParameterType(Type parameterType); MethodSignatureBuilder addException(ClassType exceptionType); MethodSignatureBuilder addException(TypeVariable exceptionType); } + /** + * Builds a generic signature of a field. Also usable for building generic signatures of record components. + */ interface FieldSignatureBuilder extends SignatureBuilder { - FieldSignatureBuilder setType(Type type); } - } diff --git a/src/main/java/io/quarkus/gizmo/SignatureElement.java b/src/main/java/io/quarkus/gizmo/SignatureElement.java index ce0b1ca..be911dc 100644 --- a/src/main/java/io/quarkus/gizmo/SignatureElement.java +++ b/src/main/java/io/quarkus/gizmo/SignatureElement.java @@ -10,7 +10,7 @@ public interface SignatureElement { /** * Use the convenient {@link SignatureBuilder} to build signatures for classes, methods and fields. * - * @param signature The signature as defined in JVMS 17, chapter "4.7.9.1. Signatures" + * @param signature The generic signature as defined in JVMS 17, chapter "4.7.9.1. Signatures" * @return the element * @see SignatureBuilder */ diff --git a/src/main/java/io/quarkus/gizmo/Type.java b/src/main/java/io/quarkus/gizmo/Type.java index dae915a..b593f0e 100644 --- a/src/main/java/io/quarkus/gizmo/Type.java +++ b/src/main/java/io/quarkus/gizmo/Type.java @@ -1,6 +1,7 @@ package io.quarkus.gizmo; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -8,26 +9,29 @@ import org.jboss.jandex.PrimitiveType.Primitive; /** - * This interface can be used to build a JVM signature for classes, methods and fields. + * Used to express types when {@linkplain SignatureBuilder building} a generic signature of some declaration. *

- * Implementations are instantiated via factory methods; for example {@link #voidType()} and {@link #classType(Class)}. + * Implementations are created via factory methods such as {@link #voidType()} and {@link #classType(Class)}. * * @see SignatureBuilder */ -public interface Type { - +public abstract class Type { // Factory methods public static VoidType voidType() { return VoidType.INSTANCE; } + public static PrimitiveType booleanType() { + return PrimitiveType.BOOLEAN; + } + public static PrimitiveType byteType() { return PrimitiveType.BYTE; } - public static PrimitiveType booleanType() { - return PrimitiveType.BOOLEAN; + public static PrimitiveType shortType() { + return PrimitiveType.SHORT; } public static PrimitiveType intType() { @@ -38,39 +42,35 @@ public static PrimitiveType longType() { return PrimitiveType.LONG; } - public static PrimitiveType shortType() { - return PrimitiveType.SHORT; + public static PrimitiveType floatType() { + return PrimitiveType.FLOAT; } public static PrimitiveType doubleType() { return PrimitiveType.DOUBLE; } - public static PrimitiveType floatType() { - return PrimitiveType.FLOAT; - } - public static PrimitiveType charType() { return PrimitiveType.CHAR; } - public static ClassType classType(DotName name) { - return classType(Objects.requireNonNull(name).toString().replace('.', '/')); + public static ClassType classType(DotName className) { + return classType(className.toString()); } - public static ClassType classType(String name) { - return new ClassType(name, null); + public static ClassType classType(String className) { + return new ClassType(className.replace('.', '/'), null); } - public static ClassType classType(Class classType) { - return classType(Objects.requireNonNull(classType).getName().replace('.', '/')); + public static ClassType classType(Class clazz) { + return classType(clazz.getName()); } - public static ParameterizedType parameterizedType(ClassType classType, Type... typeArguments) { + public static ParameterizedType parameterizedType(ClassType genericClass, Type... typeArguments) { if (typeArguments.length == 0) { throw new IllegalArgumentException("No type arguments"); } - return new ParameterizedType(classType, Arrays.asList(typeArguments), null); + return new ParameterizedType(genericClass, Arrays.asList(typeArguments), null); } public static ArrayType arrayType(Type elementType) { @@ -85,175 +85,239 @@ public static TypeVariable typeVariable(String name) { return typeVariable(name, ClassType.OBJECT); } + public static TypeVariable typeVariable(String name, Type classOrTypeVariableBound) { + Type bound = Objects.requireNonNull(classOrTypeVariableBound); + if (!bound.isClass() && !bound.isParameterizedType() && !bound.isTypeVariable()) { + throw new IllegalArgumentException("Type variable bound must be a class or a type variable"); + } + return new TypeVariable(name, bound, Collections.emptyList()); + } + public static TypeVariable typeVariable(String name, Type classBound, Type... interfaceBounds) { + if (classBound != null && !classBound.isClass() && !classBound.isParameterizedType()) { + throw new IllegalArgumentException("First type variable bound must be a class"); + } + for (Type interfaceBound : interfaceBounds) { + if (!interfaceBound.isClass() && !interfaceBound.isParameterizedType()) { + throw new IllegalArgumentException("Next type variable bounds must all be interfaces"); + } + } + return new TypeVariable(name, classBound, Arrays.asList(interfaceBounds)); } public static WildcardType wildcardTypeWithUpperBound(Type bound) { - return new WildcardType(bound, null); + return new WildcardType(Objects.requireNonNull(bound), null); } public static WildcardType wildcardTypeWithLowerBound(Type bound) { - return new WildcardType(null, bound); + return new WildcardType(null, Objects.requireNonNull(bound)); } public static WildcardType wildcardTypeUnbounded() { return new WildcardType(ClassType.OBJECT, null); } - /** - * - * @param signature - */ - void appendToSignature(StringBuilder signature); + // implementation details - /** - * - * @return the signature as defined in JVMS 17, chapter "4.7.9.1. Signatures" - */ - default String toSignature() { - StringBuilder sb = new StringBuilder(); - appendToSignature(sb); - return sb.toString(); - } + abstract void appendToSignature(StringBuilder signature); - default boolean isVoid() { + boolean isVoid() { return false; } - default boolean isPrimitive() { + boolean isPrimitive() { return false; } - default boolean isClass() { + boolean isClass() { return false; } - default boolean isArray() { + boolean isArray() { return false; } - default boolean isParameterizedType() { + boolean isParameterizedType() { return false; } - default boolean isTypeVariable() { + boolean isTypeVariable() { return false; } - default boolean isWildcard() { + boolean isWildcard() { return false; } - default VoidType asVoid() { + VoidType asVoid() { throw new IllegalStateException("Not a void"); } - default PrimitiveType asPrimitive() { + PrimitiveType asPrimitive() { throw new IllegalStateException("Not a primitive"); } - default ClassType asClass() { + ClassType asClass() { throw new IllegalStateException("Not a class"); } - default ArrayType asArray() { + ArrayType asArray() { throw new IllegalStateException("Not an array"); } - default ParameterizedType asParameterizedType() { + ParameterizedType asParameterizedType() { throw new IllegalStateException("Not a parameterized type"); } - default TypeVariable asTypeVariable() { + TypeVariable asTypeVariable() { throw new IllegalStateException("Not a type variable"); } - default WildcardType asWildcard() { + WildcardType asWildcard() { throw new IllegalStateException("Not a wildcard type"); } - // Implementations + // Types - public static class WildcardType implements Type { - - final Type lowerBound; - final Type upperBound; + public static final class VoidType extends Type { + public static final VoidType INSTANCE = new VoidType(); - WildcardType(Type upperBound, Type lowerBound) { - if (upperBound == null && lowerBound == null) { - throw new NullPointerException(); - } - this.upperBound = upperBound; - this.lowerBound = lowerBound; + @Override + void appendToSignature(StringBuilder signature) { + signature.append("V"); } @Override - public boolean isWildcard() { + boolean isVoid() { return true; } @Override - public WildcardType asWildcard() { + VoidType asVoid() { return this; } + } + + public static final class PrimitiveType extends Type { + public static final PrimitiveType BOOLEAN = new PrimitiveType(Primitive.BOOLEAN); + public static final PrimitiveType BYTE = new PrimitiveType(Primitive.BYTE); + public static final PrimitiveType SHORT = new PrimitiveType(Primitive.SHORT); + public static final PrimitiveType INT = new PrimitiveType(Primitive.INT); + public static final PrimitiveType LONG = new PrimitiveType(Primitive.LONG); + public static final PrimitiveType FLOAT = new PrimitiveType(Primitive.FLOAT); + public static final PrimitiveType DOUBLE = new PrimitiveType(Primitive.DOUBLE); + public static final PrimitiveType CHAR = new PrimitiveType(Primitive.CHAR); + + private final Primitive primitive; + + PrimitiveType(Primitive primitive) { + this.primitive = Objects.requireNonNull(primitive); + } @Override - public void appendToSignature(StringBuilder signature) { - if (lowerBound != null) { - signature.append('-').append(lowerBound.toSignature()); - } else if (upperBound.isClass() && upperBound.asClass().name.equals(ClassType.OBJECT.name)) { - signature.append('*'); - } else { - signature.append('+').append(upperBound.toSignature()); + void appendToSignature(StringBuilder signature) { + switch (primitive) { + case BOOLEAN: + signature.append("Z"); + break; + case BYTE: + signature.append("B"); + break; + case SHORT: + signature.append("S"); + case INT: + signature.append("I"); + break; + case LONG: + signature.append("J"); + break; + case FLOAT: + signature.append("F"); + break; + case DOUBLE: + signature.append("D"); + break; + case CHAR: + signature.append("C"); + break; + default: + throw new IllegalStateException("Unknown primitive type: " + primitive.toString()); } } + @Override + boolean isPrimitive() { + return true; + } + + @Override + PrimitiveType asPrimitive() { + return this; + } } - public static class TypeVariable implements Type { + public static final class ClassType extends Type { + public static final ClassType OBJECT = new ClassType("java/lang/Object", null); - final String name; - final Type classBound; - final List interfaceBounds; + private final String name; // always slash-delimited + private final Type owner; - TypeVariable(String name, Type classBound, List interfaceBounds) { + ClassType(String name, Type owner) { this.name = Objects.requireNonNull(name); - this.classBound = classBound; - this.interfaceBounds = interfaceBounds; + this.owner = owner; } - @Override - public void appendToSignature(StringBuilder signature) { - signature.append('T').append(name).append(';').toString(); + /** + * Allows building a signature like {@code Lcom/example/Outer.Inner;}. This is usually + * unnecessary, because {@code Lcom/example/Outer$Inner} is also a valid signature, + * but it's occasionally useful to build a signature of more complex inner types. + * + * @param simpleName simple name of the member class nested in this class + * @return the inner class + */ + public ClassType innerClass(String simpleName) { + return new ClassType(simpleName, this); } - public void appendTypeParameterToSignature(StringBuilder signature) { - signature.append(name).append(":"); - if (classBound != null) { - signature.append(classBound.toSignature()); - } - for (Type bound : interfaceBounds) { - signature.append(":").append(bound.toSignature()); + /** + * Allows build a signature like {@code Lcom/example/Outer.Inner;}. This is usually + * unnecessary, because {@code Lcom/example/Outer$Inner;} is also a valid signature, + * but it's occasionally useful to build a signature of more complex inner types. + * + * @param simpleName simple name of the generic member class nested in this class + * @return the inner parameterized type + */ + public ParameterizedType innerParameterizedType(String simpleName, Type... typeArguments) { + return new ParameterizedType(new ClassType(simpleName, null), Arrays.asList(typeArguments), this); + } + + @Override + void appendToSignature(StringBuilder signature) { + if (owner != null) { + // Append the owner class and replace the last semicolon with a period + owner.appendToSignature(signature); + signature.setCharAt(signature.length() - 1, '.'); + } else { + signature.append('L'); } + signature.append(name).append(';'); } @Override - public boolean isTypeVariable() { + boolean isClass() { return true; } @Override - public TypeVariable asTypeVariable() { + ClassType asClass() { return this; } - } - public static class ArrayType implements Type { - - final Type elementType; - final int dimensions; + public static final class ArrayType extends Type { + private final Type elementType; + private final int dimensions; ArrayType(Type elementType, int dimensions) { this.elementType = Objects.requireNonNull(elementType); @@ -261,52 +325,69 @@ public static class ArrayType implements Type { } @Override - public void appendToSignature(StringBuilder signature) { + void appendToSignature(StringBuilder signature) { for (int i = 0; i < dimensions; i++) { signature.append('['); } - signature.append(elementType.toSignature()); + elementType.appendToSignature(signature); } @Override - public boolean isArray() { + boolean isArray() { return true; } @Override - public ArrayType asArray() { + ArrayType asArray() { return this; } - } - public static class ParameterizedType implements Type { + public static final class ParameterizedType extends Type { + private final ClassType genericClass; + private final List typeArguments; + private final Type owner; - final ClassType classType; - final List typeArguments; - final Type declaringClassType; + ParameterizedType(ClassType genericClass, List typeArguments, Type owner) { + this.genericClass = Objects.requireNonNull(genericClass); + this.typeArguments = Objects.requireNonNull(typeArguments); + this.owner = owner; + } - ParameterizedType(ClassType classType, List typeArguments, Type declaringClassType) { - this.classType = Objects.requireNonNull(classType); - this.typeArguments = typeArguments; - this.declaringClassType = declaringClassType; + /** + * Allows build a signature like {@code Lcom/example/Outer.Inner;}. + * + * @param simpleName simple name of the member class nested in this parameterized type + * @return the inner class + */ + public ClassType innerClass(String simpleName) { + return new ClassType(simpleName, this); + } + + /** + * Allows building a signature like {@code Lcom/example/Outer.Inner;}. + * + * @param simpleName simple name of the generic member class nested in this parameterized type + * @return the inner parameterized type + */ + public ParameterizedType innerParameterizedType(String simpleName, Type... typeArguments) { + return new ParameterizedType(new ClassType(simpleName, null), Arrays.asList(typeArguments), this); } @Override - public void appendToSignature(StringBuilder signature) { - if (declaringClassType != null) { - // Append the declaring class and remove the last semicolon - declaringClassType.appendToSignature(signature); - signature.deleteCharAt(signature.length() - 1); - signature.append('.'); + void appendToSignature(StringBuilder signature) { + if (owner != null) { + // Append the owner class and replace the last semicolon with a period + owner.appendToSignature(signature); + signature.setCharAt(signature.length() - 1, '.'); } else { signature.append('L'); } - signature.append(classType.name); + signature.append(genericClass.name); if (!typeArguments.isEmpty()) { signature.append('<'); - for (Type argument : typeArguments) { - signature.append(argument.toSignature()); + for (Type typeArgument : typeArguments) { + typeArgument.appendToSignature(signature); } signature.append('>'); } @@ -314,151 +395,94 @@ public void appendToSignature(StringBuilder signature) { } @Override - public boolean isParameterizedType() { + boolean isParameterizedType() { return true; } @Override - public ParameterizedType asParameterizedType() { + ParameterizedType asParameterizedType() { return this; } - /** - * Build a signature like Lorg/acme/Parent.Inner;. - * - * @param simpleName - * @return the nested class - */ - public ClassType nestedClassType(String simpleName) { - return new ClassType(simpleName, this); - } - - /** - * Build a signature like Lorg/acme/Parent.Inner;. - * - * @param simpleName - * @return the nested class - */ - public ParameterizedType nestedParameterizedType(String simpleName, Type... typeArguments) { - return new ParameterizedType(Type.classType(simpleName), Arrays.asList(typeArguments), this); + List getTypeArguments() { + return Collections.unmodifiableList(typeArguments); } - } - public static class ClassType implements Type { - - public static ClassType OBJECT = classType(DotName.OBJECT_NAME); - - final String name; - final Type declaringClassType; + public static final class TypeVariable extends Type { + private final String name; + private final Type firstBound; // may be null if all bounds are interfaces + private final List nextBounds; - ClassType(String name, Type declaringClassType) { + TypeVariable(String name, Type firstBound, List nextBounds) { this.name = Objects.requireNonNull(name); - this.declaringClassType = declaringClassType; + this.firstBound = firstBound; + this.nextBounds = Objects.requireNonNull(nextBounds); } @Override - public void appendToSignature(StringBuilder signature) { - if (declaringClassType != null) { - // Append the declaring class and remove the last semicolon - declaringClassType.appendToSignature(signature); - signature.deleteCharAt(signature.length() - 1); - signature.append('.'); - } else { - signature.append('L'); + void appendToSignature(StringBuilder signature) { + signature.append('T').append(name).append(';'); + } + + void appendTypeParameterToSignature(StringBuilder signature) { + signature.append(name).append(":"); + if (firstBound != null) { + firstBound.appendToSignature(signature); + } + for (Type bound : nextBounds) { + signature.append(":"); + bound.appendToSignature(signature); } - signature.append(name).append(';'); } @Override - public boolean isClass() { + boolean isTypeVariable() { return true; } @Override - public ClassType asClass() { + TypeVariable asTypeVariable() { return this; } - } - public static class VoidType implements Type { + public static final class WildcardType extends Type { + private final Type upperBound; + private final Type lowerBound; - public static final VoidType INSTANCE = new VoidType(); - - @Override - public void appendToSignature(StringBuilder signature) { - signature.append("V"); + WildcardType(Type upperBound, Type lowerBound) { + if (upperBound == null && lowerBound == null) { + throw new NullPointerException(); + } + if (upperBound != null && lowerBound != null) { + throw new IllegalArgumentException(); + } + this.upperBound = upperBound; + this.lowerBound = lowerBound; } @Override - public boolean isVoid() { + boolean isWildcard() { return true; } @Override - public VoidType asVoid() { + WildcardType asWildcard() { return this; } - } - - public static class PrimitiveType implements Type { - - public static final PrimitiveType BYTE = new PrimitiveType(Primitive.BYTE); - public static final PrimitiveType CHAR = new PrimitiveType(Primitive.CHAR); - public static final PrimitiveType DOUBLE = new PrimitiveType(Primitive.DOUBLE); - public static final PrimitiveType FLOAT = new PrimitiveType(Primitive.FLOAT); - public static final PrimitiveType INT = new PrimitiveType(Primitive.INT); - public static final PrimitiveType LONG = new PrimitiveType(Primitive.LONG); - public static final PrimitiveType SHORT = new PrimitiveType(Primitive.SHORT); - public static final PrimitiveType BOOLEAN = new PrimitiveType(Primitive.BOOLEAN); - - final Primitive primitive; - - PrimitiveType(Primitive primitive) { - this.primitive = Objects.requireNonNull(primitive); - } - - @Override - public void appendToSignature(StringBuilder signature) { - signature.append(toSignature()); - } - @Override - public String toSignature() { - switch (primitive) { - case BOOLEAN: - return "Z"; - case BYTE: - return "B"; - case CHAR: - return "C"; - case DOUBLE: - return "D"; - case FLOAT: - return "F"; - case INT: - return "I"; - case LONG: - return "J"; - case SHORT: - return "S"; - default: - throw new IllegalStateException(); + void appendToSignature(StringBuilder signature) { + if (lowerBound != null) { + signature.append('-'); + lowerBound.appendToSignature(signature); + } else if (upperBound.isClass() && upperBound.asClass().name.equals(ClassType.OBJECT.name)) { + signature.append('*'); + } else { + signature.append('+'); + upperBound.appendToSignature(signature); } } - - @Override - public boolean isPrimitive() { - return true; - } - - @Override - public PrimitiveType asPrimitive() { - return this; - } - } - } diff --git a/src/test/java/io/quarkus/gizmo/SignaturesTest.java b/src/test/java/io/quarkus/gizmo/SignaturesTest.java index 8e4b3c0..ecf501d 100644 --- a/src/test/java/io/quarkus/gizmo/SignaturesTest.java +++ b/src/test/java/io/quarkus/gizmo/SignaturesTest.java @@ -23,52 +23,73 @@ public void testMethodSignatures() { // void test(long l) assertEquals("(J)V", - SignatureBuilder.forMethod().addParameter(Type.longType()).build()); + SignatureBuilder.forMethod().addParameterType(Type.longType()).build()); // List test(List list) assertEquals("(Ljava/util/List<*>;)Ljava/util/List;", SignatureBuilder.forMethod() .setReturnType(Type.parameterizedType(Type.classType(List.class), Type.classType(String.class))) - .addParameter(Type.parameterizedType(Type.classType(List.class), Type.wildcardTypeUnbounded())) + .addParameterType(Type.parameterizedType(Type.classType(List.class), Type.wildcardTypeUnbounded())) .build()); // Object test() assertEquals("()Ljava/lang/Object;", SignatureBuilder.forMethod().setReturnType(Type.classType(DotName.OBJECT_NAME)).build()); - // > String[] test(T t) + // > String[] test(T t) assertEquals(";>(TT;)[Ljava/lang/String;", SignatureBuilder.forMethod() - .setReturnType(Type.arrayType(Type.classType(String.class))) - .addParameter(Type.typeVariable("T")) .addTypeParameter(Type.typeVariable("T", null, Type.parameterizedType(Type.classType(Comparable.class), Type.typeVariable("T")))) + .setReturnType(Type.arrayType(Type.classType(String.class))) + .addParameterType(Type.typeVariable("T")) .build()); // List test(int a, T t) - assertEquals("(ITT;)Ljava/util/List;", + assertEquals("(ITT;)Ljava/util/List;", SignatureBuilder.forMethod() + .addTypeParameter(Type.typeVariable("R")) .setReturnType( Type.parameterizedType(Type.classType(DotName.createSimple(List.class)), Type.typeVariable("R"))) - .addParameter(Type.intType()) - .addParameter(Type.typeVariable("T")).build()); + .addParameterType(Type.intType()) + .addParameterType(Type.typeVariable("T")) + .build()); + + // List test(int a, T t) + assertEquals("(ITT;)Ljava/util/List;", + SignatureBuilder.forMethod() + .addTypeParameter(Type.typeVariable("R")) + .addTypeParameter(Type.typeVariable("S", Type.typeVariable("R"))) + .setReturnType( + Type.parameterizedType(Type.classType(DotName.createSimple(List.class)), + Type.typeVariable("S"))) + .addParameterType(Type.intType()) + .addParameterType(Type.typeVariable("T")) + .build()); + + // > List test(int a, T t) + assertEquals(";>(ITT;)Ljava/util/List;", + SignatureBuilder.forMethod() + .addTypeParameter(Type.typeVariable("R", null, + Type.classType(Serializable.class), + Type.parameterizedType(Type.classType(Comparable.class), Type.typeVariable("R")))) + .setReturnType( + Type.parameterizedType(Type.classType(List.class), Type.typeVariable("R"))) + .addParameterType(Type.intType()) + .addParameterType(Type.typeVariable("T")) + .build()); // boolean test(int i) assertEquals("(I)Z", SignatureBuilder.forMethod() .setReturnType(Type.booleanType()) - .addParameter(Type.intType()).build()); + .addParameterType(Type.intType()).build()); // , U extends Comparable, V extends Exception> T bbb(U arg, W arg2, OuterParam self) assertEquals( ";U::Ljava/lang/Comparable;V:Ljava/lang/Exception;>(TU;TW;Ltest/OuterParam;)TT;", SignatureBuilder.forMethod() - .setReturnType(Type.typeVariable("T")) - .addParameter(Type.typeVariable("U")) - .addParameter(Type.typeVariable("W")) - .addParameter(Type.parameterizedType(Type.classType("test/OuterParam"), - Type.typeVariable("W"))) .addTypeParameter(Type.typeVariable("T", Type.classType(Number.class), Type.parameterizedType( Type.classType(Comparable.class), @@ -76,24 +97,29 @@ public void testMethodSignatures() { .addTypeParameter(Type.typeVariable("U", null, Type.parameterizedType(Type.classType(Comparable.class), Type.typeVariable("U")))) - .addTypeParameter(Type.typeVariable("V", Type.classType(Exception.class))).build()); + .addTypeParameter(Type.typeVariable("V", Type.classType(Exception.class))) + .setReturnType(Type.typeVariable("T")) + .addParameterType(Type.typeVariable("U")) + .addParameterType(Type.typeVariable("W")) + .addParameterType(Type.parameterizedType(Type.classType("test/OuterParam"), + Type.typeVariable("W"))) + .build()); - // , U extends Comparable, V extends Exception> T test(List arg, W arg2, Foo arg3) throws IllegalArgumentException, V + // , U extends Comparable, V extends Exception> T test(List arg, W arg2, NestedParam

.Inner arg3) throws IllegalArgumentException, V assertEquals( ";U::Ljava/lang/Comparable;V:Ljava/lang/Exception;>(Ljava/util/List<+TU;>;TW;Lio/quarkus/gizmo/SignaturesTest$NestedParam.Inner;)TT;^Ljava/lang/IllegalArgumentException;^TV;", SignatureBuilder.forMethod() - .setReturnType(Type.typeVariable("T")) .addTypeParameter(Type.typeVariable("T", Type.classType(Number.class), Type.parameterizedType(Type.classType(Comparable.class), Type.typeVariable("T")))) .addTypeParameter(Type.typeVariable("U", null, Type.parameterizedType(Type.classType(Comparable.class), Type.typeVariable("U")))) .addTypeParameter(Type.typeVariable("V", Type.classType(Exception.class))) - .addParameter(Type.parameterizedType(Type.classType(List.class), + .setReturnType(Type.typeVariable("T")) + .addParameterType(Type.parameterizedType(Type.classType(List.class), Type.wildcardTypeWithUpperBound(Type.typeVariable("U")))) - .addParameter(Type.typeVariable("W")) - .addParameter(Type.parameterizedType(Type.classType(NestedParam.class), Type.typeVariable("P")) - .nestedClassType( - NestedParam.Inner.class.getSimpleName())) + .addParameterType(Type.typeVariable("W")) + .addParameterType(Type.parameterizedType(Type.classType(NestedParam.class), Type.typeVariable("P")) + .innerClass(NestedParam.Inner.class.getSimpleName())) .addException(Type.classType(IllegalArgumentException.class)) .addException(Type.typeVariable("V")) .build()); @@ -164,7 +190,7 @@ public void testFieldSignatures() { assertEquals("Lio/quarkus/gizmo/SignaturesTest$NestedParam.InnerParam;", SignatureBuilder.forField() .setType(Type.parameterizedType(Type.classType(NestedParam.class), Type.typeVariable("P")) - .nestedParameterizedType(InnerParam.class.getSimpleName(), Type.typeVariable("P"))) + .innerParameterizedType(InnerParam.class.getSimpleName(), Type.typeVariable("P"))) .build()); } @@ -192,6 +218,34 @@ public void testClassSignatures() { .addSuperInterface(Type.parameterizedType(Type.classType(Comparable.class), Type.typeVariable("T"))) .build()); + // public class OuterParam { + // public interface NestedParam { + // } + // + // public class InnerParam { + // public class InnerInnerRaw { + // public class InnerInnerInnerParam { + // public class Test + // extends OuterParam.InnerParam.InnerInnerRaw.InnerInnerInnerParam + // implements NestedParam { + // } + // } + // } + // } + // } + assertEquals("Lio/quarkus/gizmo/test/OuterParam.InnerParam.InnerInnerRaw.InnerInnerInnerParam;Lio/quarkus/gizmo/test/OuterParam$NestedParam;", + SignatureBuilder.forClass() + .addTypeParameter(Type.typeVariable("X", Type.classType(String.class))) + .addTypeParameter(Type.typeVariable("Y", Type.classType(Integer.class))) + .setSuperClass( + Type.parameterizedType(Type.classType("io.quarkus.gizmo.test.OuterParam"), Type.typeVariable("X")) + .innerParameterizedType("InnerParam", Type.typeVariable("Y")) + .innerClass("InnerInnerRaw") + .innerParameterizedType("InnerInnerInnerParam", Type.classType(String.class)) + ) + .addSuperInterface(Type.parameterizedType(Type.classType("io.quarkus.gizmo.test.OuterParam$NestedParam"), Type.typeVariable("V"))) + .build()); + try { SignatureBuilder.forClass() .setSuperClass(Type.parameterizedType(Type.classType(List.class), Type.wildcardTypeUnbounded()));