diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index b1ea614f..69bb9250 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -33,12 +33,14 @@ import org.objectweb.asm.Type; import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureWriter; +import de.dhbwstuttgart.bytecode.Exception.NotInCurrentPackageException; import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.signature.Signature; import de.dhbwstuttgart.bytecode.signature.TypeToSignature; import de.dhbwstuttgart.bytecode.utilities.KindOfLambda; import de.dhbwstuttgart.bytecode.utilities.Lambda; +import de.dhbwstuttgart.bytecode.utilities.MethodCallHelper; import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall; import de.dhbwstuttgart.bytecode.utilities.SamMethod; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; @@ -52,6 +54,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.result.ResultSet; +import javassist.NotFoundException; public class BytecodeGenMethod implements StatementVisitor { @@ -763,7 +766,7 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(InstanceOf instanceOf) { } - + @Override public void visit(MethodCall methodCall) { boolean parentBinary = isParentBinary; @@ -772,6 +775,12 @@ public class BytecodeGenMethod implements StatementVisitor { System.out.println("Methods of " + receiverName + " "); java.lang.reflect.Method methodRefl = null; String clazz = receiverName.replace("/", "."); + + String mDesc = ""; + + MethodCallHelper helper = new MethodCallHelper(methodCall, sf, resultSet); + + boolean isCreated = false; // if(!receiverName.equals(className)) { ClassLoader cLoader = ClassLoader.getSystemClassLoader(); // This will be used if the class is not standard class (not in API) @@ -801,71 +810,75 @@ public class BytecodeGenMethod implements StatementVisitor { String superClass = ""; // TODO: Test SubMatrix.jav while(true) { - for(ClassOrInterface cl : sf.getClasses()) { - if(receiverName.equals(cl.getClassName().toString())) { - superClass = cl.getSuperClass().getName().toString(); - break; - } - } - System.out.println(superClass); - - if(superClass.equals("")) - break; - try { - String superClazz = superClass.replace("/", "."); - if(superClass.contains("<")) { - superClazz = superClazz.substring(0, superClass.indexOf("<")); - } - java.lang.reflect.Method[] methods = cLoader.loadClass(superClazz).getMethods(); - System.out.println("Methods of " + superClass + " "); + superClass = helper.getSuperClass(receiverName); - for(java.lang.reflect.Method m : methods) { - if(methodCall.name.equals(m.getName())) { - methodRefl = m; - break; + try { + String superClazz = superClass.replace("/", "."); + if(superClass.contains("<")) { + superClazz = superClazz.substring(0, superClass.indexOf("<")); } + java.lang.reflect.Method[] methods = cLoader.loadClass(superClazz).getMethods(); + System.out.println("Methods of " + superClass + " "); + + for(java.lang.reflect.Method m : methods) { + if(methodCall.name.equals(m.getName())) { + methodRefl = m; + break; + } + } + + break; + } catch (Exception e3) { + receiverName = superClass; + continue; } - + } catch (NotInCurrentPackageException e2) { break; - } catch (Exception e3) { - receiverName = superClass; - continue; } + } // } } if(methodRefl == null) { - try { - cLoader2 = new URLClassLoader(new URL[] {new URL("file://"+path)}); - java.lang.reflect.Method[] methods = cLoader2.loadClass(clazz).getMethods(); - System.out.println("Methods of " + receiverName + " "); - for(int i = 0; i argListMethCall = new LinkedList<>(); String receiverRefl=""; - if(methodRefl == null) { + if(methodRefl == null && receiverName.equals(className)) { MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), receiverName, genericsAndBoundsMethod, genericsAndBounds); mDesc = method.accept(new DescriptorToString(resultSet)); methodCall.arglist.accept(this); - } else { + } else if(methodRefl != null) { System.out.println(methodCall.name + " -> Refl != null"); receiverRefl = methodRefl.getAnnotatedReceiverType().getType().toString(); for(Parameter p:methodRefl.getParameters()) { @@ -880,6 +893,8 @@ public class BytecodeGenMethod implements StatementVisitor { al.accept(argV); statement = null; } + } else { + methodCall.arglist.accept(this); } System.out.println("Methodcall ("+ methodCall.name +") Desc : " + mDesc); @@ -917,6 +932,19 @@ public class BytecodeGenMethod implements StatementVisitor { } + private String getDescForMethInCurrPkg(String name) { + // TODO Auto-generated method stub + return null; + } + + private boolean isInCurrPkg(String superClass) { + for(ClassOrInterface cl : sf.KlassenVektor) { + if(superClass.equals(cl.getClassName().toString())) + return true; + } + return false; + } + private String[] getTypes(List arguments) { String[] types = new String[arguments.size()]; for(int i = 0; i genAndBoundsClass = getGenericsAndBounds(clazz.getGenerics()); + modifyGenAndBounds(genAndBoundsClass); + for (Method m : clazz.getMethods()) { + if (name.equals(m.getName())) { + Map genAndBoundsMethod = getGenericsAndBoundsMethod(m.getGenerics()); + modifyGenAndBounds(genAndBoundsMethod); + boolean hasGen = hasGen(m, genAndBoundsClass); + NormalMethod nm = new NormalMethod(m, (HashMap) genAndBoundsClass, + (HashMap) genAndBoundsMethod, hasGen); + return nm.accept(new DescriptorToString(resultSet)); + } + } + + throw new NotFoundException("Method " + name + " is not found"); + } + + private boolean hasGen(Method m, Map genericsAndBounds) { + String retType = resultSet.resolveType(m.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); + /*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/ + boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.contains("TPH ") || retType.contains("<"); + + Map methodParamsAndTypes = new HashMap<>(); + Iterator itr = m.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + methodParamsAndTypes.put(fp.getName(), resultSet.resolveType(fp.getType()).resolvedType); + } + /*Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, wenn nicht, + * prüfe, ob einer der Parameter Typ-Variable als Typ hat*/ + if(!hasGenInParameterList) { + for(String paramName : methodParamsAndTypes.keySet()) { + String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor()); + String sigOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); + if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.contains("TPH ")||sigOfParam.contains("<")) { + hasGenInParameterList = true; + break; + } + } + } + return m.getGenerics().iterator().hasNext() || hasGenInParameterList; + } + + private Map getGenericsAndBoundsMethod(Iterable generics) { + Map genAndBounds = new HashMap<>(); + Iterator itr = generics.iterator(); + while (itr.hasNext()) { + GenericTypeVar gtv = itr.next(); + getBoundsOfTypeVar(gtv, genAndBounds); + } + return genAndBounds; + } + + private void modifyGenAndBounds(Map genAndBoundsClass) { + List visited = new ArrayList<>(genAndBoundsClass.size()); + Map toReplace = new HashMap<>(); + for (String tv : genAndBoundsClass.keySet()) { + + if (visited.contains(tv)) + continue; + + List types = new LinkedList<>(); + String bound = genAndBoundsClass.get(tv); + types.add(tv); + visited.add(tv); + boolean doReplace = false; + while (genAndBoundsClass.keySet().contains(bound)) { + doReplace = true; + types.add(bound); + visited.add(bound); + bound = genAndBoundsClass.get(bound); + } + + if (doReplace) { + for (String tt : types) { + toReplace.put(tt, bound); + } + } + } + + for (String key : toReplace.keySet()) { + genAndBoundsClass.replace(key, toReplace.get(key)); + } + + } + + private Map getGenericsAndBounds(GenericDeclarationList generics) { + Map genAndBounds = new HashMap<>(); + Iterator itr = generics.iterator(); + while (itr.hasNext()) { + GenericTypeVar gtv = itr.next(); + getBoundsOfTypeVar(gtv, genAndBounds); + } + return genAndBounds; + } + + private void getBoundsOfTypeVar(GenericTypeVar g, Map genAndBounds) { + + Iterator bItr = g.getBounds().iterator(); + while (bItr.hasNext()) { + RefTypeOrTPHOrWildcardOrGeneric b = bItr.next(); + String boundDesc = b.acceptTV(new TypeToDescriptor()); + genAndBounds.put(g.getName(), boundDesc); + } + } + + private String createDesc(Method m) { + String desc = "("; + for (FormalParameter fp : m.getParameterList()) { + String typeName = getResolvedType(fp.getType()); + RefTypeOrTPHOrWildcardOrGeneric type = resultSet.resolveType(fp.getType()).resolvedType; + if (type instanceof TypePlaceholder) { + desc += "L" + Type.getInternalName(Object.class) + ";"; + } else if (type instanceof GenericRefType) { + GenericRefType grt = (GenericRefType) type; + + } + } + return null; + } + +} diff --git a/src/test/resources/bytecode/javFiles/OL.jav b/src/test/resources/bytecode/javFiles/OL.jav index 700e50f0..83361d3c 100644 --- a/src/test/resources/bytecode/javFiles/OL.jav +++ b/src/test/resources/bytecode/javFiles/OL.jav @@ -10,8 +10,6 @@ public class OL { } - - public class OLMain { main(x) {