Add check for sealed interfaces
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 6m41s

This commit is contained in:
Daniel Holle 2024-09-13 14:23:03 +02:00
parent 72035c48f2
commit eb454aa5b2
4 changed files with 16 additions and 3 deletions

View File

@ -3,7 +3,7 @@ import java.lang.Object;
import java.lang.Float; import java.lang.Float;
import java.lang.String; import java.lang.String;
sealed interface List permits LinkedElem {} sealed interface List permits LinkedElem, Elem {}
public record LinkedElem(Integer a,List l) implements List{} //Implementiert List und wird auch permittet public record LinkedElem(Integer a,List l) implements List{} //Implementiert List und wird auch permittet

View File

@ -1599,6 +1599,16 @@ public class Codegen {
if (!(clazz instanceof TargetInterface)) if (!(clazz instanceof TargetInterface))
access |= ACC_SUPER; access |= ACC_SUPER;
// Check sealed
for (var intf : clazz.implementingInterfaces()) {
var intfClass = compiler.getClass(new JavaClassName(intf.name()));
if (intfClass.isSealed()) {
if (intfClass.getPermittedSubtypes().stream().noneMatch(type -> type.getName().equals(new JavaClassName(className)))) {
throw new CodeGenException("Sealed interface " + intfClass.getClassName() + " doesn't permit class " + className);
}
}
}
var signature = generateSignature(clazz, clazz.generics()); var signature = generateSignature(clazz, clazz.generics());
var interfaces = clazz.implementingInterfaces().stream().map(TargetType::getInternalName).toArray(String[]::new); var interfaces = clazz.implementingInterfaces().stream().map(TargetType::getInternalName).toArray(String[]::new);
var superType = clazz.superType() != null ? clazz.superType().getInternalName() : "java/lang/Object"; var superType = clazz.superType() != null ? clazz.superType().getInternalName() : "java/lang/Object";

View File

@ -393,12 +393,12 @@ public class SyntaxTreeGenerator {
if (!Objects.isNull(ctx.EXTENDS())) { if (!Objects.isNull(ctx.EXTENDS())) {
extendedInterfaces.addAll(convert(ctx.typeList(0), generics)); extendedInterfaces.addAll(convert(ctx.typeList(0), generics));
} }
List<RefType> permittedSubtypes = new ArrayList<>(); List<RefType> permittedSubtypes = null;
// Ist Bit für 'sealed'-Modifier gesetzt // Ist Bit für 'sealed'-Modifier gesetzt
if ((modifiers & 4096) != 0) { if ((modifiers & 4096) != 0) {
if (!Objects.isNull(ctx.PERMITS())) { if (!Objects.isNull(ctx.PERMITS())) {
// permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration') // permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
permittedSubtypes.addAll(convert(ctx.typeList(ctx.typeList().size() - 1), generics)); permittedSubtypes = new ArrayList<>(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
} else { } else {
// falls sealed modifier ohne 'permits'-List oder umgekehrt // falls sealed modifier ohne 'permits'-List oder umgekehrt
throw new NotImplementedException("Invalid sealed class declaration"); throw new NotImplementedException("Invalid sealed class declaration");

View File

@ -86,6 +86,9 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
return staticInitializer; return staticInitializer;
} }
public boolean isSealed() { return permittedSubtypes != null; }
public List<RefType> getPermittedSubtypes() { return permittedSubtypes != null ? permittedSubtypes : List.of(); }
public boolean isInterface() { public boolean isInterface() {
return (Modifier.INTERFACE & this.getModifiers()) != 0; return (Modifier.INTERFACE & this.getModifiers()) != 0;
} }