diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java index fec01c10..b013f495 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -29,6 +29,7 @@ import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; import de.dhbwstuttgart.bytecode.utilities.NormalConstructor; import de.dhbwstuttgart.bytecode.utilities.NormalMethod; import de.dhbwstuttgart.bytecode.utilities.Simplify; +import de.dhbwstuttgart.bytecode.utilities.SimplifyResult; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.statement.Literal; @@ -81,6 +82,17 @@ public class BytecodeGen implements ASTVisitor { ArrayList methodNameAndParamsT = new ArrayList<>(); + private HashMap simplifyResults = new HashMap<>(); + private List> simplifyResultsList = new ArrayList<>(); + + public List> getSimplifyResultsList() { + return simplifyResultsList; + } + + public void setSimplifyResultsList(List> simplifyResultsList) { + this.simplifyResultsList = simplifyResultsList; + } + public BytecodeGen(HashMap classFiles, List listOfResultSets,SourceFile sf ,String path) { this.classFiles = classFiles; this.listOfResultSets = listOfResultSets; @@ -94,6 +106,7 @@ public class BytecodeGen implements ASTVisitor { System.out.println("in Class: " + cl.getClassName().toString()); BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets, sf, path); cl.accept(classGen); + simplifyResultsList.add(classGen.getSimplifyResults()); classGen.writeClass(cl.getClassName().toString()); } } @@ -173,6 +186,10 @@ public class BytecodeGen implements ASTVisitor { right = null; } } + + SimplifyResult sRes = new SimplifyResult(consClass, tphsClass, new HashMap<>()); + simplifyResults.put(className, sRes); + Signature signature = new Signature(classOrInterface, genericsAndBounds,commonPairs,tphsClass, consClass); sig = signature.toString(); System.out.println("Signature: => " + sig); @@ -370,6 +387,14 @@ public class BytecodeGen implements ASTVisitor { // ArrayList pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons); Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); sig = signature.toString(); + if(simplifyResults.containsKey(className)) { + simplifyResults.get(className).getMethodsConstraints().put(methParamTypes, constraints); + } else { + SimplifyResult sRes = new SimplifyResult(new ArrayList<>(), new ArrayList<>(), new HashMap<>()); + sRes.getMethodsConstraints().put(methParamTypes, constraints); + simplifyResults.put(className, sRes); + } + } System.out.println(method.getName()+" ==> "+sig); NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen); @@ -386,6 +411,10 @@ public class BytecodeGen implements ASTVisitor { mv.visitEnd(); } + public HashMap getSimplifyResults() { + return simplifyResults; + } + @Override public void visit(ParameterList formalParameters) { paramsAndLocals = new HashMap<>(); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java index 07471ae1..d4d6b430 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.bytecode.descriptor; +import java.util.HashMap; import java.util.Iterator; import org.objectweb.asm.Type; @@ -44,17 +45,28 @@ public class DescriptorToString implements DescriptorVisitor{ if(method.hasGen()) { String fpDesc = fp.getType().acceptTV(new TypeToDescriptor()); if(method.getGenericsAndBoundsMethod().containsKey(fpDesc)) { - desc += "L"+method.getGenericsAndBoundsMethod().get(fpDesc)+ ";"; + String bound = getBound(fpDesc, method.getGenericsAndBoundsMethod()); + desc += "L"+bound+ ";"; }else if(method.getGenericsAndBounds().containsKey(fpDesc)){ - desc += "L"+method.getGenericsAndBounds().get(fpDesc)+ ";"; + String bound = getBound(fpDesc, method.getGenericsAndBounds()); + desc += "L"+bound+ ";"; }else { // desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()); - if(resType.subSequence(0, 4).equals("TPH ")) { + if(resType.contains("TPH ")/*resType.subSequence(0, 4).equals("TPH ")*/) { // Bound ist immer Object desc += "L"+Type.getInternalName(Object.class)+ ";"; } else { - desc += "L"+resType+ ";"; + // TODO:: + if(method.getGenericsAndBounds().containsKey(resType)) { + String bound = getBound(resType, method.getGenericsAndBounds()); + desc += "L"+bound+ ";"; + }else if(method.getGenericsAndBoundsMethod().containsKey(resType)) { + String bound = getBound(resType, method.getGenericsAndBoundsMethod()); + desc += "L"+bound+ ";"; + } else { + desc += "L"+resType+ ";"; + } } } } @@ -78,11 +90,21 @@ public class DescriptorToString implements DescriptorVisitor{ desc += ")L"+method.getGenericsAndBounds().get(ret)+ ";"; }else { String resType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); - if(resType.subSequence(0, 4).equals("TPH ")) { + if(resType.contains("TPH ")/*resType.subSequence(0, 4).equals("TPH ")*/) { // desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";"; desc += ")" + "L"+Type.getInternalName(Object.class)+ ";"; } else { - desc += ")" + "L"+resType+ ";"; + // TODO:: + if(method.getGenericsAndBounds().containsKey(resType)) { + String bound = getBound(resType, method.getGenericsAndBounds()); + desc += ")L"+bound+ ";"; + }else if(method.getGenericsAndBoundsMethod().containsKey(resType)) { + String bound = getBound(resType, method.getGenericsAndBoundsMethod()); + desc += ")L"+bound+ ";"; + } else { + desc += ")L"+resType+ ";"; + } +// desc += ")" + "L"+resType+ ";"; } } }else { @@ -93,6 +115,15 @@ public class DescriptorToString implements DescriptorVisitor{ return desc; } + private String getBound(String fpDesc, HashMap genericsAndBounds) { + String start = genericsAndBounds.get(fpDesc); + while(genericsAndBounds.containsKey(start)) { + start = genericsAndBounds.get(start); + } + + return start; + } + @Override public String visit(NormalConstructor constructor) { String desc = "("; diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java index ce0b4462..8493e9bb 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -290,7 +290,8 @@ public class Signature { break; case "GRT": GenericRefType g = (GenericRefType) t; - sv.visitTypeVariable(g.acceptTV(new TypeToSignature()).substring(1)); +// sv.visitTypeVariable(g.acceptTV(new TypeToSignature()).substring(1)); + sv.visitTypeVariable(g.acceptTV(new TypeToSignature())); break; case "TPH": RefTypeOrTPHOrWildcardOrGeneric r = resultSet.resolveType(t).resolvedType; @@ -307,7 +308,16 @@ public class Signature { System.out.println(" Signature FUN$$: "+r); sv.visitInterface().visitClassType(sig2.substring(1, sig2.length())); } else { - sv.visitClassType(sig2.substring(1, sig2.length())); + // Kann zwischen GenericRefType und RefType nicht unterscheiden + // Deswegen wird immer geprüft, ob der Name in Generic Maps liegt + String n = sig2.substring(1, sig2.length()-1); + if(genericsAndBoundsMethod.containsKey(n) || genericsAndBounds.containsKey(n)) { + sv.visitTypeVariable(n); + } else { + sv.visitClassType(n); + sv.visitEnd(); + } +// sv.visitClassType(n); } } else { @@ -456,10 +466,15 @@ public class Signature { String boundDesc = b.acceptTV(new TypeToDescriptor()); // System.out.println("GetBounds: " + boundDesc); // Ensure that <...> extends java.lang.Object OR ... - sw.visitClassBound().visitClassType(boundDesc); + if(b instanceof GenericRefType) { + sw.visitClassBound().visitTypeVariable(boundDesc); + } else { + sw.visitClassBound().visitClassType(boundDesc); + sw.visitClassBound().visitEnd(); + } genAndBounds.put(g.getName(), boundDesc); } - sw.visitClassBound().visitEnd(); +// sw.visitClassBound().visitEnd(); } public String toString() { diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/SimplifyResult.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/SimplifyResult.java new file mode 100644 index 00000000..96feb4dc --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/SimplifyResult.java @@ -0,0 +1,42 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +/** + * @author fayez + * + */ +public class SimplifyResult { + private final ArrayList classConstraints; + private final ArrayList tphsClass; + private final HashMap>> methodsConstraints; + + public SimplifyResult(ArrayList classConstraints, ArrayList tphsClass, + HashMap>> methodsConstraints) { + super(); + this.classConstraints = classConstraints; + this.tphsClass = tphsClass; + this.methodsConstraints = methodsConstraints; + } + + public ArrayList getClassConstraints() { + return classConstraints; + } + + public HashMap>> getMethodsConstraints() { + return methodsConstraints; + } + + public ArrayList getTphsClass() { + return tphsClass; + } + +} diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java index 6bf4b50b..e52cb826 100644 --- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -3,6 +3,7 @@ package de.dhbwstuttgart.core; import de.dhbwstuttgart.bytecode.BytecodeGen; +import de.dhbwstuttgart.bytecode.utilities.SimplifyResult; import de.dhbwstuttgart.environment.CompilationEnvironment; import de.dhbwstuttgart.parser.JavaTXParser; import de.dhbwstuttgart.parser.NullToken; @@ -58,7 +59,9 @@ public class JavaTXCompiler { Boolean resultmodel = true; public final Map sourceFiles = new HashMap<>(); Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+"src/test/java/logFiles" geschrieben werden soll? - + + private List>> simplifyResultsSF = new ArrayList<>(); + public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException { this(Arrays.asList(sourceFile)); } @@ -650,6 +653,7 @@ public class JavaTXCompiler { BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult,sf,path); // BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult.get(0)); bytecodeGen.visit(sf); + this.simplifyResultsSF.add(bytecodeGen.getSimplifyResultsList()); this.writeClassFile(bytecodeGen.getClassFiles(), path); } } @@ -666,4 +670,8 @@ public class JavaTXCompiler { System.out.println(name+".class file generated"); } } + + public List>> getSimplifyResults() { + return simplifyResultsSF; + } } diff --git a/src/test/java/bytecode/TypedIDTest.java b/src/test/java/bytecode/TypedIDTest.java new file mode 100644 index 00000000..29f623fc --- /dev/null +++ b/src/test/java/bytecode/TypedIDTest.java @@ -0,0 +1,38 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class TypedIDTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + + @Test + public void test() throws Exception { + path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/TypedID.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("TypedID"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/src/test/resources/bytecode/javFiles/TypedID.jav b/src/test/resources/bytecode/javFiles/TypedID.jav new file mode 100644 index 00000000..8ff8d4b6 --- /dev/null +++ b/src/test/resources/bytecode/javFiles/TypedID.jav @@ -0,0 +1,6 @@ +public class TypedID { + + id(L b){ + return b; + } +} \ No newline at end of file