From 904bdca2f4946ff9633c39cc3700f885afc4ac5a Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 25 Apr 2023 15:06:56 +0200 Subject: [PATCH] Eliminate transitive children, add missing object bounds --- .../insertGenericsJav/TestContraVariant.jav | 2 +- resources/insertGenericsJav/TestTwoCalls.jav | 4 +- .../target/generate/ASTToTargetAST.java | 46 +++++++++++++++++++ src/test/java/targetast/TestGenerics.java | 32 ++++++------- 4 files changed, 66 insertions(+), 18 deletions(-) diff --git a/resources/insertGenericsJav/TestContraVariant.jav b/resources/insertGenericsJav/TestContraVariant.jav index 9349e620..99c83de4 100644 --- a/resources/insertGenericsJav/TestContraVariant.jav +++ b/resources/insertGenericsJav/TestContraVariant.jav @@ -5,7 +5,7 @@ public class TestContraVariant { x = y; return y; } - + main(x) { return m(x); } diff --git a/resources/insertGenericsJav/TestTwoCalls.jav b/resources/insertGenericsJav/TestTwoCalls.jav index be3137f0..e3f0cfc4 100644 --- a/resources/insertGenericsJav/TestTwoCalls.jav +++ b/resources/insertGenericsJav/TestTwoCalls.jav @@ -1,10 +1,12 @@ public class TestTwoCalls { + // O -> O id(b) { var c = b; return c; } - + + // (S, T) -> T main(x,y) { id(x); return id(y); diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 195cd785..acba2a13 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -552,6 +552,7 @@ public class ASTToTargetAST { methodFindConstraints(owner, method, simplifiedConstraints, txTypeVariables, classGenerics.userDefinedGenerics, txTypeVariablesOfClass, txResult, txEquality); { // Java Generics + eliminateTransitives(javaResult); var referenced = new HashSet(); eliminateCycles(javaResult, equality, referenced); @@ -569,10 +570,12 @@ public class ASTToTargetAST { eliminateInnerTypeVariables(referenced, javaResult); equalizeTypeVariables(javaResult, equality); usedTPHsOfMethods.put(method, usedTphs); + addMissingObjectBounds(javaResult, genericsOfClass); } { var referenced = new HashSet(); // JavaTX Generics + eliminateTransitives(txResult); eliminateInfima(txResult, txEquality); for (var param : method.getParameterList().getFormalparalist()) { @@ -582,12 +585,36 @@ public class ASTToTargetAST { referenced.addAll(txTypeVariablesOfClass); eliminateInnerTypeVariables(referenced, txResult); + addMissingObjectBounds(txResult, txGenericsOfClass); } System.out.println(method.name + ": " + txResult + " & " + javaResult); return generics; } + private void eliminateChain(Set> result, List chain) { + for (var pair : new HashSet<>(result)) { + if (pair instanceof PairTPHsmallerTPH ptph && chain.get(chain.size() - 1).equals(ptph.left)) { + if (chain.contains(ptph.right)) return; + var copy = new ArrayList<>(chain); + copy.add(ptph.right); + if (copy.size() > 2) + result.remove(new PairTPHsmallerTPH(chain.get(0), ptph.right)); + eliminateChain(result, copy); + } + } + } + + void eliminateTransitives(Set> result) { + for (var pair : new HashSet<>(result)) if (pair instanceof PairTPHsmallerTPH ptph) { + var first = ptph.left; + var chain = new ArrayList(); + chain.add(ptph.left); + chain.add(ptph.right); + eliminateChain(result, chain); + } + } + void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set> generics, Map equality) { if (type instanceof TypePlaceholder tph) { tph = equality.getOrDefault(tph, tph); @@ -632,6 +659,9 @@ public class ASTToTargetAST { findAllBounds(field.getType(), txResult, txEquality); } + eliminateTransitives(javaResult); + eliminateTransitives(txResult); + System.out.println(javaResult); var referenced = new HashSet(); eliminateCycles(javaResult, equality, referenced); eliminateInfima(javaResult, equality); @@ -642,10 +672,26 @@ public class ASTToTargetAST { equalizeTypeVariables(javaResult, equality); eliminateInnerTypeVariablesOfClass(classOrInterface, txResult, txEquality, txReferenced); + addMissingObjectBounds(javaResult, null); + addMissingObjectBounds(txResult, null); + System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + txResult + ", " + javaResult); return generics; } + void addMissingObjectBounds(Set> result, Set> filter) { + outer: for (var p1 : new HashSet<>(result)) { + if (p1 instanceof PairTPHsmallerTPH ptph) { + for (var p2 : new HashSet<>(result)) { + if (ptph.right.equals(p2.getLeft())) + continue outer; + } + if (filter == null || filter.stream().noneMatch((pair) -> pair.getLeft().equals(ptph.right))) + result.add(new PairTPHequalRefTypeOrWildcardType(ptph.right, OBJECT)); + } + } + } + void equalizeTypeVariables(Set> input, Map equality) { for (var pair : new HashSet<>(input)) { if (pair instanceof PairTPHsmallerTPH ptph) { diff --git a/src/test/java/targetast/TestGenerics.java b/src/test/java/targetast/TestGenerics.java index f6308861..a9058361 100644 --- a/src/test/java/targetast/TestGenerics.java +++ b/src/test/java/targetast/TestGenerics.java @@ -90,16 +90,15 @@ public class TestGenerics { var generics = result.genericsResults.get(0); assertEquals(0, generics.get(result.clazz).size()); - assertEquals(2, generics.get(m).size()); + assertEquals(1, generics.get(m).size()); assertEquals(2, generics.get(main).size()); var N = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m); - var NChain = new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)); - assertEquals(N, NChain); + var N2 = generics.getBounds(m.getReturnType(), result.clazz, m); - var Q = generics.getBounds(m.getReturnType(), result.clazz, m); - var QChain = new BoundsList(new Bound(true, TypePlaceholder.of("N")), new Bound(true, ASTToTargetAST.OBJECT)); - assertEquals(Q, QChain); + var NChain = new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)); + assertEquals(N, N2); + assertEquals(N2, NChain); var R = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); assertEquals(R, NChain); @@ -304,17 +303,18 @@ public class TestGenerics { var main = result.findMethod("main"); var generics = result.genericsResults.get(0); - var Q = generics.getBounds(id.getReturnType(), result.clazz, id); - var N = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id); - assertEquals(Q, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); - assertEquals(N, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT))); + var O = generics.getBounds(id.getReturnType(), result.clazz, id); + var O2 = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id); + assertEquals(O, O2); + assertEquals(O2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); - var Q2 = generics.getBounds(main.getReturnType(), result.clazz, main); - var R = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); - var S = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main); - assertEquals(Q2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); - assertEquals(R, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT))); - assertEquals(S, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT))); + // TODO Maybe test in other ways if the parameter generics equals the return generics + var S = generics.getBounds(main.getReturnType(), result.clazz, main); + var S2 = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main); + var T = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main); + assertEquals(S, S2); + assertEquals(S2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); + assertEquals(T, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT))); } @Test