Skip to content

Commit

Permalink
Merge branch 'pr/759' into dev4
Browse files Browse the repository at this point in the history
  • Loading branch information
Col-E committed Jan 14, 2024
2 parents 597b481 + bd8213d commit cd4d802
Show file tree
Hide file tree
Showing 32 changed files with 1,100 additions and 189 deletions.
2 changes: 2 additions & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,6 @@ project.ext {
richtextfx = 'org.fxmisc.richtext:richtextfx:0.11.2'

treemapfx = 'software.coley:treemap-fx:1.1.0'

vineflower = 'org.vineflower:vineflower:1.9.3'
}
1 change: 1 addition & 0 deletions recaf-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ dependencies {
api regex
api jasm_core
api jasm_composistion_jvm
api vineflower
}

// Force generation of gversion data class when the version information is not up-to-date
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@ public final class ConfigGroups {
*/
public static final String SERVICE_DEBUG = SERVICE + PACKAGE_SPLIT + "debug";
/**
* Group for decompiler components.
* Group for decompilation components.
*/
public static final String SERVICE_DECOMPILE = SERVICE + PACKAGE_SPLIT + "decompile";
/**
* Group for specific decompiler components.
*/
public static final String SERVICE_DECOMPILE_IMPL = SERVICE_DECOMPILE + PACKAGE_SPLIT + "impl";
/**
* Group for IO components.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,19 @@ public AbstractDecompiler(@Nonnull String name, @Nonnull String version, @Nonnul
this.config = config;
}

@Nonnull
@Override
public String getName() {
return name;
}

@Nonnull
@Override
public String getVersion() {
return version;
}

@Nonnull
@Override
public DecompilerConfig getConfig() {
return config;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package software.coley.recaf.services.decompile;

import jakarta.annotation.Nonnull;
import org.objectweb.asm.ClassReader;
import software.coley.recaf.info.JvmClassInfo;
import software.coley.recaf.info.properties.builtin.CachedDecompileProperty;
import software.coley.recaf.workspace.model.Workspace;
Expand Down Expand Up @@ -33,13 +34,14 @@ public void addJvmInputFilter(@Nonnull JvmInputFilter filter) {
inputFilters.add(filter);
}

@Nonnull
@Override
public final DecompileResult decompile(@Nonnull Workspace workspace, @Nonnull JvmClassInfo classInfo) {
// Check for cached result, returning the cached result if found
// and only if the current config matches the one that yielded the cached result.
DecompileResult cachedResult = CachedDecompileProperty.get(classInfo, this);
if (cachedResult != null) {
if (cachedResult.getConfigHash() == getConfig().getConfigHash())
if (cachedResult.getConfigHash() == getConfig().getHash())
return cachedResult;

// Config changed, void the cache.
Expand All @@ -50,15 +52,29 @@ public final DecompileResult decompile(@Nonnull Workspace workspace, @Nonnull Jv
byte[] bytecode = classInfo.getBytecode();
for (JvmInputFilter filter : inputFilters)
bytecode = filter.filter(bytecode);
JvmClassInfo filteredBytecode = classInfo.toJvmClassBuilder().adaptFrom(new ClassReader(bytecode)).build();

// Pass to implementation.
DecompileResult result = decompile(workspace, classInfo.getName(), bytecode);
DecompileResult result = decompileInternal(workspace, filteredBytecode);

// Cache result.
CachedDecompileProperty.set(classInfo, this, result);
return result;
}

/**
* Takes on the work of {@link #decompile(Workspace, JvmClassInfo)} after the {@link #inputFilters} have been applied to the class.
*
* @param workspace
* Workspace to pull data from.
* @param classInfo
* Class to decompile.
*
* @return Decompilation result.
*/
@Nonnull
protected abstract DecompileResult decompileInternal(@Nonnull Workspace workspace, @Nonnull JvmClassInfo classInfo);

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package software.coley.recaf.services.decompile;

import jakarta.annotation.Nonnull;
import software.coley.recaf.config.BasicConfigContainer;

import static software.coley.recaf.config.ConfigGroups.SERVICE_DECOMPILE_IMPL;

/**
* Base class for fields needed by all decompiler configurations
*
* @author therathatter
*/
public class BaseDecompilerConfig extends BasicConfigContainer implements DecompilerConfig {
private int hash = 0;

/**
* @param id
* Container ID.
*/
public BaseDecompilerConfig( @Nonnull String id) {
super(SERVICE_DECOMPILE_IMPL, id);
}

@Override
public int getHash() {
return hash;
}

@Override
public void setHash(int hash) {
this.hash = hash;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import software.coley.recaf.info.properties.builtin.CachedDecompileProperty;
import software.coley.recaf.util.StringUtil;

import java.util.Objects;

Expand All @@ -18,21 +19,63 @@ public class DecompileResult {
private final int configHash;

/**
* Constructor for a successful decompilation.
*
* @param text
* Decompiled text.
* @param configHash
* Value of {@link DecompilerConfig#getHash()} of associated decompiler.
* Used to determine if cached value in {@link CachedDecompileProperty} is up-to-date with current config.
*/
public DecompileResult(@Nonnull String text, int configHash) {
this.text = text;
this.type = ResultType.SUCCESS;
this.configHash = configHash;
this.exception = null;
}

/**
* Constructor for a failed decompilation.
*
* @param exception
* Failure reason.
* @param type
* Result type.
* @param configHash
* Value of {@link DecompilerConfig#getConfigHash()} of associated decompiler.
* Value of {@link DecompilerConfig#getHash()} of associated decompiler.
* Used to determine if cached value in {@link CachedDecompileProperty} is up-to-date with current config.
*/
public DecompileResult(@Nullable String text, @Nullable Throwable exception, @Nonnull ResultType type, int configHash) {
this.text = text;
public DecompileResult(@Nonnull Throwable exception, int configHash) {
this.text = "// " + StringUtil.traceToString(exception).replace("\n", "\n// ");
this.type = ResultType.FAILURE;
this.configHash = configHash;
this.exception = exception;
this.type = type;
}

/**
* Constructor for a skipped decompilation.
*
* @param configHash
* Value of {@link DecompilerConfig#getHash()} of associated decompiler.
* Used to determine if cached value in {@link CachedDecompileProperty} is up-to-date with current config.
*/
public DecompileResult(int configHash) {
this.text = null;
this.type = ResultType.SKIPPED;
this.configHash = configHash;
this.exception = null;
}

/**
* Constructor for a skipped decompilation, with pre-defined text.
* Typically used for displaying feedback if the decompiler had an issue or timed out.
*
* @param text
* Decompiled text.
*/
public DecompileResult(@Nonnull String text) {
this.text = text;
this.type = ResultType.SKIPPED;
this.configHash = 0;
this.exception = null;
}

/**
Expand Down Expand Up @@ -62,7 +105,7 @@ public ResultType getType() {
}

/**
* @return Value of {@link DecompilerConfig#getConfigHash()} of associated decompiler.
* @return Value of {@link DecompilerConfig#getHash()} of associated decompiler.
* Used to determine if cached value in {@link CachedDecompileProperty} is up-to-date with current config.
*/
public int getConfigHash() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package software.coley.recaf.services.decompile;

import jakarta.annotation.Nonnull;
import software.coley.recaf.info.properties.builtin.CachedDecompileProperty;

/**
Expand All @@ -15,15 +16,18 @@ public interface Decompiler {
/**
* @return Decompiler name.
*/
@Nonnull
String getName();

/**
* @return Decompiler version.
*/
@Nonnull
String getVersion();

/**
* @return Decompiler config.
*/
@Nonnull
DecompilerConfig getConfig();
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* <br>
* Tracks the hash of all contained {@link ConfigValue} so that when decompilers check for
* {@link CachedDecompileProperty} they can see if the {@link DecompileResult#getConfigHash()}
* matches the current one of {@link #getConfigHash()}.
* matches the current one of {@link #getHash()}.
*
* @author Matt Coley
*/
Expand All @@ -24,20 +24,20 @@ public interface DecompilerConfig extends ConfigContainer {
*
* @return Unique hash of all contained {@link ConfigValue}.
*/
int getConfigHash();
int getHash();

/**
* @param hash
* New hash value.
*
* @see #getConfigHash() For more detail.
* @see #getHash() For more detail.
*/
void setConfigHash(int hash);
void setHash(int hash);

/**
* Called by implementations after they add all their values to the container.
*
* @see #getConfigHash() For more detail.
* @see #getHash() For more detail.
*/
default void registerConfigValuesHashUpdates() {
// Initial value computation.
Expand All @@ -53,6 +53,6 @@ private void update() {
.map(ConfigValue::getValue)
.mapToInt(value -> value == null ? 0 : value.hashCode())
.reduce((a, b) -> (31 * a) + b)
.ifPresent(this::setConfigHash);
.ifPresent(this::setHash);
}
}
Loading

0 comments on commit cd4d802

Please sign in to comment.