diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java index b8227e9b1a01..6b02140800bc 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -420,6 +420,7 @@ public class ClassWriter { } List components = cl.getRecordComponents(); + List permittedSubclassSignature = cl.getPermittedSubclasses(); if (components != null) { // records are implicitly final @@ -428,6 +429,13 @@ public class ClassWriter { appendModifiers(buffer, flags, CLASS_ALLOWED, isInterface, CLASS_EXCLUDED); + if (permittedSubclassSignature != null) { + buffer.append("sealed "); + } + else if (node.isNonSealed()) { + buffer.append("non-sealed "); + } + if (isEnum) { buffer.append("enum "); } @@ -498,9 +506,33 @@ public class ClassWriter { } } + if (permittedSubclassSignature != null) { + List permittedOuterSubClasses = getClassNodes(permittedSubclassSignature).stream() + .filter(subClass -> !subClass.enclosingClasses.contains(node.classStruct.qualifiedName)) + .collect(Collectors.toList()); + if (!permittedOuterSubClasses.isEmpty()) { // only generate permits lists for nested classes + buffer.append("permits "); + for (int i = 0; i < permittedOuterSubClasses.size(); i++) { + if (i > 0) { + buffer.append(", "); + } + ClassNode subClass = permittedOuterSubClasses.get(i); + DecompilerContext.getImportCollector().getShortName(subClass.classStruct.qualifiedName); // add qualified name to potential import list + buffer.append(subClass.simpleName); + } + buffer.append(' '); + } + } buffer.append('{').appendLineSeparator(); } + private static List getClassNodes(List qualifiedClassNames) { + return qualifiedClassNames.stream() + .map(str -> DecompilerContext.getClassProcessor().getMapRootClasses().get(str)) + .collect(Collectors.toList() + ); + } + private static boolean isVarArgRecord(StructClass cl) { String canonicalConstructorDescriptor = cl.getRecordComponents().stream().map(c -> c.getDescriptor()).collect(Collectors.joining("", "(", ")V")); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java index 7bb50aaeb939..3a2d70ecc3aa 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.java.decompiler.main; import org.jetbrains.java.decompiler.code.CodeConstants; @@ -22,6 +22,7 @@ import org.jetbrains.java.decompiler.struct.attr.StructEnclosingMethodAttribute; import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; import org.jetbrains.java.decompiler.struct.attr.StructInnerClassesAttribute; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; +import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant; import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.TextBuffer; @@ -29,6 +30,7 @@ import org.jetbrains.java.decompiler.util.TextBuffer; import java.io.IOException; import java.util.*; import java.util.Map.Entry; +import java.util.stream.Collectors; public class ClassesProcessor implements CodeConstants { public static final int AVERAGE_CLASS_SIZE = 16 * 1024; @@ -122,6 +124,27 @@ public class ClassesProcessor implements CodeConstants { } } + // set non-sealed if class extends or implements a sealed class + for (Entry ent : mapRootClasses.entrySet()) { + ClassNode clazz = ent.getValue(); + List qualifiedSealedSuperNames = new ArrayList<>(Arrays.asList(clazz.classStruct.getInterfaceNames())); + PrimitiveConstant superConst = clazz.classStruct.superClass; + if (superConst != null) qualifiedSealedSuperNames.add(superConst.getString()); + List potentialSealedSupers = qualifiedSealedSuperNames.stream() + .map(mapRootClasses::get) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + for (ClassNode potentialSealedSuper : potentialSealedSupers) { + if (potentialSealedSuper.classStruct.getPermittedSubclasses() != null && + potentialSealedSuper.classStruct.getPermittedSubclasses().contains(clazz.classStruct.qualifiedName) && + (clazz.access & CodeConstants.ACC_FINAL) == 0 && + clazz.classStruct.getPermittedSubclasses() == null + ) { + clazz.setNonSealed(true); + } + } + } + if (bDecompileInner) { // connect nested classes for (Entry ent : mapRootClasses.entrySet()) { @@ -418,6 +441,7 @@ public class ClassesProcessor implements CodeConstants { public int type; public int access; + public boolean isNonSealed = false; public String simpleName; public final StructClass classStruct; private ClassWrapper wrapper; @@ -491,6 +515,14 @@ public class ClassesProcessor implements CodeConstants { return node.wrapper; } + public boolean isNonSealed() { + return isNonSealed; + } + + public void setNonSealed(boolean nonSealed) { + isNonSealed = nonSealed; + } + public static class LambdaInformation { public String method_name; public String method_descriptor; diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java index 4809851539c0..b9739cc85bf1 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java @@ -3,6 +3,7 @@ package org.jetbrains.java.decompiler.struct; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; +import org.jetbrains.java.decompiler.struct.attr.StructPermittedSubclassesAttribute; import org.jetbrains.java.decompiler.struct.attr.StructRecordAttribute; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant; @@ -160,6 +161,12 @@ public class StructClass extends StructMember { return recordAttr.getComponents(); } + public List getPermittedSubclasses() { + StructPermittedSubclassesAttribute permittedSubClassAttr = getAttribute(StructGeneralAttribute.ATTRIBUTE_PERMITTED_SUBCLASSES); + if (permittedSubClassAttr == null) return null; + return permittedSubClassAttr.getClasses(); + } + public int[] getInterfaces() { return interfaces; } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java index 6239ee41c24e..898ef9f2f7ea 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.java.decompiler.struct.attr; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; @@ -36,6 +36,7 @@ public class StructGeneralAttribute { public static final Key ATTRIBUTE_METHOD_PARAMETERS = new Key<>("MethodParameters"); public static final Key ATTRIBUTE_MODULE = new Key<>("Module"); public static final Key ATTRIBUTE_RECORD = new Key<>("Record"); + public static final Key ATTRIBUTE_PERMITTED_SUBCLASSES = new Key<>("PermittedSubclasses"); @SuppressWarnings("unused") public static class Key { @@ -100,6 +101,8 @@ public class StructGeneralAttribute { } else if (ATTRIBUTE_RECORD.name.equals(name)) { return new StructRecordAttribute(); + } else if (ATTRIBUTE_PERMITTED_SUBCLASSES.name.equals(name)) { + return new StructPermittedSubclassesAttribute(); } else { return null; // unsupported attribute diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructPermittedSubclassesAttribute.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructPermittedSubclassesAttribute.java new file mode 100644 index 000000000000..848418bbc785 --- /dev/null +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructPermittedSubclassesAttribute.java @@ -0,0 +1,35 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.java.decompiler.struct.attr; + +import org.jetbrains.java.decompiler.struct.consts.ConstantPool; +import org.jetbrains.java.decompiler.util.DataInputFullStream; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +/* + PermittedSubclasses_attribute { + u2 attribute_name_index; + u4 attribute_length; + u2 number_of_classes; + u2 classes[number_of_classes]; + } + */ +public class StructPermittedSubclassesAttribute extends StructGeneralAttribute { + List classes; + + @Override + public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException { + int numberOfClasses = data.readUnsignedShort(); + String[] classes = new String[numberOfClasses]; + for (int i = 0; i < numberOfClasses; i++) { + classes[i] = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + } + this.classes = Arrays.asList(classes); + } + + public List getClasses() { + return classes; + } +} diff --git a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java index f84a02d0b202..1c346d4eae42 100644 --- a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -147,6 +147,24 @@ public class SingleClassesTest { @Test public void testRecordVararg() { doTest("records/TestRecordVararg"); } @Test public void testRecordGenericVararg() { doTest("records/TestRecordGenericVararg"); } @Test public void testRecordAnno() { doTest("records/TestRecordAnno"); } + @Test public void testRootWithClassInner() { doTest("sealed/RootWithClassInner"); } + @Test public void testRootWithInterfaceInner() { doTest("sealed/RootWithInterfaceInner"); } + @Test public void testRootWithClassOuter() { doTest("sealed/RootWithClassOuter", + "sealed/ClassExtends", "sealed/ClassNonSealed", "sealed/ClassNonSealedExtendsImplements"); + } + @Test public void testRootWithInterfaceOuter() { doTest("sealed/RootWithInterfaceOuter", + "sealed/ClassImplements", "sealed/InterfaceNonSealed", "sealed/ClassNonSealedExtendsImplements"); + } + @Test public void testClassNonSealed() { doTest("sealed/ClassNonSealed", + "sealed/RootWithClassOuter", "sealed/ClassExtends", "sealed/ClassNonSealedExtendsImplements"); + } + @Test public void testClassNonSealedExtendsImplements() { doTest("sealed/ClassNonSealedExtendsImplements", + "sealed/RootWithClassOuter", "sealed/ClassExtends", "sealed/ClassNonSealed"); + } + @Test public void testInterfaceNonSealed() { doTest("sealed/InterfaceNonSealed", + "sealed/RootWithInterfaceOuter", "sealed/ClassImplements", "sealed/ClassNonSealedExtendsImplements"); + } + @Test public void testRootWithModule() { doTest("sealed/foo/RootWithModule", "sealed/bar/BarClassExtends");} @Test public void testInheritanceChainCycle() { doTest("pkg/TestInheritanceChainCycle"); } @Test public void testDynamicConstantPoolEntry() { doTest("java11/TestDynamicConstantPoolEntry"); } diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/ClassExtends.class b/plugins/java-decompiler/engine/testData/classes/sealed/ClassExtends.class new file mode 100644 index 000000000000..b153738d028c Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/ClassExtends.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/ClassImplements.class b/plugins/java-decompiler/engine/testData/classes/sealed/ClassImplements.class new file mode 100644 index 000000000000..6576356f25df Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/ClassImplements.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/ClassNonSealed.class b/plugins/java-decompiler/engine/testData/classes/sealed/ClassNonSealed.class new file mode 100644 index 000000000000..fcb5e012e85f Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/ClassNonSealed.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/ClassNonSealedExtendsImplements.class b/plugins/java-decompiler/engine/testData/classes/sealed/ClassNonSealedExtendsImplements.class new file mode 100644 index 000000000000..cd97721aa387 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/ClassNonSealedExtendsImplements.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/InterfaceNonSealed.class b/plugins/java-decompiler/engine/testData/classes/sealed/InterfaceNonSealed.class new file mode 100644 index 000000000000..a74bbfd72d10 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/InterfaceNonSealed.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/RootWithClassInner$Inner.class b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithClassInner$Inner.class new file mode 100644 index 000000000000..d7e5a2112eaa Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithClassInner$Inner.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/RootWithClassInner.class b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithClassInner.class new file mode 100644 index 000000000000..0d6aa19c9a9f Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithClassInner.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/RootWithClassOuter.class b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithClassOuter.class new file mode 100644 index 000000000000..9f9125504e60 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithClassOuter.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/RootWithInterfaceInner$Inner.class b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithInterfaceInner$Inner.class new file mode 100644 index 000000000000..2fad668da34f Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithInterfaceInner$Inner.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/RootWithInterfaceInner.class b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithInterfaceInner.class new file mode 100644 index 000000000000..f5fb80a2c3f2 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithInterfaceInner.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/RootWithInterfaceOuter.class b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithInterfaceOuter.class new file mode 100644 index 000000000000..bef6fe4ff8d8 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/RootWithInterfaceOuter.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/bar/BarClassExtends.class b/plugins/java-decompiler/engine/testData/classes/sealed/bar/BarClassExtends.class new file mode 100644 index 000000000000..a6a0f0863742 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/bar/BarClassExtends.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/sealed/foo/RootWithModule.class b/plugins/java-decompiler/engine/testData/classes/sealed/foo/RootWithModule.class new file mode 100644 index 000000000000..fc12fd982b55 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/sealed/foo/RootWithModule.class differ diff --git a/plugins/java-decompiler/engine/testData/results/ClassNonSealed.dec b/plugins/java-decompiler/engine/testData/results/ClassNonSealed.dec new file mode 100644 index 000000000000..a03c12c5d9a2 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/ClassNonSealed.dec @@ -0,0 +1,5 @@ +package sealed; + +non-sealed class ClassNonSealed extends RootWithClassOuter { +} + diff --git a/plugins/java-decompiler/engine/testData/results/ClassNonSealedExtendsImplements.dec b/plugins/java-decompiler/engine/testData/results/ClassNonSealedExtendsImplements.dec new file mode 100644 index 000000000000..641302474900 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/ClassNonSealedExtendsImplements.dec @@ -0,0 +1,5 @@ +package sealed; + +non-sealed class ClassNonSealedExtendsImplements extends RootWithClassOuter implements RootWithInterfaceOuter { +} + diff --git a/plugins/java-decompiler/engine/testData/results/InterfaceNonSealed.dec b/plugins/java-decompiler/engine/testData/results/InterfaceNonSealed.dec new file mode 100644 index 000000000000..0fd51b00b7fa --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/InterfaceNonSealed.dec @@ -0,0 +1,5 @@ +package sealed; + +non-sealed interface InterfaceNonSealed extends RootWithInterfaceOuter { +} + diff --git a/plugins/java-decompiler/engine/testData/results/RootWithClassInner.dec b/plugins/java-decompiler/engine/testData/results/RootWithClassInner.dec new file mode 100644 index 000000000000..340dd2761eb0 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/RootWithClassInner.dec @@ -0,0 +1,7 @@ +package sealed; + +sealed class RootWithClassInner { + static final class Inner extends RootWithClassInner { + } +} + diff --git a/plugins/java-decompiler/engine/testData/results/RootWithClassOuter.dec b/plugins/java-decompiler/engine/testData/results/RootWithClassOuter.dec new file mode 100644 index 000000000000..8893d630b069 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/RootWithClassOuter.dec @@ -0,0 +1,5 @@ +package sealed; + +abstract sealed class RootWithClassOuter permits ClassExtends, ClassNonSealed, ClassNonSealedExtendsImplements { +} + diff --git a/plugins/java-decompiler/engine/testData/results/RootWithInterfaceInner.dec b/plugins/java-decompiler/engine/testData/results/RootWithInterfaceInner.dec new file mode 100644 index 000000000000..c7346d0149c3 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/RootWithInterfaceInner.dec @@ -0,0 +1,7 @@ +package sealed; + +sealed interface RootWithInterfaceInner { + public static final class Inner implements RootWithInterfaceInner { + } +} + diff --git a/plugins/java-decompiler/engine/testData/results/RootWithInterfaceOuter.dec b/plugins/java-decompiler/engine/testData/results/RootWithInterfaceOuter.dec new file mode 100644 index 000000000000..47a9b5dac67c --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/RootWithInterfaceOuter.dec @@ -0,0 +1,5 @@ +package sealed; + +sealed interface RootWithInterfaceOuter permits ClassImplements, InterfaceNonSealed, ClassNonSealedExtendsImplements { +} + diff --git a/plugins/java-decompiler/engine/testData/results/RootWithModule.dec b/plugins/java-decompiler/engine/testData/results/RootWithModule.dec new file mode 100644 index 000000000000..b77cb9f14399 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/RootWithModule.dec @@ -0,0 +1,7 @@ +package sealed.foo; + +import sealed.bar.BarClassExtends; + +public abstract sealed class RootWithModule permits BarClassExtends { +} + diff --git a/plugins/java-decompiler/engine/testData/src/sealed/ClassExtends.java b/plugins/java-decompiler/engine/testData/src/sealed/ClassExtends.java new file mode 100644 index 000000000000..8f2c13f3a73c --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/sealed/ClassExtends.java @@ -0,0 +1,4 @@ +package sealed; + +final class ClassExtends extends RootWithClassOuter { +} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/sealed/ClassImplements.java b/plugins/java-decompiler/engine/testData/src/sealed/ClassImplements.java new file mode 100644 index 000000000000..453f8415fa03 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/sealed/ClassImplements.java @@ -0,0 +1,4 @@ +package sealed; + +final class FinalImplements implements RootWithInterfaceOuter { +} diff --git a/plugins/java-decompiler/engine/testData/src/sealed/ClassNonSealed.java b/plugins/java-decompiler/engine/testData/src/sealed/ClassNonSealed.java new file mode 100644 index 000000000000..9474dc34d45b --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/sealed/ClassNonSealed.java @@ -0,0 +1,4 @@ +package sealed; + +non-sealed class ClassNonSealed extends RootWithClassOuter { +} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/sealed/ClassNonSealedImplements.java b/plugins/java-decompiler/engine/testData/src/sealed/ClassNonSealedImplements.java new file mode 100644 index 000000000000..05683a1216b8 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/sealed/ClassNonSealedImplements.java @@ -0,0 +1,4 @@ +package sealed; + +non-sealed class ClassNonSealedImplements extends RootWithClassOuter implements RootWithInterfaceOuter { +} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/sealed/InterfaceNonSealed.java b/plugins/java-decompiler/engine/testData/src/sealed/InterfaceNonSealed.java new file mode 100644 index 000000000000..4b79bd8f1c40 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/sealed/InterfaceNonSealed.java @@ -0,0 +1,4 @@ +package sealed; + +non-sealed interface InterfaceNonSealed extends RootWithInterfaceOuter { +} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/sealed/RootWithClassInner.java b/plugins/java-decompiler/engine/testData/src/sealed/RootWithClassInner.java new file mode 100644 index 000000000000..123872914972 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/sealed/RootWithClassInner.java @@ -0,0 +1,6 @@ +package sealed; + +sealed interface RootWithClassInner { + final class Inner implements RootWithClassInner { + } +} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/sealed/RootWithClassOuter.java b/plugins/java-decompiler/engine/testData/src/sealed/RootWithClassOuter.java new file mode 100644 index 000000000000..f905293a770a --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/sealed/RootWithClassOuter.java @@ -0,0 +1,4 @@ +package sealed; + +abstract sealed class RootWithClassOuter permits ClassExtends, ClassNonSealed, ClassNonSealedImplements { +} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/sealed/RootWithInterfaceInner.java b/plugins/java-decompiler/engine/testData/src/sealed/RootWithInterfaceInner.java new file mode 100644 index 000000000000..63d6960cdadb --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/sealed/RootWithInterfaceInner.java @@ -0,0 +1,6 @@ +package sealed; + +sealed interface RootWithInterfaceInner { + final class Inner implements RootWithInterfaceInner { + } +} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/sealed/RootWithInterfaceOuter.java b/plugins/java-decompiler/engine/testData/src/sealed/RootWithInterfaceOuter.java new file mode 100644 index 000000000000..e29d379886f0 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/sealed/RootWithInterfaceOuter.java @@ -0,0 +1,4 @@ +package sealed; + +sealed interface RootWithInterfaceOuter permits FinalImplements, InterfaceNonSealed, ClassNonSealedImplements { +} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/sealed/bar/BarClassExtends.java b/plugins/java-decompiler/engine/testData/src/sealed/bar/BarClassExtends.java new file mode 100644 index 000000000000..7d373c334b98 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/sealed/bar/BarClassExtends.java @@ -0,0 +1,6 @@ +package sealed.bar; + +import sealed.foo.RootWithModule; + +final public class BarClassExtends extends RootWithModule { +} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/sealed/foo/RootWithModule.java b/plugins/java-decompiler/engine/testData/src/sealed/foo/RootWithModule.java new file mode 100644 index 000000000000..d8034d7f3226 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/sealed/foo/RootWithModule.java @@ -0,0 +1,6 @@ +package sealed.foo; + +import sealed.bar.BarClassExtends; + +public abstract sealed class RootWithModule permits BarClassExtends { +} \ No newline at end of file