diff --git a/resources/bytecode/javFiles/Bug338.jav b/resources/bytecode/javFiles/Bug338.jav new file mode 100644 index 00000000..fa846e95 --- /dev/null +++ b/resources/bytecode/javFiles/Bug338.jav @@ -0,0 +1,11 @@ +import java.util.List; +import java.lang.Integer; +import java.lang.String; +import java.lang.Object; +import java.util.List; + +public class Bug338 { + public hashCode() { + return List.of(42); + } +} \ No newline at end of file diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 3908af06..3280f295 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.target.generate; +import de.dhbwstuttgart.bytecode.CodeGenException; import de.dhbwstuttgart.bytecode.FunNGenerator; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.environment.ByteArrayClassLoader; @@ -160,11 +161,11 @@ public class ASTToTargetAST { var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics)).toList(); var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer)).flatMap(List::stream).toList(); var fields = input.getFieldDecl().stream().map(this::convert).toList(); - var methods = groupOverloads(input.getMethods()).stream().map(m -> convert(input, m)).flatMap(List::stream).toList(); + var methods = groupOverloads(input.getMethods()).stream().map(m -> convert(input, m)).flatMap(Set::stream).toList(); TargetMethod staticConstructor = null; if (input.getStaticInitializer().isPresent()) - staticConstructor = this.convert(input, input.getStaticInitializer().get()).get(0); + staticConstructor = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow(); if (input instanceof Record) return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods); @@ -289,11 +290,11 @@ public class ASTToTargetAST { return res.toString(); } - private List convert(ClassOrInterface clazz, List overloadedMethods) { + private Set convert(ClassOrInterface clazz, List overloadedMethods) { if (overloadedMethods.size() == 1) { - return convert(clazz, overloadedMethods.get(0)); + return convert(clazz, overloadedMethods.getFirst()); } - var res = new ArrayList(); + var methods = new ArrayList(); for (var method : overloadedMethods) { var newMethod = new Method( method.modifier, @@ -305,7 +306,7 @@ public class ASTToTargetAST { method.getGenerics(), method.getOffset() ); - res.add(newMethod); + methods.add(newMethod); } // TODO Record overloading @@ -328,7 +329,15 @@ public class ASTToTargetAST { var entryPoint = new Method(template.modifier, template.name, template.getReturnType(), params, block, template.getGenerics(), new NullToken()); res.add(entryPoint); // TODO*/ - return res.stream().map(m -> convert(clazz, m)).flatMap(List::stream).toList(); + var res = new HashSet(); + for (var method : methods) { + var overloads = convert(clazz, method); + for (var overload : overloads) { + if (res.contains(overload)) throw new CodeGenException("Duplicate method found: " + overload.name() + " with signature " + overload.signature().getSignature()); + res.add(overload); + } + } + return res; } private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List overloadedMethods) { @@ -366,16 +375,15 @@ public class ASTToTargetAST { for (var i = 0; i < params.size(); i++) { var a = TargetType.toPrimitive(params.get(i).pattern().type()); var b = convert(sParams.getFormalparalist().get(i).getType()); - System.out.println(a + " " + b); if (!Objects.equals(a, b)) return false; } return true; }).findFirst(); } - private List convert(ClassOrInterface currentClass, Method method) { + private Set convert(ClassOrInterface currentClass, Method method) { generics = all.get(0); - List result = new ArrayList<>(); + Set result = new HashSet<>(); Set> parameterSet = new HashSet<>(); for (var s : all) { @@ -387,8 +395,11 @@ public class ASTToTargetAST { var superMethod = findSuperMethodToOverride(currentClass, method.getName(), params); if (superMethod.isPresent()) { // If we find a super method to override, use its parameters and return types - returnType = convert(superMethod.get().getReturnType(), this.generics.javaGenerics); - params = convert(superMethod.get().getParameterList(), method.getParameterList(), this.generics.javaGenerics); + var newReturnType = convert(superMethod.get().getReturnType(), this.generics.javaGenerics); + if (newReturnType instanceof TargetPrimitiveType && TargetType.toPrimitive(returnType).equals(newReturnType)) { + returnType = newReturnType; + params = convert(superMethod.get().getParameterList(), method.getParameterList(), this.generics.javaGenerics); + } } List finalParams = params; @@ -400,10 +411,12 @@ public class ASTToTargetAST { var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType); var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics)); - result.add(new TargetMethod(method.modifier, method.name, convert(method.block), javaSignature, txSignature)); + var newMethod = new TargetMethod(method.modifier, method.name, convert(method.block), javaSignature, txSignature); + result.add(newMethod); parameterSet.add(params); } } + return result; } diff --git a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java index 5a8b9368..bdabc81e 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java @@ -6,6 +6,7 @@ import de.dhbwstuttgart.target.tree.type.TargetType; import org.objectweb.asm.Opcodes; import java.util.List; +import java.util.Objects; import java.util.Set; public record TargetMethod(int access, String name, TargetBlock block, Signature signature, Signature txSignature) { @@ -64,5 +65,16 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature public boolean isStatic() { return (access & Opcodes.ACC_STATIC) != 0; } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TargetMethod otherMethod)) return false; + return otherMethod.signature.equals(this.signature) && otherMethod.name.equals(this.name); + } + + @Override + public int hashCode() { + return Objects.hash(name, signature); + } } diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 2b95681e..4076fede 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -1101,6 +1101,7 @@ public class TestComplete { var res = clazz.getDeclaredMethod("convert", List.class).invoke(instance, list); assertEquals(res, List.of(6, 7, 8)); } + @Test public void testBug325() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug325.jav"); @@ -1133,10 +1134,17 @@ public class TestComplete { } @Test +<<<<<<< HEAD public void testBug337() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug337.jav"); var clazz = classFiles.get("Bug337"); var instance = clazz.getDeclaredConstructor().newInstance(); clazz.getDeclaredMethod("main").invoke(instance); +======= + public void testBug338() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug338.jav"); + var clazz = classFiles.get("Bug338"); + var instance = clazz.getDeclaredConstructor().newInstance(); +>>>>>>> ea217d16d5a1d635ac7fe961b98c2ad993c14ac5 } }