Compare commits

...
11 Commits
Author SHA1 Message Date
dholle 35e8dda6bd Fix various issues with static methods, fixes #416
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 2m7s
SonarQube Scan / SonarQube Trigger (pull_request) Canceled after 16m22s
2026-11-11 17:32:58 +01:00
dholle bf22cf246e Merge pull request 'Fix #411 by setting functional interface property properly' (#431) from fix-411 into master
SonarQube Scan / SonarQube Trigger (push) Successful in 3m27s
Reviewed-on: #431
2026-11-11 15:43:24 +00:00
dholle 034cdf2e0b Merge branch 'master' into fix-411
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m34s
SonarQube Scan / SonarQube Trigger (pull_request) Successful in 3m27s
2026-11-11 16:37:23 +01:00
dholle 95ee84cb99 Fix #411 by setting functional interface property properly
SonarQube Scan / SonarQube Trigger (pull_request) Successful in 2m34s
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m31s
2026-11-11 16:29:30 +01:00
dholle 3fc098b155 Merge pull request 'Fix #412 by handling default correctly' (#430) from fix-412 into master
SonarQube Scan / SonarQube Trigger (push) Successful in 2m29s
Reviewed-on: #430
2026-11-11 14:20:19 +00:00
dholle 32ddb1132f Fix #412 by handling default correctly
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m21s
SonarQube Scan / SonarQube Trigger (pull_request) Successful in 2m33s
2026-11-11 15:13:56 +01:00
dholle 174c999543 Merge pull request 'Fix #414 by implementing the other number formats' (#429) from fix-414 into master
SonarQube Scan / SonarQube Trigger (push) Successful in 2m37s
Reviewed-on: #429
2026-11-11 13:42:55 +00:00
dholle 4b576da19d Fix #414 by implementing the other number formats
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m26s
SonarQube Scan / SonarQube Trigger (pull_request) Successful in 2m35s
2026-11-11 14:38:19 +01:00
dholle 942b8ca488 Merge pull request 'Fix #417 in Codegen and by changing constraint generation' (#428) from fix-417 into master
SonarQube Scan / SonarQube Trigger (push) Successful in 2m33s
Reviewed-on: #428
2026-11-11 13:11:03 +00:00
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
13 changed files with 127 additions and 16 deletions

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
import java.lang.Integer;
public interface Bug411 {
default f() {
return 1;
}
}
+12
View File
@@ -0,0 +1,12 @@
import java.lang.Integer;
public class Bug412 {
public m(Integer i) {
var r = 0;
switch (i) {
case 1: r = 10; break;
default: r = 20;
}
return r;
}
}
+9
View File
@@ -0,0 +1,9 @@
import java.lang.Integer;
sealed interface L<T> permits Cons, Nil {}
public record Cons<T>(T head, L<T> tail) implements L<T> {}
public record Nil<T>() implements L<T> {}
public class Bug416 {
public static <T> len(Cons(h, t)) { return 1 + len(t); }
public static <T> len(Nil()) { return 0; }
}
+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";
};
}
}
+4
View File
@@ -5,4 +5,8 @@ public class Literal {
public m2() { return 'C'; }
public m3() { return 10L; }
public m4() { return 10.5F; }
public m5() { return 10.5D; }
public m6() { return 0xFF; }
public m7() { return 0b101010; }
public m8() { return 010; }
}
@@ -1437,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();
}
}
@@ -1777,7 +1780,7 @@ public class Codegen {
if (parent != null) {
state.scope.parent = parent.scope;
}
var offset = 1;
var offset = method.isStatic() ? 0 : 1;
for (var param : method.signature().parameters()) {
state.createVariable(param.pattern().name(), param.pattern().type());
}
@@ -15,6 +15,7 @@ import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import de.dhbwstuttgart.typeinference.unify.model.*;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
@@ -54,7 +55,8 @@ public class FCGenerator {
private static Boolean isFunctionalInterface(ClassOrInterface cly) {
return (cly.isInterface() && (cly.isFunctionalInterface() || cly.getMethods().size() == 1));
// TODO isFunctionalInterface should be set properly, we shouldn't need to check it again
return (cly.isInterface() && (cly.isFunctionalInterface() || cly.getMethods().size() == 1 && Modifier.isAbstract(cly.getMethods().getFirst().modifier)));
}
private static Pair genImplFunType(ClassOrInterface cly, RefTypeOrTPHOrWildcardOrGeneric fIType, HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs) {
@@ -405,14 +405,16 @@ public class StatementGenerator {
private SwitchBlock convert(Java17Parser.SwitchBlockStatementGroupContext stmt) {
List<SwitchLabel> labels = new ArrayList<>();
stmt.switchLabel().forEach((label) -> {
var isDefault = false;
for (var label : stmt.switchLabel()) {
if (label instanceof SwitchLabelDefaultContext) isDefault = true;
labels.add(convert(label));
});
}
List<Statement> block = new ArrayList<>();
stmt.blockStatement().stream().forEach((blockStmt) -> {
block.addAll(convert(blockStmt));
});
return new SwitchBlock(labels, new Block(block, stmt.blockStatement(0).getStart()), false, stmt.getStart());
return new SwitchBlock(labels, new Block(block, stmt.blockStatement(0).getStart()), isDefault,false, stmt.getStart());
}
private SwitchLabel convert(SwitchLabelContext switchLabel) {
@@ -1033,10 +1035,22 @@ public class StatementGenerator {
private Expression convert(Java17Parser.LiteralContext literal) {
switch (literal) {
case IntLiteralContext intliteral:
var text = intliteral.getText();
var radix = 10;
if (text.startsWith("0x") || text.startsWith("0X")) {
radix = 16;
text = text.substring(2);
} else if (text.startsWith("0b") || text.startsWith("0B")) {
radix = 2;
text = text.substring(2);
} else if (text.startsWith("0") && text.length() > 1) {
radix = 8;
text = text.substring(1);
}
Number value;
if (intliteral.getText().endsWith("l") || intliteral.getText().endsWith("L"))
value = Long.parseLong(intliteral.getText().substring(0, intliteral.getText().length() - 1));
else value = Integer.parseInt(intliteral.getText());
if (text.endsWith("l") || text.endsWith("L"))
value = Long.parseLong(text.substring(0, text.length() - 1), radix);
else value = Integer.parseInt(text, radix);
return new Literal(TypePlaceholder.fresh(literal.getStart()), value, intliteral.getStart());
case FltLiteralContext floatliteral:
if (floatliteral.getText().endsWith("f") || floatliteral.getText().endsWith("F"))
@@ -409,8 +409,9 @@ public class SyntaxTreeGenerator {
}
}
boolean isFunctonalInterfce = methods.size() == 1 && Modifier.isAbstract(methods.getFirst().modifier);
var staticCtor = Optional.of(this.generateStaticConstructor(ctx.identifier().getText(), staticFieldInitializations, genericParams, ctx.getStart()));
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), staticCtor, methods, new ArrayList<>(), genericParams, superClass, true, methods.size() == 1 ? true : false, extendedInterfaces, permittedSubtypes, ctx.getStart(), fileName);
return new ClassOrInterface(modifiers, name, fields, Optional.empty(), staticCtor, methods, new ArrayList<>(), genericParams, superClass, true, isFunctonalInterfce, extendedInterfaces, permittedSubtypes, ctx.getStart(), fileName);
}
private GenericDeclarationList createEmptyGenericDeclarationList(Token classNameIdentifier) {
@@ -29,6 +29,7 @@ import org.objectweb.asm.Opcodes;
import java.lang.classfile.Opcode;
import java.lang.reflect.AccessFlag;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -630,7 +631,7 @@ public class ASTToTargetAST {
mParams,
classType,
method.name(),
false, false, method.isPrivate()
method.isStatic(), false, method.isPrivate()
);
if (method.signature().returnType() != null) {
caseBody = new TargetReturn(caseBody);
@@ -476,7 +476,7 @@ public class StatementToTargetExpression implements ASTVisitor {
.map(this::extractAllPatterns)
.flatMap(List::stream).toList();
case FormalParameter param -> List.of(new TypeVariants(param.getType(), converter.findAllVariants(param.getType())));
default -> List.of();
case null, default -> List.of();
};
}
@@ -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();
+47
View File
@@ -1230,6 +1230,10 @@ public class TestComplete {
assertEquals('C', clazz.getDeclaredMethod("m2").invoke(instance));
assertEquals(10L, clazz.getDeclaredMethod("m3").invoke(instance));
assertEquals(10.5F, clazz.getDeclaredMethod("m4").invoke(instance));
assertEquals(10.5D, clazz.getDeclaredMethod("m5").invoke(instance));
assertEquals(0xFF, clazz.getDeclaredMethod("m6").invoke(instance));
assertEquals(0b101010, clazz.getDeclaredMethod("m7").invoke(instance));
assertEquals(010, clazz.getDeclaredMethod("m8").invoke(instance));
}
@Test
@@ -1745,4 +1749,47 @@ public class TestComplete {
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));
}
@Test
public void testBug411() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug411.jav");
var clazz = classFiles.get("Bug411");
}
@Test
public void testBug412() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug412.jav");
var clazz = classFiles.get("Bug412");
var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m", Integer.class);
assertEquals(10, m.invoke(instance, 1));
assertEquals(20, m.invoke(instance, 2));
}
@Test
public void testBug416() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug416.jav");
var clazz = classFiles.get("Bug416");
var L = classFiles.get("L");
var Cons = classFiles.get("Cons");
var Nil = classFiles.get("Nil");
var consCtor = Cons.getDeclaredConstructor(Object.class, L);
var nilCtor = Nil.getDeclaredConstructor();
var list = consCtor.newInstance(1, consCtor.newInstance(2, consCtor.newInstance(3, nilCtor.newInstance())));
var len = clazz.getDeclaredMethod("len", L);
assertEquals(3, len.invoke(null, list));
}
}