Compare commits

..
10 Commits
Author SHA1 Message Date
dholle de96cda327 Fix #417 in Codegen and by changing constraint generation
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m23s
SonarQube Scan / SonarQube Trigger (pull_request) Successful in 2m36s
2026-11-11 14:00:22 +01:00
dholle 2710685db3 Merge pull request 'Fix #409 by moving increment to the beginning of the loop' (#427) from fix-409 into master
SonarQube Scan / SonarQube Trigger (push) Successful in 2m29s
Reviewed-on: #427
2026-11-11 11:25:41 +00:00
dholle e951a60ae6 Fix incorrect behavior
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m18s
SonarQube Scan / SonarQube Trigger (pull_request) Successful in 2m37s
2026-11-11 12:18:42 +01:00
dholle 825df05fac Fix #409 by moving increment to the beginning of the loop
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m17s
SonarQube Scan / SonarQube Trigger (pull_request) Failing after 1m33s
2026-11-11 12:00:59 +01:00
dholle fab3e73596 Merge branch 'fix-423'
SonarQube Scan / SonarQube Trigger (push) Canceled after 26m58s
2026-11-11 11:34:32 +01:00
dholle 392c5fa619 Merge branch 'fix-422'
SonarQube Scan / SonarQube Trigger (push) Failing after 1m39s
2026-11-11 11:31:48 +01:00
dholle e21d2d7ced Merge pull request 'Fix #421 by adding error listeners to the Parser & Lexer' (#426) from fix-421 into master
SonarQube Scan / SonarQube Trigger (push) Failing after 1m39s
Reviewed-on: #426
2026-11-11 10:28:50 +00:00
dholle 5a12545e8f Fix #421 by adding error listeners to the Parser & Lexer
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 7m30s
SonarQube Scan / SonarQube Trigger (pull_request) Failing after 1m35s
2026-11-10 15:31:41 +01:00
dholle d6c59f07f6 Add check for duplicate class definition in source files, fixes #422
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m52s
SonarQube Scan / SonarQube Trigger (pull_request) Failing after 2m24s
2026-11-10 15:04:47 +01:00
dholle eb1c5c6629 Add check for missing interface methods, fixes #423
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m22s
SonarQube Scan / SonarQube Trigger (pull_request) Failing after 2m11s
2026-11-10 14:46:41 +01:00
16 changed files with 176 additions and 233 deletions

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
import java.lang.Integer;
public class Bug409 {
public static m() {
var n = 0;
for (var i = 0; i < 5; i++) {
n = n + 1;
if (n > 100) { return -1; }
if (i == 2) { continue; }
}
return n;
}
}
+11
View File
@@ -0,0 +1,11 @@
import java.lang.Integer;
import java.lang.String;
public class Bug417 {
public name(Integer i) {
return switch (i) {
case 1 -> "one";
default -> "many";
};
}
}
+3
View File
@@ -0,0 +1,3 @@
public class Bug421 {
public m() { return 1 } // Missing semicolon
}
+2
View File
@@ -0,0 +1,2 @@
public class Bug422 {}
public class Bug422 {}
+5
View File
@@ -0,0 +1,5 @@
import java.lang.Integer;
interface Bug423I { Integer f(); }
public class Bug423 implements Bug423I { }
@@ -15,6 +15,7 @@ interface C {
}
class ClassX implements A {
void method1() {}
}
record ClassY(Integer myInt) implements C {}
+3 -3
View File
@@ -2,7 +2,7 @@ sealed interface Interface permits A, B {}
public record A() implements Interface {}
public record B() implements Interface {}
public class Matcher {
match(A()@a) { return 0; }
match(B()@b) { return 1; }
public interface Matcher {
default match(A()@a) { return 0; }
default match(B()@b) { return 1; }
}
@@ -3,7 +3,7 @@ import java.lang.Integer;
import Matcher;
import Interface;
public class M extends Matcher {}
public class M implements Matcher {}
public class PatternMatchingInterface {
public static match(matcher, v) {
@@ -1056,6 +1056,7 @@ public class Codegen {
}
Label start = new Label();
Label skip = new Label();
Label end = new Label();
mv.visitLabel(start);
if (_for.termination() != null) {
@@ -1068,13 +1069,14 @@ public class Codegen {
}
var env = new BreakEnv();
env.startLabel = start;
env.startLabel = skip;
env.endLabel = end;
state.breakStack.push(env);
generate(state, _for.body());
state.breakStack.pop();
mv.visitLabel(skip);
if (_for.increment() != null) {
_for.increment().forEach(e -> {
generate(state, e);
@@ -1435,13 +1437,16 @@ public class Codegen {
if (label instanceof TargetTypePattern || label instanceof TargetComplexPattern) {
if (label.type() instanceof TargetGenericType) types.add(Type.getType(Object.class));
else types.add(Type.getObjectType(label.type().getInternalName()));
} else if (label instanceof TargetLiteral lit) {
types.add(lit.value());
} else if (label instanceof TargetExpressionPattern expr) {
if (expr.expression() instanceof TargetLiteral literal) {
types.add(Type.getObjectType(TargetType.toWrapper(literal.type()).getInternalName()));
} else {
throw new NotImplementedException();
}
} else if (label instanceof TargetGuard guard) {
types.add(Type.getObjectType(guard.inner().type().getInternalName()));
// TODO Same here we need to evaluate constant;
} else {
logger.info(label);
throw new NotImplementedException();
}
}
@@ -1846,6 +1851,35 @@ public class Codegen {
clazz.constructors().forEach(this::generateConstructor);
clazz.methods().forEach(this::generateMethod);
// Check if non abstract class implements all interface methods
if ((access & ACC_ABSTRACT) == 0) {
for (var intf : clazz.implementingInterfaces()) {
var intfClass = compiler.getClass(new JavaClassName(intf.name()));
for (var method : intfClass.getMethods()) {
if ((method.modifier & ACC_ABSTRACT) != 0) {
// Check if the method is implemented in the current class
// TODO This is duplicate code, we should probably refactor instances of this pattern
var foundMethods = clazz.methods().stream().filter(m -> {
if (!m.name().equals(method.name)) return false;
if (m.signature().parameters().size() != method.getParameterList().getFormalparalist().size())
return false;
for (var i = 0; i < m.signature().parameters().size(); i++) {
var param1 = m.signature().parameters().get(i).pattern().type();
var param2 = converter.convert(
method.getParameterList().getParameterAt(i).getType(),
ASTToTargetAST.Generics.nullGenerics(compiler).javaGenerics());
if (!param1.equals(param2)) return false;
}
return true;
}).toList();
if (foundMethods.size() != 1) {
throw new CodeGenException("Class " + clazz.qualifiedName() + " does not implement method " + method.name + " from interface " + intfClass.getClassName());
}
}
}
}
}
if (clazz.staticConstructor() != null)
generateStaticConstructor(clazz.staticConstructor());
@@ -5,6 +5,7 @@ import de.dhbwstuttgart.bytecode.Codegen;
import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.environment.CompilationEnvironment;
import de.dhbwstuttgart.environment.DirectoryClassLoader;
import de.dhbwstuttgart.exceptions.CompilerException;
import de.dhbwstuttgart.exceptions.CompilerWarning;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.exceptions.WarningsException;
@@ -171,6 +172,8 @@ public class JavaTXCompiler {
var numberOfGenerics = decl == null ? 0 : decl.genericTypeVar().size();
var className = pkgName + (!pkgName.isEmpty() ? "." : "") + name;
if (classRegistry.contains(className))
throw new CompilerException("Duplicate class definition: " + className);
classRegistry.addName(className, numberOfGenerics);
input.add(classRegistry.getName(className));
}
@@ -0,0 +1,7 @@
package de.dhbwstuttgart.exceptions;
public class CompilerException extends RuntimeException {
public CompilerException(String message) {
super(message);
}
}
@@ -2,9 +2,8 @@ package de.dhbwstuttgart.exceptions;
import org.antlr.v4.runtime.Token;
public class ParserError extends TypeinferenceException{
public ParserError(Token offset){
super("Fehler beim Parsen", offset);
public class ParserError extends RuntimeException{
public ParserError(String message) {
super(message);
}
}
@@ -1,6 +1,7 @@
package de.dhbwstuttgart.parser;
import de.dhbwstuttgart.environment.CompilationEnvironment;
import de.dhbwstuttgart.exceptions.ParserError;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator;
import de.dhbwstuttgart.parser.antlr.Java17Lexer;
import de.dhbwstuttgart.parser.antlr.Java17Parser;
@@ -8,9 +9,7 @@ import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.util.Logger;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
@@ -21,13 +20,25 @@ public class JavaTXParser {
public static Logger logger = new Logger("Parser");
public static class ThrowingErrorListener extends BaseErrorListener {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol,
int line, int charPositionInLine, String msg, RecognitionException e) {
throw new ParserError("Syntax error at line " + line + ":" + charPositionInLine + " - " + msg);
}
}
public static Java17Parser.SourceFileContext parse(File source) throws IOException, java.lang.ClassNotFoundException {
InputStream stream = new FileInputStream(source);
// DEPRECATED: ANTLRInputStream input = new ANTLRInputStream(stream);
var errorListener = new ThrowingErrorListener();
CharStream input = CharStreams.fromStream(stream);
Java17Lexer lexer = new Java17Lexer(input);
lexer.addErrorListener(errorListener);
CommonTokenStream tokens = new CommonTokenStream(lexer);
Java17Parser parser = new Java17Parser(tokens);
parser.addErrorListener(errorListener);
return parser.sourceFile();
/*
* SyntaxTreeGenerator generator = new SyntaxTreeGenerator(environment.getRegistry(source)); return generator.convert(tree);
@@ -875,8 +875,8 @@ public class TYPEStmt implements StatementVisitor {
if (caseExpressionType == null) {
for (var child : switchStmt.getBlocks()) {
for (var label : child.getLabels()) {
if (label.getPattern() == null) {
constraintsSet.addUndConstraint(new Pair(new RefType(new JavaClassName("java.lang.Object"), new NullToken()), switchStmt.getSwitch().getType(), PairOperator.SMALLERDOT, loc(label.getOffset())));
if (label.getPattern() == null && switchStmt.getSwitch().getType() instanceof TypePlaceholder) {
constraintsSet.addUndConstraint(new Pair(new RefType(new JavaClassName("java.lang.Object"), new NullToken()), switchStmt.getSwitch().getType(), PairOperator.EQUALSDOT, loc(label.getOffset())));
}
if (label.getPattern() instanceof RecordPattern) {
RecordPattern recordPattern = (RecordPattern) label.getPattern();
+57 -212
View File
@@ -1,6 +1,8 @@
import de.dhbwstuttgart.bytecode.CodeGenException;
import de.dhbwstuttgart.core.ConsoleInterface;
import de.dhbwstuttgart.exceptions.CompilerException;
import de.dhbwstuttgart.exceptions.ParserError;
import de.dhbwstuttgart.exceptions.WarningsException;
import de.dhbwstuttgart.util.Logger;
import de.dhbwstuttgart.util.Logger.LogLevel;
@@ -41,16 +43,6 @@ public class TestComplete {
var m = applyLambda.getDeclaredMethod("m");
var result = m.invoke(instance);
assertEquals(Object.class, m.getReturnType());
assertArrayEquals(new Class<?>[0], m.getParameterTypes());
var lambda = applyLambda.getDeclaredMethod("lambda$0", Object.class);
assertEquals(Object.class, lambda.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class}, lambda.getParameterTypes());
assertEquals(2, applyLambda.getDeclaredMethods().length);
var apply = classFiles.get("Apply");
assertEquals(0, apply.getDeclaredMethods().length);
assertEquals(result.getClass(), classFiles.get("Apply"));
}
@@ -62,23 +54,6 @@ public class TestComplete {
var m2 = binaryInMeth.getDeclaredMethod("m2", Integer.class, Integer.class);
var m3 = binaryInMeth.getDeclaredMethod("m3", Integer.class);
var mInteger = binaryInMeth.getDeclaredMethod("m", Integer.class);
var mDouble = binaryInMeth.getDeclaredMethod("m", Double.class);
var m2Double = binaryInMeth.getDeclaredMethod("m2", Double.class, Double.class);
var m3Double = binaryInMeth.getDeclaredMethod("m3", Double.class);
assertEquals(Integer.class, m2.getReturnType());
assertArrayEquals(new Class<?>[]{Integer.class, Integer.class}, m2.getParameterTypes());
assertEquals(Integer.class, m3.getReturnType());
assertArrayEquals(new Class<?>[]{Integer.class}, m3.getParameterTypes());
assertEquals(Integer.class, mInteger.getReturnType());
assertArrayEquals(new Class<?>[]{Integer.class}, mInteger.getParameterTypes());
assertEquals(Double.class, mDouble.getReturnType());
assertArrayEquals(new Class<?>[]{Double.class}, mDouble.getParameterTypes());
assertEquals(Double.class, m2Double.getReturnType());
assertArrayEquals(new Class<?>[]{Double.class, Double.class}, m2Double.getParameterTypes());
assertEquals(Double.class, m3Double.getReturnType());
assertArrayEquals(new Class<?>[]{Double.class}, m3Double.getParameterTypes());
assertEquals(6, m2.invoke(instance, 2, 3));
assertEquals(4, m3.invoke(instance, 2));
@@ -87,24 +62,7 @@ public class TestComplete {
@Test
public void classGenLamTest() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "ClassGenLam.jav");
var classGenLam = classFiles.get("ClassGenLam");
classGenLam.getDeclaredConstructor().newInstance();
assertEquals(1, classGenLam.getTypeParameters().length);
var typeParameter = classGenLam.getTypeParameters()[0];
var lam = classGenLam.getDeclaredField("lam");
assertEquals("lam", lam.getName());
assertEquals("Fun1$$LTPH$_$LTPH$_$", lam.getType().getName());
assertTrue(lam.getGenericType() instanceof ParameterizedType);
var lamType = (ParameterizedType) lam.getGenericType();
assertEquals(2, lamType.getActualTypeArguments().length);
assertEquals(typeParameter, lamType.getActualTypeArguments()[0]);
assertEquals(typeParameter, lamType.getActualTypeArguments()[1]);
var lambda = classGenLam.getDeclaredMethod("lambda$0", Object.class);
assertEquals(Object.class, lambda.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class}, lambda.getParameterTypes());
classFiles.get("ClassGenLam").getDeclaredConstructor().newInstance();
}
@Test
@@ -114,13 +72,6 @@ public class TestComplete {
var instance = fac.getDeclaredConstructor().newInstance();
var getFac = fac.getDeclaredMethod("getFac", Integer.class);
var getFacDouble = fac.getDeclaredMethod("getFac", Double.class);
assertEquals(0, fac.getDeclaredFields().length);
assertEquals(Double.class, getFac.getReturnType());
assertArrayEquals(new Class<?>[]{Integer.class}, getFac.getParameterTypes());
assertEquals(Double.class, getFacDouble.getReturnType());
assertArrayEquals(new Class<?>[]{Double.class}, getFacDouble.getParameterTypes());
// assertEquals(6, getFac.invoke(instance, 3)); TODO This could be either an Integer or a Double so this simple test fails
}
@@ -134,21 +85,6 @@ public class TestComplete {
var instance = constructor.newInstance();
var getFact = fac.getDeclaredMethod("getFact", Integer.class);
var lambda = fac.getDeclaredMethod("lambda$0", Object.class);
var fact = fac.getDeclaredField("fact");
assertEquals(1, fac.getDeclaredFields().length);
assertEquals("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$", fact.getType().getName());
assertTrue(fact.getGenericType() instanceof ParameterizedType);
var factType = (ParameterizedType) fact.getGenericType();
assertEquals(2, factType.getActualTypeArguments().length);
assertEquals(Integer.class, factType.getActualTypeArguments()[0]);
assertEquals(Integer.class, factType.getActualTypeArguments()[1]);
assertEquals(Integer.class, getFact.getReturnType());
assertArrayEquals(new Class<?>[]{Integer.class}, getFact.getParameterTypes());
assertEquals(Integer.class, lambda.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class}, lambda.getParameterTypes());
assertEquals(6, getFact.invoke(instance, 3));
}
@@ -157,14 +93,7 @@ public class TestComplete {
var classFiles = generateClassFiles(createClassLoader(), "Field.jav");
var field = classFiles.get("Field");
var instance = field.getDeclaredConstructor().newInstance();
var x = field.getDeclaredField("x");
var m = field.getDeclaredMethod("m");
assertEquals(1, field.getFields().length);
assertEquals(Integer.class, x.getType());
assertEquals(Integer.class, x.getGenericType());
assertEquals(Integer.class, m.getReturnType());
assertArrayEquals(new Class<?>[0], m.getParameterTypes());
}
@Test
@@ -178,24 +107,6 @@ public class TestComplete {
m2.invoke(instance, 1);
var m = fieldtph2.getDeclaredMethod("m", Object.class);
var typeParameters = fieldtph2.getTypeParameters();
assertEquals(2, typeParameters.length);
var p = typeParameters[0];
var t = typeParameters[1];
assertEquals("P", p.getName());
assertEquals("T", t.getName());
assertEquals(p, t.getBounds()[0]);
assertEquals(Object.class, a.getType());
assertEquals(t, a.getGenericType());
assertEquals(Object.class, m.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class}, m.getParameterTypes());
assertEquals(p, m.getGenericReturnType());
assertEquals(p, m.getGenericParameterTypes()[0]);
assertEquals(void.class, m2.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class}, m2.getParameterTypes());
assertEquals(t, m2.getGenericParameterTypes()[0]);
assertEquals(1, m.invoke(instance, 1));
}
@@ -208,35 +119,6 @@ public class TestComplete {
var instance = ctor.newInstance("C");
var a = fieldTphConsMeth.getDeclaredField("a");
var id = fieldTphConsMeth.getDeclaredMethod("id", Object.class);
var typeParameter = fieldTphConsMeth.getTypeParameters()[0];
var setA = fieldTphConsMeth.getDeclaredMethod("setA", Object.class);
var m = fieldTphConsMeth.getDeclaredMethod("m", Object.class, Object.class);
assertEquals(1, fieldTphConsMeth.getTypeParameters().length);
assertEquals("AAB", typeParameter.getName());
assertEquals(Object.class, a.getType());
assertEquals(typeParameter, a.getGenericType());
assertEquals(Object.class, ctor.getParameterTypes()[0]);
assertEquals(1, ctor.getTypeParameters().length);
assertEquals(typeParameter, ctor.getTypeParameters()[0].getBounds()[0]);
assertEquals(ctor.getTypeParameters()[0], ctor.getGenericParameterTypes()[0]);
assertEquals(Object.class, setA.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class}, setA.getParameterTypes());
assertEquals(typeParameter, setA.getGenericReturnType());
assertEquals(setA.getTypeParameters()[0], setA.getGenericParameterTypes()[0]);
assertEquals(typeParameter, setA.getTypeParameters()[0].getBounds()[0]);
assertEquals(Object.class, id.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class}, id.getParameterTypes());
assertEquals(typeParameter, id.getGenericReturnType());
assertEquals(typeParameter, id.getGenericParameterTypes()[0]);
assertEquals(void.class, m.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class, Object.class}, m.getParameterTypes());
assertEquals(3, m.getTypeParameters().length);
assertEquals(Object.class, m.getTypeParameters()[0].getBounds()[0]);
assertEquals(m.getTypeParameters()[2], m.getTypeParameters()[1].getBounds()[0]);
assertEquals(m.getTypeParameters()[0], m.getTypeParameters()[2].getBounds()[0]);
assertEquals(m.getTypeParameters()[0], m.getGenericParameterTypes()[0]);
assertEquals(m.getTypeParameters()[1], m.getGenericParameterTypes()[1]);
assertEquals(42, id.invoke(instance, 42));
assertEquals("C", a.get(instance));
@@ -252,39 +134,9 @@ public class TestComplete {
var instance2 = ctor.newInstance("C", 42, false);
var m = fieldTphMMeth.getDeclaredMethod("m", Object.class, Object.class, Boolean.class);
var m2 = fieldTphMMeth.getDeclaredMethod("m2", Object.class);
var m3 = fieldTphMMeth.getDeclaredMethod("m3", Object.class);
var a = fieldTphMMeth.getDeclaredField("a");
var classTypeParameter = fieldTphMMeth.getTypeParameters()[0];
assertEquals(1, fieldTphMMeth.getTypeParameters().length);
assertEquals("AF", classTypeParameter.getName());
assertEquals(Object.class, a.getType());
assertEquals(classTypeParameter, a.getGenericType());
assertArrayEquals(new Class<?>[]{Object.class, Object.class, Boolean.class}, ctor.getParameterTypes());
assertEquals(2, ctor.getTypeParameters().length);
assertEquals(classTypeParameter, ctor.getTypeParameters()[0].getBounds()[0]);
assertEquals(classTypeParameter, ctor.getTypeParameters()[1].getBounds()[0]);
assertEquals(Object.class, m.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class, Object.class, Boolean.class}, m.getParameterTypes());
assertEquals(2, m.getTypeParameters().length);
assertEquals(Object.class, m.getTypeParameters()[0].getBounds()[0]);
assertEquals(m.getTypeParameters()[0], m.getTypeParameters()[1].getBounds()[0]);
assertEquals(m.getTypeParameters()[0], m.getGenericReturnType());
assertEquals(m.getTypeParameters()[0], m.getGenericParameterTypes()[0]);
assertEquals(m.getTypeParameters()[1], m.getGenericParameterTypes()[1]);
assertEquals(void.class, m2.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class}, m2.getParameterTypes());
assertEquals(classTypeParameter, m2.getTypeParameters()[0].getBounds()[0]);
assertEquals(m2.getTypeParameters()[0], m2.getGenericParameterTypes()[0]);
assertEquals(Object.class, m3.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class}, m3.getParameterTypes());
assertEquals(classTypeParameter, m3.getTypeParameters()[0].getBounds()[0]);
assertEquals(m3.getTypeParameters()[0], m3.getGenericReturnType());
assertEquals(m3.getTypeParameters()[0], m3.getGenericParameterTypes()[0]);
assertEquals(42, m.invoke(instance1, "C", 42, false));
var a = fieldTphMMeth.getDeclaredField("a");
assertEquals("C", a.get(instance1));
assertEquals(42, a.get(instance2));
}
@@ -292,74 +144,19 @@ public class TestComplete {
@Test
public void genTest() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Gen.jav");
var gen = classFiles.get("Gen");
var m = gen.getDeclaredMethod("m", Vector.class);
assertEquals(0, gen.getDeclaredFields().length);
assertEquals(Vector.class, m.getReturnType());
assertArrayEquals(new Class<?>[]{Vector.class}, m.getParameterTypes());
assertTrue(m.getGenericReturnType() instanceof ParameterizedType);
var returnType = (ParameterizedType) m.getGenericReturnType();
assertEquals(Vector.class, returnType.getRawType());
assertArrayEquals(new Type[]{Integer.class}, returnType.getActualTypeArguments());
assertTrue(m.getGenericParameterTypes()[0] instanceof ParameterizedType);
var parameterType = (ParameterizedType) m.getGenericParameterTypes()[0];
assertEquals(Vector.class, parameterType.getRawType());
assertArrayEquals(new Type[]{Integer.class}, parameterType.getActualTypeArguments());
}
@Test
public void idTest() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Id.jav");
var id = classFiles.get("Id");
id.getDeclaredConstructor().newInstance();
assertEquals(1, id.getTypeParameters().length);
assertEquals("FAU", id.getTypeParameters()[0].getName());
var id2 = id.getDeclaredField("id2");
assertEquals("Fun1$$LTPH$_$LTPH$_$", id2.getType().getName());
var lambda = id.getDeclaredMethod("lambda$0", Object.class);
assertEquals(Object.class, lambda.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class}, lambda.getParameterTypes());
var id3 = id.getDeclaredMethod("id3", Object.class);
assertEquals(Object.class, id3.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class}, id3.getParameterTypes());
assertEquals(1, id3.getTypeParameters().length);
assertEquals("V", id3.getTypeParameters()[0].getName());
var instance = classFiles.get("Id").getDeclaredConstructor().newInstance();
}
@Test
public void infTest() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Inf.jav");
var inf = classFiles.get("Inf");
inf.getDeclaredConstructor().newInstance();
var m = inf.getDeclaredMethod("m", Object.class, Object.class, Object.class);
assertEquals(0, inf.getDeclaredFields().length);
assertEquals(void.class, m.getReturnType());
assertArrayEquals(new Class<?>[]{Object.class, Object.class, Object.class}, m.getParameterTypes());
assertEquals(5, m.getTypeParameters().length);
var zn = m.getTypeParameters()[0];
var zo = m.getTypeParameters()[1];
var q = m.getTypeParameters()[2];
var o = m.getTypeParameters()[3];
var zp = m.getTypeParameters()[4];
assertEquals("ZN", zn.getName());
assertEquals("ZO", zo.getName());
assertEquals("Q", q.getName());
assertEquals("O", o.getName());
assertEquals("ZP", zp.getName());
assertEquals(zo, zn.getBounds()[0]);
assertEquals(zp, zo.getBounds()[0]);
assertEquals(zn, q.getBounds()[0]);
assertEquals(zn, o.getBounds()[0]);
assertEquals(Object.class, zp.getBounds()[0]);
assertEquals(o, m.getGenericParameterTypes()[0]);
assertEquals(zn, m.getGenericParameterTypes()[1]);
assertEquals(q, m.getGenericParameterTypes()[2]);
var instance = classFiles.get("Inf").getDeclaredConstructor().newInstance();
// TODO check generics
}
@Test
@@ -1286,9 +1083,9 @@ public class TestComplete {
assertEquals(40.0, m.invoke(instance, d, 0));
}
@Disabled("Waiting for #407, skipping for now")
@Test
public void testPatternMatchingInterface() throws Exception {
ConsoleInterface.logLevel = LogLevel.INFO;
var classFiles = generateClassFiles(createClassLoader(), false, "Matcher.jav", "PatternMatchingInterface.jav");
var Intf = classFiles.get("Interface");
var clazz = classFiles.get("PatternMatchingInterface");
@@ -1905,9 +1702,57 @@ public class TestComplete {
@Test
public void testBug406() throws Exception {
ConsoleInterface.logLevel = LogLevel.INFO;
var classFiles = generateClassFiles(createClassLoader(), "Bug406.jav");
var clazz = classFiles.get("Bug406");
clazz.getDeclaredMethod("main", List.class).invoke(null, List.of());
}
@Test
public void testBug423() throws Exception {
try {
var classFiles = generateClassFiles(createClassLoader(), "Bug423.jav");
fail("No exception thrown!");
} catch (CodeGenException e) {
assertEquals("Class Bug423 does not implement method f from interface Bug423I", e.getMessage());
}
}
@Test
public void testBug422() throws Exception {
try {
var classFiles = generateClassFiles(createClassLoader(), "Bug422.jav");
fail("Shouldn't compile!");
} catch (CompilerException e) {
assertEquals("Duplicate class definition: Bug422", e.getMessage());
}
}
@Test
public void testBug421() throws Exception {
try {
var classFiles = generateClassFiles(createClassLoader(), "Bug421.jav");
fail("Shouldn't compile!");
} catch (ParserError e) {
assertEquals("Syntax error at line 2:26 - no viable alternative at input 'm() { return 1 }'", e.getMessage());
}
}
@Test
public void testBug409() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug409.jav");
var clazz = classFiles.get("Bug409");
var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m");
assertEquals(5, m.invoke(instance));
}
@Test
public void testBug417() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug417.jav");
var clazz = classFiles.get("Bug417");
var instance = clazz.getDeclaredConstructor().newInstance();
var name = clazz.getDeclaredMethod("name", Integer.class);
assertEquals("one", name.invoke(instance, 1));
assertEquals("many", name.invoke(instance, 2));
}
}
+13 -4
View File
@@ -5,7 +5,6 @@ import de.dhbwstuttgart.bytecode.Codegen;
import de.dhbwstuttgart.environment.DirectoryClassLoader;
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.factory.NameGenerator;
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.target.tree.MethodParameter;
@@ -17,7 +16,6 @@ import de.dhbwstuttgart.target.tree.type.TargetFunNType;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.target.tree.type.TargetType;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@@ -204,9 +202,20 @@ public class TestCodegen {
@Test
public void testFor() throws Exception {
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("For"));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "forLoop", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(TargetType.Integer, "sum", new TargetLiteral.IntLiteral(0)), new TargetFor(List.of(new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0))), new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)), List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1)))), new TargetBlock(List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetLocalVar(TargetType.Integer, "i")))))), new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum")))));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "forLoop", List.of(), TargetType.Integer,
new TargetBlock(List.of(new TargetVarDecl(TargetType.Integer, "sum", new TargetLiteral.IntLiteral(0)),
new TargetFor(List.of(new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0))),
new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"),
new TargetLiteral.IntLiteral(10)), List.of(new TargetAssign(TargetType.Integer,
new TargetLocalVar(TargetType.Integer, "i"),
new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1)))),
new TargetBlock(List.of(
new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"),
new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"),
new TargetLocalVar(TargetType.Integer, "i")))))),
new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum")))));
var clazz = generateClass(targetClass, createClassLoader());
assertEquals(clazz.getDeclaredMethod("forLoop").invoke(null), 45);
assertEquals(45, clazz.getDeclaredMethod("forLoop").invoke(null));
}
@Test