[java-decompiler] IJ-CR-18473 Decompile permitted list entry when it isn't resolvable

Decompile all entries in the permitted list, even when the class isn't recognized by the decompiler.

GitOrigin-RevId: 3192b763b1d3d58ee576a1ea874cef685e749e5d
This commit is contained in:
Bart van Helvert
2021-12-15 19:04:32 +01:00
committed by intellij-monorepo-bot
parent 3f9fff686a
commit e8a528acf3

View File

@@ -420,7 +420,7 @@ public class ClassWriter {
}
List<StructRecordComponent> components = cl.getRecordComponents();
List<String> permittedSubclassSignature = cl.getPermittedSubclasses();
List<String> permittedSubclassQualifiedNames = cl.getPermittedSubclasses();
if (components != null) {
// records are implicitly final
@@ -429,7 +429,7 @@ public class ClassWriter {
appendModifiers(buffer, flags, CLASS_ALLOWED, isInterface, CLASS_EXCLUDED);
if (permittedSubclassSignature != null) {
if (permittedSubclassQualifiedNames != null) {
buffer.append("sealed ");
}
else if (node.isNonSealed()) {
@@ -506,19 +506,24 @@ public class ClassWriter {
}
}
if (permittedSubclassSignature != null) {
List<ClassNode> permittedOuterSubClasses = getClassNodes(permittedSubclassSignature).stream()
.filter(subClass -> !subClass.enclosingClasses.contains(node.classStruct.qualifiedName))
.collect(Collectors.toList());
if (!permittedOuterSubClasses.isEmpty()) { // only generate permits lists for non-nested classes
if (permittedSubclassQualifiedNames != null && !permittedSubclassQualifiedNames.isEmpty()) {
Set<String> qualifiedNested = node.nested.stream()
.map(nestedNode -> nestedNode.classStruct.qualifiedName)
.collect(Collectors.toSet());
boolean allSubClassesAreNested = Set.copyOf(permittedSubclassQualifiedNames).equals(qualifiedNested);
if (!allSubClassesAreNested) { // only generate permits lists for non-nested classes
buffer.append("permits ");
for (int i = 0; i < permittedOuterSubClasses.size(); i++) {
if (i > 0) {
buffer.append(", ");
for (int i = 0; i < permittedSubclassQualifiedNames.size(); i++) {
String qualifiedName = permittedSubclassQualifiedNames.get(i);
boolean isNested = qualifiedNested.contains(qualifiedName);
if (!isNested) {
if (i > 0) {
buffer.append(", ");
}
DecompilerContext.getImportCollector().getShortName(qualifiedName);
String simpleName = qualifiedName.substring(qualifiedName.lastIndexOf('/') + 1);
buffer.append(simpleName);
}
ClassNode subClass = permittedOuterSubClasses.get(i);
DecompilerContext.getImportCollector().getShortName(subClass.classStruct.qualifiedName); // add qualified name to potential import list
buffer.append(subClass.simpleName);
}
buffer.append(' ');
}
@@ -526,20 +531,6 @@ public class ClassWriter {
buffer.append('{').appendLineSeparator();
}
private static List<ClassNode> getClassNodes(List<String> qualifiedClassNames) {
return qualifiedClassNames.stream()
.map(str -> {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(str);
if (node == null) {
DecompilerContext.getLogger().writeMessage("Could not find class " + str, IFernflowerLogger.Severity.WARN);
}
return node;
})
.filter(Objects::nonNull)
.collect(Collectors.toList()
);
}
private static boolean isVarArgRecord(StructClass cl) {
String canonicalConstructorDescriptor =
cl.getRecordComponents().stream().map(c -> c.getDescriptor()).collect(Collectors.joining("", "(", ")V"));