diff --git a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java index d59f4c01..5718e72d 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java @@ -135,8 +135,7 @@ public class GeneratedGenericsFinder implements ASTVisitor { classOrInterface.accept(tphExtractor); //PL 2020-10-16: Ab hier GGenerics implementieren durch Ali //Rueckgabe an generatedGenericsForSF -// fogg = new FamilyOfGeneratedGenerics(tphExtractor); -// fogg.getClassConstraints(); + fogg = new FamilyOfGeneratedGenerics(tphExtractor); tphsClass = tphExtractor.tphsClass; simplifiedConstraints = GenericsGenerator.simplifyConstraints(tphExtractor, tphsClass); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/FamilyOfGeneratedGenerics.java b/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/FamilyOfGeneratedGenerics.java index 640111d4..4f7d25ed 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/FamilyOfGeneratedGenerics.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/FamilyOfGeneratedGenerics.java @@ -1,17 +1,28 @@ package de.dhbwstuttgart.bytecode.insertGenerics; +import de.dhbwstuttgart.bytecode.TPHExtractor; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class FamilyOfGeneratedGenerics { + public List allConstraints = new ArrayList<>(); + public HashMap> posOfTPHs = new HashMap<>(); + public List classConstraints = new ArrayList<>(); - public static List getClassConstraints(List cs, HashMap posOfTphs) { //Inputparameter List constraintsSet weg + public FamilyOfGeneratedGenerics(TPHExtractor tphExtractor) { + this.allConstraints = tphExtractor.allCons; + this.posOfTPHs = positionConverter(tphExtractor.allTPHS, tphExtractor.ListOfMethodsAndTph); + this.classConstraints = getClassConstraints(allConstraints,posOfTPHs); + } + + public static List getClassConstraints(List cs, HashMap> posOfTphs) { //Inputparameter List constraintsSet weg List cs_cl = new ArrayList<>(); - List classConstraints1 = typeOfANodeOfAField(cs, cs_cl, posOfTphs); + List classConstraints1 = typeOfANodeOfAField(cs, posOfTphs); for (ClassConstraint cons: classConstraints1) { if (!checkForDuplicates(cons, cs_cl)) { cs_cl.add(cons); @@ -32,7 +43,7 @@ public class FamilyOfGeneratedGenerics { return cs_cl; } - public static List getMethodConstraints(List cs, HashMap posOfTphs) { + public static List getMethodConstraints(List cs, HashMap> posOfTphs) { //TODO: Regeln List cs_m = new ArrayList<>(); List methodConstraints1 = typeOfTheMethodInClSigma(cs, cs_m, posOfTphs); @@ -49,12 +60,13 @@ public class FamilyOfGeneratedGenerics { * Def. FGG: erste Zeile von cs_cl * {T < .T' | T is a type variable in a type of a node of a field} */ - public static List typeOfANodeOfAField(List allConstraints, List cs_cl, HashMap posOfTphs) { + public static List typeOfANodeOfAField(List allConstraints, HashMap> posOfTphs) { + //RuntimeException re = new RuntimeException("enthält EQUALS-Relation"); List tempCC= new ArrayList<>(); for(TPHConstraint allCons: allConstraints){ if(posOfTphs.containsKey(allCons.getLeft()) && allCons.getRight()!=null && allCons.getRel()==Relation.EXTENDS) { for(String tph: posOfTphs.keySet()) { - if(tph == allCons.getLeft() && posOfTphs.get(tph) == PositionFinder.Position.FIELD) { + if(tph == allCons.getLeft() && posOfTphs.get(tph).fst == PositionFinder.Position.FIELD) { ClassConstraint consToAdd = new ClassConstraint(tph, allCons.getRight(), allCons.getRel()); if (!checkForDuplicates(consToAdd, tempCC)) { tempCC.add(consToAdd); @@ -62,6 +74,9 @@ public class FamilyOfGeneratedGenerics { } } } + /*else if (allCons.getRel() != Relation.EXTENDS) { + throw re; + }*/ } return tempCC; } @@ -92,17 +107,16 @@ public class FamilyOfGeneratedGenerics { * {T <. Object | ((T is a type variable in a type of a node of a field * or (\exists T~: (T~ <. T) \in cs_cl)) and (\existsnot T': T <. T') \in cs)} */ - public static List hasNoSupertypeForClassTypes(List allConstraints, List cs_cl, HashMap posOfTphs) { + public static List hasNoSupertypeForClassTypes(List allConstraints, List cs_cl, HashMap> posOfTphs) { List tempCC= new ArrayList<>(); for(TPHConstraint allCons: allConstraints) { for(ClassConstraint cCons: cs_cl) { for(String tph: posOfTphs.keySet()) { - if( (posOfTphs.get(tph) == PositionFinder.Position.FIELD) || - (posOfTphs.containsKey(cCons.getRight()) && cCons.getLeft() != null) && - (allCons.getLeft() == tph && allCons.getRight() == null) && - allCons.getRel()==Relation.EXTENDS && cCons.getRel()==Relation.EXTENDS && - cCons.getRight() == tph && allCons.getLeft() == tph) { - ClassConstraint consToAdd = new ClassConstraint(cCons.getRight(), "Object", Relation.EXTENDS); + boolean tvInField = posOfTphs.get(tph).fst == PositionFinder.Position.FIELD; + boolean hasSmallerTVInClCons = (posOfTphs.containsKey(cCons.getRight()) && cCons.getRight() == tph && cCons.getLeft() != null); + if( ((tvInField || hasSmallerTVInClCons) && cCons.getRel()==Relation.EXTENDS) && + checkUpperBound(allConstraints, tph) && allCons.getRel()==Relation.EXTENDS) { + ClassConstraint consToAdd = new ClassConstraint(tph, "Object", Relation.EXTENDS); if (!checkForDuplicates(consToAdd, tempCC)){ tempCC.add(consToAdd); } @@ -112,22 +126,28 @@ public class FamilyOfGeneratedGenerics { } return tempCC; } -/* + public static boolean checkUpperBound(List cs, String tph) { + for(int i=0; i typeOfTheMethodInClSigma(List allConstraints, List cs_m, HashMap posOfTphs) { // cl_\sigma?? + public static List typeOfTheMethodInClSigma(List allConstraints, List cs_m, HashMap> posOfTphs) { // cl_\sigma?? //TODO: List tempCC= new ArrayList<>(); for(TPHConstraint allCons: allConstraints){ if(posOfTphs.containsKey(allCons.getLeft()) && allCons.getRight()!=null && allCons.getRel()==Relation.EXTENDS) { for(String tph: posOfTphs.keySet()) { - if(tph == allCons.getLeft() && (posOfTphs.get(tph) == PositionFinder.Position.METHOD || posOfTphs.get(tph) == PositionFinder.Position.CONSTRUCTOR)) { + if(tph == allCons.getLeft() && (posOfTphs.get(tph).fst == PositionFinder.Position.METHOD || posOfTphs.get(tph).fst == PositionFinder.Position.CONSTRUCTOR)) { MethodConstraint consToAdd = new MethodConstraint(allCons.getLeft(), allCons.getRight(), allCons.getRel()); if (!checkForDuplicates(consToAdd, tempCC)) { tempCC.add(consToAdd); @@ -208,7 +228,6 @@ public class FamilyOfGeneratedGenerics { return buildTransitiveClosure(tcList); } } - //TODO: über aktualisierte Liste laufen wegen Updates -> Rekursion? } } } @@ -216,6 +235,27 @@ public class FamilyOfGeneratedGenerics { } + public static HashMap> positionConverter(HashMap allTphs, List listOfMethodsAndTphs) { + HashMap> convertedPositions = new HashMap<>(); + for(String tph: allTphs.keySet()) { + if(allTphs.get(tph)) { //if true, then tph is a method-TPH + for(MethodAndTPH methTph: listOfMethodsAndTphs) { + if (methTph.getTphs().contains(tph)) { + convertedPositions.put(tph, new PairTphMethod<>(PositionFinder.Position.METHOD, methTph.getId())); + } + } + } else { // else it is in the class-TPH + convertedPositions.put(tph, new PairTphMethod<>(PositionFinder.Position.FIELD, null)); + } + } + return convertedPositions; + } + +/* public PositionFinder.Position positionConverter(TPHExtractor tphExtractor) { + if(tphExtractor.allTPHS.keySet()) + }*/ + + diff --git a/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PairTphMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PairTphMethod.java new file mode 100644 index 00000000..75313ba9 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PairTphMethod.java @@ -0,0 +1,43 @@ +package de.dhbwstuttgart.bytecode.insertGenerics; + +import java.util.Objects; + +/** A generic class for pairs. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ + + +public class PairTphMethod { + public final A fst; + public final B snd; + + public PairTphMethod(A fst, B snd) { + this.fst = fst; + this.snd = snd; + } + + public String toString() { + return "PairTphMethod[" + fst + "," + snd + "]"; + } + + public boolean equals(Object other) { + return + other instanceof PairTphMethod && + Objects.equals(fst, ((PairTphMethod)other).fst) && + Objects.equals(snd, ((PairTphMethod)other).snd); + } + + public int hashCode() { + if (fst == null) return (snd == null) ? 0 : snd.hashCode() + 1; + else if (snd == null) return fst.hashCode() + 2; + else return fst.hashCode() * 17 + snd.hashCode(); + } + + public static PairTphMethod of(A a, B b) { + return new PairTphMethod<>(a,b); + } +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PositionFinder.java b/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PositionFinder.java index c5638360..33ecfbc6 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PositionFinder.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PositionFinder.java @@ -7,7 +7,9 @@ import java.util.HashMap; import java.util.Set; public class PositionFinder{ - static HashMap posOfTphs = new HashMap(); + static HashMap> posOfTphs = new HashMap>(); + + static PairTphMethod whichMethod; // gibt an, in welcher Methode sich TPH befindet (Position.METHOD, id_of_method) public enum Position{ METHOD, @@ -15,7 +17,7 @@ public class PositionFinder{ FIELD } - public static HashMap getPositionOfTPH(SourceFile sf, Set tphs) { + public static HashMap> getPositionOfTPH(SourceFile sf, Set tphs) { new Walker().visit(sf); for (String tph: posOfTphs.keySet()) { @@ -24,16 +26,16 @@ public class PositionFinder{ return null; } - public static void putPositionInMethod(String tph) { - posOfTphs.put(tph, Position.METHOD); + public static void putPositionInMethod(String tph, String methodId) { + posOfTphs.put(tph, new PairTphMethod<>(Position.METHOD, methodId)); } public static void putPositionInField(String tph) { - posOfTphs.put(tph, Position.FIELD); + posOfTphs.put(tph, new PairTphMethod<>(Position.FIELD, null)); } - public static void putPositionInConstructor(String tph) { - posOfTphs.put(tph, Position.CONSTRUCTOR); + public static void putPositionInConstructor(String tph, String id) { + posOfTphs.put(tph, new PairTphMethod<>(Position.CONSTRUCTOR, id)); } @@ -46,9 +48,11 @@ public class PositionFinder{ public void visit(TypePlaceholder tph) { if (inMethod) { if (inConstructor) { - putPositionInConstructor(tph.getName()); +// System.out.println(tph); +// putPositionInConstructor(tph.getName(),); } - putPositionInMethod(tph.getName()); +// System.out.println(tph); +// putPositionInMethod(tph.getName(),); } else { putPositionInField(tph.getName()); } diff --git a/src/test/java/insertGenerics/FamilyOfGeneratedGenericsTest.java b/src/test/java/insertGenerics/FamilyOfGeneratedGenericsTest.java index d8c4fb8e..b6eb41ce 100644 --- a/src/test/java/insertGenerics/FamilyOfGeneratedGenericsTest.java +++ b/src/test/java/insertGenerics/FamilyOfGeneratedGenericsTest.java @@ -1,10 +1,8 @@ package insertGenerics; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; -import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; -import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; -import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; -import de.dhbwstuttgart.bytecode.insertGenerics.PositionFinder; +import de.dhbwstuttgart.bytecode.insertGenerics.*; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; import junit.framework.TestCase; import java.util.ArrayList; @@ -23,9 +21,10 @@ public class FamilyOfGeneratedGenericsTest extends TestCase { List inputConstraints = new ArrayList<>(); inputConstraints.add(new TPHConstraint("B", "A", TPHConstraint.Relation.EXTENDS)); - HashMap tphPositions = new HashMap<>(); - tphPositions.put("A", PositionFinder.Position.METHOD); - tphPositions.put("B", PositionFinder.Position.METHOD); + HashMap> tphPositions = new HashMap<>(); + PairTphMethod meth1 = new PairTphMethod(PositionFinder.Position.METHOD, "m1"); + tphPositions.put("A", meth1); + tphPositions.put("B", meth1); List classConstraints = FamilyOfGeneratedGenerics.getClassConstraints(inputConstraints, tphPositions); assertTrue(classConstraints.isEmpty()); @@ -53,16 +52,151 @@ public class FamilyOfGeneratedGenericsTest extends TestCase { List inputConstraints = new ArrayList<>(); inputConstraints.add(new TPHConstraint("A", "B", TPHConstraint.Relation.EXTENDS)); - HashMap tphPositions = new HashMap<>(); - tphPositions.put("A", PositionFinder.Position.FIELD); - tphPositions.put("B", PositionFinder.Position.METHOD); + HashMap> tphPositions = new HashMap<>(); + PairTphMethod posOfA = new PairTphMethod<>(PositionFinder.Position.FIELD, null); + tphPositions.put("A", posOfA); + PairTphMethod posOfB = new PairTphMethod<>(PositionFinder.Position.METHOD, "fReturn"); + tphPositions.put("B", posOfB); /* - ClassConstraints should be the same as the input constraint + ClassConstraints should not be the same as the input constraint */ List classConstraints = FamilyOfGeneratedGenerics.getClassConstraints(inputConstraints, tphPositions); - assertTrue(classConstraints.size() == 1); - assertTrue(classConstraints.get(0).getLeft().equals("A")); - assertTrue(classConstraints.get(0).getRight().equals("B")); + System.out.println(classConstraints); + assertTrue(classConstraints.size() == 2); + //assertTrue(classConstraints.get(0).getLeft().equals("A")); + //assertTrue(classConstraints.get(0).getRight().equals("B")); } + + public void testSecondLineOfClassConstraints() { + /* + class Example() { + A a; + B b = a; + C anyMethod() { + F f; + return f; + } + D otherMethod(E e) { + this.b = e; + e = this.a; + return e; + } + } + */ + + List inputConstraints = new ArrayList<>(); + inputConstraints.add(new TPHConstraint("A", "B", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("F", "C", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("E", "B", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("A", "E", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("E", "D", TPHConstraint.Relation.EXTENDS)); + + HashMap> tphPositions = new HashMap<>(); + PairTphMethod posOfA = new PairTphMethod<>(PositionFinder.Position.FIELD, null); + PairTphMethod posOfB = new PairTphMethod<>(PositionFinder.Position.FIELD, null); + PairTphMethod posOfC = new PairTphMethod<>(PositionFinder.Position.METHOD, "anyMethod"); + PairTphMethod posOfD = new PairTphMethod<>(PositionFinder.Position.METHOD, "otherMethod"); + PairTphMethod posOfE = new PairTphMethod<>(PositionFinder.Position.METHOD, "otherMethod"); + PairTphMethod posOfF = new PairTphMethod<>(PositionFinder.Position.METHOD, "anyMethod"); + + tphPositions.put("A", posOfA); + tphPositions.put("B", posOfB); + tphPositions.put("C", posOfC); + tphPositions.put("F", posOfF); + tphPositions.put("D", posOfD); + tphPositions.put("E", posOfE); + + List classConstraints = FamilyOfGeneratedGenerics.getClassConstraints(inputConstraints, tphPositions); + System.out.println(classConstraints); + assertFalse(classConstraints.isEmpty()); + assertTrue(classConstraints.size() == 6); + + } + + public void testTPHsAndGenerics() { + /* + class TPHsAndGenerics { + Fun1 id = x -> x; + C id2 (D x) { + return id.apply(x); + } + E m(F a, G b){ + var c = m2(a,b); + return a; + } + H m2(I a, J b){ + return b; + } + } + */ + + List inputConstraints = new ArrayList<>(); + inputConstraints.add(new TPHConstraint("A","B", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("B","C", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("D","A", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("F","E", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("F","I", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("G","J", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("J","H", TPHConstraint.Relation.EXTENDS)); + + HashMap> tphPositions = new HashMap<>(); + PairTphMethod posOfA = new PairTphMethod<>(PositionFinder.Position.FIELD, null); + PairTphMethod posOfB = new PairTphMethod<>(PositionFinder.Position.FIELD, null); + PairTphMethod posOfC = new PairTphMethod<>(PositionFinder.Position.METHOD, "id2"); + PairTphMethod posOfD = new PairTphMethod<>(PositionFinder.Position.METHOD, "id2"); + PairTphMethod posOfE = new PairTphMethod<>(PositionFinder.Position.METHOD, "m"); + PairTphMethod posOfF = new PairTphMethod<>(PositionFinder.Position.METHOD, "m"); + PairTphMethod posOfG = new PairTphMethod<>(PositionFinder.Position.METHOD, "m"); + PairTphMethod posOfH = new PairTphMethod<>(PositionFinder.Position.METHOD, "m2"); + PairTphMethod posOfI = new PairTphMethod<>(PositionFinder.Position.METHOD, "m2"); + PairTphMethod posOfJ = new PairTphMethod<>(PositionFinder.Position.METHOD, "m2"); + + tphPositions.put("A", posOfA); + tphPositions.put("B", posOfB); + tphPositions.put("C", posOfC); + tphPositions.put("D", posOfD); + tphPositions.put("E", posOfE); + tphPositions.put("F", posOfF); + tphPositions.put("G", posOfG); + tphPositions.put("H", posOfH); + tphPositions.put("I", posOfI); + tphPositions.put("J", posOfJ); + + List classConstraints = FamilyOfGeneratedGenerics.getClassConstraints(inputConstraints, tphPositions); + System.out.println(classConstraints); + + assertFalse(classConstraints.isEmpty()); + assertTrue(classConstraints.size() == 3); + } + + + public void testPositionConverter() { + HashMap allTphsOld = new HashMap<>(); + List listOfMethodsAndTphs = new ArrayList<>(); + allTphsOld.put("A", true); + allTphsOld.put("B", false); + MethodAndTPH m1 = new MethodAndTPH("m1"); + m1.getTphs().add("A"); + MethodAndTPH bla = new MethodAndTPH("bla"); + MethodAndTPH blubb = new MethodAndTPH("blubb"); +// blubb.getTphs().add("A"); + listOfMethodsAndTphs.add(bla); + listOfMethodsAndTphs.add(blubb); + listOfMethodsAndTphs.add(m1); + + + + HashMap> allTphsNew = FamilyOfGeneratedGenerics.positionConverter(allTphsOld, listOfMethodsAndTphs); + System.out.println(allTphsNew); + //was tun wenn zwei (oder mehr) Methoden gleiches TPH enthalten? + //ist dies möglich oder werden die TPHs immer verschieden initialisiert und dann erst am Ende gemappt? + //überarbeiten oder lassen? + + + assertTrue(allTphsNew.get("A").fst.equals(PositionFinder.Position.METHOD)); + assertTrue(allTphsNew.get("B").fst.equals(PositionFinder.Position.FIELD)); + } + + } \ No newline at end of file diff --git a/src/test/java/insertGenerics/TestExample42.java b/src/test/java/insertGenerics/TestExample42.java index fd7dd95d..8a44d3fc 100644 --- a/src/test/java/insertGenerics/TestExample42.java +++ b/src/test/java/insertGenerics/TestExample42.java @@ -1,3 +1,4 @@ +/* package insertGenerics; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; @@ -52,3 +53,4 @@ public class TestExample42 { List testCons; } } +*/