diff --git a/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java b/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java index a9e2162e6..4a5e9ed83 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java @@ -9,6 +9,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; @@ -26,10 +27,16 @@ import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.ParameterList; import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.statement.Assign; +import de.dhbwstuttgart.syntaxtree.statement.AssignToField; +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver; +import de.dhbwstuttgart.syntaxtree.statement.FieldVar; import de.dhbwstuttgart.syntaxtree.statement.LocalVar; import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; import de.dhbwstuttgart.syntaxtree.statement.MethodCall; import de.dhbwstuttgart.syntaxtree.statement.Return; +import de.dhbwstuttgart.syntaxtree.statement.Statement; import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; @@ -45,13 +52,17 @@ import de.dhbwstuttgart.typeinference.result.ResultSet; public class TPHExtractor extends AbstractASTWalker { // Alle TPHs der Felder werden iKopf der Klasse definiert // alle TPHs der Klasse: (TPH, is in Method?) - public final SourceFile sf; /* - * ordnet den Methodennamen ihre jeweiligen Methodenrespraesentationen in der abstrakte Syntax zu + * ordnet den Methodennamen ihre jeweiligen Methodenrespraesentationen der abstrakte Syntax in der jeweiligen aktuellen Klasse zu */ - public final HashMap nameToMeth; + public HashMap nameToMeth; + + /* + * ordnet den Methodennamen ihre jeweiligen Methodenrespraesentationen der abstrakte Syntax in der jeweiligen aktuellen Klasse zu + */ + public HashMap nameToField; public final HashMap allTPHS = new HashMap<>(); public final List tphsClass = new ArrayList<>(); MethodAndTPH methodAndTph; @@ -65,12 +76,8 @@ public class TPHExtractor extends AbstractASTWalker { private ResultSet resultSet; private Resolver resolver; - public TPHExtractor(SourceFile sf) { - this.sf = sf; - this.nameToMeth = new HashMap<>(); - for(Method m : sf.getAllMethods()) { - this.nameToMeth.put(m.getName(), m); - } + public TPHExtractor() { + } public void setResultSet(ResultSet resultSet) { @@ -214,6 +221,28 @@ public class TPHExtractor extends AbstractASTWalker { ListOfMethodsAndTph.add(methodAndTph); } + @Override + public void visit(ClassOrInterface classOrInterface) { + Optional optInitialConstructor = classOrInterface.getfieldInitializations(); + this.nameToField = new HashMap<>(); + if (optInitialConstructor.isPresent()) { + classOrInterface.getfieldInitializations() + .get() + .block + .statements + .stream() + .filter(s -> s instanceof Assign) + .forEach(as -> + this.nameToField.put(((AssignToField)(((Assign)as).lefSide)).field.fieldVarName, ((Assign)as).rightSide)); + } + + this.nameToMeth = new HashMap<>(); + for(Method m : classOrInterface.getMethods()) { + this.nameToMeth.put(m.getName(), m); + } + super.visit(classOrInterface); + } + @Override public void visit(Constructor cons) { inMethod = false; @@ -252,26 +281,37 @@ public class TPHExtractor extends AbstractASTWalker { @Override public void visit(MethodCall methodCall) { + String fieldOrMethName; super.visit(methodCall); - if (nameToMeth.keySet().contains(methodCall.name)) {//Method-call of a method in the actuial Sourcefile - Iterator paraIt = nameToMeth.get(methodCall.name).getParameterList().iterator(); - methodCall.getArgumentList() - .getArguments() - .forEach(x -> { - RefTypeOrTPHOrWildcardOrGeneric left = resultSet.resolveType(x.getType()).resolvedType; - RefTypeOrTPHOrWildcardOrGeneric right = resultSet.resolveType(paraIt.next().getType()).resolvedType; - if (left instanceof TypePlaceholder && methodAndTph.getTphs().contains(((TypePlaceholder)left).getName())) { - if (right instanceof TypePlaceholder) { - methodAndTph.addPair(allPairs.stream().filter( + if (nameToMeth.keySet().contains(fieldOrMethName = methodCall.name) //Method-call of a method in the actuial Sourcefile + || (methodCall.name.equals("apply") && + (methodCall.receiver instanceof ExpressionReceiver) && + (((ExpressionReceiver)methodCall.receiver).expr instanceof FieldVar) && + nameToField.keySet().contains(fieldOrMethName=((FieldVar)((ExpressionReceiver)methodCall.receiver).expr).fieldVarName) + ) + ) + { + Iterator paraIt = + methodCall.name.equals("apply") + ? ((LambdaExpression)nameToField.get(fieldOrMethName)).params.iterator() + : nameToMeth.get(methodCall.name).getParameterList().iterator(); + methodCall.getArgumentList() + .getArguments() + .forEach(x -> { + RefTypeOrTPHOrWildcardOrGeneric left = resultSet.resolveType(x.getType()).resolvedType; + RefTypeOrTPHOrWildcardOrGeneric right = resultSet.resolveType(paraIt.next().getType()).resolvedType; + if (left instanceof TypePlaceholder && methodAndTph.getTphs().contains(((TypePlaceholder)left).getName())) { + if (right instanceof TypePlaceholder) { + methodAndTph.addPair(allPairs.stream().filter( p -> (p.getLeft() instanceof TypePlaceholder && p.getRight() instanceof TypePlaceholder) && ((TypePlaceholder)p.getLeft()).getName().equals(((TypePlaceholder)left).getName()) && ((TypePlaceholder)p.getRight()).getName().equals(((TypePlaceholder)right).getName()) ).findFirst() .get()); - } - } - }); + } + } + }); } } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java index 71c44f83b..6a89bde3c 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java @@ -86,7 +86,7 @@ public class GeneratedGenericsFinder implements ASTVisitor { public GeneratedGenericsFinder(SourceFile sf, Collection listOfResultSets) { this.sf = sf; this.listOfResultSets = listOfResultSets; - this.tphExtractor = new TPHExtractor(sf); + this.tphExtractor = new TPHExtractor(); } public GenericGenratorResultForSourceFile findGeneratedGenerics() { diff --git a/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/FamilyOfGeneratedGenerics.java b/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/FamilyOfGeneratedGenerics.java index 4859ab631..77d17f003 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/FamilyOfGeneratedGenerics.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/FamilyOfGeneratedGenerics.java @@ -4,10 +4,14 @@ 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 de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.ResultPair; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.stream.Collectors; + import org.objectweb.asm.Type; public class FamilyOfGeneratedGenerics { @@ -15,7 +19,7 @@ public class FamilyOfGeneratedGenerics { // HashMap speichert ob TPH in einer Methode oder in der Klasse ist; und wenn es in der Methode ist, in welcher Methode public HashMap>> posOfTPHs = new HashMap<>(); public List classConstraints = new ArrayList<>(); - public List methodConstraints = new ArrayList<>(); + //public List methodConstraints = new ArrayList<>(); public HashMap> methodConstraintsWithPosition = new HashMap<>(); private static final String objectType = Type.getInternalName(Object.class); @@ -24,7 +28,7 @@ public class FamilyOfGeneratedGenerics { this.allConstraints = tphExtractor.allCons; this.posOfTPHs = positionConverter(tphExtractor.allTPHS, tphExtractor.ListOfMethodsAndTph); this.classConstraints = getClassConstraints(allConstraints,posOfTPHs); - this.methodConstraints = getMethodConstraints(allConstraints,classConstraints,posOfTPHs, tphExtractor.ListOfMethodsAndTph); + //this.methodConstraints = getMethodConstraints(allConstraints,classConstraints,posOfTPHs, null, tphExtractor.ListOfMethodsAndTph); this.methodConstraintsWithPosition = getMethodConstraintsWithPosition(allConstraints,classConstraints,posOfTPHs, tphExtractor.ListOfMethodsAndTph); } @@ -59,10 +63,19 @@ public class FamilyOfGeneratedGenerics { return cs_cl; } - public static List getMethodConstraints(List cs, List cs_cl, HashMap>> posOfTphs, List listOfMethodsAndTph) { + public static List getMethodConstraints(List cs, + List cs_cl, + HashMap>> posOfTphs, + ArrayList> methodConstraints1Pairs, + List listOfMethodsAndTph) { List cs_m = new ArrayList<>(); List methodConstraints1 = typeOfTheMethodInClSigma(cs, posOfTphs); - //List methodConstraints1 = listOfMethodsAndTph. + + List methodConstraints1prime = + methodConstraints1Pairs.stream() + .map(p -> new MethodConstraint(p.getLeft().getName(), p.getRight().getName(), Relation.EXTENDS)) + .collect(Collectors.toList()); + for (MethodConstraint cons: methodConstraints1) { if (!checkForDuplicates(cons, cs_m)) { cs_m.add(cons); @@ -123,7 +136,7 @@ public class FamilyOfGeneratedGenerics { } } } - listOfThisMethod = getMethodConstraints(cs,cs_cl,posOfTPHsForThisMethod,listOfMethodsAndTph); + listOfThisMethod = getMethodConstraints(cs,cs_cl,posOfTPHsForThisMethod, method.getBasePairs(),listOfMethodsAndTph); tempMethodConstraintsWithPosition.put(currentMethod, listOfThisMethod); } } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java index de434ebb6..e26eca109 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java @@ -53,5 +53,9 @@ public class MethodAndTPH { public TypePlaceholder getReturnType() { return returnType; } + + public ArrayList> getBasePairs() { + return basePairs; + } } diff --git a/src/test/java/constraintSimplify/FamilyOfGenerics.java b/src/test/java/constraintSimplify/FamilyOfGenerics.java index 01b204b61..e5c9ad131 100644 --- a/src/test/java/constraintSimplify/FamilyOfGenerics.java +++ b/src/test/java/constraintSimplify/FamilyOfGenerics.java @@ -24,7 +24,7 @@ public class FamilyOfGenerics { public void generateBC() throws Exception { SourceFile sf = generateAST(); PositionFinder.getPositionOfTPH(sf, null); - TPHExtractor tphExtractor = new TPHExtractor(sf); + TPHExtractor tphExtractor = new TPHExtractor(); List results = new ArrayList(); GeneratedGenericsFinder generatedGenericsFinder = new GeneratedGenericsFinder(sf, results); } diff --git a/src/test/java/insertGenerics/TestTPHsAndGenerics.java b/src/test/java/insertGenerics/TestTPHsAndGenerics.java index ed5016c7e..e49ed3445 100644 --- a/src/test/java/insertGenerics/TestTPHsAndGenerics.java +++ b/src/test/java/insertGenerics/TestTPHsAndGenerics.java @@ -1,72 +1,58 @@ package insertGenerics; -import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; -import de.dhbwstuttgart.core.JavaTXCompiler; -import de.dhbwstuttgart.syntaxtree.SourceFile; -import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; -import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; -import de.dhbwstuttgart.typedeployment.TypeInsert; -import de.dhbwstuttgart.typedeployment.TypeInsertFactory; -import de.dhbwstuttgart.typeinference.result.ResultSet; -import org.junit.Test; + import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; + import de.dhbwstuttgart.core.JavaTXCompiler; + import de.dhbwstuttgart.syntaxtree.SourceFile; + import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; + import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; + import de.dhbwstuttgart.typedeployment.TypeInsert; + import de.dhbwstuttgart.typedeployment.TypeInsertFactory; + import de.dhbwstuttgart.typeinference.result.ResultSet; + import org.junit.Test; + + import java.io.File; + import java.io.IOException; + import java.lang.reflect.InvocationTargetException; + import java.net.URL; + import java.net.URLClassLoader; + import java.nio.charset.Charset; + import java.nio.charset.StandardCharsets; + import java.nio.file.Files; + import java.nio.file.Paths; + import java.util.HashSet; + import java.util.List; + import java.util.Set; -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.HashSet; -import java.util.List; -import java.util.Set; public class TestTPHsAndGenerics { - public static final String rootDirectory = System.getProperty("user.dir")+"/src/test/resources/insertGenericsJav/"; + private static final String rootDirectory = System.getProperty("user.dir")+"/src/test/resources/insertGenericsJav/"; + private String pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/"; + private static ClassLoader loader; + private static Class classToTest; + private static Object instanceOfClass; + private static String className = "TestTPHsAndGenerics"; + + @Test + public void ggFinder() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + execute(new File(rootDirectory+className+".jav")); + } - @Test - public void ggFinder() throws IOException, ClassNotFoundException { - execute(new File(rootDirectory+"TestTPHSAndGenerics.jav")); - } + private static class TestResultSet{ - private static class TestResultSet{ + } - } - - public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { - JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); - for(File f : compiler.sourceFiles.keySet()){ - SourceFile sf = compiler.sourceFiles.get(f); - } - List results = compiler.typeInference(); - List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); - //compiler.generateBytecode(rootDirectory+"xxx.class", results, simplifyResultsForAllSourceFiles); - for(File f : compiler.sourceFiles.keySet()){ - SourceFile sf = compiler.sourceFiles.get(f); - System.out.println(ASTTypePrinter.print(sf)); - System.out.println(ASTPrinter.print(sf)); - //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen - assert results.size()>0; - Set insertedTypes = new HashSet<>(); - for(ResultSet resultSet : results){ - Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet, results, simplifyResultsForAllSourceFiles); - assert result.size()>0; - String content = readFile(f.getPath(), StandardCharsets.UTF_8); - for(TypeInsert tip : result){ - insertedTypes.add(tip.insert(content)); - } - } - for(String s : insertedTypes){ - System.out.println(s); - } - } - return new TestResultSet(); - } - - static String readFile(String path, Charset encoding) - throws IOException - { - byte[] encoded = Files.readAllBytes(Paths.get(path)); - return new String(encoded, encoding); - } -} + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + /* + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + */ + return new TestResultSet(); + + } + }