Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb1c5c6629 | ||
|
|
a5c8d93e4c | ||
|
|
e70f071c63 | ||
|
|
f66499b4fe |
No files matched your search
@@ -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 {}
|
||||
|
||||
@@ -1846,6 +1846,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());
|
||||
|
||||
|
||||
@@ -618,7 +618,7 @@ public class ASTToTargetAST {
|
||||
}
|
||||
}
|
||||
|
||||
private static TargetExpression generateCall(TargetMethod method, List<TargetLocalVar> params, TargetType classType, boolean isInterface) {
|
||||
private static TargetExpression generateCall(TargetMethod method, List<TargetLocalVar> params, TargetType classType) {
|
||||
var mParams = new ArrayList<TargetExpression>();
|
||||
for (var i = 0; i < params.size(); i++) {
|
||||
var tpe = method.signature().parameters().get(i).pattern().type();
|
||||
@@ -626,11 +626,11 @@ public class ASTToTargetAST {
|
||||
}
|
||||
TargetExpression caseBody = new TargetMethodCall(
|
||||
method.signature().returnType(),
|
||||
method.isStatic() ? new TargetClassName(classType) : new TargetThis(classType),
|
||||
new TargetThis(classType),
|
||||
mParams,
|
||||
classType,
|
||||
method.name(),
|
||||
method.isStatic(), isInterface, method.isPrivate()
|
||||
false, false, method.isPrivate()
|
||||
);
|
||||
if (method.signature().returnType() != null) {
|
||||
caseBody = new TargetReturn(caseBody);
|
||||
@@ -638,11 +638,11 @@ public class ASTToTargetAST {
|
||||
return caseBody;
|
||||
}
|
||||
|
||||
private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetLocalVar> params, List<TargetPattern> patterns, List<TargetMethod> methods, TargetType classType, boolean isInterface) {
|
||||
private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetLocalVar> params, List<TargetPattern> patterns, List<TargetMethod> methods, TargetType classType) {
|
||||
if (methods.isEmpty()) throw new DebugException("Couldn't find a candidate for switch overloading");
|
||||
if (methods.size() == 1) {
|
||||
var method = methods.getFirst();
|
||||
return generateCall(method, params, classType, isInterface);
|
||||
return generateCall(method, params, classType);
|
||||
}
|
||||
|
||||
var cases = new ArrayList<TargetSwitch.Case>();
|
||||
@@ -691,11 +691,11 @@ public class ASTToTargetAST {
|
||||
}).toList();
|
||||
|
||||
if (candidates.isEmpty()) {
|
||||
var body = new TargetBlock(List.of(generateCall(method, params, classType, isInterface)));
|
||||
var body = new TargetBlock(List.of(generateCall(method, params, classType)));
|
||||
cases.add(new TargetSwitch.Case(List.of(lastPattern), body));
|
||||
} else {
|
||||
//candidates.forEach(m -> Target.logger.info(m.getSignature()));
|
||||
var caseBody = generatePatternOverloadsRec(offset + 1, expr, params, patternsRec, candidates, classType, isInterface);
|
||||
var caseBody = generatePatternOverloadsRec(offset + 1, expr, params, patternsRec, candidates, classType);
|
||||
var body = new TargetBlock(List.of(caseBody));
|
||||
var case_ = new TargetSwitch.Case(List.of(lastPattern), body);
|
||||
|
||||
@@ -787,7 +787,7 @@ public class ASTToTargetAST {
|
||||
var parameters = resParams.stream().map( p -> new TargetLocalVar(p.pattern().type(), p.pattern().name())).toList();
|
||||
|
||||
var classType = new TargetRefType(clazz.getClassName().toString());
|
||||
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(resParams.getFirst().pattern().type(), resParams.getFirst().pattern().name()), parameters, List.of(), methods, classType, clazz.isInterface());
|
||||
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(resParams.getFirst().pattern().type(), resParams.getFirst().pattern().name()), parameters, List.of(), methods, classType);
|
||||
var block = new TargetBlock(List.of(stmt));
|
||||
|
||||
var generics = new HashSet<>(firstMethod.signature().generics());
|
||||
@@ -870,7 +870,7 @@ public class ASTToTargetAST {
|
||||
|
||||
// Generate dispatch method
|
||||
var classType = new TargetRefType(clazz.getClassName().toString());
|
||||
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(signatureParams.getFirst().pattern().type(), signatureParams.getFirst().pattern().name()), parameters, List.of(), res, classType, clazz.isInterface());
|
||||
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(signatureParams.getFirst().pattern().type(), signatureParams.getFirst().pattern().name()), parameters, List.of(), res, classType);
|
||||
var block = new TargetBlock(List.of(stmt));
|
||||
|
||||
var bridgeMethod = new TargetMethod(firstMethod.access(), firstMethod.name(), block, group.signature.java, group.signature.tx, firstMethod.base(), null);
|
||||
|
||||
@@ -256,9 +256,9 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
foundMethod = findMethod(receiverName, methodCall.name, signature, converter.compiler).orElseThrow(
|
||||
() -> new DebugException("Method " + methodCall.name + " not found (" + finalSignature + ") on class " + receiverName)
|
||||
);
|
||||
if (foundMethod != null) {
|
||||
signature = foundMethod.getParameterList().getFormalparalist().stream().map(pattern -> converter.convert(pattern.getType(), generics)).toList();
|
||||
}
|
||||
//if (foundMethod != null) {
|
||||
// signature = foundMethod.getParameterList().getFormalparalist().stream().map(pattern -> converter.convert(pattern.getType(), generics)).toList();
|
||||
//}
|
||||
}
|
||||
|
||||
if (!isFunNType) {
|
||||
|
||||
@@ -1083,6 +1083,7 @@ public class TestComplete {
|
||||
|
||||
@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");
|
||||
@@ -1703,4 +1704,14 @@ public class TestComplete {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user