diff --git a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java index 5b8e841a..8aad3813 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/GenerateGenerics.java @@ -23,7 +23,7 @@ public abstract class GenerateGenerics { private final ASTToTargetAST astToTargetAST; public class TPH { - final TypePlaceholder wrap; + private final TypePlaceholder wrap; TPH(TypePlaceholder wrap) { this.wrap = wrap; @@ -212,6 +212,7 @@ public abstract class GenerateGenerics { equality.put(entry.getKey(), to); } } + to.setVariance(from.getVariance()); equality.put(from, to); referenced.remove(new TPH(from)); referenced.add(new TPH(to)); @@ -292,8 +293,10 @@ public abstract class GenerateGenerics { if (expressionReceiver.expr instanceof This) { var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.getArgumentList()); if (optMethod.isEmpty()) return; - var method = optMethod.get(); - var generics = generics(owner, method); + var method2 = optMethod.get(); + System.out.println("In: " + method.getName() + " Method: " + method2.getName()); + System.out.println(simplifiedConstraints); + var generics = family(owner, method2); // transitive and var all = transitiveClosure(generics); @@ -325,6 +328,7 @@ public abstract class GenerateGenerics { if (!T1s.contains(R1) || !T2s.contains(R2)) continue; var newPair = new PairLT(R1, R2); + System.out.println("New pair: " + newPair); newPairs.add(newPair); if (!containsRelation(result, newPair)) @@ -501,10 +505,10 @@ public abstract class GenerateGenerics { abstract void generics(ClassOrInterface owner, Method method, Set result, Set javaTypeVariablesOfClass); Set family(ClassOrInterface owner, Method method) { + Set result = new HashSet<>(); if (familyOfMethods.containsKey(method)) return familyOfMethods.get(method); - var result = new HashSet(); familyOfMethods.put(method, result); var classGenerics = generics(owner); @@ -524,19 +528,22 @@ public abstract class GenerateGenerics { } Set generics(ClassOrInterface owner, Method method) { - if (computedGenericsOfMethods.containsKey(method)) - return computedGenericsOfMethods.get(method); + if (computedGenericsOfMethods.containsKey(method)) { + var cached = computedGenericsOfMethods.get(method); + System.out.println("Cached " + method.getName() + ": " + cached); + return cached; + } + + var result = new HashSet(); + computedGenericsOfMethods.put(method, result); var classGenerics = generics(owner); - HashSet typeVariablesOfClass = new HashSet<>(); - for (var pair : classGenerics) { typeVariablesOfClass.add(pair.left); } - var result = new HashSet<>(family(owner, method)); - computedGenericsOfMethods.put(method, result); + result.addAll(family(owner, method)); var referenced = new HashSet(); @@ -552,7 +559,7 @@ public abstract class GenerateGenerics { generics(owner, method, result, referenced); usedTPHsOfMethods.put(method, usedTphs); - addMissingObjectBounds(result, classGenerics, usedTphs); + normalize(result, classGenerics, usedTphs); System.out.println(this.getClass().getSimpleName() + " " + method.name + ": " + result); return result; @@ -631,16 +638,18 @@ public abstract class GenerateGenerics { findTphs(field.getType(), referencedByClass); } - addMissingObjectBounds(javaResult, null, referencedByClass); + normalize(javaResult, null, referencedByClass); System.out.println(this.getClass().getSimpleName() + " Class " + classOrInterface.getClassName().getClassName() + ": " + javaResult); return javaResult; } - void addMissingObjectBounds(Set result, Set classGenerics, Set usedTphs) { + void normalize(Set result, Set classGenerics, Set usedTphs) { outer: for (var tph : usedTphs) { for (var p1 : new HashSet<>(result)) { + if (p1 instanceof PairLT ptph && ptph.left.equals(ptph.right)) + result.remove(p1); // TODO This is a bit strange if (p1.left.equals(tph)) continue outer; } @@ -683,12 +692,13 @@ public abstract class GenerateGenerics { } if (variance == 1) continue; + var start = chain.get(0); var prev = start; for (var i = 1; i < index; i++) { var cur = chain.get(i); if (!referenced.contains(cur)) continue; - addToEquality(cur.wrap, start.resolve(), referenced); + addToEquality(cur.resolve(), start.resolve(), referenced); TPH finalPrev = prev; input.removeIf(p -> p.equals(new PairLT(finalPrev, cur))); for (var pair2 : new HashSet<>(input)) { @@ -722,13 +732,32 @@ public abstract class GenerateGenerics { for (var field : classOrInterface.getFieldDecl()) { findTphs(field.getType(), referenced); } + doIterationForMethods(classOrInterface); for (var method : classOrInterface.getMethods()) { - generics(classOrInterface, method); referenced.addAll(usedTPHsOfMethods.get(method)); } eliminateInnerTypeVariables(referenced, input); } + void doIterationForMethods(ClassOrInterface classOrInterface) { + familyOfMethods.clear(); + + var oldFamily = new HashMap>(); + do { + oldFamily.clear(); + oldFamily.putAll(familyOfMethods); + familyOfMethods.clear(); + for (var method : classOrInterface.getMethods()) { + family(classOrInterface, method); + } + System.out.println(familyOfMethods); + } while(!oldFamily.equals(familyOfMethods)); + + for (var method : classOrInterface.getMethods()) { + generics(classOrInterface, method); + } + } + private void findChain(Set referenced, Set input, Set output, TPH start, TPH end, Set chain) { if (referenced.contains(end)) { var pair = new PairLT(start, end); @@ -793,7 +822,7 @@ public abstract class GenerateGenerics { var right = cycle.get(i + 1); var pair = new PairLT(left, right); input.remove(pair); - addToEquality(left.wrap, newTph, referenced); + addToEquality(left.resolve(), newTph, referenced); } } } @@ -806,9 +835,10 @@ public abstract class GenerateGenerics { var left = constraint.left; Set infima = new HashSet<>(); for (var pair : input) { - if (pair instanceof PairLT stph) - if (pair.left.wrap.equals(constraint.left.wrap)) + if (pair instanceof PairLT stph) { + if (pair.left.equals(constraint.left)) infima.add(stph); + } } if (infima.size() > 1) { foundInfima = true; @@ -826,19 +856,19 @@ public abstract class GenerateGenerics { addToPairs(input, new PairLT(left, new TPH(newTph))); input.removeAll(infima); for (var infimum : infima) { - addToEquality(infimum.right.wrap, newTph, referenced); + addToEquality(infimum.right.resolve(), newTph, referenced); new HashSet<>(input).forEach(pair -> { - if (pair.left.wrap.equals(infimum.right.wrap)) { + if (pair.left.equals(infimum.right)) { input.remove(pair); if (pair instanceof PairLT stph) { - if (!newTph.equals(stph.right.wrap)) + if (!newTph.equals(stph.right.resolve())) addToPairs(input, new PairLT(new TPH(newTph), stph.right)); } else if (pair instanceof PairEQ rtph) { addToPairs(input, new PairEQ(new TPH(newTph), rtph.right)); } - } else if (pair instanceof PairLT stph && stph.right.wrap.equals(infimum.right.wrap)) { + } else if (pair instanceof PairLT stph && stph.right.equals(infimum.right)) { input.remove(pair); - if (!newTph.equals(stph.left.wrap)) + if (!newTph.equals(stph.left.resolve())) addToPairs(input, new PairLT(stph.left, new TPH(newTph))); } }); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/JavaGenerics.java b/src/main/java/de/dhbwstuttgart/target/generate/JavaGenerics.java index f2f08542..16be617e 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/JavaGenerics.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/JavaGenerics.java @@ -15,7 +15,7 @@ final class JavaGenerics extends GenerateGenerics { void generics(ClassOrInterface owner, Method method, Set result, Set referenced) { eliminateCycles(result, referenced); eliminateInfima(result, referenced); - //equalizeTypeVariables(result, referenced); + equalizeTypeVariables(result, referenced); eliminateInnerTypeVariables(referenced, result); }