From 623705d38aa1aa029f6453fc3f5b5ca93ba0c753 Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Wed, 7 Nov 2018 15:29:37 +0100 Subject: [PATCH] (Transivitaet) Algorithmus funktioniert --- .../dhbwstuttgart/bytecode/BytecodeGen.java | 441 +----------------- .../bytecode/signature/Signature.java | 362 +++----------- .../bytecode/utilities/Simplify.java | 432 +++++++++++++++++ 3 files changed, 523 insertions(+), 712 deletions(-) create mode 100644 src/de/dhbwstuttgart/bytecode/utilities/Simplify.java diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index 399abd471..6399904fb 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -26,6 +26,7 @@ import de.dhbwstuttgart.bytecode.signature.TypeToString; 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.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.statement.Literal; @@ -61,8 +62,7 @@ public class BytecodeGen implements ASTVisitor { HashMap paramsAndLocals = new HashMap<>(); // stores generics and their bounds of class HashMap genericsAndBounds = new HashMap<>(); - // stores generics and their bounds of method - HashMap genericsAndBoundsMethod = new HashMap<>(); + private final TPHExtractor tphExtractor = new TPHExtractor(); private final ArrayList commonPairs = new ArrayList<>(); @@ -185,6 +185,10 @@ public class BytecodeGen implements ASTVisitor { System.out.println(a.getLeft().toString() + " = " + a.getRight().toString()); }); System.out.println("---------------"); + + // stores generics and their bounds of method + HashMap genericsAndBoundsMethod = new HashMap<>(); + field.getParameterList().accept(this); String methParamTypes = field.name+"%%"; @@ -215,8 +219,8 @@ public class BytecodeGen implements ASTVisitor { } String sig = null; if(hasGen) { - ArrayList pairs = simplifyPairs(field.name,tphExtractor.allPairs, tphExtractor.allCons); - Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,pairs); + HashMap> constraints = Simplify.simplifyConstraints(field.name, tphExtractor); + Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); sig = signature.toString(); } NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen); @@ -253,6 +257,8 @@ public class BytecodeGen implements ASTVisitor { } methodNameAndParamsT.add(methParamTypes); System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes); + // stores generics and their bounds of method + HashMap genericsAndBoundsMethod = new HashMap<>(); String methDesc = null; // Method getModifiers() ? @@ -287,11 +293,9 @@ public class BytecodeGen implements ASTVisitor { System.out.println("ALL CONST: " + tphExtractor.allCons.size()); tphExtractor.allCons.forEach(c->System.out.println(c.toString())); System.out.println("----------------"); - HashMap> constraints = simplifyPairs(method.name,tphExtractor.allCons); - ArrayList pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons); - System.out.println(method.name + " => Simplified Pairs: "); - pairs.forEach(p->System.out.println(p.TA1.getName() + " -> "+p.TA2.getName())); - Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet, pairs); + HashMap> constraints = Simplify.simplifyConstraints(method.name, tphExtractor); +// ArrayList pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons); + Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); sig = signature.toString(); } System.out.println(method.getName()+" ==> "+sig); @@ -309,419 +313,6 @@ public class BytecodeGen implements ASTVisitor { mv.visitEnd(); } - private HashMap> simplifyPairs(String name, ArrayList allCons) { - // 1. check if there are any cycles like L set L=R and: - // * remove both constraints - // * substitute L with R in all constraint - // b)no => go to next step - // 2. check the result of step 1 if there are any equal-constraints like L=R, M=R .. - // a) yes => put all such TPhs in a map and define "key-Cons" - // -- key-Cons = TPH < Object -- - // put this Constraint and the - // b) no - // 3. is - ArrayList consToRemove = new ArrayList<>(); - // step 1: - for(TPHConstraint c : allCons) { - - String left = c.getLeft(); - String right = c.getRight(); - if(c.getRel() == Relation.EXTENDS) { - TPHConstraint revCon = getReverseConstraint(allCons,left,right); - if(revCon != null) { - revCon.setRel(Relation.EQUAL); - consToRemove.add(revCon); - c.setRel(Relation.EQUAL); - substituteTPH(allCons,left, right); - } - } - } - System.out.println(); - System.out.println("NEW ALL CONST: " + allCons.size()); - allCons.forEach(c->System.out.println(c.toString())); - System.out.println("----------------"); - allCons.removeAll(consToRemove); - consToRemove = new ArrayList<>(); - - int size = allCons.size(); - - System.out.println("AFTER DELETE ALL CONST: " + allCons.size()); - allCons.forEach(c->System.out.println(c.toString())); - System.out.println("----------------"); - HashMap> result = new HashMap<>(); - - for(TPHConstraint c : allCons) { - if(c.getRel()==Relation.EQUAL) { - HashSet equalTPHs = getEqualsTPHs(result, c); - TPHConstraint constraint = getKeyConstraint(result,c); - equalTPHs.add(c.getLeft()); - equalTPHs.add(c.getRight()); - result.put(constraint, equalTPHs); - consToRemove.add(c); - size--; - } - } - System.out.println("Step 2 Result: "); - result.forEach((c,hs)->{ - System.out.print(c.toString() + " -> "); - hs.forEach(s->{ - System.out.print(s + ", "); - }); - System.out.println(); - }); - System.out.println("----------------"); - allCons.removeAll(consToRemove); - allCons.addAll(result.keySet()); - - if(!allCons.isEmpty() && allCons.size()<2) { - - if(!result.containsKey(allCons.get(0))) - result.put(allCons.get(0), null); - - return result; - } - - size += result.keySet().size(); - - for(TPHConstraint c : allCons) { - if(c.getRight().equals(Type.getInternalName(Object.class))) - size--; - } - - ArrayList methodTphs = new ArrayList<>(); - for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { - if(m.getName().equals(name)) { - methodTphs = m.getTphs(); - break; - } - } - - HashMap subAndSuper = new HashMap<>(); - for(TPHConstraint c : allCons) { - if(subAndSuper.containsKey(c.getLeft())) { - LinkedList all = new LinkedList<>(); - all.add(c.getLeft()); - String sup =c.getRight(); - all.add(sup); - HashMap ss = new HashMap<>(); - for(TPHConstraint constr : allCons) { - ss.put(constr.getLeft(), constr.getRight()); - } - while(ss.containsKey(sup)) { - sup = ss.get(sup); - all.add(sup); - } - if(!containTPH(methodTphs, all.getLast())) - continue; - } - subAndSuper.put(c.getLeft(), c.getRight()); - } - - int numOfVisitedPairs = 0; - for(String sub : subAndSuper.keySet()) { - if(isTPHInConstraint(result,sub)) - continue; - - if(!containTPH(methodTphs,sub)) - continue; - - if(numOfVisitedPairs>=size) - break; - LinkedList tphInRel = new LinkedList<>(); - tphInRel.add(sub); - String superT = subAndSuper.get(sub); - tphInRel.add(superT); - - numOfVisitedPairs++; - boolean isCycle = false; - while(subAndSuper.containsKey(superT)) { - superT = subAndSuper.get(superT); - if(tphInRel.contains(superT)) { - isCycle = true; - break; - } - tphInRel.add(superT); - numOfVisitedPairs++; - } - - // Subtype - String subTphRes = tphInRel.getFirst(); - // Die größte Supertype - String superTphRes = tphInRel.getLast(); - - while(subAndSuper.containsValue(subTphRes)) { - for(String tph : subAndSuper.keySet()) { - if(containTPH(methodTphs,tph) && subAndSuper.get(tph).equals(subTphRes)) { - subTphRes = tph; - break; - } - } - if(subTphRes.equals(tphInRel.getFirst())) { - break; - } - tphInRel.addFirst(subTphRes); - numOfVisitedPairs++; - } - - subTphRes = tphInRel.getFirst(); - - int i = 2; - while(!containTPH(methodTphs,superTphRes) && (tphInRel.size()-i) >0) { - superTphRes = tphInRel.get(tphInRel.size()-i); - i++; - } - - if(!containTPH(methodTphs, superTphRes)) { - result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); - } else { - result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), null); - result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); - } - } - System.out.println("ZwischenResult: "); - result.forEach((c,hs)->{ - if(c!=null) { - System.out.print(c.toString() + " -> "); - if(hs == null) { - System.out.print(" [] "); - }else { - hs.forEach(s->{ - System.out.print(s + ", "); - }); - } - } - - - System.out.println(); - }); - System.out.println("----------------"); - return result; - } - - private boolean isTPHInConstraint(HashMap> result, String sub) { - for(TPHConstraint c : result.keySet()) { - if(c.getLeft().equals(sub)) - return true; - } - return false; - } - - private boolean containTPH(ArrayList methodTphs, String sub) { - for(TypePlaceholder tph : methodTphs) { - if(tph.getName().equals(sub)) - return true; - } - return false; - } - - private TPHConstraint getKeyConstraint(HashMap> result, TPHConstraint toFind) { - for(TPHConstraint c : result.keySet()) { - if(c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) - return c; - } - return new ExtendsConstraint(toFind.getRight(), Type.getInternalName(Object.class), Relation.EXTENDS); - } - - private HashSet getEqualsTPHs(HashMap> result, TPHConstraint toFind) { - for(TPHConstraint c : result.keySet()) { - if(c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) - return result.get(c); - } - return new HashSet<>(); - } - - private ArrayList simplifyPairs(String methodName, ArrayList allPairs, ArrayList allCons) { - allPairs.forEach(p->System.out.print(p.TA1 + " < "+ p.TA2+ " ; ")); - - // 1. check if there are any cycles like L set L=R and: - // * remove both constraints - // * substitute L with R in all constraint - // b)no => go to next step - // 2. check the result of step 1 if there are any equal-constraints like L=R, M=R .. - // a) yes - // b) no - ArrayList consToRemove = new ArrayList<>(); - // step 1: - for(TPHConstraint c : allCons) { - - String left = c.getLeft(); - String right = c.getRight(); - if(c.getRel() == Relation.EXTENDS) { - TPHConstraint revCon = getReverseConstraint(allCons,left,right); - if(revCon != null) { - revCon.setRel(Relation.EQUAL); - consToRemove.add(revCon); - c.setRel(Relation.EQUAL); - substituteTPH(allCons,left, right); - } - } - } - System.out.println(); - System.out.println("NEW ALL CONST: " + allCons.size()); - allCons.forEach(c->System.out.println(c.toString())); - System.out.println("----------------"); - allCons.removeAll(consToRemove); - System.out.println("AFTER DELETE ALL CONST: " + allCons.size()); - allCons.forEach(c->System.out.println(c.toString())); - System.out.println("----------------"); - if(allPairs.size() < 2) - return allPairs; - - ArrayList simplifiedPairs = new ArrayList<>(); - - ArrayList> beforeSimplify = new ArrayList<>(); - - MethodAndTPH method; - ArrayList methodTphs = new ArrayList<>(); - ArrayList methodPairs = new ArrayList<>(); - for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { - if(m.getName().equals(methodName)) { - methodTphs = m.getTphs(); - methodPairs = m.getPairs(); - break; - } - } - - HashMap subAndSuperTph = new HashMap<>(); - for(GenericInsertPair p : allPairs) { - // Tph2.jav - if(subAndSuperTph.containsKey(p.TA1)) { - if(methodTphs.contains(subAndSuperTph.get(p.TA1))) - continue; - } - subAndSuperTph.put(p.TA1, p.TA2); - } - int numOfVisitedPairs = 0; - for(TypePlaceholder subTph: subAndSuperTph.keySet()) { - - if(numOfVisitedPairs>=subAndSuperTph.size()) - break; - - if(!methodTphs.contains(subTph)) - continue; - - HashMap tphsInRel= new HashMap<>(); - - tphsInRel.put(tphsInRel.size(), subTph); - TypePlaceholder superTph = subAndSuperTph.get(subTph); - tphsInRel.put(tphsInRel.size(), superTph); - - numOfVisitedPairs++; - boolean isCycle = false; - while(subAndSuperTph.containsKey(superTph)) { - superTph = subAndSuperTph.get(superTph); - if(tphsInRel.containsValue(superTph)) { - isCycle = true; - break; - } - tphsInRel.put(tphsInRel.size(), superTph); - numOfVisitedPairs++; - } - - // Subtype - TypePlaceholder subTphRes = tphsInRel.get(0); - // Die größte Supertype - TypePlaceholder superTphRes = tphsInRel.get(tphsInRel.size()-1); - - while(subAndSuperTph.containsValue(subTphRes)) { - for(TypePlaceholder tph : subAndSuperTph.keySet()) { - if(methodTphs.contains(tph) && subAndSuperTph.get(tph).equals(subTphRes)) { - subTphRes = tph; - break; - } - } - if(subTphRes.equals(tphsInRel.get(0))) { - break; - } - tphsInRel.put(0, subTphRes); - numOfVisitedPairs++; - } - - subTphRes = tphsInRel.get(0); - - int i = 2; - while(!methodTphs.contains(superTphRes) && (tphsInRel.size()-i) >0) { - superTphRes = tphsInRel.get(tphsInRel.size()-i); - i++; - } - - if((methodTphs.contains(superTphRes) || !tphExtractor.allTPHS.containsKey(superTphRes)) - && !subTphRes.equals(superTphRes)) { - - beforeSimplify.add(tphsInRel); - } - - // teste noch den Fall X < Y und Y nicht in TPHS der Methode - // Dann hat man nach der While-Schleife X < Y - // Y muss durch Object ersetzt. - - // Zweite Operand für die Fälle wie in Lambda.jav (Paramtrisierte Typen) - if((methodTphs.contains(superTphRes) || !tphExtractor.allTPHS.containsKey(superTphRes)) - && !subTphRes.equals(superTphRes)) { - GenericInsertPair sPair = new GenericInsertPair(subTphRes, superTphRes); - simplifiedPairs.add(sPair); - } - } - beforeSimplify.forEach(e->{ - System.out.println("=> "); - e.forEach((v,k) -> { - System.out.print(v + "->" + k + ", "); - }); - System.out.println(); - System.out.println("----------------------"); - }); - - if(beforeSimplify.size()>1) { - int i = 0; - while(i e: beforeSimplify) { - if(!e.equals(beforeSimplify.get(i)) && e.containsValue(sub)) { - GenericInsertPair sPair = new GenericInsertPair(e.get(0), sub); - System.out.println("To remove = " + e.get(0)+ " " +e.get(e.size()-1)); - removePair(simplifiedPairs,e.get(0), e.get(e.size()-1)); - simplifiedPairs.add(sPair); - } - } - i++; - } - } - - return simplifiedPairs; - } - - private void substituteTPH(ArrayList allCons,String left ,String right) { - allCons.forEach(c->{ - if(c.getRel() == Relation.EXTENDS) { - if(c.getLeft().equals(left)) - c.setLeft(right); - if(c.getRight().equals(left)) - c.setRight(right); - } - }); - } - - private TPHConstraint getReverseConstraint(ArrayList allCons, String left, String right) { - for(TPHConstraint c : allCons) { - if(c.getLeft().equals(right) && c.getRight().equals(left)){ - return c; - } - } - return null; - } - - private void removePair(ArrayList simplifiedPairs, TypePlaceholder typePlaceholder, TypePlaceholder typePlaceholder2) { - for(GenericInsertPair p : simplifiedPairs) { - if(p.TA1.equals(typePlaceholder) && p.TA2.equals(typePlaceholder2)) { - simplifiedPairs.remove(p); - return; - } - } - } - @Override public void visit(ParameterList formalParameters) { paramsAndLocals = new HashMap<>(); @@ -964,15 +555,15 @@ public class BytecodeGen implements ASTVisitor { throw new NotImplementedException(); } - private class TPHExtractor extends AbstractASTWalker{ + public class TPHExtractor extends AbstractASTWalker{ // Alle TPHs der Felder werden iKopf der Klasse definiert // alle TPHs der Klasse: (TPH, is in Method?) final HashMap allTPHS = new HashMap<>(); MethodAndTPH methodAndTph; Boolean inMethod = false; - final ArrayList ListOfMethodsAndTph = new ArrayList<>(); + public final ArrayList ListOfMethodsAndTph = new ArrayList<>(); final ArrayList allPairs = new ArrayList<>(); - final ArrayList allCons = new ArrayList<>(); + public final ArrayList allCons = new ArrayList<>(); @Override public void visit(TypePlaceholder tph) { diff --git a/src/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/de/dhbwstuttgart/bytecode/signature/Signature.java index 396686485..8626cbf9f 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -2,15 +2,18 @@ package de.dhbwstuttgart.bytecode.signature; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import org.objectweb.asm.Type; import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureWriter; +import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; -import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; -import de.dhbwstuttgart.syntaxtree.AbstractASTWalker; +import de.dhbwstuttgart.bytecode.utilities.Simplify; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.Constructor; import de.dhbwstuttgart.syntaxtree.GenericTypeVar; @@ -36,7 +39,7 @@ public class Signature { private HashMap methodParamsAndTypes; private ResultSet resultSet; private ArrayList commonPairs; - private ArrayList methodPairs; + private HashMap> methodConstraints; public Signature(ClassOrInterface classOrInterface, HashMap genericsAndBounds,ArrayList commonPairs) { this.classOrInterface = classOrInterface; @@ -47,24 +50,26 @@ public class Signature { } public Signature(Constructor constructor, HashMap genericsAndBounds, - HashMap methodParamsAndTypes,ResultSet resultSet,ArrayList methodPairs) { + HashMap methodParamsAndTypes,ResultSet resultSet, + HashMap> methodConstraints) { this.constructor = constructor; this.genericsAndBounds = genericsAndBounds; this.methodParamsAndTypes = methodParamsAndTypes; this.resultSet = resultSet; - this.methodPairs = methodPairs; + this.methodConstraints = methodConstraints; sw = new SignatureWriter(); createSignatureForConsOrMethod(this.constructor,true); } public Signature(Method method, HashMap genericsAndBoundsMethod,HashMap genericsAndBounds, - HashMap methodParamsAndTypes, ResultSet resultSet, ArrayList methodPairs) { + HashMap methodParamsAndTypes, ResultSet resultSet, + HashMap> methodConstraints) { this.method = method; this.genericsAndBoundsMethod = genericsAndBoundsMethod; this.genericsAndBounds = genericsAndBounds; this.methodParamsAndTypes = methodParamsAndTypes; this.resultSet = resultSet; - this.methodPairs = methodPairs; + this.methodConstraints = methodConstraints; sw = new SignatureWriter(); createSignatureForConsOrMethod(this.method,false); } @@ -111,15 +116,16 @@ public class Signature { getBoundsOfTypeVar(g,genericsAndBoundsMethod); } - //TODO: paramtrisierte Typen mit Generics, Type Variablen müssen definiert werden. - // Wenn die RückgabeType eine TPH ist, wird als generic behandelt // z.B: Type = TPH K => wird eine Formal Type Parameter K$ erzeugt und Bound = Object if(!isConstructor) { String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); - ArrayList allPairs = new ArrayList<>(); + ArrayList allConsBeforeSimplify = new ArrayList<>(); + + HashMap> allConstraints = new HashMap<>(); + if(ret.contains("<")) { - allPairs = getAllPairs((RefType) resultSet.resolveType(method.getReturnType()).resolvedType); + allConsBeforeSimplify = getAllConstraints((RefType) resultSet.resolveType(method.getReturnType()).resolvedType); } for(String paramName : methodParamsAndTypes.keySet()) { @@ -127,102 +133,22 @@ public class Signature { String pT = t.acceptTV(new TypeToSignature()); if(pT.contains("<")) - allPairs.addAll(getAllPairs((RefType) t)); + allConsBeforeSimplify = getAllConstraints((RefType) t); } - - createTypeVars(allPairs); + boolean doSimplify = false; + if(!allConsBeforeSimplify.isEmpty()) { + addConstraintsToMap(allConstraints,allConsBeforeSimplify); + doSimplify = true; + } + createTypeVars(allConstraints, doSimplify); if(!ret.equals("V")) { - // TODO TypeToSignature nochmal kontrollieren und schauen ob man dort wirklich - // T... braucht und L ... if(ret.contains("$") && !ret.contains("$$") && !ret.contains("<")) { if(genericsAndBounds.containsKey(ret)) { genericsAndBoundsMethod.put(ret.substring(1), genericsAndBounds.get(ret.substring(1))); - }else { - sw.visitFormalTypeParameter(ret.substring(1)); - sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); - genericsAndBoundsMethod.put(ret.substring(1), Type.getInternalName(Object.class)); - sw.visitClassBound().visitEnd(); } } -// if(ret.contains("<")) { -// RefType ref = (RefType) resultSet.resolveType(method.getReturnType()).resolvedType; -// if(hasTPHs(ref)) { -// createSignatureForParameterizedType(ref); -// } -// System.out.println("HAS WC = " + hasWC(ref)); -// if(hasWC(ref)) -// createSigForParamTypeWithWC(ref); -// } - } - } - - // Parameters - for(String paramName : methodParamsAndTypes.keySet()) { - RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); - String pT = t.acceptTV(new TypeToSignature()); - // S.o - if(t instanceof TypePlaceholder) { - String gP = t.acceptTV(new TypeToSignature()); - if(!genericsAndBounds.containsKey(gP.substring(1)) && !genericsAndBoundsMethod.containsKey(gP.substring(1))) { - sw.visitFormalTypeParameter(gP.substring(1)); - String bound = Type.getInternalName(Object.class); - boolean isTypeVar = false; - for(GenericInsertPair pair : methodPairs) { - if(pT.substring(1,pT.length()-1).equals(pair.TA1.getName())) { - bound = pair.TA2.getName()+"$"; - isTypeVar = true; - break; - } - } - - if(isTypeVar) { - sw.visitClassBound().visitTypeVariable(bound); - }else { - sw.visitClassBound().visitClassType(bound); - sw.visitClassBound().visitEnd(); - } - - genericsAndBoundsMethod.put(gP.substring(1), bound); - } - } - -// if(pT.contains("<")) { -// RefType ref = (RefType) methodParamsAndTypes.get(paramName); -// if(hasTPHs(ref)) -// createSignatureForParameterizedType(ref); -// -// if(hasWC(ref)) -// createSigForParamTypeWithWC(ref); -// } - - for(GenericInsertPair p:methodPairs) { - String name = p.TA1.getName()+"$"; - if(!genericsAndBoundsMethod.containsKey(name)) { - sw.visitFormalTypeParameter(name); - sw.visitClassBound().visitTypeVariable(p.TA2.getName()+"$"); - genericsAndBoundsMethod.put(name, p.TA2.getName()+"$"); - } - } - - ArrayList types = new ArrayList<>(); - ArrayList superTypes = new ArrayList<>(); - - for(GenericInsertPair p : methodPairs) { - types.add(p.TA1); - superTypes.add(p.TA2); - } - - for(GenericInsertPair p : methodPairs) { - String name = p.TA2.getName()+"$"; - if(!types.contains(p.TA2) && !genericsAndBoundsMethod.containsKey(name)) { - String bound = Type.getInternalName(Object.class); - sw.visitFormalTypeParameter(name); - sw.visitClassBound().visitClassType(bound); - genericsAndBoundsMethod.put(name, bound); - sw.visitClassBound().visitEnd(); - } } } @@ -243,126 +169,56 @@ public class Signature { // sw.visitEnd(); } - private void createTypeVars(ArrayList allPairs) { - allPairs.addAll(methodPairs); - ArrayList simplifiedPairs = simplifyPairs(allPairs); + private void addConstraintsToMap(HashMap> allConstraints, + ArrayList allConsBeforeSimplify) { + for(TPHConstraint tphCons : allConsBeforeSimplify) { + allConstraints.put(tphCons, null); + } + } + + private String getEqualTPH(HashMap> methodConstraints, String tph) { + for(TPHConstraint cons : methodConstraints.keySet()) { + if(methodConstraints.get(cons) != null) { + if(methodConstraints.get(cons).contains(tph)) { + return cons.getLeft(); + } + } + } + return tph; + } + + private void createTypeVars(HashMap> allConstraints, boolean doSimplify) { + allConstraints.putAll(methodConstraints); - HashMap names = new HashMap<>(); - - for(GenericInsertPair pair : simplifiedPairs) { -// if(ref.getParaList().contains(pair.TA1)) { - String sub = pair.TA1.getName()+"$"; - String superT = pair.TA2.getName()+"$"; - names.put(sub, superT); -// } + HashMap> simplifiedConstraints; + if(doSimplify) { + simplifiedConstraints = Simplify.simplifyContraints(allConstraints); + }else { + simplifiedConstraints = allConstraints; } - for(String sub : names.keySet()) { + for(TPHConstraint cons : simplifiedConstraints.keySet()) { + // need subst. + String sub = cons.getLeft()+"$"; if(!genericsAndBoundsMethod.containsKey(sub) && !genericsAndBounds.containsKey(sub)) { sw.visitFormalTypeParameter(sub); - String bound = names.get(sub); - sw.visitClassBound().visitTypeVariable(bound); - genericsAndBoundsMethod.put(sub, bound); - } - } - - for(String superT : names.values()) { - if(!names.containsKey(superT)) { - if(!genericsAndBoundsMethod.containsKey(superT) && !genericsAndBounds.containsKey(superT)) { - sw.visitFormalTypeParameter(superT); + String bound = cons.getRight(); + if(bound.equals(Type.getInternalName(Object.class))) { sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); sw.visitClassBound().visitEnd(); - genericsAndBoundsMethod.put(superT, Type.getInternalName(Object.class)); + genericsAndBoundsMethod.put(sub, bound); + } else { + String boundName = bound+"$"; + sw.visitClassBound().visitTypeVariable(boundName); + genericsAndBoundsMethod.put(sub, boundName); } } - } - } - - private void createSigForParamTypeWithWC(RefType ref) { - for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { - if(p instanceof WildcardType) { - String name = null; - if(((WildcardType) p).getInnerType() instanceof GenericRefType) { - name = new TypeToSignature().visit((GenericRefType)((WildcardType) p).getInnerType()); - } - if(((WildcardType) p).getInnerType() instanceof TypePlaceholder) { - name = new TypeToSignature().visit((TypePlaceholder)((WildcardType) p).getInnerType()); - name = name.substring(1); - } - if(name != null) { - if(!genericsAndBoundsMethod.containsKey(name) && !genericsAndBounds.containsKey(name)) { - sw.visitFormalTypeParameter(name); - sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); - sw.visitClassBound().visitEnd(); - genericsAndBoundsMethod.put(name, Type.getInternalName(Object.class)); - } - } - } - } - - } - - private boolean hasWC(RefType ref) { - for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { - System.out.println("HAS WCs: " + p.acceptTV(new TypeToString())); - System.out.println("HAS WCs: " + p.getClass()); - if(p.acceptTV(new TypeToString()).contains("WC")) - return true; } - return false; } - - private void createSignatureForParameterizedType(RefType ref) { -// ArrayList allPairs = getAllPairs(ref); -// allPairs.addAll(methodPairs); -// ArrayList simplifiedPairs = simplifyPairs(allPairs); -// -// HashMap names = new HashMap<>(); -// -// for(GenericInsertPair pair : simplifiedPairs) { -// if(ref.getParaList().contains(pair.TA1)) { -// String sub = pair.TA1.getName()+"$"; -// String superT = pair.TA2.getName()+"$"; -// names.put(sub, superT); -// } -// } -// -// for(String sub : names.keySet()) { -// if(!genericsAndBoundsMethod.containsKey(sub) && !genericsAndBounds.containsKey(sub)) { -// sw.visitFormalTypeParameter(sub); -// String bound = names.get(sub); -// sw.visitClassBound().visitTypeVariable(bound); -// genericsAndBoundsMethod.put(sub, bound); -// } -// } -// -// for(String superT : names.values()) { -// if(!names.containsKey(superT)) { -// if(!genericsAndBoundsMethod.containsKey(superT) && !genericsAndBounds.containsKey(superT)) { -// sw.visitFormalTypeParameter(superT); -// sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); -// sw.visitClassBound().visitEnd(); -// genericsAndBoundsMethod.put(superT, Type.getInternalName(Object.class)); -// } -// } -// } - - for(RefTypeOrTPHOrWildcardOrGeneric p: ref.getParaList()) { - if(p instanceof TypePlaceholder) { - String name = ((TypePlaceholder) p).getName() + "$"; - if(!genericsAndBoundsMethod.containsKey(name) && !genericsAndBounds.containsKey(name)) { - sw.visitFormalTypeParameter(name); - sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); - sw.visitClassBound().visitEnd(); - genericsAndBoundsMethod.put(name, Type.getInternalName(Object.class)); - } - } - } - } - - private ArrayList getAllPairs(RefType ref) { - final ArrayList res = new ArrayList<>(); + + private ArrayList getAllConstraints(RefType ref) { + final ArrayList res = new ArrayList<>(); for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { ResolvedType resType; if(p instanceof WildcardType) { @@ -374,8 +230,9 @@ public class Signature { RefTypeOrTPHOrWildcardOrGeneric resolved = resType.resolvedType; if(resolved instanceof TypePlaceholder) { resType.additionalGenerics.forEach(ag ->{ - if(!contains(res,ag)) { - res.add(ag); + TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); + if(!contains(res,constr)) { + res.add(constr); } }); } @@ -384,9 +241,10 @@ public class Signature { ResolvedType resType2 = resultSet.resolveType(resWC.getInnerType()); if(resType2.resolvedType instanceof TypePlaceholder) { resType2.additionalGenerics.forEach(ag ->{ - if(!contains(res,ag)) { - res.add(ag); - } + TPHConstraint constr = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); + if(!contains(res,constr)) { + res.add(constr); + } }); } } @@ -395,81 +253,10 @@ public class Signature { System.out.println("RES GIP === " + res.size()); return res; } - - private boolean contains(ArrayList pairs, GenericInsertPair genPair) { - for(int i=0; i simplifyPairs(ArrayList allPairs) { - ArrayList simplifiedPairs = new ArrayList<>(); - - HashMap subAndSuperTph = new HashMap<>(); - for(GenericInsertPair p : allPairs) { - if(!p.TA1.equals(p.TA2)) - subAndSuperTph.put(p.TA1, p.TA2); - } - - subAndSuperTph.forEach((k,v)->System.out.println(k.getName() + " || " + v.getName())); - - int numOfVisitedPairs = 0; - for(TypePlaceholder subTph: subAndSuperTph.keySet()) { - - if(numOfVisitedPairs>=subAndSuperTph.size()) - break; - - HashMap tphsInRel= new HashMap<>(); - - tphsInRel.put(tphsInRel.size(), subTph); - TypePlaceholder superTph = subAndSuperTph.get(subTph); - tphsInRel.put(tphsInRel.size(), superTph); - - numOfVisitedPairs++; - - while(subAndSuperTph.containsKey(superTph)) { - superTph = subAndSuperTph.get(superTph); - if(tphsInRel.containsValue(superTph)) { - break; - } - tphsInRel.put(tphsInRel.size(), superTph); - numOfVisitedPairs++; - } - - // Subtype - TypePlaceholder subTphRes = tphsInRel.get(0); - // Die größte Supertype - TypePlaceholder superTphRes = tphsInRel.get(tphsInRel.size()-1); - - - while(subAndSuperTph.containsValue(subTphRes)) { - for(TypePlaceholder tph : subAndSuperTph.keySet()) { - if(subAndSuperTph.get(tph).equals(subTphRes)) { - subTphRes = tph; - break; - } - } - tphsInRel.put(0, subTphRes); - numOfVisitedPairs++; - } - - subTphRes = tphsInRel.get(0); - GenericInsertPair sPair = new GenericInsertPair(subTphRes, superTphRes); - simplifiedPairs.add(sPair); - } - return simplifiedPairs; - } - - private boolean hasTPHs(RefType ref) { - for(RefTypeOrTPHOrWildcardOrGeneric p : ref.getParaList()) { - System.out.println("HAS TPHs: " + p.acceptTV(new TypeToString())); - if(p.acceptTV(new TypeToString()).contains("WC")){ - continue; - } - if(resultSet.resolveType(p).resolvedType instanceof TypePlaceholder) + private boolean contains(ArrayList constraints, TPHConstraint constr) { + for(int i=0; i> simplifyConstraints(String name, TPHExtractor tphExtractor) { + // 1. check if there are any cycles like L set L=R and: + // * remove both constraints + // * substitute L with R in all constraint + // b)no => go to next step + // 2. check the result of step 1 if there are any equal-constraints like L=R, M=R .. + // a) yes => put all such TPhs in a map and define "key-Cons" + // -- key-Cons = TPH < Object -- + // put this Constraint and the + // b) no + // 3. is + + ArrayList allCons = tphExtractor.allCons; + ArrayList consToRemove = new ArrayList<>(); + // step 1: + for(TPHConstraint c : allCons) { + + String left = c.getLeft(); + String right = c.getRight(); + if(c.getRel() == Relation.EXTENDS) { + TPHConstraint revCon = getReverseConstraint(allCons,left,right); + if(revCon != null) { + revCon.setRel(Relation.EQUAL); + consToRemove.add(revCon); + c.setRel(Relation.EQUAL); + substituteTPH(allCons,left, right); + } + } + } + System.out.println(); + System.out.println("NEW ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + allCons.removeAll(consToRemove); + consToRemove = new ArrayList<>(); + + int size = allCons.size(); + + System.out.println("AFTER DELETE ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + HashMap> result = new HashMap<>(); + + for(TPHConstraint c : allCons) { + if(c.getRel()==Relation.EQUAL) { + HashSet equalTPHs = getEqualsTPHs(result, c); + TPHConstraint constraint = getKeyConstraint(result,c); + equalTPHs.add(c.getLeft()); + equalTPHs.add(c.getRight()); + result.put(constraint, equalTPHs); + consToRemove.add(c); + size--; + } + } + System.out.println("Step 2 Result: "); + result.forEach((c,hs)->{ + System.out.print(c.toString() + " -> "); + hs.forEach(s->{ + System.out.print(s + ", "); + }); + System.out.println(); + }); + System.out.println("----------------"); + allCons.removeAll(consToRemove); + allCons.addAll(result.keySet()); + + if(!allCons.isEmpty() && allCons.size()<2) { + + if(!result.containsKey(allCons.get(0))) + result.put(allCons.get(0), null); + + return result; + } + + size += result.keySet().size(); + + for(TPHConstraint c : allCons) { + if(c.getRight().equals(Type.getInternalName(Object.class))) + size--; + } + ArrayList methodTphs = new ArrayList<>(); + for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { + if(m.getName().equals(name)) { + methodTphs = m.getTphs(); + break; + } + } + + HashMap subAndSuper = new HashMap<>(); + for(TPHConstraint c : allCons) { + if(subAndSuper.containsKey(c.getLeft())) { + LinkedList all = new LinkedList<>(); + all.add(c.getLeft()); + String sup =c.getRight(); + all.add(sup); + HashMap ss = new HashMap<>(); + for(TPHConstraint constr : allCons) { + ss.put(constr.getLeft(), constr.getRight()); + } + while(ss.containsKey(sup)) { + sup = ss.get(sup); + all.add(sup); + } + if(!containTPH(methodTphs, all.getLast())) + continue; + } + subAndSuper.put(c.getLeft(), c.getRight()); + } + + int numOfVisitedPairs = 0; + for(String sub : subAndSuper.keySet()) { + if(isTPHInConstraint(result,sub)) + continue; + + if(!containTPH(methodTphs,sub)) + continue; + + if(numOfVisitedPairs>=size) + break; + LinkedList tphInRel = new LinkedList<>(); + tphInRel.add(sub); + String superT = subAndSuper.get(sub); + tphInRel.add(superT); + + numOfVisitedPairs++; + while(subAndSuper.containsKey(superT)) { + superT = subAndSuper.get(superT); + if(tphInRel.contains(superT)) { + break; + } + tphInRel.add(superT); + numOfVisitedPairs++; + } + + // Subtype + String subTphRes = tphInRel.getFirst(); + // Die größte Supertype + String superTphRes = tphInRel.getLast(); + + while(subAndSuper.containsValue(subTphRes)) { + for(String tph : subAndSuper.keySet()) { + if(containTPH(methodTphs,tph) && subAndSuper.get(tph).equals(subTphRes)) { + subTphRes = tph; + break; + } + } + if(subTphRes.equals(tphInRel.getFirst())) { + break; + } + tphInRel.addFirst(subTphRes); + numOfVisitedPairs++; + } + + subTphRes = tphInRel.getFirst(); + + int i = 2; + while(!containTPH(methodTphs,superTphRes) && (tphInRel.size()-i) >0) { + superTphRes = tphInRel.get(tphInRel.size()-i); + i++; + } + + if(!containTPH(methodTphs, superTphRes)) { + result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + } else { + result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), null); + result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + } + } + + for(TypePlaceholder tph : methodTphs) { + if(!isTPHInConstraint(result, tph.getName())) { + result.put(new ExtendsConstraint(tph.getName(), Type.getInternalName(Object.class), Relation.EXTENDS), null); + } + } + + System.out.println("EndResult: "); + result.forEach((c,hs)->{ + if(c!=null) { + System.out.print(c.toString() + " -> "); + if(hs == null) { + System.out.print(" [] "); + }else { + hs.forEach(s->{ + System.out.print(s + ", "); + }); + } + } + + + System.out.println(); + }); + System.out.println("----------------"); + return result; + } + + public static HashMap> simplifyContraints(HashMap> allConstraints) { + // 1. check if there are any cycles like L set L=R and: + // * remove both constraints + // * substitute L with R in all constraint + // b)no => go to next step + // 2. check the result of step 1 if there are any equal-constraints like L=R, M=R .. + // a) yes => put all such TPhs in a map and define "key-Cons" + // -- key-Cons = TPH < Object -- + // put this Constraint and the + // b) no + // 3. is + ArrayList allCons = new ArrayList<>(); + for(TPHConstraint tphCons : allConstraints.keySet()) { + allCons.add(tphCons); + } + ArrayList consToRemove = new ArrayList<>(); + // step 1: + for(TPHConstraint c : allCons) { + + String left = c.getLeft(); + String right = c.getRight(); + if(c.getRel() == Relation.EXTENDS) { + TPHConstraint revCon = getReverseConstraint(allCons,left,right); + if(revCon != null) { + revCon.setRel(Relation.EQUAL); + consToRemove.add(revCon); + c.setRel(Relation.EQUAL); + substituteTPH(allCons,left, right); + } + } + } + System.out.println(); + System.out.println("NEW ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + allCons.removeAll(consToRemove); + consToRemove = new ArrayList<>(); + +// int size = allCons.size(); + + System.out.println("AFTER DELETE ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + HashMap> result = new HashMap<>(); + + for(TPHConstraint c : allCons) { + if(c.getRel()==Relation.EQUAL) { + HashSet equalTPHs = getEqualsTPHs(result, c); + TPHConstraint constraint = getKeyConstraint(result,c); + equalTPHs.add(c.getLeft()); + equalTPHs.add(c.getRight()); + result.put(constraint, equalTPHs); + consToRemove.add(c); +// size--; + } + } + System.out.println("Step 2 Result: "); + result.forEach((c,hs)->{ + System.out.print(c.toString() + " -> "); + hs.forEach(s->{ + System.out.print(s + ", "); + }); + System.out.println(); + }); + System.out.println("----------------"); + allCons.removeAll(consToRemove); + allCons.addAll(result.keySet()); + + if(!allCons.isEmpty() && allCons.size()<2) { + + if(!result.containsKey(allCons.get(0))) + result.put(allCons.get(0), null); + + return result; + } + +// size += result.keySet().size(); + +// for(TPHConstraint c : allCons) { +// if(c.getRight().equals(Type.getInternalName(Object.class))) +// size--; +// } + + HashMap subAndSuper = new HashMap<>(); + + for(TPHConstraint c : allCons) { + subAndSuper.put(c.getLeft(), c.getRight()); + } + +// int numOfVisitedPairs = 0; + for(String sub : subAndSuper.keySet()) { + if(isTPHInConstraint(result,sub)) + continue; + +// if(numOfVisitedPairs>=size) +// break; + + LinkedList tphInRel = new LinkedList<>(); + tphInRel.add(sub); + String superT = subAndSuper.get(sub); + tphInRel.add(superT); + +// numOfVisitedPairs++; + while(subAndSuper.containsKey(superT)) { + superT = subAndSuper.get(superT); + if(tphInRel.contains(superT)) { + break; + } + tphInRel.add(superT); +// numOfVisitedPairs++; + } + + // Subtype + String subTphRes = tphInRel.getFirst(); + // Die größte Supertype + String superTphRes = tphInRel.getLast(); + + while(subAndSuper.containsValue(subTphRes)) { + for(String tph : subAndSuper.keySet()) { + if(subAndSuper.get(tph).equals(subTphRes)) { + subTphRes = tph; + break; + } + } + if(subTphRes.equals(tphInRel.getFirst())) { + break; + } + tphInRel.addFirst(subTphRes); +// numOfVisitedPairs++; + } + + subTphRes = tphInRel.getFirst(); + + int i = 2; + while(superTphRes.equals(Type.getInternalName(Object.class)) && (tphInRel.size()-i) >0) { + superTphRes = tphInRel.get(tphInRel.size()-i); + i++; + } + if(superTphRes.equals(Type.getInternalName(Object.class))) { + result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + } else { + result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), null); + result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + } + + } + System.out.println("EndResult: "); + result.forEach((c,hs)->{ + if(c!=null) { + System.out.print(c.toString() + " -> "); + if(hs == null) { + System.out.print(" [] "); + }else { + hs.forEach(s->{ + System.out.print(s + ", "); + }); + } + } + + + System.out.println(); + }); + System.out.println("----------------"); + return result; + } + + private static void substituteTPH(ArrayList allCons,String left ,String right) { + allCons.forEach(c->{ + if(c.getRel() == Relation.EXTENDS) { + if(c.getLeft().equals(left)) + c.setLeft(right); + if(c.getRight().equals(left)) + c.setRight(right); + } + }); + } + + private static TPHConstraint getReverseConstraint(ArrayList allCons, String left, String right) { + for(TPHConstraint c : allCons) { + if(c.getLeft().equals(right) && c.getRight().equals(left)){ + return c; + } + } + return null; + } + + private static boolean isTPHInConstraint(HashMap> result, String sub) { + for(TPHConstraint c : result.keySet()) { + if(c.getLeft().equals(sub)) + return true; + } + return false; + } + + private static boolean containTPH(ArrayList methodTphs, String sub) { + for(TypePlaceholder tph : methodTphs) { + if(tph.getName().equals(sub)) + return true; + } + return false; + } + + private static TPHConstraint getKeyConstraint(HashMap> result, TPHConstraint toFind) { + for(TPHConstraint c : result.keySet()) { + if(c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) + return c; + } + return new ExtendsConstraint(toFind.getRight(), Type.getInternalName(Object.class), Relation.EXTENDS); + } + + private static HashSet getEqualsTPHs(HashMap> result, TPHConstraint toFind) { + for(TPHConstraint c : result.keySet()) { + if(c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) + return result.get(c); + } + return new HashSet<>(); + } +}