Skip to content

Commit

Permalink
fix: Bump version -> 2.15.6 & Update dependencies, JFX should support…
Browse files Browse the repository at this point in the history
… Mac M1

Also update class patcher, CFR/FF decompilers
  • Loading branch information
Col-E committed Dec 15, 2021
1 parent fb04fb4 commit 4b82d8c
Show file tree
Hide file tree
Showing 8 changed files with 321 additions and 188 deletions.
4 changes: 4 additions & 0 deletions checkstyle-suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,8 @@
<suppress checks="CyclomaticComplexity"
files="IllegalBytecodePatcherUtil.java"
lines="0-9999"/>

<suppress checks="ClassDataAbstractionCoupling"
files="FernFlowerAccessor.java"
lines="0-9999"/>
</suppressions>
10 changes: 5 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
<groupId>me.coley</groupId>
<artifactId>recaf</artifactId>
<url>https://github.com/Col-E/Recaf/</url>
<version>2.21.5</version>
<version>2.21.6</version>
<name>Recaf</name>
<description>A modern java bytecode editor</description>
<!-- Variables -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<asm.version>9.2</asm.version>
<analysis.version>1.6.0</analysis.version>
<dude.version>1.7.3</dude.version>
<cfr.version>0.151</cfr.version>
<ff.version>403</ff.version>
<dude.version>1.8.0</dude.version>
<cfr.version>0.152</cfr.version>
<ff.version>1.5.498.23</ff.version>
<procyon.version>0.5.36</procyon.version>
<junit.version>5.8.1</junit.version>
<pico.version>4.6.1</pico.version>
Expand Down Expand Up @@ -128,7 +128,7 @@
<!-- http://files.minecraftforge.net/maven/net/minecraftforge/fernflower/ -->
<dependency>
<groupId>net.minecraftforge</groupId>
<artifactId>fernflower</artifactId>
<artifactId>forgeflower</artifactId>
<version>${ff.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/me/coley/recaf/Recaf.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
* @author Matt
*/
public class Recaf {
public static final String VERSION = "2.21.5";
public static final String VERSION = "2.21.6";
public static final String DOC_URL = "https://col-e.github.io/Recaf-documentation/";
public static final int ASM_VERSION = Opcodes.ASM9;
private static Controller currentController;
Expand Down Expand Up @@ -80,7 +80,7 @@ private static void init() {
// Bypass JDK restrictions.
VMUtil.patch();
// Patch in dependencies
SelfDependencyPatcher.patch();
SelfDependencyPatcher.ensureJavafxSupport();
// Fix title bar not displaying in GTK systems
System.setProperty("jdk.gtk.version", "2");
// Fix for this dumb "feature" - https://mattryall.net/blog/the-infamous-turkish-locale-bug
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package me.coley.recaf.decompile.fernflower;

import me.coley.recaf.workspace.Workspace;
import org.jetbrains.java.decompiler.main.*;
import org.jetbrains.java.decompiler.main.extern.*;
import org.jetbrains.java.decompiler.struct.*;
import org.jetbrains.java.decompiler.main.ClassesProcessor;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.IdentityRenamerFactory;
import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.extern.IResultSaver;
import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor;
import org.jetbrains.java.decompiler.struct.IDecompiledData;
import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.lazy.LazyLoader;
import org.jetbrains.java.decompiler.util.TextBuffer;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
import java.util.Locale;
import java.util.Map;

/**
* FernFlower accessor. Modified from {@link org.jetbrains.java.decompiler.main.Fernflower} to
Expand All @@ -37,13 +45,15 @@ public class FernFlowerAccessor implements IDecompiledData {
public FernFlowerAccessor(IBytecodeProvider provider, IResultSaver saver, Map<String, Object>
properties, IFernflowerLogger logger) {
String level = (String) properties.get(IFernflowerPreferences.LOG_LEVEL);
if(level != null) {
if (level != null) {
logger.setSeverity(IFernflowerLogger.Severity.valueOf(level.toUpperCase(Locale.ENGLISH)));
}
structContext = new StructContextDecorator(saver, this, new LazyLoader(provider));
classProcessor = new ClassesProcessor(structContext);
DecompilerContext context = new DecompilerContext(properties, logger, structContext,
classProcessor, null);
int threadCount = 1;
DecompilerContext context = new DecompilerContext(
properties, threadCount, logger, structContext, classProcessor,
new PoolInterceptor(), new IdentityRenamerFactory());
DecompilerContext.setCurrentContext(context);
}

Expand All @@ -66,8 +76,32 @@ public void addWorkspace(Workspace workspace) throws IOException, ReflectiveOper
/**
* Analyze classes in the workspace.
*/
public void analyze() {
public void analyze() throws IOException, InterruptedException {
classProcessor.loadClasses(null);
// The threading model with FF makes no damn sense and there is NO documentaiton.
// Uuggggghhhhhhh....
// Sorry, you get shit performance on a single thread until I find some docs.
/*
DecompilerContext root = DecompilerContext.getCurrentContext();
ExecutorService pool = Executors.newWorkStealingPool();
for (StructClass cl : structContext.getClasses().values())
pool.submit(() -> {
try {
DecompilerContext.cloneContext(root);
classProcessor.processClass(cl);
} catch (Throwable t) {
t.printStackTrace();
}
});
pool.shutdown();
pool.awaitTermination(10, TimeUnit.SECONDS);
*/
for (StructClass cl : structContext.getClasses().values())
try {
classProcessor.processClass(cl);
} catch (Throwable t) {
t.printStackTrace();
}
}

/**
Expand All @@ -86,13 +120,23 @@ public String decompile(String name) {
@Override
public String getClassEntryName(StructClass cl, String entryName) {
ClassesProcessor.ClassNode node = classProcessor.getMapRootClasses().get(cl.qualifiedName);
if(node.type != ClassesProcessor.ClassNode.CLASS_ROOT) {
if (node.type != ClassesProcessor.ClassNode.CLASS_ROOT) {
return null;
} else {
return entryName.substring(0, entryName.lastIndexOf(".class")) + ".java";
}
}

@Override
public boolean processClass(StructClass structClass) {
try {
classProcessor.processClass(structClass);
return true;
} catch (IOException e) {
return false;
}
}

@Override
public String getClassContent(StructClass cl) {
TextBuffer buffer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ private void setup(Workspace workspace) {
decompiler = new FernFlowerAccessor(provider, DUMMY_COLLECTOR, getOptions(), LOGGER);
try {
decompiler.addWorkspace(workspace);
decompiler.analyze();
} catch(IOException ex) {
throw new IllegalStateException("Failed to load inputs for FernFlower!", ex);
} catch(ReflectiveOperationException ex) {
Expand All @@ -94,7 +95,6 @@ private void setup(Workspace workspace) {
} catch(Exception ex) {
throw new IllegalStateException(ex);
}
decompiler.analyze();
lastWorkspace = workspace;
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package me.coley.recaf.decompile.fernflower;

import me.coley.recaf.util.Log;
import me.coley.recaf.workspace.JavaResource;
import me.coley.recaf.workspace.Workspace;
import org.jetbrains.java.decompiler.main.extern.IResultSaver;
import org.jetbrains.java.decompiler.struct.*;
import org.jetbrains.java.decompiler.struct.IDecompiledData;
import org.jetbrains.java.decompiler.struct.StructContext;
import org.jetbrains.java.decompiler.struct.lazy.LazyLoader;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Map;

import static me.coley.recaf.util.CollectionUtil.*;
import static me.coley.recaf.util.CollectionUtil.copySet;

/**
* Decorator for StructContext to support Recaf workspaces.
Expand All @@ -26,7 +25,7 @@ public class StructContextDecorator extends StructContext {
* Result saver <i>(Unused/noop)</i>
* @param data
* Data instance, should be an instance of
* {@link me.coley.recaf.decompile.fernflower.FernFlowerAccessor}.
* {@link me.coley.recaf.decompile.fernflower.FernFlowerAccessor}.
* @param loader
* LazyLoader to hold links to class resources.
*/
Expand All @@ -40,40 +39,24 @@ public StructContextDecorator(IResultSaver saver, IDecompiledData data, LazyLoad
*
* @throws IOException
* Thrown if a class cannot be read.
* @throws ReflectiveOperationException
* Thrown if the parent loader could not be fetched.
* @throws IndexOutOfBoundsException
* Thrown if FernFlower can't read the class.
* <i>(IE: It fails on newer Java class files)</i>
*/
public void addWorkspace(Workspace workspace) throws IOException,
ReflectiveOperationException {
LazyLoader loader = getLoader();
public void addWorkspace(Workspace workspace) throws IOException {
// Add primary resource classes
addResource(workspace.getPrimary(), loader);
addResource(workspace.getPrimary());
for (JavaResource resource : workspace.getLibraries())
addResource(resource, loader);
addResource(resource);
}

private void addResource(JavaResource resource, LazyLoader loader) throws IOException {
private void addResource(JavaResource resource) throws IOException {
// Iterate resource class entries
for(Map.Entry<String, byte[]> entry : copySet(resource.getClasses().entrySet())) {
for (Map.Entry<String, byte[]> entry : copySet(resource.getClasses().entrySet())) {
String name = entry.getKey();
String simpleName = name.substring(name.lastIndexOf('/') + 1);
byte[] code = entry.getValue();
// register class in the map and lazy-loader.
try {
getClasses().put(name, new StructClass(code, true, loader));
loader.addClassLink(name, new LazyLoader.Link(null, name + ".class"));
} catch (Throwable t) {
Log.debug("Error populating FF Struct from code, class={}", name);
}
addData(name, simpleName, code, true);
}
}

private LazyLoader getLoader() throws ReflectiveOperationException {
// Hack to access private parent loader
Field floader = StructContext.class.getDeclaredField("loader");
floader.setAccessible(true);
return (LazyLoader) floader.get(this);
}
}
21 changes: 19 additions & 2 deletions src/main/java/me/coley/recaf/util/StringUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public static String generateName(String alphabet, int index) {
int m = 8;
final char[] array = new char[m];
int n = m - 1;
while(index > charz.length - 1) {
while (index > charz.length - 1) {
int k = Math.abs(-(index % alphabetLength));
array[n--] = charz[k];
index /= alphabetLength;
Expand All @@ -91,7 +91,7 @@ public static String generateName(String alphabet, int index) {
*/
public static String indent(int level, String indent) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < level; i++)
for (int i = 0; i < level; i++)
sb.append(indent);
return sb.toString();
}
Expand Down Expand Up @@ -123,4 +123,21 @@ public static String limit(String str, int maxLength) {
public static <E extends Enum<?>> String toString(E value) {
return value.name().substring(0, 1).toUpperCase() + value.name().substring(1).toLowerCase();
}

/**
* @param pattern
* Pattern to look for.
* @param text
* Text to check.
*
* @return Number of times the given pattern appears in the text.
*/
public static int count(String pattern, String text) {
int count = 0;
while (text.contains(pattern)) {
text = text.replaceFirst(pattern, "");
count++;
}
return count;
}
}
Loading

0 comments on commit 4b82d8c

Please # to comment.