Use JavaClassName instead of Strings

This commit is contained in:
JanUlrich 2019-12-14 15:35:52 +01:00
parent 09a6aec65d
commit af5b23e31a
11 changed files with 82 additions and 44 deletions

View File

@ -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<ResultSet> listOfResultSets;
@ -107,7 +108,7 @@ public class BytecodeGen implements ASTVisitor {
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes = new HashMap<>();
byte[] bytecode;
HashMap<String, byte[]> classFiles;
HashMap<JavaClassName, byte[]> classFiles;
private final ArrayList<String> methodNameAndParamsT = new ArrayList<>();
private final ArrayList<String> fieldNameAndParamsT = new ArrayList<>();
@ -119,7 +120,7 @@ public class BytecodeGen implements ASTVisitor {
private Resolver resolver;
public BytecodeGen(HashMap<String, byte[]> classFiles, Collection<ResultSet> listOfResultSets, List<GenericGenratorResultForSourceFile> simplifyResultsForAllSourceFiles, SourceFile sf,
public BytecodeGen(HashMap<JavaClassName, byte[]> classFiles, Collection<ResultSet> listOfResultSets, List<GenericGenratorResultForSourceFile> 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<String, byte[]> getClassFiles() {
public HashMap<JavaClassName, byte[]> 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<ResultSet> 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());

View File

@ -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<String, Integer> 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<String, byte[]> classFiles;
private HashMap<JavaClassName, byte[]> classFiles;
private int constructorPos = 0;
private ArrayList<RefTypeOrTPHOrWildcardOrGeneric> varsFunInterface = new ArrayList<>();;
// generate bytecode for constructor
public BytecodeGenMethod(String className, String superClass,ResultSet resultSet, Method m, MethodVisitor mv,
HashMap<String, Integer> paramsAndLocals, ClassWriter cw, HashMap<String, String> genericsAndBoundsMethod,
HashMap<String, String> genericsAndBounds, boolean isInterface, HashMap<String, byte[]> classFiles,
SourceFile sf,String path, Block block, int constructorPos) {
public BytecodeGenMethod(JavaClassName className, String superClass, ResultSet resultSet, Method m, MethodVisitor mv,
HashMap<String, Integer> paramsAndLocals, ClassWriter cw, HashMap<String, String> genericsAndBoundsMethod,
HashMap<String, String> genericsAndBounds, boolean isInterface, HashMap<JavaClassName, byte[]> 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<String, Integer> paramsAndLocals, ClassWriter cw, HashMap<String, String> genericsAndBoundsMethod,
HashMap<String, String> genericsAndBounds, boolean isInterface, HashMap<String, byte[]> classFiles, SourceFile sf,String path) {
HashMap<String, String> genericsAndBounds, boolean isInterface, HashMap<JavaClassName, byte[]> 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<String> usedVars, ResultSet resultSet, MethodVisitor mv,
int indexOfFirstParamLam, boolean isInterface, HashMap<String, byte[]> classFiles, String path, int lamCounter, SourceFile sf,HashMap<String, String> genericsAndBoundsMethod,
public BytecodeGenMethod(JavaClassName className, ClassWriter cw, LambdaExpression lambdaExpression, ArrayList<String> usedVars, ResultSet resultSet, MethodVisitor mv,
int indexOfFirstParamLam, boolean isInterface, HashMap<JavaClassName, byte[]> classFiles, String path, int lamCounter, SourceFile sf,HashMap<String, String> genericsAndBoundsMethod,
HashMap<String, String> 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<Boolean> 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));

View File

@ -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<String> 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<ResultSet> listOfResultSetsList = new ArrayList<>(listOfResultSets);
boolean isVisited = false;

View File

@ -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<String> tphsClass, final ConstraintsSimplierResult simplifiedConstraints) {
List<GenericsGeneratorResult> classConstraints = generateConstraintsForClass(tphExtractor,

View File

@ -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()

View File

@ -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<GenericsGeneratorResult> 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<GenericsGeneratorResult> classConstraints,
GenericGeneratorResultsForAllMethods methodsAndTheirConstraints) {
public GenericsGeneratorResultForClass(JavaClassName className, List<GenericsGeneratorResult> 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;
}

View File

@ -714,7 +714,7 @@ public class JavaTXCompiler {
return ret;
}
public void generateBytecodForFile(String path, HashMap<String, byte[]> classFiles, SourceFile sf,
public void generateBytecodForFile(String path, HashMap<JavaClassName, byte[]> classFiles, SourceFile sf,
List<ResultSet> typeinferenceResult) throws IOException {
try {
List<GenericGenratorResultForSourceFile> 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<ResultSet> typeinferenceResult = this.typeInference();
List<GenericGenratorResultForSourceFile> simplifyResultsForAllSourceFiles = getGeneratedGenericResultsForAllSourceFiles(
@ -770,27 +772,28 @@ public class JavaTXCompiler {
public void generateBytecode(String path, List<ResultSet> typeinferenceResult,
List<GenericGenratorResultForSourceFile> simplifyResultsForAllSourceFiles) throws IOException {
for (File f : sourceFiles.keySet()) {
HashMap<String, byte[]> classFiles = new HashMap<>();
HashMap<JavaClassName, byte[]> 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<String, byte[]> classFiles, String path) throws IOException {
private void writeClassFile(HashMap<JavaClassName, byte[]> 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");

View File

@ -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;
}
}

View File

@ -47,7 +47,7 @@ public class TypeInsertFactory {
new TypeToInsertString(resolvedType.resolvedType).insert);
List<GenericGenratorResultForSourceFile> 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());
}

View File

@ -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());
}
}

View File

@ -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