From eb454aa5b2b24c548499f2f9f983b2732ee6d3a1 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Fri, 13 Sep 2024 14:23:03 +0200 Subject: [PATCH] Add check for sealed interfaces --- resources/bytecode/javFiles/SwitchRecordList.jav | 2 +- src/main/java/de/dhbwstuttgart/bytecode/Codegen.java | 10 ++++++++++ .../SyntaxTreeGenerator/SyntaxTreeGenerator.java | 4 ++-- .../de/dhbwstuttgart/syntaxtree/ClassOrInterface.java | 3 +++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/resources/bytecode/javFiles/SwitchRecordList.jav b/resources/bytecode/javFiles/SwitchRecordList.jav index 27ca9217..ea2ab707 100644 --- a/resources/bytecode/javFiles/SwitchRecordList.jav +++ b/resources/bytecode/javFiles/SwitchRecordList.jav @@ -3,7 +3,7 @@ import java.lang.Object; import java.lang.Float; 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 diff --git a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java index 3943232d..513944dd 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -1599,6 +1599,16 @@ public class Codegen { if (!(clazz instanceof TargetInterface)) 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 interfaces = clazz.implementingInterfaces().stream().map(TargetType::getInternalName).toArray(String[]::new); var superType = clazz.superType() != null ? clazz.superType().getInternalName() : "java/lang/Object"; diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index 6d33464a..fab148e0 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -393,12 +393,12 @@ public class SyntaxTreeGenerator { if (!Objects.isNull(ctx.EXTENDS())) { extendedInterfaces.addAll(convert(ctx.typeList(0), generics)); } - List permittedSubtypes = new ArrayList<>(); + List permittedSubtypes = null; // Ist Bit für 'sealed'-Modifier gesetzt if ((modifiers & 4096) != 0) { if (!Objects.isNull(ctx.PERMITS())) { // 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 { // falls sealed modifier ohne 'permits'-List oder umgekehrt throw new NotImplementedException("Invalid sealed class declaration"); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java b/src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java index 834fabb7..3bcd1228 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java @@ -86,6 +86,9 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope { return staticInitializer; } + public boolean isSealed() { return permittedSubtypes != null; } + public List getPermittedSubtypes() { return permittedSubtypes != null ? permittedSubtypes : List.of(); } + public boolean isInterface() { return (Modifier.INTERFACE & this.getModifiers()) != 0; }