From af5b23e31aa731758eadd292f097bc2350474543 Mon Sep 17 00:00:00 2001 From: JanUlrich Date: Sat, 14 Dec 2019 15:35:52 +0100 Subject: [PATCH] Use JavaClassName instead of Strings --- .../dhbwstuttgart/bytecode/BytecodeGen.java | 17 ++++++------ .../bytecode/BytecodeGenMethod.java | 27 ++++++++++--------- .../GeneratedGenericsFinder.java | 5 ++-- .../genericsGenerator/GenericsGenerator.java | 3 ++- .../GenericGenratorResultForSourceFile.java | 6 +++-- .../GenericsGeneratorResultForClass.java | 12 +++++---- .../de/dhbwstuttgart/core/JavaTXCompiler.java | 21 ++++++++------- .../parser/scope/JavaClassName.java | 13 ++++++++- .../typedeployment/TypeInsertFactory.java | 2 +- src/test/java/packages/Bytecode.java | 4 +-- vorgehen.md | 16 +++++++++++ 11 files changed, 82 insertions(+), 44 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java index 508bd520..e0602731 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -7,6 +7,7 @@ import java.util.Iterator; import java.util.List; import java.util.Optional; +import de.dhbwstuttgart.parser.scope.JavaClassName; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; @@ -81,7 +82,7 @@ public class BytecodeGen implements ASTVisitor { String type; public static RefTypeOrTPHOrWildcardOrGeneric THISTYPE = null; - private String className; + private JavaClassName className; private String pkgName; private boolean isInterface; private Collection listOfResultSets; @@ -107,7 +108,7 @@ public class BytecodeGen implements ASTVisitor { HashMap methodParamsAndTypes = new HashMap<>(); byte[] bytecode; - HashMap classFiles; + HashMap classFiles; private final ArrayList methodNameAndParamsT = new ArrayList<>(); private final ArrayList fieldNameAndParamsT = new ArrayList<>(); @@ -119,7 +120,7 @@ public class BytecodeGen implements ASTVisitor { private Resolver resolver; - public BytecodeGen(HashMap classFiles, Collection listOfResultSets, List simplifyResultsForAllSourceFiles, SourceFile sf, + public BytecodeGen(HashMap classFiles, Collection listOfResultSets, List simplifyResultsForAllSourceFiles, SourceFile sf, String path) { this.classFiles = classFiles; this.listOfResultSets = listOfResultSets; @@ -135,7 +136,7 @@ public class BytecodeGen implements ASTVisitor { System.out.println("in Class: " + cl.getClassName().toString()); BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets, simplifyResultsForAllSourceFiles, sf, path); cl.accept(classGen); - classGen.writeClass(cl.getClassName().toString()); + classGen.writeClass(cl.getClassName()); } } @@ -145,20 +146,20 @@ public class BytecodeGen implements ASTVisitor { * * @param name name of the class with which the bytecode is to be associated */ - private void writeClass(String name) { + private void writeClass(JavaClassName name) { bytecode = cw.toByteArray(); classFiles.put(name, bytecode); } - public HashMap getClassFiles() { + public HashMap getClassFiles() { return classFiles; } @Override public void visit(ClassOrInterface classOrInterface) { - className = classOrInterface.getClassName().toString(); + className = classOrInterface.getClassName(); cw.visitSource(className + ".jav", null); @@ -172,7 +173,7 @@ public class BytecodeGen implements ASTVisitor { // resultSet = listOfResultSets.get(0); boolean isVisited = false; List listOfResultSetsList = new ArrayList<>(listOfResultSets); - generatedGenerics = simplifyResultsForAllSourceFiles.stream().map(sr->sr.getSimplifyResultsByName(pkgName, className)).findFirst().get(); + generatedGenerics = simplifyResultsForAllSourceFiles.stream().map(sr->sr.getSimplifyResultsByName(className)).findFirst().get(); for (int i = 0; i < listOfResultSetsList.size(); i++) { //for (ResultSet rs : listOfResultSets) { superClass = classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 46caa52b..9a485561 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -15,6 +15,7 @@ import java.util.List; import de.dhbwstuttgart.bytecode.utilities.*; import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr.Operator; import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr.Operation; @@ -45,7 +46,7 @@ public class BytecodeGenMethod implements StatementVisitor { private Method m; private MethodVisitor mv; private HashMap paramsAndLocals = new HashMap<>(); - private String className; + private JavaClassName className; private int lamCounter; private ClassWriter cw; private ResultSet resultSet; @@ -71,16 +72,16 @@ public class BytecodeGenMethod implements StatementVisitor { private boolean isRightSideALambda = false; private KindOfLambda kindOfLambda; - private HashMap classFiles; + private HashMap classFiles; private int constructorPos = 0; private ArrayList varsFunInterface = new ArrayList<>();; // generate bytecode for constructor - public BytecodeGenMethod(String className, String superClass,ResultSet resultSet, Method m, MethodVisitor mv, - HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod, - HashMap genericsAndBounds, boolean isInterface, HashMap classFiles, - SourceFile sf,String path, Block block, int constructorPos) { + public BytecodeGenMethod(JavaClassName className, String superClass, ResultSet resultSet, Method m, MethodVisitor mv, + HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod, + HashMap genericsAndBounds, boolean isInterface, HashMap classFiles, + SourceFile sf, String path, Block block, int constructorPos) { this.className = className; this.superClass = superClass; @@ -105,9 +106,9 @@ public class BytecodeGenMethod implements StatementVisitor { } - public BytecodeGenMethod(String className, String superClass,ResultSet resultSet, Method m, MethodVisitor mv, + public BytecodeGenMethod(JavaClassName className, String superClass,ResultSet resultSet, Method m, MethodVisitor mv, HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod, - HashMap genericsAndBounds, boolean isInterface, HashMap classFiles, SourceFile sf,String path) { + HashMap genericsAndBounds, boolean isInterface, HashMap classFiles, SourceFile sf,String path) { this.className = className; this.superClass = superClass; @@ -129,8 +130,8 @@ public class BytecodeGenMethod implements StatementVisitor { } - public BytecodeGenMethod(String className, ClassWriter cw, LambdaExpression lambdaExpression, ArrayList usedVars, ResultSet resultSet, MethodVisitor mv, - int indexOfFirstParamLam, boolean isInterface, HashMap classFiles, String path, int lamCounter, SourceFile sf,HashMap genericsAndBoundsMethod, + public BytecodeGenMethod(JavaClassName className, ClassWriter cw, LambdaExpression lambdaExpression, ArrayList usedVars, ResultSet resultSet, MethodVisitor mv, + int indexOfFirstParamLam, boolean isInterface, HashMap classFiles, String path, int lamCounter, SourceFile sf,HashMap genericsAndBoundsMethod, HashMap genericsAndBounds) { this.className = className; this.cw = cw; @@ -622,7 +623,7 @@ public class BytecodeGenMethod implements StatementVisitor { } String newDesc = addUsedVarsToDesugaredMethodDescriptor(lamDesc); // first check if capturing lambda then invokestatic or invokespecial - Handle arg2 = new Handle(staticOrSpecial, this.className, desugaredMethodName, newDesc, false); + Handle arg2 = new Handle(staticOrSpecial, this.className.toString(), desugaredMethodName, newDesc, false); // Descriptor of functional interface methode SamMethod samMethod = new SamMethod(kindOfLambda.getArgumentList(), lambdaExpression.getType()); // Desc: (this/nothing)TargetType @@ -797,7 +798,7 @@ public class BytecodeGenMethod implements StatementVisitor { } if(methodRefl == null) { - boolean toCreate = !receiverName.equals(className) && helper.isInCurrPkg(clazz); + boolean toCreate = !receiverName.equals(className.toString()) && helper.isInCurrPkg(clazz); if(toCreate) { try { mDesc = helper.getDesc(clazz); @@ -832,7 +833,7 @@ public class BytecodeGenMethod implements StatementVisitor { System.out.println("Methodcall type : " + resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor())); List argListMethCall = new LinkedList<>(); String receiverRefl=""; - if(methodRefl == null && receiverName.equals(className)) { + if(methodRefl == null && receiverName.equals(className.toString())) { MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), receiverName, genericsAndBoundsMethod, genericsAndBounds); mDesc = method.accept(new DescriptorToString(resultSet)); diff --git a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java index 5e473ebe..ba55c4c7 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java @@ -16,6 +16,7 @@ import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; import de.dhbwstuttgart.bytecode.utilities.MethodUtility; import de.dhbwstuttgart.bytecode.utilities.Resolver; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.ASTVisitor; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.Constructor; @@ -75,7 +76,7 @@ public class GeneratedGenericsFinder implements ASTVisitor { private final List methodNameAndParamsT = new ArrayList<>(); private String pkgName; - private String className; + private JavaClassName className; private Resolver resolver; /** @@ -117,7 +118,7 @@ public class GeneratedGenericsFinder implements ASTVisitor { */ @Override public void visit(ClassOrInterface classOrInterface) { - className = classOrInterface.getClassName().toString(); + className = classOrInterface.getClassName(); List listOfResultSetsList = new ArrayList<>(listOfResultSets); boolean isVisited = false; diff --git a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGenerator.java b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGenerator.java index a541025c..8e5bd481 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGenerator.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGenerator.java @@ -12,6 +12,7 @@ import java.util.Set; import java.util.stream.Collectors; import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.*; +import de.dhbwstuttgart.parser.scope.JavaClassName; import org.objectweb.asm.Type; import de.dhbwstuttgart.bytecode.TPHExtractor; @@ -30,7 +31,7 @@ public class GenericsGenerator { class constraints: tphClass < tphMeth1, tphMeth1 < tphMeth2, tphMeth2 < Object */ - public static GenericsGeneratorResultForClass generateConstraints(final String className, final TPHExtractor tphExtractor, + public static GenericsGeneratorResultForClass generateConstraints(final JavaClassName className, final TPHExtractor tphExtractor, final List tphsClass, final ConstraintsSimplierResult simplifiedConstraints) { List classConstraints = generateConstraintsForClass(tphExtractor, diff --git a/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericGenratorResultForSourceFile.java b/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericGenratorResultForSourceFile.java index 85d0bcbf..f0d11473 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericGenratorResultForSourceFile.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericGenratorResultForSourceFile.java @@ -3,6 +3,8 @@ */ package de.dhbwstuttgart.bytecode.genericsGeneratorTypes; +import de.dhbwstuttgart.parser.scope.JavaClassName; + import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; @@ -37,9 +39,9 @@ public class GenericGenratorResultForSourceFile { genericGeneratorResultForAllClasses.add(sResClass); } - public GenericsGeneratorResultForClass getSimplifyResultsByName(String pkgName, String name) { + public GenericsGeneratorResultForClass getSimplifyResultsByName(JavaClassName name) { - if (this.pkgName.equals(pkgName)) { + if (this.pkgName.equals(name.getPackageName())) { return genericGeneratorResultForAllClasses.stream() .filter(sr -> sr.getClassName().equals(name)) .findAny() diff --git a/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericsGeneratorResultForClass.java b/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericsGeneratorResultForClass.java index d6532ecb..eaeb1f3a 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericsGeneratorResultForClass.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericsGeneratorResultForClass.java @@ -3,6 +3,8 @@ */ package de.dhbwstuttgart.bytecode.genericsGeneratorTypes; +import de.dhbwstuttgart.parser.scope.JavaClassName; + import java.util.Collections; import java.util.List; @@ -11,11 +13,11 @@ import java.util.List; * */ public class GenericsGeneratorResultForClass { - private final String className; + private final JavaClassName className; private final List classConstraints; private final GenericGeneratorResultsForAllMethods methodsAndTheirConstraints; - public GenericsGeneratorResultForClass(String className) { + public GenericsGeneratorResultForClass(JavaClassName className) { this(className, Collections.emptyList(), new GenericGeneratorResultsForAllMethods()); } /** @@ -23,8 +25,8 @@ public class GenericsGeneratorResultForClass { * @param classConstraints * @param methodsAndTheirConstraints */ - public GenericsGeneratorResultForClass(String className, List classConstraints, - GenericGeneratorResultsForAllMethods methodsAndTheirConstraints) { + public GenericsGeneratorResultForClass(JavaClassName className, List classConstraints, + GenericGeneratorResultsForAllMethods methodsAndTheirConstraints) { this.className = className; this.classConstraints = classConstraints; this.methodsAndTheirConstraints = methodsAndTheirConstraints; @@ -33,7 +35,7 @@ public class GenericsGeneratorResultForClass { /** * @return the className */ - public String getClassName() { + public JavaClassName getClassName() { return className; } diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java index 5f107ed0..3c234175 100644 --- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -714,7 +714,7 @@ public class JavaTXCompiler { return ret; } - public void generateBytecodForFile(String path, HashMap classFiles, SourceFile sf, + public void generateBytecodForFile(String path, HashMap classFiles, SourceFile sf, List typeinferenceResult) throws IOException { try { List genericResults = getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); @@ -753,7 +753,9 @@ public class JavaTXCompiler { return result; } - // um pfad erweitern + /** + * @param path - can be null, then class file output is in the same directory as the parsed source files + */ public void generateBytecode(String path) throws ClassNotFoundException, IOException, BytecodeGeneratorError { List typeinferenceResult = this.typeInference(); List simplifyResultsForAllSourceFiles = getGeneratedGenericResultsForAllSourceFiles( @@ -770,27 +772,28 @@ public class JavaTXCompiler { public void generateBytecode(String path, List typeinferenceResult, List simplifyResultsForAllSourceFiles) throws IOException { for (File f : sourceFiles.keySet()) { - HashMap classFiles = new HashMap<>(); + HashMap classFiles = new HashMap<>(); SourceFile sf = sourceFiles.get(f); BytecodeGen bytecodeGen = new BytecodeGen(classFiles, typeinferenceResult, simplifyResultsForAllSourceFiles, sf, path); bytecodeGen.visit(sf); - String packagePath = sf.getPkgName().replace(".","/"); if(path == null){ - path = f.getPath(); + path = f.getParent(); //Set path to path of the parsed .jav file + }else{ + path += sf.getPkgName().replace(".","/"); //add package path to root path } - writeClassFile(bytecodeGen.getClassFiles(), path + packagePath); + writeClassFile(bytecodeGen.getClassFiles(), path); } } - private void writeClassFile(HashMap classFiles, String path) throws IOException { + private void writeClassFile(HashMap classFiles, String path) throws IOException { FileOutputStream output; - for (String name : classFiles.keySet()) { + for (JavaClassName name : classFiles.keySet()) { byte[] bytecode = classFiles.get(name); System.out.println("generating " + name + ".class file ..."); // output = new FileOutputStream(new File(System.getProperty("user.dir") + // "/testBytecode/generatedBC/" +name+".class")); - output = new FileOutputStream(new File(path + name + ".class")); + output = new FileOutputStream(new File(path + File.separator + name.getClassName() + ".class")); output.write(bytecode); output.close(); System.out.println(name + ".class file generated"); diff --git a/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassName.java b/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassName.java index b87ff719..534d0916 100644 --- a/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassName.java +++ b/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassName.java @@ -84,7 +84,15 @@ public class JavaClassName { @Override public String toString() { - return (packageName!=null ? packageName.toString() : "") + name; + return (packageName!=null ? packageName.toString() + "." : "") + name; + } + + public String getPackageName() { + return (packageName!=null ? packageName.toString() : ""); + } + + public String getClassName(){ + return name; } } @@ -130,6 +138,9 @@ class PackageName{ String ret = ""; if(names == null)return ""; for(String n : names)ret+=n+"."; + if (ret != null && ret.length() > 0 && ret.charAt(ret.length() - 1) == '.') { + ret = ret.substring(0, ret.length() - 1); + } return ret; } } diff --git a/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java b/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java index 44bfd2ff..ebef5263 100644 --- a/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java +++ b/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java @@ -47,7 +47,7 @@ public class TypeInsertFactory { new TypeToInsertString(resolvedType.resolvedType).insert); List simplifyResults = JavaTXCompiler.INSTANCE.getGeneratedGenericResultsForAllSourceFiles(newResults); for (GenericGenratorResultForSourceFile simplifyResultsEntries : simplifyResults) { - GenericsGeneratorResultForClass genericResultsForClass = simplifyResultsEntries.getSimplifyResultsByName("", cl.getClassName().toString()); + GenericsGeneratorResultForClass genericResultsForClass = simplifyResultsEntries.getSimplifyResultsByName(cl.getClassName()); return new TypeInsert(insertPoint, createGenericInsert(genericResultsForClass, cl, m, resultSet, offset), resolvedType.getResultPair()); } diff --git a/src/test/java/packages/Bytecode.java b/src/test/java/packages/Bytecode.java index f02c83fa..1f7854c1 100644 --- a/src/test/java/packages/Bytecode.java +++ b/src/test/java/packages/Bytecode.java @@ -14,12 +14,12 @@ public class Bytecode extends TestCase { public void testSetPackageNameInBytecode() throws IOException, ClassNotFoundException { JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"packageNameTest.jav")); compiler.typeInference(); - File f = new File(rootDirectory + "Test.class"); + File f = new File(rootDirectory + "TestClass.class"); if(f.exists() && !f.isDirectory()) { f.delete(); } compiler.generateBytecode(null); - f = new File(rootDirectory + "Test.class"); + f = new File(rootDirectory + "TestClass.class"); assertTrue(f.exists()); } } diff --git a/vorgehen.md b/vorgehen.md index 61b62c4f..f6a3f169 100644 --- a/vorgehen.md +++ b/vorgehen.md @@ -28,3 +28,19 @@ * Optional * damit lässt sich ein andere ort zur Ausgabe der Class-files bestimmen +# Tasks +## Class files in richtigen Ordner legen ## +* Wenn Pfad übergeben, dann in Pfad + packageName +* Ohne Pfad, direkt neben die Source File legen +* wenn Source File nicht in richtigem Ordner -> Warnung ausgeben + +## Class files einlesen +* Wenn Classpath übergeben + * Suchen in Classpath + packageName +* Wenn nichts übergeben + * dann currentDirectory + packageName +* Für die Tests muss korrekter Classpath gesetzt werden + +## Class files mit packageNamen versehen +* In die Class file muss noch der korrekte name geschrieben werden + * kann möglicherweise ASM