diff --git a/README.md b/README.md index 743894e..353cff0 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,5 @@ To search/replace in a file, press CTRL + F. To open a class, press CTRL + T. To change settings like auto-computation of stack frames and max locals/stack press CTRL + O. + +To go to the method definition of the selected line's invoke-method press CTRL + G. diff --git a/src/me/ByteEdit/main/Assembler.java b/src/me/ByteEdit/edit/Assembler.java similarity index 98% rename from src/me/ByteEdit/main/Assembler.java rename to src/me/ByteEdit/edit/Assembler.java index b490f5f..0ad456c 100644 --- a/src/me/ByteEdit/main/Assembler.java +++ b/src/me/ByteEdit/edit/Assembler.java @@ -1,6 +1,5 @@ -package me.ByteEdit.main; +package me.ByteEdit.edit; -import java.awt.Color; import java.io.StringReader; import java.lang.reflect.Constructor; import java.util.ArrayList; @@ -42,10 +41,14 @@ import org.objectweb.asm.tree.TryCatchBlockNode; import org.objectweb.asm.tree.TypeInsnNode; import org.objectweb.asm.tree.VarInsnNode; +import me.ByteEdit.main.Main; +import me.ByteEdit.utils.ClassUtil; +import me.ByteEdit.utils.CustomBufferedReader; + public class Assembler { public static ClassNode assemble(String input) { - Main.textArea.removeAllLineHighlights(); + Main.txtByteEditView.removeAllLineHighlights(); CustomBufferedReader read = null; try { ClassNode clazz = new ClassNode(); @@ -80,15 +83,15 @@ public class Assembler { { s = s.substring(0, s.length() - 2); if (s.contains(" implements ")) { - String interfaces = s.substring(s.indexOf(" implements ") + 12); + String interfaces = s.substring(s.lastIndexOf(" implements ") + 12); clazz.interfaces = new ArrayList<>(); for (String interf : interfaces.split(", ")) { clazz.interfaces.add(interf); } - s = s.substring(0, s.indexOf(" implements ")); + s = s.substring(0, s.lastIndexOf(" implements ")); } - clazz.superName = s.substring(s.indexOf(" extends ") + 9); - s = s.substring(0, s.indexOf(" extends ")); + clazz.superName = s.substring(s.lastIndexOf(" extends ") + 9); + s = s.substring(0, s.lastIndexOf(" extends ")); String[] split = s.split(" "); clazz.name = split[split.length - 1]; clazz.access = ClassUtil.ACC_SUPER; @@ -319,11 +322,11 @@ public class Assembler { } else if (!s.startsWith("\t")) { s = s.substring(0, s.length() - 2); if (s.contains(" throws ")) { - String exceptions = s.substring(s.indexOf(" throws ") + 8); + String exceptions = s.substring(s.lastIndexOf(" throws ") + 8); for (String excp : exceptions.split(", ")) { node.exceptions.add(excp); } - s = s.substring(0, s.indexOf(" throws ")); + s = s.substring(0, s.lastIndexOf(" throws ")); } String[] split = s.split(" "); node.desc = split[split.length - 1]; @@ -410,7 +413,8 @@ public class Assembler { } catch (Throwable e) { System.err.println("Error at line: " + read.currentLine); try { - Main.textArea.addLineHighlight(read.currentLine, Color.RED.darker()); + Main.txtByteEditView.setCaretPosition(Main.txtByteEditView.getLineStartOffset(read.currentLine)); + Main.showError(e.getMessage()); } catch (BadLocationException e1) { System.err.println("Can't show line!"); } diff --git a/src/me/ByteEdit/main/Disassembler.java b/src/me/ByteEdit/edit/Disassembler.java similarity index 55% rename from src/me/ByteEdit/main/Disassembler.java rename to src/me/ByteEdit/edit/Disassembler.java index a3ab87f..9b2a70c 100644 --- a/src/me/ByteEdit/main/Disassembler.java +++ b/src/me/ByteEdit/edit/Disassembler.java @@ -1,4 +1,4 @@ -package me.ByteEdit.main; +package me.ByteEdit.edit; import java.lang.reflect.Field; import java.util.ArrayList; @@ -8,6 +8,7 @@ import java.util.List; import org.objectweb.asm.Handle; import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.AnnotationNode; @@ -34,13 +35,46 @@ import org.objectweb.asm.tree.TryCatchBlockNode; import org.objectweb.asm.tree.TypeInsnNode; import org.objectweb.asm.tree.VarInsnNode; +import me.ByteEdit.utils.ClassUtil; +import me.ByteEdit.utils.OpcodesReverse; + public class Disassembler { public static String disassemble(ClassNode classNode) { + return disassemble(classNode, null).getDisassembly(); + } + + public static class DisassembleTuple { + + private final String dis; + private final int line; + + public DisassembleTuple(String dis) { + this.dis = dis; + this.line = -1; + } + + public DisassembleTuple(String dis, int line) { + this.dis = dis; + this.line = line; + } + + public String getDisassembly() { + return dis; + } + + public int getLine() { + return line; + } + + } + + public static DisassembleTuple disassemble(ClassNode classNode, MethodNode methodToFind) { if (classNode == null) { - return "ClassNode is null! This is not a valid java class file!"; + return new DisassembleTuple("ClassNode is null! This is not a valid java class file!"); } try { + int lineFound = -1; String s = ""; s += "// #Annotations\n"; if (classNode.visibleAnnotations != null && !classNode.visibleAnnotations.isEmpty()) { @@ -264,6 +298,9 @@ public class Disassembler { s += "\n"; } } + if (mn.equals(methodToFind)) { + lineFound = s.split("\\n").length; + } s += "\t" + ClassUtil.getAccessFlagsFull(mn.access) + mn.name + " " + mn.desc + " "; if (mn.exceptions != null && !mn.exceptions.isEmpty()) { String exceptionStr = ""; @@ -287,10 +324,10 @@ public class Disassembler { } } s += "}\n"; - return s; + return new DisassembleTuple(s, lineFound); } catch (Throwable e) { - return "Class couldn't be decompiled:\n" + e.getClass().getName() + ": " + e.getMessage() + "\n" - + Arrays.toString(e.getStackTrace()).replace(", ", "\n\tat ").replace("[", "\tat ").replace("]", "") + "\n"; + return new DisassembleTuple("Class couldn't be decompiled:\n" + e.getClass().getName() + ": " + e.getMessage() + "\n" + + Arrays.toString(e.getStackTrace()).replace(", ", "\n\tat ").replace("[", "\tat ").replace("]", "") + "\n"); } } @@ -317,223 +354,213 @@ public class Disassembler { } } for (AbstractInsnNode n : mn.instructions.toArray()) { - switch (n.getClass().getSimpleName()) { - case "FieldInsnNode": { - FieldInsnNode node = (FieldInsnNode) n; - s += "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + node.desc + " " + node.owner + "/" + node.name - + "\n"; - break; - } - case "LabelNode": { - LabelNode node = (LabelNode) n; - s += "\t\t// label " + labels.get(node.getLabel()) + "\n"; - break; - } - case "FrameNode": { - FrameNode node = (FrameNode) n; - s += "\t\t// frame " + node.type + " l:"; - ArrayList arr = new ArrayList<>(); - if (node.local != null) { - for (Object o : node.local) { - if (o == null) { - arr.add(null); - } else { - if (o instanceof String) { - arr.add((String) o); - } else if (o instanceof LabelNode) { - arr.add("(label) " + labels.get(((LabelNode) o).getLabel())); - } else { - arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o); - } - } - } - s += arr.toString(); - } else { - s += "null"; - } - arr.clear(); - s += " s:"; - if (node.stack != null) { - for (Object o : node.stack) { - if (o == null) { - arr.add(null); - } else { - if (o instanceof String) { - arr.add((String) o); - } else if (o instanceof LabelNode) { - arr.add("(label) " + labels.get(((LabelNode) o).getLabel())); - } else { - arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o); - } - } - } - s += arr.toString(); - } else { - s += "null"; - } - s += "\n"; - break; - } - case "LineNumberNode": { - LineNumberNode node = (LineNumberNode) n; - s += "\t\t// line " + node.line + " " + labels.get(node.start.getLabel()) + "\n"; - break; - } - case "InvokeDynamicInsnNode": { - InvokeDynamicInsnNode node = (InvokeDynamicInsnNode) n; - s += "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " [\n\t\t\tname: " + node.name + "\n\t\t\tdesc: " - + node.desc + "\n\t\t\tHandle: [\n\t\t\t\tname: " + node.bsm.getName() + "\n\t\t\t\towner: " - + node.bsm.getOwner() + "\n\t\t\t\tdesc: " + node.bsm.getDesc() + "\n\t\t\t\tisInterface: " - + node.bsm.isInterface() + "\n\t\t\t\ttag: " + node.bsm.getTag() + "\n\t\t\t]\n\t\t\targs: [\n"; - for (Object l : node.bsmArgs) { - if (l.getClass().getName().equals("org.objectweb.asm.Type")) { - Type type = (Type) l; - int off = 0; - int len = 0; - char[] buf = null; - try { - Field f_off = Type.class.getDeclaredField("off"); - f_off.setAccessible(true); - off = f_off.getInt(type); - Field f_len = Type.class.getDeclaredField("len"); - f_len.setAccessible(true); - len = f_len.getInt(type); - Field f_buf = Type.class.getDeclaredField("buf"); - f_buf.setAccessible(true); - buf = (char[]) f_buf.get(type); - } catch (Exception e) {} - s += "\t\t\t\tType: [\n\t\t\t\t\ttype: " + ClassUtil.getClassNameFromType(type) + "\n\t\t\t\t\toff: " + off - + "\n\t\t\t\t\tlen: " + len + "\n\t\t\t\t\tbuf: " + ClassUtil.getDecompiledValue(new String(buf), ""); - s += "\n\t\t\t\t]\n"; - } else if (l.getClass().getName().equals("org.objectweb.asm.Handle")) { - Handle h = (Handle) l; - s += "\t\t\t\tHandle: [\n\t\t\t\t\tname: " + h.getName() + "\n\t\t\t\t\towner: " + h.getOwner() - + "\n\t\t\t\t\tdesc: " + h.getDesc() + "\n\t\t\t\t\tisInterface: " + h.isInterface() - + "\n\t\t\t\t\ttag: " + h.getTag(); - s += "\n\t\t\t\t]\n"; - } else { - s += "\t\t\t\t" + ClassUtil.getDecompiledValue(l, "") + "\n"; - } - } - s += "\t\t\t]\n\t\t]\n"; - break; - } - case "MethodInsnNode": { - MethodInsnNode node = (MethodInsnNode) n; - s += "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + node.desc + " " + node.owner + "/" + node.name - + "\n"; - break; - } - case "TypeInsnNode": { - TypeInsnNode node = (TypeInsnNode) n; - s += "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.desc + "\n"; - break; - } - case "MultiANewArrayInsnNode": { - MultiANewArrayInsnNode node = (MultiANewArrayInsnNode) n; - s += "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + node.desc + " " + node.dims + "\n"; - break; - } - case "LdcInsnNode": { - LdcInsnNode node = (LdcInsnNode) n; - switch (node.cst.getClass().getSimpleName()) { - case "String": - case "Double": - case "Integer": - case "Float": - case "Long": { - s += "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + ClassUtil.getDecompiledValue(node.cst, "") - + "\n"; - break; - } - case "Type": { - Type type = (Type) node.cst; - int off = 0; - int len = 0; - char[] buf = null; - try { - Field f_off = Type.class.getDeclaredField("off"); - f_off.setAccessible(true); - off = f_off.getInt(type); - Field f_len = Type.class.getDeclaredField("len"); - f_len.setAccessible(true); - len = f_len.getInt(type); - Field f_buf = Type.class.getDeclaredField("buf"); - f_buf.setAccessible(true); - buf = (char[]) f_buf.get(type); - } catch (Exception e) {} - s += "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " Type: [\n\t\t\ttype: " - + ClassUtil.getClassNameFromType(type) + "\n\t\t\toff: " + off + "\n\t\t\tlen: " + len + "\n\t\t\tbuf: " - + ClassUtil.getDecompiledValue(new String(buf), ""); - s += "\n\t\t]\n"; - break; - } - default: { - s += "\t\tUNRESOLVED TYPE! " + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " - + node.cst.getClass().getName().replace(".", "/") + " " + node.cst + "\n"; - break; - } - } - break; - } - case "VarInsnNode": { - VarInsnNode node = (VarInsnNode) n; - s += "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + "\n"; - break; - } - case "InsnNode": { - InsnNode node = (InsnNode) n; - s += "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + "\n"; - break; - } - case "IntInsnNode": { - IntInsnNode node = (IntInsnNode) n; - if (n.getOpcode() == 188) { - s += "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + ClassUtil.getArrayTypeByID(node.operand) + "\n"; - } else { - s += "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.operand + "\n"; - } - break; - } - case "JumpInsnNode": { - JumpInsnNode node = (JumpInsnNode) n; - s += "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + labels.get(node.label.getLabel()) + "\n"; - break; - } - case "TableSwitchInsnNode": { - TableSwitchInsnNode node = (TableSwitchInsnNode) n; - s += "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tmin: " + node.min + "\n\t\t\tmax: " + node.max - + "\n\t\t\tdefault: " + labels.get(node.dflt.getLabel()) + "\n\t\t\tlabels: [\n"; - for (LabelNode l : node.labels) { - s += "\t\t\t\t" + labels.get(l.getLabel()) + "\n"; - } - s += "\t\t\t]\n\t\t]\n"; - break; - } - case "LookupSwitchInsnNode": { - LookupSwitchInsnNode node = (LookupSwitchInsnNode) n; - s += "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tdefault: " + labels.get(node.dflt.getLabel()) - + "\n\t\t\tkeys: [\n"; - for (Integer l : node.keys) { - s += "\t\t\t\t" + l + "\n"; - } - s += "\t\t\t]" + "\n\t\t\tlabels: [\n"; - for (LabelNode l : node.labels) { - s += "\t\t\t\t" + labels.get(l.getLabel()) + "\n"; - } - s += "\t\t\t]\n\t\t]\n"; - break; - } - case "IincInsnNode": { - IincInsnNode node = (IincInsnNode) n; - s += "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + " " + node.incr + "\n"; - break; - } - default: - s += "\t\tNOT HANDLED! " + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + n.getClass().getSimpleName() + "\n"; - break; - } + s += disassembleInstruction(n, labels); } return new String[] { s, localVarTable, tryCatchTable }; } + + public static String disassembleInstruction(AbstractInsnNode n, HashMap labels) { + switch (n.getClass().getSimpleName()) { + case "FieldInsnNode": { + FieldInsnNode node = (FieldInsnNode) n; + return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + node.desc + " " + node.owner + "/" + node.name + + "\n"; + } + case "LabelNode": { + LabelNode node = (LabelNode) n; + return "\t\t// label " + labels.get(node.getLabel()) + "\n"; + } + case "FrameNode": { + FrameNode node = (FrameNode) n; + String s = "\t\t// frame " + node.type + " l:"; + ArrayList arr = new ArrayList<>(); + if (node.local != null) { + for (Object o : node.local) { + if (o == null) { + arr.add(null); + } else { + if (o instanceof String) { + arr.add((String) o); + } else if (o instanceof LabelNode) { + arr.add("(label) " + labels.get(((LabelNode) o).getLabel())); + } else { + arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o); + } + } + } + s += arr.toString(); + } else { + s += "null"; + } + arr.clear(); + s += " s:"; + if (node.stack != null) { + for (Object o : node.stack) { + if (o == null) { + arr.add(null); + } else { + if (o instanceof String) { + arr.add((String) o); + } else if (o instanceof LabelNode) { + arr.add("(label) " + labels.get(((LabelNode) o).getLabel())); + } else { + arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o); + } + } + } + s += arr.toString(); + } else { + s += "null"; + } + s += "\n"; + return s; + } + case "LineNumberNode": { + LineNumberNode node = (LineNumberNode) n; + return "\t\t// line " + node.line + " " + labels.get(node.start.getLabel()) + "\n"; + } + case "InvokeDynamicInsnNode": { + InvokeDynamicInsnNode node = (InvokeDynamicInsnNode) n; + String s = "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " [\n\t\t\tname: " + node.name + "\n\t\t\tdesc: " + + node.desc + "\n\t\t\tHandle: [\n\t\t\t\tname: " + node.bsm.getName() + "\n\t\t\t\towner: " + node.bsm.getOwner() + + "\n\t\t\t\tdesc: " + node.bsm.getDesc() + "\n\t\t\t\tisInterface: " + node.bsm.isInterface() + "\n\t\t\t\ttag: " + + node.bsm.getTag() + "\n\t\t\t]\n\t\t\targs: [\n"; + for (Object l : node.bsmArgs) { + if (l.getClass().getName().equals("org.objectweb.asm.Type")) { + Type type = (Type) l; + int off = 0; + int len = 0; + char[] buf = null; + try { + Field f_off = Type.class.getDeclaredField("off"); + f_off.setAccessible(true); + off = f_off.getInt(type); + Field f_len = Type.class.getDeclaredField("len"); + f_len.setAccessible(true); + len = f_len.getInt(type); + Field f_buf = Type.class.getDeclaredField("buf"); + f_buf.setAccessible(true); + buf = (char[]) f_buf.get(type); + } catch (Exception e) {} + s += "\t\t\t\tType: [\n\t\t\t\t\ttype: " + ClassUtil.getClassNameFromType(type) + "\n\t\t\t\t\toff: " + off + + "\n\t\t\t\t\tlen: " + len + "\n\t\t\t\t\tbuf: " + ClassUtil.getDecompiledValue(new String(buf), ""); + s += "\n\t\t\t\t]\n"; + } else if (l.getClass().getName().equals("org.objectweb.asm.Handle")) { + Handle h = (Handle) l; + s += "\t\t\t\tHandle: [\n\t\t\t\t\tname: " + h.getName() + "\n\t\t\t\t\towner: " + h.getOwner() + + "\n\t\t\t\t\tdesc: " + h.getDesc() + "\n\t\t\t\t\tisInterface: " + h.isInterface() + "\n\t\t\t\t\ttag: " + + h.getTag(); + s += "\n\t\t\t\t]\n"; + } else { + s += "\t\t\t\t" + ClassUtil.getDecompiledValue(l, "") + "\n"; + } + } + s += "\t\t\t]\n\t\t]\n"; + return s; + } + case "MethodInsnNode": { + MethodInsnNode node = (MethodInsnNode) n; + return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + node.desc + " " + node.owner + "/" + node.name + + "\n"; + } + case "TypeInsnNode": { + TypeInsnNode node = (TypeInsnNode) n; + return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.desc + "\n"; + } + case "MultiANewArrayInsnNode": { + MultiANewArrayInsnNode node = (MultiANewArrayInsnNode) n; + return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + node.desc + " " + node.dims + "\n"; + } + case "LdcInsnNode": { + LdcInsnNode node = (LdcInsnNode) n; + switch (node.cst.getClass().getSimpleName()) { + case "String": + case "Double": + case "Integer": + case "Float": + case "Long": { + return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + ClassUtil.getDecompiledValue(node.cst, "") + + "\n"; + } + case "Type": { + Type type = (Type) node.cst; + int off = 0; + int len = 0; + char[] buf = null; + try { + Field f_off = Type.class.getDeclaredField("off"); + f_off.setAccessible(true); + off = f_off.getInt(type); + Field f_len = Type.class.getDeclaredField("len"); + f_len.setAccessible(true); + len = f_len.getInt(type); + Field f_buf = Type.class.getDeclaredField("buf"); + f_buf.setAccessible(true); + buf = (char[]) f_buf.get(type); + } catch (Exception e) {} + String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " Type: [\n\t\t\ttype: " + + ClassUtil.getClassNameFromType(type) + "\n\t\t\toff: " + off + "\n\t\t\tlen: " + len + "\n\t\t\tbuf: " + + ClassUtil.getDecompiledValue(new String(buf), ""); + s += "\n\t\t]\n"; + return s; + } + default: { + return "\t\tUNRESOLVED TYPE! " + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + + node.cst.getClass().getName().replace(".", "/") + " " + node.cst + "\n"; + } + } + } + case "VarInsnNode": { + VarInsnNode node = (VarInsnNode) n; + return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + "\n"; + } + case "InsnNode": { + InsnNode node = (InsnNode) n; + return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + "\n"; + } + case "IntInsnNode": { + IntInsnNode node = (IntInsnNode) n; + if (n.getOpcode() == Opcodes.NEWARRAY) { + return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + ClassUtil.getArrayTypeByID(node.operand) + "\n"; + } else { + return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.operand + "\n"; + } + } + case "JumpInsnNode": { + JumpInsnNode node = (JumpInsnNode) n; + return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + labels.get(node.label.getLabel()) + "\n"; + } + case "TableSwitchInsnNode": { + TableSwitchInsnNode node = (TableSwitchInsnNode) n; + String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tmin: " + node.min + "\n\t\t\tmax: " + node.max + + "\n\t\t\tdefault: " + labels.get(node.dflt.getLabel()) + "\n\t\t\tlabels: [\n"; + for (LabelNode l : node.labels) { + s += "\t\t\t\t" + labels.get(l.getLabel()) + "\n"; + } + s += "\t\t\t]\n\t\t]\n"; + return s; + } + case "LookupSwitchInsnNode": { + LookupSwitchInsnNode node = (LookupSwitchInsnNode) n; + String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tdefault: " + labels.get(node.dflt.getLabel()) + + "\n\t\t\tkeys: [\n"; + for (Integer l : node.keys) { + s += "\t\t\t\t" + l + "\n"; + } + s += "\t\t\t]" + "\n\t\t\tlabels: [\n"; + for (LabelNode l : node.labels) { + s += "\t\t\t\t" + labels.get(l.getLabel()) + "\n"; + } + s += "\t\t\t]\n\t\t]\n"; + return s; + } + case "IincInsnNode": { + IincInsnNode node = (IincInsnNode) n; + return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + " " + node.incr + "\n"; + } + default: + return "\t\tNOT HANDLED! " + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + n.getClass().getSimpleName() + "\n"; + } + } + } diff --git a/src/me/ByteEdit/main/JavaAssemblyTokenMaker.java b/src/me/ByteEdit/edit/JavaAssemblyTokenMaker.java similarity index 99% rename from src/me/ByteEdit/main/JavaAssemblyTokenMaker.java rename to src/me/ByteEdit/edit/JavaAssemblyTokenMaker.java index bf1db8d..9ad6cbc 100644 --- a/src/me/ByteEdit/main/JavaAssemblyTokenMaker.java +++ b/src/me/ByteEdit/edit/JavaAssemblyTokenMaker.java @@ -5,7 +5,7 @@ * This library is distributed under a modified BSD license. See the included * RSyntaxTextArea.License.txt file for details. */ -package me.ByteEdit.main; +package me.ByteEdit.edit; import java.io.IOException; import java.io.Reader; diff --git a/src/me/ByteEdit/main/OptionBox.java b/src/me/ByteEdit/edit/OptionBox.java similarity index 98% rename from src/me/ByteEdit/main/OptionBox.java rename to src/me/ByteEdit/edit/OptionBox.java index 902baee..4325e2b 100644 --- a/src/me/ByteEdit/main/OptionBox.java +++ b/src/me/ByteEdit/edit/OptionBox.java @@ -1,4 +1,4 @@ -package me.ByteEdit.main; +package me.ByteEdit.edit; import java.awt.EventQueue; import java.awt.Toolkit; diff --git a/src/me/ByteEdit/main/SearchBox.java b/src/me/ByteEdit/edit/SearchBox.java similarity index 77% rename from src/me/ByteEdit/main/SearchBox.java rename to src/me/ByteEdit/edit/SearchBox.java index fa30cf5..afc9e1b 100644 --- a/src/me/ByteEdit/main/SearchBox.java +++ b/src/me/ByteEdit/edit/SearchBox.java @@ -1,4 +1,4 @@ -package me.ByteEdit.main; +package me.ByteEdit.edit; import java.awt.Toolkit; import java.awt.event.ActionEvent; @@ -17,6 +17,8 @@ import javax.swing.KeyStroke; import javax.swing.UIManager; import javax.swing.border.EmptyBorder; +import me.ByteEdit.main.Main; + public class SearchBox extends JFrame { public JPanel contentPane; @@ -106,20 +108,20 @@ public class SearchBox extends JFrame { } public void find() { - int startPos = Main.textArea.getCaretPosition(); + int startPos = Main.txtByteEditView.getCaretPosition(); String toFind = txtFind.getText(); - String txt = chckbxCaseSensitive.isSelected() ? Main.textArea.getText().substring(startPos) - : Main.textArea.getText().substring(startPos).toLowerCase(); + String txt = chckbxCaseSensitive.isSelected() ? Main.txtByteEditView.getText().substring(startPos) + : Main.txtByteEditView.getText().substring(startPos).toLowerCase(); int index = txt.indexOf(chckbxCaseSensitive.isSelected() ? toFind : toFind.toLowerCase()); if (index == -1) { - txt = chckbxCaseSensitive.isSelected() ? Main.textArea.getText() : Main.textArea.getText().toLowerCase(); + txt = chckbxCaseSensitive.isSelected() ? Main.txtByteEditView.getText() : Main.txtByteEditView.getText().toLowerCase(); index = txt.indexOf(chckbxCaseSensitive.isSelected() ? toFind : toFind.toLowerCase()); startPos = 0; if (index == -1) { return; } } - Main.textArea.select(startPos + index, startPos + index + toFind.length()); + Main.txtByteEditView.select(startPos + index, startPos + index + toFind.length()); } public void replaceFind() { @@ -128,22 +130,22 @@ public class SearchBox extends JFrame { } public void replace() { - String txt = Main.textArea.getText(); - int startPos = Main.textArea.getSelectionStart(); - Main.textArea.replaceSelection(txtReplace.getText()); - Main.textArea.select(startPos, startPos + txtReplace.getText().length()); + String txt = Main.txtByteEditView.getText(); + int startPos = Main.txtByteEditView.getSelectionStart(); + Main.txtByteEditView.replaceSelection(txtReplace.getText()); + Main.txtByteEditView.select(startPos, startPos + txtReplace.getText().length()); } public void replaceAll() { String toFind = txtFind.getText(); String toReplace = txtReplace.getText(); - String txt = Main.textArea.getText(); - int prev = Main.textArea.getCaretPosition(); + String txt = Main.txtByteEditView.getText(); + int prev = Main.txtByteEditView.getCaretPosition(); if (chckbxCaseSensitive.isSelected()) { - Main.textArea.replaceRange(txt.replace(toFind, toReplace), 0, txt.length()); + Main.txtByteEditView.replaceRange(txt.replace(toFind, toReplace), 0, txt.length()); } else { - Main.textArea.replaceRange(txt.replaceAll("(?i)" + Pattern.quote(toFind), toReplace), 0, txt.length()); + Main.txtByteEditView.replaceRange(txt.replaceAll("(?i)" + Pattern.quote(toFind), toReplace), 0, txt.length()); } - Main.textArea.setCaretPosition(prev); + Main.txtByteEditView.setCaretPosition(prev); } } diff --git a/src/me/ByteEdit/main/TypeOpenBox.java b/src/me/ByteEdit/edit/TypeOpenBox.java similarity index 98% rename from src/me/ByteEdit/main/TypeOpenBox.java rename to src/me/ByteEdit/edit/TypeOpenBox.java index 6e9f3db..e590341 100644 --- a/src/me/ByteEdit/main/TypeOpenBox.java +++ b/src/me/ByteEdit/edit/TypeOpenBox.java @@ -1,4 +1,4 @@ -package me.ByteEdit.main; +package me.ByteEdit.edit; import java.awt.Toolkit; import java.awt.event.ActionEvent; @@ -18,6 +18,8 @@ import javax.swing.event.DocumentListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; +import me.ByteEdit.main.Main; + public class TypeOpenBox extends JFrame { public JPanel contentPane; diff --git a/src/me/ByteEdit/main/Main.java b/src/me/ByteEdit/main/Main.java index 2c185ec..8783045 100644 --- a/src/me/ByteEdit/main/Main.java +++ b/src/me/ByteEdit/main/Main.java @@ -30,6 +30,7 @@ import java.util.Map.Entry; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; +import java.util.regex.Pattern; import javax.swing.JComponent; import javax.swing.JDialog; @@ -46,6 +47,7 @@ import javax.swing.border.EmptyBorder; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.text.BadLocationException; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; @@ -67,6 +69,15 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; +import me.ByteEdit.edit.Assembler; +import me.ByteEdit.edit.Disassembler; +import me.ByteEdit.edit.Disassembler.DisassembleTuple; +import me.ByteEdit.edit.OptionBox; +import me.ByteEdit.edit.SearchBox; +import me.ByteEdit.edit.TypeOpenBox; +import me.ByteEdit.utils.ClassUtil; +import me.ByteEdit.utils.OpcodesReverse; + public class Main extends JFrame { public static Main INSTANCE; @@ -76,11 +87,13 @@ public class Main extends JFrame { public static HashMap OTHER_FILES = new HashMap<>(); public static HashMap classNodes = new HashMap<>(); public static String currentNodeName; - public static RSyntaxTextArea textArea; + public static RSyntaxTextArea txtByteEditView; public static SearchBox searchBox; public static TypeOpenBox typeOpenBox; public static OptionBox optionBox; public static JTree tree; + public static RTextScrollPane scrollPane_ByteEdit; + public static Theme theme; /** * Launch the application. @@ -172,90 +185,12 @@ public class Main extends JFrame { contentPane.add(splitPane); JScrollPane scrollPane = new JScrollPane(); splitPane.setLeftComponent(scrollPane); - textArea = new RSyntaxTextArea(); CompletionProvider provider = createCompletionProvider(); AutoCompletion ac = new AutoCompletion(provider); ac.setShowDescWindow(true); - ac.install(textArea); FoldParserManager.get().addFoldParserMapping(SyntaxConstants.SYNTAX_STYLE_JAVA_DISASSEMBLE, new CurlyFoldParser(false, true)); - textArea.setCodeFoldingEnabled(true); - textArea.addKeyListener(new KeyAdapter() { - - @Override - public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == 116 && currentNodeName != null) { - try { - ClassNode classNode = classNodes.get(currentNodeName); - int prev = textArea.getCaretPosition(); - String dis = Disassembler.disassemble(classNode); - String substr = currentNodeName.substring(0, currentNodeName.length() - 6); - for (String key : Main.classNodes.keySet()) { - if (key.contains("$")) { - String[] split = key.split("\\$"); - if (split[0].equals(substr)) { - dis += "\n" + Disassembler.disassemble(classNodes.get(key)); - } - } - } - textArea.setText(dis); - textArea.setCaretPosition(prev); - } catch (Exception e2) {} - } - } - }); - KeyStroke ctrlF = KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_DOWN_MASK); - textArea.registerKeyboardAction(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - searchBox.setVisible(true); - searchBox.txtFind.requestFocusInWindow(); - searchBox.txtFind.select(0, searchBox.txtFind.getText().length()); - } - }, ctrlF, JComponent.WHEN_IN_FOCUSED_WINDOW); - KeyStroke ctrlT = KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_DOWN_MASK); - textArea.registerKeyboardAction(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - typeOpenBox.setVisible(true); - typeOpenBox.txtSearch.requestFocusInWindow(); - typeOpenBox.txtSearch.select(0, typeOpenBox.txtSearch.getText().length()); - } - }, ctrlT, JComponent.WHEN_IN_FOCUSED_WINDOW); - KeyStroke ctrlS = KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK); - textArea.registerKeyboardAction(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - String txt = textArea.getText(); - for (String s : txt.split("\\/\\/ #Annotations\n")) { - if (s.isEmpty()) - continue; - ClassNode node = Assembler.assemble(s); - if (node == null) { - continue; - } - if (classNodes.replace(node.name + ".class", node) == null) { - classNodes.put(node.name + ".class", node); - } - } - } - }, ctrlS, JComponent.WHEN_FOCUSED); - KeyStroke ctrlO = KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_DOWN_MASK); - textArea.registerKeyboardAction(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - optionBox.setVisible(true); - } - }, ctrlO, JComponent.WHEN_IN_FOCUSED_WINDOW); - textArea.setEditable(true); - textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA_DISASSEMBLE); - textArea.setCodeFoldingEnabled(true); try { Theme theme = Theme.load(getClass().getClassLoader().getResourceAsStream("org/fife/eclipse.xml")); - theme.apply(textArea); } catch (IOException e2) { e2.printStackTrace(); } @@ -280,13 +215,6 @@ public class Main extends JFrame { } } }); - tree.registerKeyboardAction(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - save(); - } - }, ctrlS, JComponent.WHEN_FOCUSED); tree.setFont(new Font("Verdana", Font.PLAIN, 11)); tree.setBackground(Color.LIGHT_GRAY); if (tree.getCellRenderer() instanceof DefaultTreeCellRenderer) { @@ -315,13 +243,6 @@ public class Main extends JFrame { } } }); - RTextScrollPane scrollPane_TextArea = new RTextScrollPane(); - textArea.setBackground(Color.LIGHT_GRAY); - scrollPane_TextArea.setViewportView(textArea); - scrollPane_TextArea.setLineNumbersEnabled(true); - scrollPane_TextArea.setFoldIndicatorEnabled(true); - scrollPane_TextArea.getGutter().setBackground(Color.LIGHT_GRAY); - splitPane.setRightComponent(scrollPane_TextArea); new DropTarget(tree, new DropTargetListener() { @Override @@ -367,25 +288,194 @@ public class Main extends JFrame { @Override public void dragExit(DropTargetEvent dte) {} }); + + txtByteEditView = new RSyntaxTextArea(); + ac.install(txtByteEditView); + txtByteEditView.setCodeFoldingEnabled(true); + txtByteEditView.addKeyListener(new KeyAdapter() { + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == 116 && currentNodeName != null) { + try { + ClassNode classNode = classNodes.get(currentNodeName); + int prev = txtByteEditView.getCaretPosition(); + String dis = Disassembler.disassemble(classNode); + String substr = currentNodeName.substring(0, currentNodeName.length() - 6); + for (String key : Main.classNodes.keySet()) { + if (key.contains("$")) { + String[] split = key.split("\\$"); + if (split[0].equals(substr)) { + dis += "\n" + Disassembler.disassemble(classNodes.get(key)); + } + } + } + txtByteEditView.setText(dis); + txtByteEditView.setCaretPosition(prev); + } catch (Exception e2) {} + } + } + }); + KeyStroke ctrlF = KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_DOWN_MASK); + KeyStroke ctrlT = KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_DOWN_MASK); + KeyStroke ctrlS = KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK); + KeyStroke ctrlG = KeyStroke.getKeyStroke(KeyEvent.VK_G, KeyEvent.CTRL_DOWN_MASK); + KeyStroke ctrlO = KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_DOWN_MASK); + // global + txtByteEditView.registerKeyboardAction(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + searchBox.setVisible(true); + searchBox.txtFind.requestFocusInWindow(); + searchBox.txtFind.select(0, searchBox.txtFind.getText().length()); + } + }, ctrlF, JComponent.WHEN_IN_FOCUSED_WINDOW); + txtByteEditView.registerKeyboardAction(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + typeOpenBox.setVisible(true); + typeOpenBox.txtSearch.requestFocusInWindow(); + typeOpenBox.txtSearch.select(0, typeOpenBox.txtSearch.getText().length()); + } + }, ctrlT, JComponent.WHEN_IN_FOCUSED_WINDOW); + txtByteEditView.registerKeyboardAction(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + optionBox.setVisible(true); + } + }, ctrlO, JComponent.WHEN_IN_FOCUSED_WINDOW); + // specific + tree.registerKeyboardAction(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + save(); + } + }, ctrlS, JComponent.WHEN_FOCUSED); + txtByteEditView.registerKeyboardAction(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + saveCurrentClassNode(); + } + }, ctrlS, JComponent.WHEN_FOCUSED); + txtByteEditView.registerKeyboardAction(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + try { + goToSelected(); + } catch (BadLocationException e1) { + e1.printStackTrace(); + } + } + }, ctrlG, JComponent.WHEN_FOCUSED); + txtByteEditView.setEditable(true); + txtByteEditView.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA_DISASSEMBLE); + txtByteEditView.setCodeFoldingEnabled(true); + scrollPane_ByteEdit = new RTextScrollPane(); + try { + theme = Theme.load(getClass().getClassLoader().getResourceAsStream("org/fife/eclipse.xml")); + theme.apply(txtByteEditView); + } catch (IOException e2) { + e2.printStackTrace(); + } + + splitPane.setRightComponent(scrollPane_ByteEdit); + txtByteEditView.setBackground(Color.LIGHT_GRAY); + scrollPane_ByteEdit.setViewportView(txtByteEditView); + scrollPane_ByteEdit.setLineNumbersEnabled(true); + scrollPane_ByteEdit.setFoldIndicatorEnabled(true); + scrollPane_ByteEdit.getGutter().setBackground(Color.LIGHT_GRAY); } - public static void selectFile(String s) { + private final Pattern jumpableInstructionPattern = Pattern.compile("^\t\t(?!//|\t+).+ .+"); + + public void goToSelected() throws BadLocationException { + int lineStart = txtByteEditView.getLineStartOffsetOfCurrentLine(); + int lineEnd = txtByteEditView.getLineEndOffsetOfCurrentLine() - 1; + String line = txtByteEditView.getText(lineStart, lineEnd - lineStart); + if (!jumpableInstructionPattern.matcher(line).matches()) { + return; + } + line = line.substring(2); + if (line.startsWith("invoke")) { + String[] split = line.split(" "); + String desc = split[1]; + String className = split[2]; + String[] nameSplit = className.split("/"); + String methodName = nameSplit[nameSplit.length - 1]; + className = className.substring(0, className.length() - methodName.length() - 1); + ClassNode classNode = classNodes.get(className + ".class"); + if (classNode == null) { + return; + } + for (MethodNode mn : classNode.methods) { + if (mn.name.equals(methodName) && mn.desc.equals(desc)) { + while (classNode.outerClass != null) { + classNode = classNodes.get(classNode.outerClass + ".class"); + } + int lineFound = selectFileWithSearch(classNode.name + ".class", mn); + if (lineFound != -1) { + Main.txtByteEditView.setCaretPosition(Main.txtByteEditView.getLineStartOffset(lineFound)); + } + break; + } + } + } + } + + private void saveCurrentClassNode() { + String txt = txtByteEditView.getText(); + for (String s : txt.split("\\/\\/ #Annotations\n")) { + if (s.isEmpty()) + continue; + ClassNode node = Assembler.assemble(s); + if (node == null) { + continue; + } + if (classNodes.replace(node.name + ".class", node) == null) { + classNodes.put(node.name + ".class", node); + } + } + } + + public static int selectFileWithSearch(String s, MethodNode methodToFind) { if (s.endsWith(".class")) { currentNodeName = s; + int lineFound = -1; ClassNode classNode = classNodes.get(s); - String dis = Disassembler.disassemble(classNode); + String dis = ""; + DisassembleTuple tuple = Disassembler.disassemble(classNode, methodToFind); + if (tuple.getLine() != -1) { + lineFound = dis.split("\\n").length + tuple.getLine() - 1; + } + dis += tuple.getDisassembly(); String substr = s.substring(0, s.length() - 6); for (String key : Main.classNodes.keySet()) { if (key.contains("$")) { String[] split = key.split("\\$"); if (split[0].equals(substr)) { - dis += "\n" + Disassembler.disassemble(classNodes.get(key)); + tuple = Disassembler.disassemble(classNodes.get(key), methodToFind); + if (tuple.getLine() != -1) { + lineFound = dis.split("\\n").length + tuple.getLine() + 1; + } + dis += "\n" + tuple.getDisassembly(); } } } - textArea.setText(dis); - textArea.setCaretPosition(0); + txtByteEditView.setText(dis); + txtByteEditView.setCaretPosition(0); + return lineFound; } + return -1; + } + + public static int selectFile(String s) { + return selectFileWithSearch(s, null); } public void save() { @@ -474,7 +564,7 @@ public class Main extends JFrame { } } - public void showError(Throwable e) { + public static void showError(Throwable e) { String s = e.toString() + "\n"; StackTraceElement[] stackTrace = e.getStackTrace(); for (StackTraceElement ste : stackTrace) { @@ -482,7 +572,10 @@ public class Main extends JFrame { break; s += "\tat " + ste + "\n"; } - JOptionPane.showMessageDialog(this, s, "Error!", JOptionPane.ERROR_MESSAGE); + } + + public static void showError(String s) { + JOptionPane.showMessageDialog(INSTANCE, s, "Error!", JOptionPane.ERROR_MESSAGE); } class ArchiveTreeModel extends DefaultTreeModel { diff --git a/src/me/ByteEdit/main/ClassUtil.java b/src/me/ByteEdit/utils/ClassUtil.java similarity index 99% rename from src/me/ByteEdit/main/ClassUtil.java rename to src/me/ByteEdit/utils/ClassUtil.java index ef565c2..54b4f81 100644 --- a/src/me/ByteEdit/main/ClassUtil.java +++ b/src/me/ByteEdit/utils/ClassUtil.java @@ -1,4 +1,4 @@ -package me.ByteEdit.main; +package me.ByteEdit.utils; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/me/ByteEdit/main/CustomBufferedReader.java b/src/me/ByteEdit/utils/CustomBufferedReader.java similarity index 92% rename from src/me/ByteEdit/main/CustomBufferedReader.java rename to src/me/ByteEdit/utils/CustomBufferedReader.java index d687d66..ec526b5 100644 --- a/src/me/ByteEdit/main/CustomBufferedReader.java +++ b/src/me/ByteEdit/utils/CustomBufferedReader.java @@ -1,4 +1,4 @@ -package me.ByteEdit.main; +package me.ByteEdit.utils; import java.io.BufferedReader; import java.io.IOException; diff --git a/src/me/ByteEdit/main/ExternalTypeEnumeration.java b/src/me/ByteEdit/utils/ExternalTypeEnumeration.java similarity index 97% rename from src/me/ByteEdit/main/ExternalTypeEnumeration.java rename to src/me/ByteEdit/utils/ExternalTypeEnumeration.java index d491ff0..3fb0de6 100644 --- a/src/me/ByteEdit/main/ExternalTypeEnumeration.java +++ b/src/me/ByteEdit/utils/ExternalTypeEnumeration.java @@ -1,4 +1,4 @@ -package me.ByteEdit.main; +package me.ByteEdit.utils; public class ExternalTypeEnumeration { diff --git a/src/me/ByteEdit/main/OpcodesReverse.java b/src/me/ByteEdit/utils/OpcodesReverse.java similarity index 99% rename from src/me/ByteEdit/main/OpcodesReverse.java rename to src/me/ByteEdit/utils/OpcodesReverse.java index 1a42aa1..438a626 100644 --- a/src/me/ByteEdit/main/OpcodesReverse.java +++ b/src/me/ByteEdit/utils/OpcodesReverse.java @@ -1,4 +1,4 @@ -package me.ByteEdit.main; +package me.ByteEdit.utils; public class OpcodesReverse { diff --git a/src/org/fife/ui/rsyntaxtextarea/RSyntaxDocument.java b/src/org/fife/ui/rsyntaxtextarea/RSyntaxDocument.java index 1025e35..e611fb0 100644 --- a/src/org/fife/ui/rsyntaxtextarea/RSyntaxDocument.java +++ b/src/org/fife/ui/rsyntaxtextarea/RSyntaxDocument.java @@ -22,7 +22,7 @@ import org.fife.ui.rsyntaxtextarea.modes.AbstractMarkupTokenMaker; import org.fife.ui.rtextarea.RDocument; import org.fife.util.DynamicIntArray; -import me.ByteEdit.main.JavaAssemblyTokenMaker; +import me.ByteEdit.edit.JavaAssemblyTokenMaker; /** * The document used by {@link org.fife.ui.rsyntaxtextarea.RSyntaxTextArea}.