From d77f2176f2f73814ee7c68a54ae05be6f5bae27a Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Wed, 10 Jul 2019 15:26:16 +0200 Subject: [PATCH] Generics generator step 1 --- .../bytecode/constraint/TPHConstraint.java | 4 + .../genericsGenerator/CyclesFinder.java | 76 +++++++++++++++++++ .../genericsGenerator/GenericsGenerator.java | 50 ++++++++++++ .../GenericsGeneratorUtility.java | 76 +++++++++++++++++++ .../bytecode/genericsGenerator/LongCycle.java | 38 ++++++++++ .../genericsGenerator/SimpleCycle.java | 69 +++++++++++++++++ .../bytecode/signature/Signature.java | 2 +- .../simplifyRes/GenericsGeneratorResult.java | 55 ++++++++++++++ .../simplifyRes/SimplifyResultFinder.java | 3 +- src/test/java/bytecode/SimpleCycleTest.java | 38 ++++++++++ .../bytecode/javFiles/SimpleCycle.jav | 8 ++ 11 files changed, 417 insertions(+), 2 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/CyclesFinder.java create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGenerator.java create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGeneratorUtility.java create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/LongCycle.java create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/SimpleCycle.java create mode 100644 src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/GenericsGeneratorResult.java create mode 100644 src/test/java/bytecode/SimpleCycleTest.java create mode 100644 src/test/resources/bytecode/javFiles/SimpleCycle.jav diff --git a/src/main/java/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java b/src/main/java/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java index e0f3b4c08..6bd8bcab0 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java @@ -44,6 +44,10 @@ public class TPHConstraint { return left.equals(tph)||right.equals(tph); } + public boolean equalConstraint(TPHConstraint constraint) { + return rel == constraint.getRel() && left.equals(constraint.getLeft()) && right.equals(constraint.getRight()); + } + @Override public String toString() { if(rel == Relation.EXTENDS) { diff --git a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/CyclesFinder.java b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/CyclesFinder.java new file mode 100644 index 000000000..e54ba0afe --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/CyclesFinder.java @@ -0,0 +1,76 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGenerator; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; + +/** + * @author fayez + * + */ +public class CyclesFinder { + private final List allCons; + + public CyclesFinder(List allCons) { + this.allCons = allCons; + } + + public List findSimpleCycles() { + List simpleCycles = new ArrayList<>(); + allCons.forEach(c->{ + String left = c.getLeft(); + String right = c.getRight(); + if (c.getRel() == Relation.EXTENDS && !containsInCycle(c,simpleCycles)) { + Optional revCon = GenericsGeneratorUtility.getReverseConstraint(allCons, left, right); + if(revCon.isPresent()) { + TPHConstraint reverseConstraint = revCon.get(); + SimpleCycle simpleCycle = new SimpleCycle(c, reverseConstraint); + simpleCycles.add(simpleCycle); + } + } + }); + + return simpleCycles; + } + + private boolean containsInCycle(TPHConstraint c, List simpleCycles) { + return simpleCycles.stream().filter(sc->{ + return sc.contains(c); + }).count() > 0; + } + + public List findLongCycles() { + List vistedConstraints = new ArrayList<>(allCons.size()); + + for(TPHConstraint constraint : allCons) { + vistedConstraints.add(constraint); + checkConstraint(constraint,vistedConstraints); + } + return null; + } + + private void checkConstraint(TPHConstraint constraint, List vistedConstraints) { + List tphsInRelation = new LinkedList<>(); + tphsInRelation.add(constraint.getLeft()); + tphsInRelation.add(constraint.getRight()); + for(TPHConstraint con : allCons) { + if(!vistedConstraints.contains(con)) { + String left = con.getLeft(); + String right = con.getRight(); + int lastIndex = tphsInRelation.size()-1; + if(left.equals(tphsInRelation.get(lastIndex))) { + tphsInRelation.add(right); + } + } + } + } + + +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGenerator.java b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGenerator.java new file mode 100644 index 000000000..e6921e925 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGenerator.java @@ -0,0 +1,50 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGenerator; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import de.dhbwstuttgart.bytecode.TPHExtractor; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.simplifyRes.GenericsGeneratorResult; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; +import de.dhbwstuttgart.bytecode.utilities.MethodUtility; +import de.dhbwstuttgart.syntaxtree.Method; + +/** + * @author fayez + * + */ +public class GenericsGenerator { + + public static List generateConstraintsForMethod(Method method, TPHExtractor tphExtractor, + List tphsClass) { + List allCons = tphExtractor.allCons; + String methodID = MethodUtility.createID(tphExtractor.getResolver(), method); + List methodTPHS = GenericsGeneratorUtility.getMethodTPHS(methodID ,tphExtractor.ListOfMethodsAndTph); + + List consToRemove = new ArrayList<>(); + + CyclesFinder cyclesFinder = new CyclesFinder(allCons); + /* find all simple cycles if they are exist */ + List simpleCycles = cyclesFinder.findSimpleCycles(); + + if(!simpleCycles.isEmpty()) { + GenericsGeneratorUtility.modifyRelation(simpleCycles); + GenericsGeneratorUtility.removeAllReverseConstraints(allCons,simpleCycles); + GenericsGeneratorUtility.substituteTPH(allCons, simpleCycles); + } + + /* find all long cycles */ + List longCycles = cyclesFinder.findLongCycles(); + + return null; + } + +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGeneratorUtility.java b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGeneratorUtility.java new file mode 100644 index 000000000..f8bfadf22 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGeneratorUtility.java @@ -0,0 +1,76 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGenerator; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; + +/** + * @author fayez + * + */ +public class GenericsGeneratorUtility { + /** + * Returns a list of type placeholders names of a specified method + * + * @param methodID The id of the method ReturnTypeMethodName(ParameterTypes) + * @param listOfMethodsAndTph List of all methods + * @return a list of type placehoders names + */ + public static List getMethodTPHS(String methodID, ArrayList listOfMethodsAndTph) { + return listOfMethodsAndTph.stream().filter(mt->mt.getId().equals(methodID)).findAny().get().getTphs(); + } + + /** + * Returns a reverse constraint of a specified constraint which is given by its left and right + * side + * + * @param allCons List of all constraints + * @param left The left side of the given constraint + * @param right The right side of the given constraint + * @return An Optional object which contains the reverse constraint if it is exist + */ + public static Optional getReverseConstraint(List allCons, String left, String right) { + return allCons.stream().filter(c->{ + return c.getRight().equals(left) && c.getLeft().equals(right); + }).findAny(); + } + + /** + * Substitutes the old name by the new name in all constraints + * + * @param allCons List of all constraints + * @param oldName The name to be replaced + * @param newName The new name + */ + public static void substituteTPH(List allCons, String oldName, String newName) { + allCons.forEach(c->{ + if(c.getLeft().equals(oldName)) + c.setLeft(newName); + if(c.getRight().equals(oldName)) + c.setRight(newName); + }); + + } + + public static void modifyRelation(List simpleCycles) { + simpleCycles.forEach(sc->{ + sc.getConstraint().setRel(Relation.EQUAL); + sc.getReverseConstraint().setRel(Relation.EQUAL); + }); + } + + public static void removeAllReverseConstraints(List allCons, List simpleCycles) { + simpleCycles.forEach(sc->allCons.remove(sc.getReverseConstraint())); + } + + public static void substituteTPH(List allCons, List simpleCycles) { + simpleCycles.forEach(sc->substituteTPH(allCons, sc.getConstraint().getLeft(), sc.getConstraint().getRight())); + } +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/LongCycle.java b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/LongCycle.java new file mode 100644 index 000000000..0d2c4debe --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/LongCycle.java @@ -0,0 +1,38 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGenerator; + +import java.util.List; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; + +/** + * @author fayez + * + */ +public class LongCycle { + private final List constraints; + + /** + * @param constraints + */ + public LongCycle(List constraints) { + this.constraints = constraints; + } + + /** + * @return the constraints + */ + public List getConstraints() { + return constraints; + } + + public boolean containConstraint(TPHConstraint constraint) { + for(TPHConstraint c : constraints) { + if(c.equalConstraint(constraint)) + return true; + } + return false; + } +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/SimpleCycle.java b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/SimpleCycle.java new file mode 100644 index 000000000..6218e4a08 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/SimpleCycle.java @@ -0,0 +1,69 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGenerator; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; + +/** + * @author fayez + * + */ +public class SimpleCycle { + private TPHConstraint constraint; + private TPHConstraint reverseConstraint; + + /** + * @param constraint + * @param reverseConstraint + */ + public SimpleCycle(TPHConstraint constraint, TPHConstraint reverseConstraint) { + this.constraint = constraint; + this.reverseConstraint = reverseConstraint; + } + + /** + * @return the constraint + */ + public TPHConstraint getConstraint() { + return constraint; + } + + /** + * @param constraint the constraint to set + */ + public void setConstraint(TPHConstraint constraint) { + this.constraint = constraint; + } + + /** + * @return the reverseConstraint + */ + public TPHConstraint getReverseConstraint() { + return reverseConstraint; + } + + /** + * @param reverseConstraint the reverseConstraint to set + */ + public void setReverseConstraint(TPHConstraint reverseConstraint) { + this.reverseConstraint = reverseConstraint; + } + + public boolean contains(TPHConstraint c) { + if (constraint.getLeft().equals(c.getLeft()) && constraint.getRight().equals(c.getRight()) + && constraint.getRel().equals(c.getRel())) + return true; + if (reverseConstraint.getLeft().equals(c.getLeft()) && reverseConstraint.getRight().equals(c.getRight()) + && reverseConstraint.getRel().equals(c.getRel())) + return true; + + return false; + } + + @Override + public String toString() { + return constraint.toString() + " -> " + reverseConstraint.toString(); + } + +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java index e7f870c5e..f9ab3d47e 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -318,7 +318,7 @@ public class Signature { break; case "TPH": RefTypeOrTPHOrWildcardOrGeneric r = resultSet.resolveType(t).resolvedType; - // der Fall wenn die Type eine Interface ist, muss betrachtet werden + // der Fall wenn der Typ eine Interface ist, muss betrachtet werden // Deswegen muss in ResutSet noch enthalten werden, ob die Type eine // Interface oder eine Klasse ist. diff --git a/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/GenericsGeneratorResult.java b/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/GenericsGeneratorResult.java new file mode 100644 index 000000000..7b7f8b2d5 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/GenericsGeneratorResult.java @@ -0,0 +1,55 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.simplifyRes; + +import java.util.Set; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; + +/** + * @author fayez + * + */ +public class GenericsGeneratorResult { + private TPHConstraint constraint; + /** + * contains the names of all type placeholders which are equals to the left side of + * the constraint {@link #constraint}. + */ + private Set equalsTPHs; + /** + * @param constraint + * @param equalsTPHs + */ + public GenericsGeneratorResult(TPHConstraint constraint, Set equalsTPHs) { + this.constraint = constraint; + this.equalsTPHs = equalsTPHs; + } + + /** + * @return the constraint + */ + public TPHConstraint getConstraint() { + return constraint; + } + /** + * @param constraint the constraint to set + */ + public void setConstraint(TPHConstraint constraint) { + this.constraint = constraint; + } + /** + * @return the equalsTPHs + */ + public Set getEqualsTPHs() { + return equalsTPHs; + } + /** + * @param equalsTPHs the equalsTPHs to set + */ + public void setEqualsTPHs(Set equalsTPHs) { + this.equalsTPHs = equalsTPHs; + } + +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/SimplifyResultFinder.java b/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/SimplifyResultFinder.java index bcc023d99..751947b7c 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/SimplifyResultFinder.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/SimplifyResultFinder.java @@ -17,6 +17,7 @@ import de.dhbwstuttgart.bytecode.BytecodeGen; import de.dhbwstuttgart.bytecode.TPHExtractor; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; +import de.dhbwstuttgart.bytecode.genericsGenerator.GenericsGenerator; import de.dhbwstuttgart.bytecode.signature.Signature; import de.dhbwstuttgart.bytecode.signature.TypeToSignature; import de.dhbwstuttgart.bytecode.signature.TypeToString; @@ -274,7 +275,7 @@ public class SimplifyResultFinder implements ASTVisitor { // zwite operand muss weggelassen werden if (hasGenInParameterList || resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString()) .equals("TPH")) { - + List ggR = GenericsGenerator.generateConstraintsForMethod(method, tphExtractor, tphsClass); Map> constraints = Simplify.simplifyConstraints(method, tphExtractor, tphsClass); diff --git a/src/test/java/bytecode/SimpleCycleTest.java b/src/test/java/bytecode/SimpleCycleTest.java new file mode 100644 index 000000000..19e28bc23 --- /dev/null +++ b/src/test/java/bytecode/SimpleCycleTest.java @@ -0,0 +1,38 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class SimpleCycleTest { + + 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 generateGen() throws Exception { + path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/SimpleCycle.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("SimpleCycle"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + +} diff --git a/src/test/resources/bytecode/javFiles/SimpleCycle.jav b/src/test/resources/bytecode/javFiles/SimpleCycle.jav new file mode 100644 index 000000000..16243d200 --- /dev/null +++ b/src/test/resources/bytecode/javFiles/SimpleCycle.jav @@ -0,0 +1,8 @@ +public class SimpleCycle { + + m(a,b){ + a = b; + b = a; + } + +} \ No newline at end of file