Skip to content
This repository was archived by the owner on Aug 28, 2024. It is now read-only.

Commit

Permalink
Merge pull request #52 from BaseMC/upstreamupdate/github.com/fesh0r/f…
Browse files Browse the repository at this point in the history
…ernflower/master

UpstreamUpdate from https://github.com/fesh0r/fernflower
  • Loading branch information
litetex authored Feb 21, 2021
2 parents 9329886 + e59c63b commit c93b971
Show file tree
Hide file tree
Showing 14 changed files with 186 additions and 126 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ sourceSets {
test.java.srcDirs 'test'
}

repositories { jcenter() }
repositories { mavenCentral() }
dependencies {
testCompile 'junit:junit:4.13.2'
testCompile 'org.assertj:assertj-core:3.19.0'
Expand Down
135 changes: 83 additions & 52 deletions src/org/jetbrains/java/decompiler/main/ClassWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,6 @@ else if (enumFields) {
}
}

if (cl.hasModifier(CodeConstants.ACC_MODULE)) {
StructModuleAttribute moduleAttribute = cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_MODULE);
if (moduleAttribute != null) {
writeModuleInfoBody(buffer, moduleAttribute);
}
}

buffer.appendIndent(indent).append('}');

if (node.type != ClassNode.CLASS_ANONYMOUS) {
Expand All @@ -269,10 +262,10 @@ else if (enumFields) {
DecompilerContext.getLogger().endWriteClass();
}

@SuppressWarnings("SpellCheckingInspection")
private static boolean isSyntheticRecordMethod(StructClass cl, StructMethod mt, TextBuffer code) {
if (cl.getRecordComponents() != null) {
String name = mt.getName(), descriptor = mt.getDescriptor();
//noinspection SpellCheckingInspection
if (name.equals("equals") && descriptor.equals("(Ljava/lang/Object;)Z") ||
name.equals("hashCode") && descriptor.equals("()I") ||
name.equals("toString") && descriptor.equals("()Ljava/lang/String;")) {
Expand All @@ -285,48 +278,101 @@ private static boolean isSyntheticRecordMethod(StructClass cl, StructMethod mt,
return false;
}

private static void writeModuleInfoBody(TextBuffer buffer, StructModuleAttribute moduleAttribute) {
for (StructModuleAttribute.RequiresEntry requires : moduleAttribute.requires) {
buffer.appendIndent(1).append("requires ").append(requires.moduleName.replace('/', '.')).append(';').appendLineSeparator();
}
public static void packageInfoToJava(StructClass cl, TextBuffer buffer) {
appendAnnotations(buffer, 0, cl, -1);

for (StructModuleAttribute.ExportsEntry exports : moduleAttribute.exports) {
buffer.appendIndent(1).append("exports ").append(exports.packageName.replace('/', '.'));
int index = cl.qualifiedName.lastIndexOf('/');
String packageName = cl.qualifiedName.substring(0, index).replace('/', '.');
buffer.append("package ").append(packageName).append(';').appendLineSeparator().appendLineSeparator();
}

List<String> exportToModules = exports.exportToModules;
if (exportToModules.size() > 0) {
buffer.append(" to").appendLineSeparator();
appendFQClassNames(buffer, exportToModules);
}
public static void moduleInfoToJava(StructClass cl, TextBuffer buffer) {
appendAnnotations(buffer, 0, cl, -1);

buffer.append(';').appendLineSeparator();
StructModuleAttribute moduleAttribute = cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_MODULE);

if ((moduleAttribute.moduleFlags & CodeConstants.ACC_OPEN) != 0) {
buffer.append("open ");
}

for (StructModuleAttribute.OpensEntry opens : moduleAttribute.opens) {
buffer.appendIndent(1).append("opens ").append(opens.packageName.replace('/', '.'));
buffer.append("module ").append(moduleAttribute.moduleName).append(" {").appendLineSeparator();

writeModuleInfoBody(buffer, moduleAttribute);

List<String> opensToModules = opens.opensToModules;
if (opensToModules.size() > 0) {
buffer.append(" to").appendLineSeparator();
appendFQClassNames(buffer, opensToModules);
buffer.append('}').appendLineSeparator();
}

private static void writeModuleInfoBody(TextBuffer buffer, StructModuleAttribute moduleAttribute) {
boolean newLineNeeded = false;

List<StructModuleAttribute.RequiresEntry> requiresEntries = moduleAttribute.requires;
if (!requiresEntries.isEmpty()) {
for (StructModuleAttribute.RequiresEntry requires : requiresEntries) {
if (!isGenerated(requires.flags)) {
buffer.appendIndent(1).append("requires ").append(requires.moduleName.replace('/', '.')).append(';').appendLineSeparator();
newLineNeeded = true;
}
}
}

buffer.append(';').appendLineSeparator();
List<StructModuleAttribute.ExportsEntry> exportsEntries = moduleAttribute.exports;
if (!exportsEntries.isEmpty()) {
if (newLineNeeded) buffer.appendLineSeparator();
for (StructModuleAttribute.ExportsEntry exports : exportsEntries) {
if (!isGenerated(exports.flags)) {
buffer.appendIndent(1).append("exports ").append(exports.packageName.replace('/', '.'));
List<String> exportToModules = exports.exportToModules;
if (exportToModules.size() > 0) {
buffer.append(" to").appendLineSeparator();
appendFQClassNames(buffer, exportToModules);
}
buffer.append(';').appendLineSeparator();
newLineNeeded = true;
}
}
}

for (String uses : moduleAttribute.uses) {
buffer.appendIndent(1).append("uses ").append(ExprProcessor.buildJavaClassName(uses)).append(';').appendLineSeparator();
List<StructModuleAttribute.OpensEntry> opensEntries = moduleAttribute.opens;
if (!opensEntries.isEmpty()) {
if (newLineNeeded) buffer.appendLineSeparator();
for (StructModuleAttribute.OpensEntry opens : opensEntries) {
if (!isGenerated(opens.flags)) {
buffer.appendIndent(1).append("opens ").append(opens.packageName.replace('/', '.'));
List<String> opensToModules = opens.opensToModules;
if (opensToModules.size() > 0) {
buffer.append(" to").appendLineSeparator();
appendFQClassNames(buffer, opensToModules);
}
buffer.append(';').appendLineSeparator();
newLineNeeded = true;
}
}
}

List<String> usesEntries = moduleAttribute.uses;
if (!usesEntries.isEmpty()) {
if (newLineNeeded) buffer.appendLineSeparator();
for (String uses : usesEntries) {
buffer.appendIndent(1).append("uses ").append(ExprProcessor.buildJavaClassName(uses)).append(';').appendLineSeparator();
}
newLineNeeded = true;
}

for (StructModuleAttribute.ProvidesEntry provides : moduleAttribute.provides) {
buffer.appendIndent(1).append("provides ").append(ExprProcessor.buildJavaClassName(provides.interfaceName)).append(" with").appendLineSeparator();
@SuppressWarnings({"SSBasedInspection", "RedundantSuppression"}) List<String> javaNames =
provides.implementationNames.stream().map(ExprProcessor::buildJavaClassName).collect(Collectors.toList());
appendFQClassNames(buffer, javaNames);
buffer.append(';').appendLineSeparator();
List<StructModuleAttribute.ProvidesEntry> providesEntries = moduleAttribute.provides;
if (!providesEntries.isEmpty()) {
if (newLineNeeded) buffer.appendLineSeparator();
for (StructModuleAttribute.ProvidesEntry provides : providesEntries) {
buffer.appendIndent(1).append("provides ").append(ExprProcessor.buildJavaClassName(provides.interfaceName)).append(" with").appendLineSeparator();
appendFQClassNames(buffer, provides.implementationNames.stream().map(ExprProcessor::buildJavaClassName).collect(Collectors.toList()));
buffer.append(';').appendLineSeparator();
}
}
}

private static boolean isGenerated(int flags) {
return (flags & (CodeConstants.ACC_SYNTHETIC | CodeConstants.ACC_MANDATED)) != 0;
}

private static void addTracer(StructClass cls, StructMethod method, BytecodeMappingTracer tracer) {
StructLineNumberTableAttribute table = method.getAttribute(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
tracer.setLineNumberTable(table);
Expand All @@ -349,7 +395,6 @@ private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent)
boolean isEnum = DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM) && (flags & CodeConstants.ACC_ENUM) != 0;
boolean isInterface = (flags & CodeConstants.ACC_INTERFACE) != 0;
boolean isAnnotation = (flags & CodeConstants.ACC_ANNOTATION) != 0;
boolean isModuleInfo = (flags & CodeConstants.ACC_MODULE) != 0 && cl.hasAttribute(StructGeneralAttribute.ATTRIBUTE_MODULE);

if (isDeprecated) {
appendDeprecation(buffer, indent);
Expand Down Expand Up @@ -395,24 +440,10 @@ else if (isInterface) {
else if (components != null) {
buffer.append("record ");
}
else if (isModuleInfo) {
StructModuleAttribute moduleAttribute = cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_MODULE);

if ((moduleAttribute.moduleFlags & CodeConstants.ACC_OPEN) != 0) {
buffer.append("open ");
}

buffer.append("module ");
buffer.append(moduleAttribute.moduleName);
}
else {
buffer.append("class ");
}

// Handled above
if (!isModuleInfo) {
buffer.append(node.simpleName);
}
buffer.append(node.simpleName);

GenericClassDescriptor descriptor = getGenericClassDescriptor(cl);
if (descriptor != null && !descriptor.fparameters.isEmpty()) {
Expand Down Expand Up @@ -1245,4 +1276,4 @@ private static void appendFQClassNames(TextBuffer buffer, List<String> names) {
}
}
}
}
}
80 changes: 45 additions & 35 deletions src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -302,55 +302,65 @@ public void writeClass(StructClass cl, TextBuffer buffer) throws IOException {
return;
}

boolean packageInfo = cl.isSynthetic() && "package-info".equals(root.simpleName);
boolean moduleInfo = cl.hasModifier(CodeConstants.ACC_MODULE) && cl.hasAttribute(StructGeneralAttribute.ATTRIBUTE_MODULE);

DecompilerContext.getLogger().startReadingClass(cl.qualifiedName);
try {
ImportCollector importCollector = new ImportCollector(root);
DecompilerContext.startClass(importCollector);

new LambdaProcessor().processClass(root);
if (packageInfo) {
ClassWriter.packageInfoToJava(cl, buffer);

// add simple class names to implicit import
addClassnameToImport(root, importCollector);
importCollector.writeImports(buffer, false);
}
else if (moduleInfo) {
TextBuffer moduleBuffer = new TextBuffer(AVERAGE_CLASS_SIZE);
ClassWriter.moduleInfoToJava(cl, moduleBuffer);

// build wrappers for all nested classes (that's where actual processing takes place)
initWrappers(root);
importCollector.writeImports(buffer, true);

new NestedClassProcessor().processClass(root, root);
buffer.append(moduleBuffer);
}
else {
new LambdaProcessor().processClass(root);

new NestedMemberAccess().propagateMemberAccess(root);
// add simple class names to implicit import
addClassNameToImport(root, importCollector);

TextBuffer classBuffer = new TextBuffer(AVERAGE_CLASS_SIZE);
new ClassWriter().classToJava(root, classBuffer, 0, null);
// build wrappers for all nested classes (that's where actual processing takes place)
initWrappers(root);

int index = cl.qualifiedName.lastIndexOf("/");
if (index >= 0) {
String packageName = cl.qualifiedName.substring(0, index).replace('/', '.');
new NestedClassProcessor().processClass(root, root);

buffer.append("package ");
buffer.append(packageName);
buffer.append(";");
buffer.appendLineSeparator();
buffer.appendLineSeparator();
}
new NestedMemberAccess().propagateMemberAccess(root);

int import_lines_written = importCollector.writeImports(buffer);
if (import_lines_written > 0) {
buffer.appendLineSeparator();
}
TextBuffer classBuffer = new TextBuffer(AVERAGE_CLASS_SIZE);
new ClassWriter().classToJava(root, classBuffer, 0, null);

int offsetLines = buffer.countLines();
int index = cl.qualifiedName.lastIndexOf('/');
if (index >= 0) {
String packageName = cl.qualifiedName.substring(0, index).replace('/', '.');
buffer.append("package ").append(packageName).append(';').appendLineSeparator().appendLineSeparator();
}

buffer.append(classBuffer);
importCollector.writeImports(buffer, true);

if (DecompilerContext.getOption(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING)) {
BytecodeSourceMapper mapper = DecompilerContext.getBytecodeSourceMapper();
mapper.addTotalOffset(offsetLines);
if (DecompilerContext.getOption(IFernflowerPreferences.DUMP_ORIGINAL_LINES)) {
buffer.dumpOriginalLineNumbers(mapper.getOriginalLinesMapping());
}
if (DecompilerContext.getOption(IFernflowerPreferences.UNIT_TEST_MODE)) {
buffer.appendLineSeparator();
mapper.dumpMapping(buffer, true);
int offsetLines = buffer.countLines();

buffer.append(classBuffer);

if (DecompilerContext.getOption(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING)) {
BytecodeSourceMapper mapper = DecompilerContext.getBytecodeSourceMapper();
mapper.addTotalOffset(offsetLines);
if (DecompilerContext.getOption(IFernflowerPreferences.DUMP_ORIGINAL_LINES)) {
buffer.dumpOriginalLineNumbers(mapper.getOriginalLinesMapping());
}
if (DecompilerContext.getOption(IFernflowerPreferences.UNIT_TEST_MODE)) {
buffer.appendLineSeparator();
mapper.dumpMapping(buffer, true);
}
}
}
}
Expand All @@ -375,13 +385,13 @@ private static void initWrappers(ClassNode node) {
}
}

private static void addClassnameToImport(ClassNode node, ImportCollector imp) {
private static void addClassNameToImport(ClassNode node, ImportCollector imp) {
if (node.simpleName != null && node.simpleName.length() > 0) {
imp.getShortName(node.type == ClassNode.CLASS_ROOT ? node.classStruct.qualifiedName : node.simpleName, false);
}

for (ClassNode nd : node.nested) {
addClassnameToImport(nd, imp);
addClassNameToImport(nd, imp);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2000-2018 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. 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.collectors;

import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
Expand Down Expand Up @@ -150,21 +150,14 @@ else if (!mapSimpleNames.containsKey(shortName)) {
return result == null ? shortName : result;
}

public int writeImports(TextBuffer buffer) {
int importLinesWritten = 0;

public void writeImports(TextBuffer buffer, boolean addSeparator) {
List<String> imports = packImports();

for (String s : imports) {
buffer.append("import ");
buffer.append(s);
buffer.append(';');
for (String line : imports) {
buffer.append("import ").append(line).append(';').appendLineSeparator();
}
if (addSeparator && !imports.isEmpty()) {
buffer.appendLineSeparator();

importLinesWritten++;
}

return importLinesWritten;
}

private List<String> packImports() {
Expand All @@ -181,4 +174,4 @@ private List<String> packImports() {
.map(ent -> ent.getValue() + "." + ent.getKey())
.collect(Collectors.toList());
}
}
}
Loading

0 comments on commit c93b971

Please # to comment.