Hinzufügen von FunNGenerator Tests und Bugfixing bei generateSpecializedBytecode().
TPHs werden nun direkt zu Generics substituiert und TypeToSignature wurde verbessert, sodass korrekte Signaturen für Generics generiert werden.
This commit is contained in:
parent
1b5eacf921
commit
5b970f9359
@ -56,11 +56,11 @@ public final class FunNGenerator implements FunNUtilities{
|
||||
|
||||
for (int currentParameter = 1; currentParameter <= numberArguments; currentParameter++){
|
||||
superFunNClassSignature.append(String.format("%s%d:%s",argumentGenericBase, currentParameter, objectSignature));
|
||||
superFunNMethodSignature.append(String.format("T%s;", applySignature( new GenericRefType(argumentGenericBase + currentParameter, null))));
|
||||
superFunNMethodSignature.append(applySignature( new GenericRefType(argumentGenericBase + currentParameter, null)));
|
||||
superFunNMethodDescriptor.append(objectSignature);
|
||||
}
|
||||
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
|
||||
superFunNMethodSignature.append(String.format(")T%s;", applySignature(new GenericRefType(returnGeneric, null))));
|
||||
superFunNMethodSignature.append(String.format(")%s", applySignature(new GenericRefType(returnGeneric, null))));
|
||||
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
|
||||
|
||||
ClassWriter classWriter = new ClassWriter(0);
|
||||
@ -81,8 +81,10 @@ public final class FunNGenerator implements FunNUtilities{
|
||||
public byte[] generateSpecializedBytecode(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) {
|
||||
Objects.requireNonNull(argumentTypes);
|
||||
Objects.requireNonNull(returnType);
|
||||
//generates a list of all params and substitutes the TPH
|
||||
List<RefTypeOrTPHOrWildcardOrGeneric> parameters = Stream
|
||||
.concat(argumentTypes.stream(), Stream.of(returnType))
|
||||
.map(FunNGenerator::substituteTPH)
|
||||
.collect(Collectors.toList());
|
||||
RefType superFunN = new RefType(new JavaClassName(getSuperClassName(argumentTypes.size())), parameters , null);
|
||||
StringBuilder funNClassSignature = new StringBuilder(objectSignature + (superFunN.acceptTV(new TypeToSignature(false))));
|
||||
@ -94,12 +96,6 @@ public final class FunNGenerator implements FunNUtilities{
|
||||
GenericRefType generic = (GenericRefType) typeArgument;
|
||||
String signatureOfArgument = generic.getParsedName();
|
||||
if(genericSignature.contains(signatureOfArgument)) continue;
|
||||
genericSignature += String.format("%s:%s", signatureOfArgument, applyDescriptor(generic));
|
||||
containsGeneric = true;
|
||||
} else if(typeArgument instanceof TypePlaceholder){
|
||||
TypePlaceholder placeholder = (TypePlaceholder) typeArgument;
|
||||
String signatureOfArgument = applySignature(placeholder).substring(1);
|
||||
if(genericSignature.contains(signatureOfArgument)) continue;
|
||||
genericSignature += String.format("%s:%s", signatureOfArgument, objectSignature);
|
||||
containsGeneric = true;
|
||||
}
|
||||
@ -166,4 +162,12 @@ public final class FunNGenerator implements FunNUtilities{
|
||||
* @return the name for the type {@code a} which should be used in the specialized name for FunN.
|
||||
*/
|
||||
private String applyNameDescriptor(RefTypeOrTPHOrWildcardOrGeneric a){ return a instanceof TypePlaceholder ? "LTPH;" : String.format("L%s;", applyDescriptor(a)); }
|
||||
|
||||
private static RefTypeOrTPHOrWildcardOrGeneric substituteTPH(RefTypeOrTPHOrWildcardOrGeneric t) {
|
||||
if (t instanceof TypePlaceholder) {
|
||||
TypePlaceholder tph = (TypePlaceholder) t;
|
||||
return new GenericRefType(tph.getName()+"$", t.getOffset());
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
@ -102,9 +102,20 @@ public class TypeToSignature implements TypeVisitor<String> {
|
||||
return sig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changed that the correct signature is returned:
|
||||
* returns now T...; expect of only ...
|
||||
* where ... is {@code genericRefType.getParsedName()}
|
||||
*
|
||||
* @since Studienarbeit Type Erasure
|
||||
* @author etiennezink
|
||||
*
|
||||
* @param genericRefType
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String visit(GenericRefType genericRefType) {
|
||||
return genericRefType.getParsedName().replace(".", "/");
|
||||
return String.format("T%s;", genericRefType.getParsedName()).replace(".", "/");
|
||||
}
|
||||
|
||||
private Optional<GenericsGeneratorResult> getEqualTPHFromClassConstraints(List<GenericsGeneratorResult> listOfConstraints, String tph) {
|
||||
|
@ -8,12 +8,13 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class FunNGeneratorTest {
|
||||
|
||||
@ -23,108 +24,206 @@ public class FunNGeneratorTest {
|
||||
static GenericRefType genericT = new GenericRefType("T", null);
|
||||
|
||||
@BeforeClass
|
||||
public static void StartUp(){
|
||||
public static void setUp(){
|
||||
funNGenerator = FunNGenerator.getInstance();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SuperClassName_0(){
|
||||
public void superClassName_0(){
|
||||
var superClassName = funNGenerator.getSuperClassName(0);
|
||||
assertEquals("Fun0$$", superClassName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SuperClassName_1(){
|
||||
public void superClassName_1(){
|
||||
var superClassName = funNGenerator.getSuperClassName(1);
|
||||
assertEquals("Fun1$$", superClassName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SpecializedClassName_VoidVoid(){
|
||||
public void specializedClassName_VoidVoid(){
|
||||
var specializedClassName = funNGenerator.getSpecializedClassName(Arrays.asList(), voidType);
|
||||
assertEquals("Fun0$$Ljava$lang$Void$_$", specializedClassName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SpecializedClassName_VoidInt(){
|
||||
public void specializedClassName_VoidInt(){
|
||||
var specializedClassName = funNGenerator.getSpecializedClassName(Arrays.asList(), integerType);
|
||||
assertEquals("Fun0$$Ljava$lang$Integer$_$", specializedClassName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SpecializedClassName_IntInt(){
|
||||
public void specializedClassName_IntInt(){
|
||||
var specializedClassName = funNGenerator.getSpecializedClassName(Arrays.asList(integerType), integerType);
|
||||
assertEquals("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$", specializedClassName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SpecializedClassName_IntT(){
|
||||
public void specializedClassName_IntT(){
|
||||
var specializedClassName = funNGenerator.getSpecializedClassName(Arrays.asList(integerType), genericT);
|
||||
assertEquals("Fun1$$Ljava$lang$Integer$_$LT$_$", specializedClassName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SpecializedClassName_IntTPH(){
|
||||
public void specializedClassName_IntTPH(){
|
||||
var specializedClassName = funNGenerator.getSpecializedClassName(Arrays.asList(integerType), TypePlaceholder.fresh(null));
|
||||
assertEquals("Fun1$$Ljava$lang$Integer$_$LTPH$_$", specializedClassName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Signature_IntInt(){
|
||||
public void signature_IntInt(){
|
||||
var classSignature = funNGenerator.getSpecializedSignature(Arrays.asList(integerType), integerType);
|
||||
assertEquals("LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$;", classSignature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Signature_IntT(){
|
||||
public void signature_IntT(){
|
||||
var classSignature = funNGenerator.getSpecializedSignature(Arrays.asList(integerType), genericT);
|
||||
assertEquals("LFun1$$Ljava$lang$Integer$_$LT$_$;", classSignature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Descriptor_IntInt(){
|
||||
public void descriptor_IntInt(){
|
||||
var classSignature = funNGenerator.getSpecializedDescriptor(Arrays.asList(integerType), integerType);
|
||||
//does not have to contain L and ; because TypeToDescriptor returns the descriptor without these characters as well
|
||||
assertEquals("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$", classSignature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Descriptor_IntT(){
|
||||
public void descriptor_IntT(){
|
||||
var classSignature = funNGenerator.getSpecializedDescriptor(Arrays.asList(integerType), genericT);
|
||||
//does not have to contain L and ; because TypeToDescriptor returns the descriptor without these characters as well
|
||||
assertEquals("Fun1$$Ljava$lang$Integer$_$LT$_$", classSignature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void GetArguments_Empty(){
|
||||
public void getArguments_Empty(){
|
||||
var arguments = funNGenerator.getArguments(Arrays.asList());
|
||||
assertTrue(arguments.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void GetArguments_Int(){
|
||||
public void getArguments_Int(){
|
||||
var arguments = funNGenerator.getArguments(Arrays.asList(integerType));
|
||||
assertTrue(arguments.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void GetArguments_IntT(){
|
||||
public void getArguments_IntT(){
|
||||
var arguments = funNGenerator.getArguments(Arrays.asList(integerType, genericT));
|
||||
assertTrue(arguments.size() == 1);
|
||||
assertTrue(arguments.contains(integerType));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void GetArguments_IntTInt(){
|
||||
public void getArguments_IntTInt(){
|
||||
var arguments = funNGenerator.getArguments(Arrays.asList(integerType, genericT, integerType));
|
||||
assertTrue(arguments.size() == 2);
|
||||
assertTrue(arguments.contains(integerType));
|
||||
assertTrue(arguments.contains(genericT));
|
||||
}
|
||||
|
||||
//ToDo Etienne: get return Type Test
|
||||
@Test
|
||||
public void getReturnType_Empty(){
|
||||
var returnType = funNGenerator.getReturnType(Arrays.asList());
|
||||
assertNull(returnType);
|
||||
}
|
||||
|
||||
//ToDo Etienne: Super Bytecode Test
|
||||
@Test
|
||||
public void getReturnType_Int(){
|
||||
var returnType = funNGenerator.getReturnType(Arrays.asList(integerType));
|
||||
assertEquals(integerType, returnType);
|
||||
}
|
||||
|
||||
//ToDo Etienne: Specialized Bytecode Test
|
||||
@Test
|
||||
public void getReturnType_IntT(){
|
||||
var returnType = funNGenerator.getReturnType(Arrays.asList(integerType, genericT));
|
||||
assertEquals(genericT, returnType);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void superBytecode_0(){
|
||||
var superBytecode = funNGenerator.generateSuperBytecode(0);
|
||||
assertArrayEquals(superBytecodeReference_0(), superBytecode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void superBytecode_1(){
|
||||
var superBytecode = funNGenerator.generateSuperBytecode(1);
|
||||
assertArrayEquals(superBytecodeReference_1(), superBytecode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void superBytecode_2(){
|
||||
var superBytecode = funNGenerator.generateSuperBytecode(2);
|
||||
assertArrayEquals(superBytecodeReference_2(), superBytecode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specializedBytecode_VoidInt(){
|
||||
var specializedBytecode = funNGenerator.generateSpecializedBytecode(Arrays.asList(), integerType);
|
||||
assertArrayEquals(specializedBytecodeReference_VoidInt(), specializedBytecode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specializedBytecode_IntInt(){
|
||||
var specializedBytecode = funNGenerator.generateSpecializedBytecode(Arrays.asList(integerType), integerType);
|
||||
assertArrayEquals(specializedBytecodeReference_IntInt(), specializedBytecode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specializedBytecode_TIntInt(){
|
||||
var specializedBytecode = funNGenerator.generateSpecializedBytecode(Arrays.asList(genericT, integerType), integerType);
|
||||
assertArrayEquals(specializedBytecodeReference_TIntInt(), specializedBytecode);
|
||||
}
|
||||
|
||||
//super bytecode reference methods
|
||||
private static byte[] superBytecodeReference_0() {
|
||||
var classWriter = new ClassWriter(0);
|
||||
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun0$$", "<R:Ljava/lang/Object;>Ljava/lang/Object;", "java/lang/Object", null);
|
||||
var methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "()Ljava/lang/Object;", "()TR;", null);
|
||||
methodVisitor.visitEnd();
|
||||
classWriter.visitEnd();
|
||||
return classWriter.toByteArray();
|
||||
}
|
||||
|
||||
private static byte[] superBytecodeReference_1() {
|
||||
var classWriter = new ClassWriter(0);
|
||||
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun1$$", "<T1:Ljava/lang/Object;R:Ljava/lang/Object;>Ljava/lang/Object;", "java/lang/Object", null);
|
||||
var methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "(Ljava/lang/Object;)Ljava/lang/Object;", "(TT1;)TR;", null);
|
||||
methodVisitor.visitEnd();
|
||||
classWriter.visitEnd();
|
||||
return classWriter.toByteArray();
|
||||
}
|
||||
|
||||
private static byte[] superBytecodeReference_2() {
|
||||
ClassWriter classWriter = new ClassWriter(0);
|
||||
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun2$$", "<T1:Ljava/lang/Object;T2:Ljava/lang/Object;R:Ljava/lang/Object;>Ljava/lang/Object;", "java/lang/Object", null);
|
||||
var methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", "(TT1;TT2;)TR;", null);
|
||||
methodVisitor.visitEnd();
|
||||
classWriter.visitEnd();
|
||||
return classWriter.toByteArray();
|
||||
}
|
||||
|
||||
//specialized bytecode reference methods
|
||||
private static byte[] specializedBytecodeReference_VoidInt() {
|
||||
ClassWriter classWriter = new ClassWriter(0);
|
||||
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun0$$Ljava$lang$Integer$_$", "Ljava/lang/Object;LFun0$$<Ljava/lang/Integer;>;", "java/lang/Object", new String[]{"Fun0$$"});
|
||||
classWriter.visitEnd();
|
||||
return classWriter.toByteArray();
|
||||
}
|
||||
|
||||
private static byte[] specializedBytecodeReference_IntInt() {
|
||||
ClassWriter classWriter = new ClassWriter(0);
|
||||
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$", "Ljava/lang/Object;LFun1$$<Ljava/lang/Integer;Ljava/lang/Integer;>;", "java/lang/Object", new String[]{"Fun1$$"});
|
||||
classWriter.visitEnd();
|
||||
return classWriter.toByteArray();
|
||||
}
|
||||
|
||||
private static byte[] specializedBytecodeReference_TIntInt() {
|
||||
ClassWriter classWriter = new ClassWriter(0);
|
||||
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun2$$LT$_$Ljava$lang$Integer$_$Ljava$lang$Integer$_$", "<T:Ljava/lang/Object;>Ljava/lang/Object;LFun2$$<TT;Ljava/lang/Integer;Ljava/lang/Integer;>;", "java/lang/Object", new String[]{"Fun2$$"});
|
||||
classWriter.visitEnd();
|
||||
return classWriter.toByteArray();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user