|
|
|
@ -2,7 +2,9 @@ package de.dhbwstuttgart.bytecode;
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.Iterator;
|
|
|
|
|
import java.util.LinkedList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
|
|
|
@ -13,6 +15,9 @@ import org.objectweb.asm.MethodVisitor;
|
|
|
|
|
import org.objectweb.asm.Opcodes;
|
|
|
|
|
import org.objectweb.asm.Type;
|
|
|
|
|
|
|
|
|
|
import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint;
|
|
|
|
|
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
|
|
|
|
|
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation;
|
|
|
|
|
import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
|
|
|
|
|
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
|
|
|
|
|
import de.dhbwstuttgart.bytecode.signature.Signature;
|
|
|
|
@ -175,6 +180,11 @@ public class BytecodeGen implements ASTVisitor {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void visit(Constructor field) {
|
|
|
|
|
System.out.println("ResultSet: ");
|
|
|
|
|
resultSet.results.forEach(a->{
|
|
|
|
|
System.out.println(a.getLeft().toString() + " = " + a.getRight().toString());
|
|
|
|
|
});
|
|
|
|
|
System.out.println("---------------");
|
|
|
|
|
field.getParameterList().accept(this);
|
|
|
|
|
|
|
|
|
|
String methParamTypes = field.name+"%%";
|
|
|
|
@ -205,7 +215,7 @@ public class BytecodeGen implements ASTVisitor {
|
|
|
|
|
}
|
|
|
|
|
String sig = null;
|
|
|
|
|
if(hasGen) {
|
|
|
|
|
ArrayList<GenericInsertPair> pairs = simplifyPairs(field.name,tphExtractor.allPairs);
|
|
|
|
|
ArrayList<GenericInsertPair> pairs = simplifyPairs(field.name,tphExtractor.allPairs, tphExtractor.allCons);
|
|
|
|
|
Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,pairs);
|
|
|
|
|
sig = signature.toString();
|
|
|
|
|
}
|
|
|
|
@ -274,7 +284,11 @@ public class BytecodeGen implements ASTVisitor {
|
|
|
|
|
/* if method has generics or return type is TPH, create signature */
|
|
|
|
|
// zwite operand muss weggelassen werden
|
|
|
|
|
if(hasGen||resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString()).equals("TPH")) {
|
|
|
|
|
ArrayList<GenericInsertPair> pairs = simplifyPairs(method.name,tphExtractor.allPairs);
|
|
|
|
|
System.out.println("ALL CONST: " + tphExtractor.allCons.size());
|
|
|
|
|
tphExtractor.allCons.forEach(c->System.out.println(c.toString()));
|
|
|
|
|
System.out.println("----------------");
|
|
|
|
|
HashMap<TPHConstraint, HashSet<String>> constraints = simplifyPairs(method.name,tphExtractor.allCons);
|
|
|
|
|
ArrayList<GenericInsertPair> 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);
|
|
|
|
@ -295,9 +309,263 @@ public class BytecodeGen implements ASTVisitor {
|
|
|
|
|
mv.visitEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ArrayList<GenericInsertPair> simplifyPairs(String methodName, ArrayList<GenericInsertPair> allPairs) {
|
|
|
|
|
private HashMap<TPHConstraint, HashSet<String>> simplifyPairs(String name, ArrayList<TPHConstraint> allCons) {
|
|
|
|
|
// 1. check if there are any cycles like L<R and R<L:
|
|
|
|
|
// a) yes => 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<TPHConstraint> 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<TPHConstraint, HashSet<String>> result = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
for(TPHConstraint c : allCons) {
|
|
|
|
|
if(c.getRel()==Relation.EQUAL) {
|
|
|
|
|
HashSet<String> 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.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<TypePlaceholder> methodTphs = new ArrayList<>();
|
|
|
|
|
for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) {
|
|
|
|
|
if(m.getName().equals(name)) {
|
|
|
|
|
methodTphs = m.getTphs();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HashMap<String, String> subAndSuper = new HashMap<>();
|
|
|
|
|
for(TPHConstraint c : allCons) {
|
|
|
|
|
if(subAndSuper.containsKey(c.getLeft())) {
|
|
|
|
|
LinkedList<String> all = new LinkedList<>();
|
|
|
|
|
all.add(c.getLeft());
|
|
|
|
|
String sup =c.getRight();
|
|
|
|
|
all.add(sup);
|
|
|
|
|
HashMap<String, String> 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<String> 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<TPHConstraint, HashSet<String>> result, String sub) {
|
|
|
|
|
for(TPHConstraint c : result.keySet()) {
|
|
|
|
|
if(c.getLeft().equals(sub))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean containTPH(ArrayList<TypePlaceholder> methodTphs, String sub) {
|
|
|
|
|
for(TypePlaceholder tph : methodTphs) {
|
|
|
|
|
if(tph.getName().equals(sub))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private TPHConstraint getKeyConstraint(HashMap<TPHConstraint, HashSet<String>> 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<String> getEqualsTPHs(HashMap<TPHConstraint,HashSet<String>> 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<GenericInsertPair> simplifyPairs(String methodName, ArrayList<GenericInsertPair> allPairs, ArrayList<TPHConstraint> allCons) {
|
|
|
|
|
allPairs.forEach(p->System.out.print(p.TA1 + " < "+ p.TA2+ " ; "));
|
|
|
|
|
|
|
|
|
|
// 1. check if there are any cycles like L<R and R<L:
|
|
|
|
|
// a) yes => 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<TPHConstraint> 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;
|
|
|
|
|
|
|
|
|
@ -425,6 +693,26 @@ public class BytecodeGen implements ASTVisitor {
|
|
|
|
|
return simplifiedPairs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void substituteTPH(ArrayList<TPHConstraint> 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<TPHConstraint> 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<GenericInsertPair> simplifiedPairs, TypePlaceholder typePlaceholder, TypePlaceholder typePlaceholder2) {
|
|
|
|
|
for(GenericInsertPair p : simplifiedPairs) {
|
|
|
|
|
if(p.TA1.equals(typePlaceholder) && p.TA2.equals(typePlaceholder2)) {
|
|
|
|
@ -492,7 +780,6 @@ public class BytecodeGen implements ASTVisitor {
|
|
|
|
|
fv.visitEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// access flages?? modifiers
|
|
|
|
|
@Override
|
|
|
|
|
public void visit(Field field) {
|
|
|
|
|
System.out.println("In Field ---");
|
|
|
|
@ -685,6 +972,7 @@ public class BytecodeGen implements ASTVisitor {
|
|
|
|
|
Boolean inMethod = false;
|
|
|
|
|
final ArrayList<MethodAndTPH> ListOfMethodsAndTph = new ArrayList<>();
|
|
|
|
|
final ArrayList<GenericInsertPair> allPairs = new ArrayList<>();
|
|
|
|
|
final ArrayList<TPHConstraint> allCons = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void visit(TypePlaceholder tph) {
|
|
|
|
@ -699,6 +987,8 @@ public class BytecodeGen implements ASTVisitor {
|
|
|
|
|
if(inMethod)
|
|
|
|
|
methodAndTph.getPairs().add(ag);
|
|
|
|
|
allPairs.add(ag);
|
|
|
|
|
TPHConstraint con = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS);
|
|
|
|
|
allCons.add(con);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|