Skip to content

Commit

Permalink
fix: Inline expressions do not have access to classes loaded in Recaf…
Browse files Browse the repository at this point in the history
…'s workspace
  • Loading branch information
Col-E committed Dec 22, 2020
1 parent 87949de commit b61a54e
Show file tree
Hide file tree
Showing 18 changed files with 463 additions and 293 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<groupId>me.coley</groupId>
<artifactId>recaf</artifactId>
<url>https://github.com/Col-E/Recaf/</url>
<version>2.16.2</version>
<version>2.16.3</version>
<name>Recaf</name>
<description>A modern java bytecode editor</description>
<!-- Variables -->
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/me/coley/recaf/Recaf.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* @author Matt
*/
public class Recaf {
public static final String VERSION = "2.16.2";
public static final String VERSION = "2.16.3";
public static final String DOC_URL = "https://col-e.github.io/Recaf/documentation.html";
public static final int ASM_VERSION = Opcodes.ASM9;
private static Controller currentController;
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/me/coley/recaf/compiler/JavacCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
public class JavacCompiler {
private List<String> pathItems;
private final Map<String, VirtualJavaFileObject> unitMap = new HashMap<>();
private final Options options = new Options();
private final JavacOptions options = new JavacOptions();
private DiagnosticListener<VirtualJavaFileObject> listener;

/**
Expand Down Expand Up @@ -137,7 +137,7 @@ public Map<String, byte[]> getUnits() {
/**
* @return Compiler options.
*/
public Options options() {
public JavacOptions options() {
return options;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* @author Matt
*/
public class Options {
public class JavacOptions {
/**
* Include variable data in compilation.
*/
Expand All @@ -21,20 +21,20 @@ public class Options {
/**
* Class version to target.
*/
private TargetVersion target = TargetVersion.V8;
private JavacTargetVersion target = JavacTargetVersion.V8;

/**
* @return Class version to target.
*/
public TargetVersion getTarget() {
public JavacTargetVersion getTarget() {
return target;
}

/**
* @param target
* Targeted version.
*/
public void setTarget(TargetVersion target) {
public void setTarget(JavacTargetVersion target) {
this.target = target;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
*
* @author Matt
*/
public enum TargetVersion {
public enum JavacTargetVersion {
V4("1.4"), V5("1.5"), V6("1.6"), V7("1.7"), V8("1.8"), V9("9"), V10("10"), V11("11"), V12("12"), V13("13");

/**
* Value to pass as a compiler argument.
*/
private final String opt;

TargetVersion(String opt) {
JavacTargetVersion(String opt) {
this.opt = opt;
}

Expand All @@ -36,7 +36,7 @@ public int version() {
*
* @return version from class file major version.
*/
public static TargetVersion fromClassMajor(int version) {
public static JavacTargetVersion fromClassMajor(int version) {
switch(version) {
case Opcodes.V1_4:
return V4;
Expand Down Expand Up @@ -66,7 +66,7 @@ public static TargetVersion fromClassMajor(int version) {
/**
* @return Minimum version supported by Javac.
*/
public static TargetVersion getMinJavacSupport() {
public static JavacTargetVersion getMinJavacSupport() {
try {
Class<?> cls = Class.forName("com.sun.tools.javac.jvm.Target");
Field min = cls.getDeclaredField("MIN");
Expand All @@ -82,7 +82,7 @@ public static TargetVersion getMinJavacSupport() {
/**
* @return Maximum version supported by Javac.
*/
public static TargetVersion getMaxJavacSupport() {
public static JavacTargetVersion getMaxJavacSupport() {
try {
return fromClassMajor(VMUtil.getVmVersion());
} catch (Exception ex) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package me.coley.recaf.parse.bytecode;
package me.coley.recaf.compiler;

import javassist.CtBehavior;
import me.coley.recaf.util.OpcodeUtil;
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/me/coley/recaf/compiler/JavassistCodeGen.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package me.coley.recaf.compiler;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.bytecode.Bytecode;
import javassist.compiler.JvstCodeGen;
import me.coley.recaf.workspace.Workspace;

/**
* Modified code generator for Javassist to pull information from Recaf.
*
* @author Matt
*/
public class JavassistCodeGen extends JvstCodeGen {
/**
* @param workspace
* Workspace to pull class information from.
* @param bytecode
* Target generated bytecode wrapper.
* @param declaringClass
* Class containing the method our expression resides in.
* @param classPool
* Class pool to use.
*/
public JavassistCodeGen(Workspace workspace, Bytecode bytecode, CtClass declaringClass, ClassPool classPool) {
super(bytecode, declaringClass, classPool);
setTypeChecker(new JavassistTypeChecker(workspace, declaringClass, classPool, this));
resolver = new JavassistMemberResolver(workspace, classPool);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package me.coley.recaf.compiler;

import javassist.bytecode.Bytecode;
import javassist.compiler.SymbolTable;

/**
* Compilation results.
*
* @author Matt
*/
public class JavassistCompilationResult {
private final Bytecode bytecode;
private final SymbolTable symbols;

/**
* @param bytecode
* Generated bytecode.
* @param symbols
* Generated symbols, if any.
*/
public JavassistCompilationResult(Bytecode bytecode, SymbolTable symbols) {
this.bytecode = bytecode;
this.symbols = symbols;
}

/**
* @return Generated bytecode.
*/
public Bytecode getBytecode() {
return bytecode;
}

/**
* @return Generated symbols, if any.
*/
public SymbolTable getSymbols() {
return symbols;
}
}
107 changes: 107 additions & 0 deletions src/main/java/me/coley/recaf/compiler/JavassistCompiler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package me.coley.recaf.compiler;

import javassist.*;
import javassist.bytecode.LocalVariableAttribute;
import javassist.compiler.*;
import me.coley.recaf.parse.bytecode.VariableNameCache;
import org.objectweb.asm.tree.LocalVariableNode;

import java.util.List;

/**
* Javassist compiler utility.
*
* @author Matt
*/
public class JavassistCompiler {

/**
* Compile an independent method body.
*
* @param declaring
* Declaring type that contains the method.
* @param src
* Source of the method declaration.
*
* @return Compiled method.
*
* @throws CannotCompileException
* When a compilation error occurred.
*/
public static CtMethod compileMethod(CtClass declaring, String src) throws CannotCompileException {
try {
Javac compiler = new Javac(declaring);
CtMember obj = compiler.compile(src);
if (obj instanceof CtMethod)
return (CtMethod) obj;
} catch (CompileError e) {
throw new CannotCompileException(e);
}
throw new CannotCompileException("Not a method");
}

/**
* Compile an independent method body.
*
* @param declaring
* Declaring type that contains the method.
* @param containerMethod
* Declaring method that will contain the expression.
* @param expression
* Source of the expression.
* @param existingVars
* Variable information to populate.
* @param varCache
* Variable name and index information.
*
* @return Compiled expression.
*
* @throws CannotCompileException
* When a compilation error occurred.
*/
public static JavassistCompilationResult compileExpression(CtClass declaring, CtBehavior containerMethod,
String expression, List<LocalVariableNode> existingVars,
VariableNameCache varCache)
throws CannotCompileException {
try {
JavassistExpressionJavac compiler = new JavassistExpressionJavac(declaring, varCache);
populateVariables(compiler, existingVars);
populateVariables(compiler, containerMethod);
compiler.compileStmnt(expression);
return new JavassistCompilationResult(compiler.getGeneratedBytecode(), compiler.getLastCompiledSymbols());
} catch (CompileError e) {
throw new CannotCompileException(e);
}
}

private static void populateVariables(JavassistExpressionJavac compiler, List<LocalVariableNode> variables) {
JvstCodeGen gen = compiler.getGen();
SymbolTable symbolTable = compiler.getRootSTable();
for (LocalVariableNode variable : variables) {
try {
gen.recordVariable(variable.desc, variable.name, variable.index, symbolTable);
} catch (CompileError ignored) {
// ignored
}
}
}

private static void populateVariables(JavassistExpressionJavac compiler, CtBehavior containerMethod) {
LocalVariableAttribute variables = (LocalVariableAttribute)
containerMethod.getMethodInfo().getCodeAttribute().getAttribute(LocalVariableAttribute.tag);
if (variables != null) {
JvstCodeGen gen = compiler.getGen();
SymbolTable symbolTable = compiler.getRootSTable();
for (int i = 0; i < variables.tableLength(); i++) {
int index = variables.index(i);
String signature = variables.signature(i);
String name = variables.variableName(i);
try {
gen.recordVariable(signature, name, index, symbolTable);
} catch (CompileError ignored) {
// ignored
}
}
}
}
}
Loading

0 comments on commit b61a54e

Please sign in to comment.