From 75a905656469fe7f6d2f5911ecd374c752c9cb79 Mon Sep 17 00:00:00 2001 From: Charles Daniels Date: Sat, 14 Oct 2017 13:35:05 -0400 Subject: [PATCH 1/6] Added code-quality assurance tools to pom.xml * Added CheckStyle to perform static analysis on the Recaf codebase. * View output on the console with "mvn checkstyle:check". * Added FindBugs to check for common anti-patterns that tend to cause bugs. * View the output on the console with "mvn clean compile; mvn findbugs:check". * View the output in the GUI with "mvn clean compile; mvn findbugs:gui". * "mvn site" should now include HTML versions of the CheckStyle and FindBugs reports. Note that for the FindBugs one to show up, you might need to run "mvn clean compile" before "mvn site". * In the future, the project should be configured to refuse to compile if any CheckStyle or FindBugs issues are present (i.e. after the standing issues are fixed). * For CheckStyle: http://maven.apache.org/plugins/maven-checkstyle-plugin/usage.html * For FindBugs: http://memorynotfound.com/findbugs-maven-plugin-fail-build/ --- pom.xml | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 8a145d275..189acc8f4 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ 4.0.0 Recaf - Recaf + Recaf https://github.com/Col-E/Recaf/ 0.7 Recaf @@ -62,7 +62,42 @@ jar-with-dependencies - + - \ No newline at end of file + + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.5 + + + Max + + Low + + true + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + + checkstyle + + + + + + + + From dd262982c1b271bbace03b97057fa3fc2750f8a5 Mon Sep 17 00:00:00 2001 From: Charles Daniels Date: Sat, 14 Oct 2017 14:33:40 -0400 Subject: [PATCH 2/6] Enabled JavaDoc generation, and updated code so the JavaDoc would compile. There were lots of method where JavaDoc was throwing errors due to description fields not being filled out. I have filled all of them in, and done my best to make my descriptions accurate. There were a few places where I was insufficiently familiar with the code and simply left TODOS. More work needs to be done to get the JavaDoc for this project into a useful state, but it (the JavaDoc) at least actually compiles now. --- pom.xml | 6 ++ src/me/coley/recaf/asm/AsmUtil.java | 38 +++---- src/me/coley/recaf/asm/OpcodeUtil.java | 11 ++- src/me/coley/recaf/asm/PluginClassReader.java | 4 +- src/me/coley/recaf/cfr/CFRSetting.java | 10 +- src/me/coley/recaf/ui/FileChoosers.java | 19 ++-- src/me/coley/recaf/ui/FontUtil.java | 6 +- src/me/coley/recaf/ui/Gui.java | 12 +-- src/me/coley/recaf/ui/HtmlRenderer.java | 54 +++++----- .../internalframe/OpcodeCreationBox.java | 18 ++-- .../recaf/ui/component/list/OpcodeList.java | 52 +++++----- .../ui/component/panel/DecompilePanel.java | 2 +- .../panel/OpcodeTypeSwitchPanel.java | 5 +- .../recaf/ui/component/panel/TabbedPanel.java | 54 ++++++---- .../component/panel/TagTypeSwitchPanel.java | 5 +- .../ui/component/table/VariableTable.java | 16 +-- src/me/coley/recaf/util/Misc.java | 40 ++++---- src/me/coley/recaf/util/StreamUtil.java | 99 +++++++++---------- 18 files changed, 235 insertions(+), 216 deletions(-) diff --git a/pom.xml b/pom.xml index 189acc8f4..3db5e600a 100644 --- a/pom.xml +++ b/pom.xml @@ -97,6 +97,12 @@ + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.0-M1 + diff --git a/src/me/coley/recaf/asm/AsmUtil.java b/src/me/coley/recaf/asm/AsmUtil.java index 42c1c19bb..2cfda2dc4 100644 --- a/src/me/coley/recaf/asm/AsmUtil.java +++ b/src/me/coley/recaf/asm/AsmUtil.java @@ -20,10 +20,11 @@ public class AsmUtil { /** * Reads the classes of the given jar into a map. - * - * @param jarPath - * @return - * @throws IOException + * + * @param jarPath Path to jarfile to read classes from. + * @return Map of classes from the specified jarfile. + * @throws IOException If an error was encountered while reading the + * jarfile. */ public Map readClasses(String jarPath) throws IOException { Map map = new HashMap<>(); @@ -54,10 +55,11 @@ public Map readClasses(String jarPath) throws IOException { /** * Reads non-classes from the given jar. - * - * @param jarPath - * @return - * @throws IOException + * + * @param jarPath Path to jarfile to read non-classes from. + * @return Map of non-classes from the specified jarfile. + * @throws IOException If an error was encountered while reading the + * jarfile. */ public Map readNonClasses(String jarPath) throws IOException { Map map = new HashMap<>(); @@ -78,9 +80,9 @@ public Map readNonClasses(String jarPath) throws IOException { /** * Creates a ClassNode from the given ClassReader. - * - * @param cr - * @return + * + * @param cr The class read to obtain the node from. + * @return The node obtained from cr. */ private ClassNode getNode(ClassReader cr) { ClassNode cn = new ClassNode(); @@ -90,10 +92,10 @@ private ClassNode getNode(ClassReader cr) { /** * Creates a ClassNode from the given class. - * - * @param c - * @return - * @throws IOException + * + * @param c The target class. + * @return Node generated from c. + * @throws IOException If an error occurs while loading the class. */ public ClassNode getNode(Class c) throws IOException { String name = c.getName(); @@ -109,9 +111,9 @@ public ClassNode getNode(Class c) throws IOException { /** * Writes a ClassNode to a byte array. - * - * @param cn - * @return + * + * @param cn The target class node. + * @return ByteArray representation of cn. */ public byte[] toBytes(ClassNode cn) { ClassWriter cw = new NonReflectionWriter(recaf.options.classFlagsOutput); diff --git a/src/me/coley/recaf/asm/OpcodeUtil.java b/src/me/coley/recaf/asm/OpcodeUtil.java index 51605649c..542fb21e8 100644 --- a/src/me/coley/recaf/asm/OpcodeUtil.java +++ b/src/me/coley/recaf/asm/OpcodeUtil.java @@ -173,9 +173,14 @@ public static String[] typeToCodes(int type) { /** * Return smaller subset of the {@link #OPS_INSN} string array. - * - * @param name - * @return + * + * @param name The name of the target array. + * @return The desired subset. + * + * TODO: I have no idea what this is, just filling in some stubs + * so JavaDoc is happy. + * + * - Charles */ public static String[] getInsnSubset(String name) { //@formatter:off diff --git a/src/me/coley/recaf/asm/PluginClassReader.java b/src/me/coley/recaf/asm/PluginClassReader.java index d91913b6a..7bce581e4 100644 --- a/src/me/coley/recaf/asm/PluginClassReader.java +++ b/src/me/coley/recaf/asm/PluginClassReader.java @@ -6,9 +6,9 @@ import org.objectweb.asm.ClassReader; /** - * TODO: Plugin system, allow users to run scripts on input (Ex: Onload -> + * TODO: Plugin system, allow users to run scripts on input (Ex: Onload >- * run decrypt strings plugin). - * + * * @author Matt */ public class PluginClassReader extends ClassReader { diff --git a/src/me/coley/recaf/cfr/CFRSetting.java b/src/me/coley/recaf/cfr/CFRSetting.java index b052bbcb2..8426936c2 100644 --- a/src/me/coley/recaf/cfr/CFRSetting.java +++ b/src/me/coley/recaf/cfr/CFRSetting.java @@ -88,10 +88,10 @@ public void setEnabled(boolean enabled) { this.on = enabled; } - /** - * Returns a map of the settings and their current status. - * - * @return + /** Obtain repreesntation of the CFR settings as a string map. + * + * @return <String, String(of boolean)> map of the settings and their + * current status. */ public static Map toStringMap() { Map options = new HashMap<>(); @@ -100,4 +100,4 @@ public static Map toStringMap() { } return options; } -} \ No newline at end of file +} diff --git a/src/me/coley/recaf/ui/FileChoosers.java b/src/me/coley/recaf/ui/FileChoosers.java index 84155f3fc..54f82ea77 100644 --- a/src/me/coley/recaf/ui/FileChoosers.java +++ b/src/me/coley/recaf/ui/FileChoosers.java @@ -9,25 +9,20 @@ public class FileChoosers { private JFileChooser fileChooser; /** - * Returns the file chooser. If it is null it is instantiated and set to the + * @return The file chooser. If it is null it is instantiated and set to the * working directory with a filter for jar files. - * - * @return */ public JFileChooser getFileChooser() { return getFileChooser("Java Archives", "jar"); } /** - * Returns the file chooser. If it is null it is instantiated and set to the + * @return The file chooser. If it is null it is instantiated and set to the * working directory with a filter for the given file type. To allow any * type, have the parameters be null. - * - * @param fileType - * Name of the type of file - * @param extension - * Actual file extension. - * @return + * + * @param fileType Name of the type of file + * @param extension Actual file extension. */ public JFileChooser getFileChooser(String fileType, String extension) { if (fileChooser == null) { @@ -48,8 +43,8 @@ public JFileChooser getFileChooser(String fileType, String extension) { /** * Creates and returns a file chooser set in the working directory. - * - * @return + * + * @return The file chooser. */ public JFileChooser createFileSaver() { JFileChooser fileSaver = new JFileChooser(); diff --git a/src/me/coley/recaf/ui/FontUtil.java b/src/me/coley/recaf/ui/FontUtil.java index 419a44f90..84b42447d 100644 --- a/src/me/coley/recaf/ui/FontUtil.java +++ b/src/me/coley/recaf/ui/FontUtil.java @@ -33,9 +33,9 @@ public class FontUtil { /** * Create a bounding box for the visual representation of the given text. * - * @param text - * @param font - * @return + * @param text The text. + * @param font The font in which to render the text. + * @return The bounding box. */ public static Rectangle2D getStringBounds(String text, Font font) { return font.getStringBounds(text, frc); diff --git a/src/me/coley/recaf/ui/Gui.java b/src/me/coley/recaf/ui/Gui.java index 011277f31..749dbbe0b 100644 --- a/src/me/coley/recaf/ui/Gui.java +++ b/src/me/coley/recaf/ui/Gui.java @@ -98,7 +98,7 @@ public void actionPerformed(ActionEvent e) { /* * JMenu mnEdit = new JMenu("Edit"); JMenuItem mntmUndo = new * JMenuItem("Undo"); mntmUndo.addActionListener(new ActionListener() { - * + * * @Override public void actionPerformed(ActionEvent e) { * recaf.history.undoLast(); } }); mnEdit.add(mntmUndo); * menuBar.add(mnEdit); @@ -172,8 +172,8 @@ public final void drop(final DropTargetDropEvent event) { /** * Creates a new tab with the text of the exception. - * - * @param e + * + * @param e The exception. */ public void displayError(Throwable e) { JTextArea text = new JTextArea(); @@ -195,8 +195,8 @@ public void displayError(Throwable e) { /** * Opens up a class tab for the given class-node, or opens an existing page * if one is found. - * - * @param node + * + * @param node The node. */ public void addClassView(ClassNode node) { if (tabbedContent.hasCached(node.name)) { @@ -215,7 +215,7 @@ public void addClassView(ClassNode node) { /** * Opens up a tab for the given component, or opens an existing page if one * is found. - * + * * @param title * Title of tab. * @param component diff --git a/src/me/coley/recaf/ui/HtmlRenderer.java b/src/me/coley/recaf/ui/HtmlRenderer.java index 9b5f29b8e..57b309cd5 100644 --- a/src/me/coley/recaf/ui/HtmlRenderer.java +++ b/src/me/coley/recaf/ui/HtmlRenderer.java @@ -12,11 +12,10 @@ public interface HtmlRenderer { final String colGray = "#555555"; /** - * HTML escape '&', '<' and '>'. - * - * @param s - * Text to escape - * @return + * HTML escape '&', '<' and '>'. + * + * @param s Text to escape + * @return Text with amp, lt, and gt escaped correctly. */ default String escape(String s) { return s.replace("&", "&").replace("<", "<").replace(">", ">"); @@ -24,21 +23,26 @@ default String escape(String s) { /** * Converts a given type to a string. - * - * @param type - * @return + * + * @param type The type object. + * @return String representation of the type object. */ default String getTypeStr(Type type) { return getTypeStr(type, null); } /** - * Converts a given type to a string. Output will be simplified if enabled - * in passed options. - * - * @param type - * @param options - * @return + * Converts a given type to a string. Output will be simplified if + * enabled in passed options. + * + * TODO: this javadoc should either link to documentation for the + * Options class, or document how to use it correctly in this context. + * + * - Charles + * + * @param type The type object. + * @param options Options object. + * @return String representation of the type object. */ default String getTypeStr(Type type, Options options) { String s = ""; @@ -79,19 +83,19 @@ default String getTypeStr(Type type, Options options) { /** * Italicize the given text. - * - * @param input - * @return + * + * @param input Text to italicize. + * @return HTML markup to italicize the text. */ default String italic(String input) { return "" + input + ""; } - + /** * Bold the given text. - * - * @param input - * @return + * + * @param input Text to bold. + * @return HTML markup with the text bolded. */ default String bold(String input) { return "" + input + ""; @@ -99,10 +103,10 @@ default String bold(String input) { /** * Color the given text. - * - * @param color - * @param input - * @return + * + * @param color The color to turn the text, must be a valid HTML color. + * @param input The text to color. + * @return HTML markup with the text colored appropriately. */ default String color(String color, String input) { return "" + input + ""; diff --git a/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java b/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java index 3a11bade3..9d626cef8 100644 --- a/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java @@ -167,10 +167,10 @@ public void itemStateChanged(ItemEvent evt) { } /** - * Create an opcode from the current open card. If there's an input error no - * node is returned. - * - * @return + * Create an opcode from the current open card. If there's an input + * error no node is returned. + * + * @return The opcode created. */ public AbstractInsnNode create() { try { @@ -217,7 +217,7 @@ public AbstractInsnNode create() { /** * Get selected opcode. - * + * * @return */ private int getOpcode() { @@ -226,7 +226,7 @@ private int getOpcode() { /** * Get value for the current card pertaining to the given key as a String. - * + * * @param key * Label associated with an input. * @return @@ -237,7 +237,7 @@ private String getString(String key) { /** * Get value for the current card pertaining to the given key as an integer. - * + * * @param key * Label associated with an input. * @return @@ -248,7 +248,7 @@ private int getInt(String key) { /** * Get value for the current card pertaining to the given key. - * + * * @param key * Label associated with an input. * @return @@ -263,7 +263,7 @@ private Object get(String key) { /** * Set to array. - * + * * @param set * @return */ diff --git a/src/me/coley/recaf/ui/component/list/OpcodeList.java b/src/me/coley/recaf/ui/component/list/OpcodeList.java index a1bdb4a40..522c34b5b 100644 --- a/src/me/coley/recaf/ui/component/list/OpcodeList.java +++ b/src/me/coley/recaf/ui/component/list/OpcodeList.java @@ -76,12 +76,10 @@ public void repopulate() { /** * Get the background color for the given opcode. - * - * @param index - * Opcode index. - * @param value - * Opcode value. - * @return + * + * @param index Opcode index. + * @param value Opcode value. + * @return Background color. */ public Color getColorFor(int index, AbstractInsnNode value) { if (colorMap.containsKey(value)) { @@ -92,12 +90,10 @@ public Color getColorFor(int index, AbstractInsnNode value) { /** * Get the appended text for the given opcode. - * - * @param index - * Opcode index. - * @param value - * Opcode value. - * @return + * + * @param index Opcode index. + * @param value Opcode value. + * @return appended text. */ public String getAppendFor(int index, AbstractInsnNode value) { if (appendMap.containsKey(value)) { @@ -108,10 +104,9 @@ public String getAppendFor(int index, AbstractInsnNode value) { /** * Get the arbitrary label identifier for the given label opcode. - * - * @param ain - * Label opcode. - * @return + * + * @param ain Label opcode. + * @return label identifier. */ public String getLabelName(AbstractInsnNode ain) { return labels.getOrDefault(ain, "(New Label)"); @@ -119,8 +114,8 @@ public String getLabelName(AbstractInsnNode ain) { /** * Get the method node associated with the list. - * - * @return + * + * @return the method node. */ public MethodNode getMethod() { return method; @@ -128,8 +123,9 @@ public MethodNode getMethod() { /** * Getter for {@link #colorMap}. - * - * @return + * + * @return Map associating AbstractInsnNode instances with their + * colors. */ public Map getColorMap() { return colorMap; @@ -137,8 +133,9 @@ public Map getColorMap() { /** * Getter for {@link #appendMap}. - * - * @return + * + * @return Map associated AbstractInsnNode instances with their + * appended text. */ public Map getAppendMap() { return appendMap; @@ -146,9 +143,14 @@ public Map getAppendMap() { /** * Set key-modifiers. - * - * @param control - * @param shift + * + * @param control TODO + * @param shift TODO + * + * TODO: What do control and shift correspond to? What is this method + * for? + * + * - Charles */ public void setModifiers(boolean control, boolean shift) { this.controlDown = control; diff --git a/src/me/coley/recaf/ui/component/panel/DecompilePanel.java b/src/me/coley/recaf/ui/component/panel/DecompilePanel.java index 2695fea03..5c7a75681 100644 --- a/src/me/coley/recaf/ui/component/panel/DecompilePanel.java +++ b/src/me/coley/recaf/ui/component/panel/DecompilePanel.java @@ -58,7 +58,7 @@ public DecompilePanel(ClassNode cn, MethodNode mn) { * Returns a title for the containing parent to access (Groupbox / * InternalWindow). * - * @return + * @return The title. */ public String getTitle() { String s = "CFR: " + classNode.name; diff --git a/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java b/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java index 5940a34a6..3f8e84379 100644 --- a/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java +++ b/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java @@ -166,9 +166,8 @@ private void setLayout(int size) { } /** - * Get the number of radio buttons. - * - * @return + * @return the number of radio buttons. + */ public int getOptionCount() { return compToOpcode.keySet().size(); diff --git a/src/me/coley/recaf/ui/component/panel/TabbedPanel.java b/src/me/coley/recaf/ui/component/panel/TabbedPanel.java index d83285b3c..b2dd8168f 100644 --- a/src/me/coley/recaf/ui/component/panel/TabbedPanel.java +++ b/src/me/coley/recaf/ui/component/panel/TabbedPanel.java @@ -14,7 +14,7 @@ /** * Wrapper for Tabbed Pane, providing extra abilities such as tab removal and * redirection. - * + * * @author Matt */ @SuppressWarnings("serial") @@ -50,9 +50,13 @@ public void mouseReleased(MouseEvent e) { /** * Adds a tab to the panel. - * - * @param title - * @param component + * + * @param title The tab's title. + * @param component The component. + * + * TODO: What is the component for? + * + * - Charles */ public void addTab(String title, Component component) { pane.add(title, component); @@ -63,21 +67,25 @@ public void addTab(String title, Component component) { } /** - * Determines if the tab with the given title and component should cached - * for redirection, instead of duplicating tabs. - * - * @param title - * @param component - * @return + * Determines if the tab with the given title and component should + * cached for redirection, instead of duplicating tabs. + * + * @param title The tab's title. + * @param component The component. + * + * TODO: What is the component for? + * + * - Charles + * + * @return true if the tab should be cached. */ private boolean shouldCache(String title, Component component) { return title.contains("Error: "); } /** - * Get the number of open tabs. - * - * @return + * @return The number of open tabs. + */ public int getTabCount() { return pane.getTabCount(); @@ -85,8 +93,8 @@ public int getTabCount() { /** * Set the selected tab. - * - * @param index + * + * @param index Index of the tab. */ public void setSelectedTab(int index) { pane.setSelectedIndex(index); @@ -95,9 +103,13 @@ public void setSelectedTab(int index) { /** * Check if a tab by the given title exists and is available for * redirection. - * - * @param title - * @return + * + * @param title Title of the tab to check. + * @return true if the tab is available for redirection. + * + * TODO: Is the return accurate? I'm not entirely sure what this does. + * + * - Charles */ public boolean hasCached(String title) { return children.containsKey(title); @@ -105,9 +117,9 @@ public boolean hasCached(String title) { /** * Retrieve the index of the cached tab by its title. - * - * @param title - * @return + * + * @param title The title of the tab. + * @return The tab's index. */ public int getCachedIndex(String title) { for (int i = 0; i < getTabCount(); i++) { diff --git a/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java b/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java index 932036ead..315b31d80 100644 --- a/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java +++ b/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java @@ -83,9 +83,8 @@ private void setValue(int value) { } /** - * Get the number of radio buttons. - * - * @return + * @return The number of radio buttons. + */ public int getOptionCount() { return compToTag.keySet().size(); diff --git a/src/me/coley/recaf/ui/component/table/VariableTable.java b/src/me/coley/recaf/ui/component/table/VariableTable.java index 43882fb68..f64ef3103 100644 --- a/src/me/coley/recaf/ui/component/table/VariableTable.java +++ b/src/me/coley/recaf/ui/component/table/VariableTable.java @@ -16,8 +16,8 @@ /** * JTable populated by local variable data from a given MethodNode.
- * Constructed via {@link #create(MethodNode)}. - * + * Constructed via {@link #create(OpcodeList, MethodNode)}. + * * @author Matt */ @SuppressWarnings("serial") @@ -27,11 +27,11 @@ public class VariableTable extends JTable { /** * Construct a local variable table from the given method. - * - * @param list - * - * @param method - * @return + * + * @param list List of opcodes. + * + * @param method The method. + * @return VariableTable containing the local variables for the method. */ public static VariableTable create(OpcodeList list, MethodNode method) { boolean showSignatures = options.showVariableSignatureInTable; @@ -127,7 +127,7 @@ private VariableTable(String[] column, String[][] data) { * Override the getPrefferedScrollableViewportSize to prevent the wrapping * scroll pane from adding lots of pointless empty space near the bottom of * the container. - * + * * Credits: https://stackoverflow.com/a/42436205/8071915 */ @Override diff --git a/src/me/coley/recaf/util/Misc.java b/src/me/coley/recaf/util/Misc.java index f9f4bb908..415c80464 100644 --- a/src/me/coley/recaf/util/Misc.java +++ b/src/me/coley/recaf/util/Misc.java @@ -89,13 +89,15 @@ public static void writeFile(String path, String content) throws IOException { /** * Adds a path to a given parent node. Also updates the given model. - * - * @param parent - * @param dirPath - * @param cn - * Class - * @param model - * Model to add node to + * + * @param parent The parent node. + * @param dirPath TODO + * @param cn Class + * @param model Model to add node to + * + * TODO: document dirPath param; I'm not sure what it's for. + * + * - Charles */ public static ASMTreeNode generateTreePath(ASMTreeNode parent, List dirPath, ClassNode cn, DefaultTreeModel model) { ASMTreeNode ret = null; @@ -119,15 +121,13 @@ public static ASMTreeNode generateTreePath(ASMTreeNode parent, List dirP /** * Adds a path to a given parent node. Also updates the given model. - * - * @param parent - * @param dirPath - * @param cn - * Class - * @param mn - * Method in class - * @param model - * Model to add node to + * + * @param parent The parent node + * @param dirPath TODO + * + * TODO: document dirPath param; I'm not sure what it's for. + * + * - Charles */ public static ASMTreeNode getTreePath(ASMTreeNode parent, List dirPath) { ASMTreeNode node = parent; @@ -141,10 +141,10 @@ public static ASMTreeNode getTreePath(ASMTreeNode parent, List dirPath) /** * Get or create the tree node for the given class node from the given * model. - * - * @param model - * @param classNode - * @return + * + * @param model The default tree model to use. + * @param classNode The class node. + * @return The tree node. */ public static ASMTreeNode getOrCreateNode(DefaultTreeModel model, ClassNode classNode) { ASMTreeNode root = (ASMTreeNode) model.getRoot(); diff --git a/src/me/coley/recaf/util/StreamUtil.java b/src/me/coley/recaf/util/StreamUtil.java index 0979494f2..2b4a1defb 100644 --- a/src/me/coley/recaf/util/StreamUtil.java +++ b/src/me/coley/recaf/util/StreamUtil.java @@ -9,60 +9,55 @@ import java.util.stream.Stream; public class StreamUtil { - private final static int BUFF_SIZE = (int) Math.pow(128, 2); + private final static int BUFF_SIZE = (int) Math.pow(128, 2); - /** - * Creates a DataInputStream from byte[]. - * - * @param data - * byte[] to convert to DataInputStream. - * @return - * @throws Exception - */ - public static IndexableDataStream fromBytes(byte[] data) { - return new IndexableDataStream(data); - } + /** + * Creates a DataInputStream from byte[]. + * + * @param data byte[] to convert to DataInputStream. + * @return The data input stream. + */ + public static IndexableDataStream fromBytes(byte[] data) { + return new IndexableDataStream(data); + } - /** - * Reads the bytes from the inputstream into a byte array. - * - * @param is - * InputStream to read from. - * @return - * @throws IOException - * Thrown if the given input stream cannot be read from. - */ - public static byte[] fromStream(InputStream is) throws IOException { - try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { - int r; - byte[] data = new byte[BUFF_SIZE]; - while ((r = is.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, r); - } - buffer.flush(); - return buffer.toByteArray(); - } - } + /** + * Reads the bytes from the inputstream into a byte array. + * + * @param is InputStream to read from. + * @return byt earray representation of the input stream. + * @throws IOException Thrown if the given input stream cannot be read + * from. + */ + public static byte[] fromStream(InputStream is) throws IOException { + try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { + int r; + byte[] data = new byte[BUFF_SIZE]; + while ((r = is.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, r); + } + buffer.flush(); + return buffer.toByteArray(); + } + } - /** - * Sorts the stream of java names. - * - * @param stream - * Stream of names. - * @return - */ - public static Stream sortJavaNames(Stream stream) { - return stream.sorted(new JavaNameSorter()); - } + /** + * Sorts the stream of java names. + * + * @param stream Stream of names. + * @return The stream, sorted. + */ + public static Stream sortJavaNames(Stream stream) { + return stream.sorted(new JavaNameSorter()); + } - /** - * Creates a list of sorted java names from a given collection. - * - * @param names - * Collection of names. - * @return - */ - public static List listOfSortedJavaNames(Collection names) { - return sortJavaNames(names.stream()).collect(Collectors.toList()); - } + /** + * Creates a list of sorted java names from a given collection. + * + * @param names Collection of names. + * @return The collection, sorted and converted to a list. + */ + public static List listOfSortedJavaNames(Collection names) { + return sortJavaNames(names.stream()).collect(Collectors.toList()); + } } From 864ea1fcb506f09856b9cfe42b0511819867e12a Mon Sep 17 00:00:00 2001 From: Charles Daniels Date: Sat, 14 Oct 2017 16:30:21 -0400 Subject: [PATCH 3/6] Ran astyle on the entire Recaf codebase. This reduced the number of checkstyle warnings by about 400, and should provide a good starting point for ongoing code style and quality improvement. --- src/me/coley/recaf/Options.java | 200 ++--- src/me/coley/recaf/Recaf.java | 100 +-- src/me/coley/recaf/asm/Access.java | 76 +- src/me/coley/recaf/asm/AsmUtil.java | 198 ++--- src/me/coley/recaf/asm/JarData.java | 50 +- .../coley/recaf/asm/NonReflectionWriter.java | 172 ++-- src/me/coley/recaf/asm/OpcodeUtil.java | 811 +++++++++--------- src/me/coley/recaf/asm/PluginClassReader.java | 6 +- src/me/coley/recaf/cfr/CFRResourceLookup.java | 66 +- src/me/coley/recaf/cfr/CFRSetting.java | 166 ++-- src/me/coley/recaf/cfr/CFRSourceImpl.java | 44 +- src/me/coley/recaf/ui/FileChoosers.java | 90 +- src/me/coley/recaf/ui/FontUtil.java | 56 +- src/me/coley/recaf/ui/Gui.java | 422 ++++----- src/me/coley/recaf/ui/HtmlRenderer.java | 200 ++--- src/me/coley/recaf/ui/Icons.java | 122 +-- .../recaf/ui/component/LabeledComponent.java | 14 +- .../recaf/ui/component/ReleaseListener.java | 18 +- .../ui/component/action/ActionButton.java | 18 +- .../ui/component/action/ActionCheckBox.java | 18 +- .../ui/component/action/ActionMenuItem.java | 24 +- .../ui/component/action/ActionTextField.java | 46 +- .../ui/component/internalframe/AccessBox.java | 36 +- .../component/internalframe/BasicFrame.java | 38 +- .../component/internalframe/DecompileBox.java | 14 +- .../internalframe/DefaultValueBox.java | 14 +- .../ui/component/internalframe/EditBox.java | 62 +- .../internalframe/ExceptionsListBox.java | 74 +- .../internalframe/MemberDefinitionBox.java | 84 +- .../internalframe/OpcodeCreationBox.java | 522 +++++------ .../internalframe/OpcodeListBox.java | 20 +- .../component/internalframe/TryCatchBox.java | 116 +-- .../list/MemberNodeClickListener.java | 382 ++++----- .../ui/component/list/MemberNodeRenderer.java | 204 ++--- .../ui/component/list/OpcodeCellRenderer.java | 490 ++++++----- .../ui/component/list/OpcodeKeyListener.java | 66 +- .../recaf/ui/component/list/OpcodeList.java | 260 +++--- .../component/list/OpcodeMouseListener.java | 446 +++++----- .../list/OpcodeSelectionListener.java | 180 ++-- .../recaf/ui/component/panel/AccessPanel.java | 182 ++-- .../ui/component/panel/AsmFlagsPanel.java | 92 +- .../ui/component/panel/ClassDisplayPanel.java | 288 +++---- .../ui/component/panel/DecompilePanel.java | 140 +-- .../component/panel/LabelSwitcherPanel.java | 126 +-- .../panel/OpcodeTypeSwitchPanel.java | 344 ++++---- .../recaf/ui/component/panel/SearchPanel.java | 396 ++++----- .../recaf/ui/component/panel/TabbedPanel.java | 206 ++--- .../component/panel/TagTypeSwitchPanel.java | 158 ++-- .../recaf/ui/component/table/MemberTable.java | 128 +-- .../ui/component/table/VariableTable.java | 218 ++--- .../ui/component/tree/ASMFieldTreeNode.java | 18 +- .../ui/component/tree/ASMInsnTreeNode.java | 18 +- .../ui/component/tree/ASMMethodTreeNode.java | 18 +- .../recaf/ui/component/tree/ASMTreeNode.java | 32 +- .../recaf/ui/component/tree/JarFileTree.java | 82 +- .../ui/component/tree/JavaTreeListener.java | 94 +- .../ui/component/tree/JavaTreeRenderer.java | 130 +-- src/me/coley/recaf/util/JavaNameSorter.java | 42 +- src/me/coley/recaf/util/Misc.java | 268 +++--- src/me/coley/recaf/util/StreamUtil.java | 94 +- 60 files changed, 4540 insertions(+), 4459 deletions(-) diff --git a/src/me/coley/recaf/Options.java b/src/me/coley/recaf/Options.java index 595bbe8f9..179467f33 100644 --- a/src/me/coley/recaf/Options.java +++ b/src/me/coley/recaf/Options.java @@ -14,108 +14,108 @@ import me.coley.recaf.util.Misc; public class Options { - /** - * File to store config in. - */ - private final static File optionsFile = new File("rcoptions.json"); - /** - * Show confirmation prompt on doing potentially dangerous things. - */ - public boolean confirmDeletions = true; - /** - * Show extra jump information. - */ - public boolean opcodeShowJumpHelp = true; - /** - * Simplify descriptor displays on the opcode list. - */ - public boolean opcodeSimplifyDescriptors = true; - /** - * Display variable's signature in the opcode edit window for variable - * opcodes. Allows editing of signatures (Generic types) and - * significantly increases the edit window size. - */ - public boolean showVariableSignatureInTable; - /** - * Flags for reading in classes. - */ - public int classFlagsInput = ClassReader.EXPAND_FRAMES; - /** - * Flags for writing classes. - */ - public int classFlagsOutput = ClassWriter.COMPUTE_FRAMES; - /** - * Max length for text in ldc opcodes to be displayed. - */ - public int ldcMaxLength = 125; + /** + * File to store config in. + */ + private final static File optionsFile = new File("rcoptions.json"); + /** + * Show confirmation prompt on doing potentially dangerous things. + */ + public boolean confirmDeletions = true; + /** + * Show extra jump information. + */ + public boolean opcodeShowJumpHelp = true; + /** + * Simplify descriptor displays on the opcode list. + */ + public boolean opcodeSimplifyDescriptors = true; + /** + * Display variable's signature in the opcode edit window for variable + * opcodes. Allows editing of signatures (Generic types) and + * significantly increases the edit window size. + */ + public boolean showVariableSignatureInTable; + /** + * Flags for reading in classes. + */ + public int classFlagsInput = ClassReader.EXPAND_FRAMES; + /** + * Flags for writing classes. + */ + public int classFlagsOutput = ClassWriter.COMPUTE_FRAMES; + /** + * Max length for text in ldc opcodes to be displayed. + */ + public int ldcMaxLength = 125; - public Options() { - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - save(); - } - }); - } + public Options() { + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + save(); + } + }); + } - /** - * Load from configuration. - */ - public void load() { - if (!optionsFile.exists()) { - return; - } - try { - JsonObject json = Json.parse(Misc.readFile(optionsFile.getAbsolutePath())).asObject(); - for (Field field : Options.class.getDeclaredFields()) { - String name = field.getName(); - JsonValue value = json.get(name); - if (value == null) { - continue; - } - field.setAccessible(true); - if (value.isBoolean()) { - field.set(this, value.asBoolean()); - } else if (value.isNumber()) { - field.set(this, value.asInt()); - } else if (value.isString()) { - field.set(this, value.asString()); - } - } - } catch (Exception e) { - // TODO: Propper logging - e.printStackTrace(); - } - } + /** + * Load from configuration. + */ + public void load() { + if (!optionsFile.exists()) { + return; + } + try { + JsonObject json = Json.parse(Misc.readFile(optionsFile.getAbsolutePath())).asObject(); + for (Field field : Options.class.getDeclaredFields()) { + String name = field.getName(); + JsonValue value = json.get(name); + if (value == null) { + continue; + } + field.setAccessible(true); + if (value.isBoolean()) { + field.set(this, value.asBoolean()); + } else if (value.isNumber()) { + field.set(this, value.asInt()); + } else if (value.isString()) { + field.set(this, value.asString()); + } + } + } catch (Exception e) { + // TODO: Propper logging + e.printStackTrace(); + } + } - /** - * Save current settings to configuration. - */ - public void save() { - try { - if (!optionsFile.exists()) { - optionsFile.createNewFile(); - } - JsonObject json = Json.object(); - for (Field field : Options.class.getDeclaredFields()) { - field.setAccessible(true); - String name = field.getName(); - Object value = field.get(this); - if (value instanceof Boolean) { - json.set(name, (boolean) value); - } else if (value instanceof Integer) { - json.set(name, (int) value); - } else if (value instanceof String) { - json.set(name, (String) value); - } - } - StringWriter w = new StringWriter(); - json.writeTo(w, WriterConfig.PRETTY_PRINT); - Misc.writeFile(optionsFile.getAbsolutePath(), w.toString()); - } catch (Exception e) { - // TODO: Propper logging - e.getMessage(); - } - } + /** + * Save current settings to configuration. + */ + public void save() { + try { + if (!optionsFile.exists()) { + optionsFile.createNewFile(); + } + JsonObject json = Json.object(); + for (Field field : Options.class.getDeclaredFields()) { + field.setAccessible(true); + String name = field.getName(); + Object value = field.get(this); + if (value instanceof Boolean) { + json.set(name, (boolean) value); + } else if (value instanceof Integer) { + json.set(name, (int) value); + } else if (value instanceof String) { + json.set(name, (String) value); + } + } + StringWriter w = new StringWriter(); + json.writeTo(w, WriterConfig.PRETTY_PRINT); + Misc.writeFile(optionsFile.getAbsolutePath(), w.toString()); + } catch (Exception e) { + // TODO: Propper logging + e.getMessage(); + } + } } diff --git a/src/me/coley/recaf/Recaf.java b/src/me/coley/recaf/Recaf.java index 71af8e847..7e464c735 100644 --- a/src/me/coley/recaf/Recaf.java +++ b/src/me/coley/recaf/Recaf.java @@ -14,62 +14,62 @@ import me.coley.recaf.ui.Gui; public class Recaf { - private static Recaf instance; - public Gui window; - public File currentJar; - public JarData jarData; - public FileChoosers fileChoosers; - public Options options; - public AsmUtil asm; + private static Recaf instance; + public Gui window; + public File currentJar; + public JarData jarData; + public FileChoosers fileChoosers; + public Options options; + public AsmUtil asm; - public Recaf() { - instance = this; - fileChoosers = new FileChoosers(); - options = new Options(); - options.load(); - asm = new AsmUtil(); - } + public Recaf() { + instance = this; + fileChoosers = new FileChoosers(); + options = new Options(); + options.load(); + asm = new AsmUtil(); + } - public void openFile(File file) throws IOException { - this.currentJar = file; - this.jarData = new JarData(file); - this.window.updateTree(); - this.window.getFrame().setTitle("Recaf: " + file.getName()); - } + public void openFile(File file) throws IOException { + this.currentJar = file; + this.jarData = new JarData(file); + this.window.updateTree(); + this.window.getFrame().setTitle("Recaf: " + file.getName()); + } - public void saveFile(File file) throws IOException { - this.jarData.save(file); - } + public void saveFile(File file) throws IOException { + this.jarData.save(file); + } - public void selectClass(ClassNode node) { - this.window.addClassView(node); - } + public void selectClass(ClassNode node) { + this.window.addClassView(node); + } - public void showGui() { - EventQueue.invokeLater(new Runnable() { - public void run() { - try { - window = new Gui(); - window.getFrame().setVisible(true); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } + public void showGui() { + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + window = new Gui(); + window.getFrame().setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } - public static Recaf getInstance() { - return instance; - } + public static Recaf getInstance() { + return instance; + } - public static void main(String[] args) { - try { - UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); - } catch (Exception e) { - e.printStackTrace(); - } - Recaf program = new Recaf(); - program.showGui(); + public static void main(String[] args) { + try { + UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); + } catch (Exception e) { + e.printStackTrace(); + } + Recaf program = new Recaf(); + program.showGui(); - } + } } diff --git a/src/me/coley/recaf/asm/Access.java b/src/me/coley/recaf/asm/Access.java index 7fc14d993..84dde6c03 100644 --- a/src/me/coley/recaf/asm/Access.java +++ b/src/me/coley/recaf/asm/Access.java @@ -2,7 +2,7 @@ /** * A utility for checking and generating object access. - * + * * @author Matt */ public class Access { @@ -36,7 +36,7 @@ public class Access { ABSTRACT | STRICT; public static final int INTERFACE_MODIFIERS = PUBLIC | PROTECTED | PRIVATE | - ABSTRACT | STATIC | STRICT | + ABSTRACT | STATIC | STRICT | SYNTHETIC; public static final int CONSTRUCTOR_MODIFIERS = PUBLIC | PROTECTED | PRIVATE | @@ -51,24 +51,60 @@ public class Access { STATIC | TRANSIENT | FINAL | VOLATILE | SYNTHETIC; // Access checking - public static boolean isAbstract(int acc){return(acc & ABSTRACT)!=0;} - public static boolean isAnnotation(int acc){return(acc & ANNOTATION)!=0;} - public static boolean isBridge(int acc){return(acc & BRIDGE)!=0;} - public static boolean isEnum(int acc){return(acc & ENUM)!=0;} - public static boolean isFinal(int acc){return(acc & FINAL)!=0;} - public static boolean isInterface(int acc){return(acc & INTERFACE)!=0;} - public static boolean isNative(int acc){return(acc & NATIVE)!=0;} - public static boolean isPrivate(int acc){return(acc & PRIVATE)!=0;} - public static boolean isProtected(int acc){return(acc & PROTECTED)!=0;} - public static boolean isPublic(int acc){return(acc & PUBLIC)!=0;} - public static boolean isStatic(int acc){return(acc & STATIC)!=0;} - public static boolean isStrict(int acc){return(acc & STRICT)!=0;} - public static boolean isSuper(int acc){return(acc & SUPER)!=0;} - public static boolean isSynchronized(int acc){return(acc & SYNCHRONIZED)!=0;} - public static boolean isSynthetic(int acc){return(acc & SYNTHETIC)!=0;} - public static boolean isTransient(int acc){return(acc & TRANSIENT)!=0;} - public static boolean isVarargs(int acc){return(acc & VARARGS)!=0;} - public static boolean isVolatile(int acc){return(acc & VOLATILE)!=0;} + public static boolean isAbstract(int acc) { + return(acc & ABSTRACT)!=0; + } + public static boolean isAnnotation(int acc) { + return(acc & ANNOTATION)!=0; + } + public static boolean isBridge(int acc) { + return(acc & BRIDGE)!=0; + } + public static boolean isEnum(int acc) { + return(acc & ENUM)!=0; + } + public static boolean isFinal(int acc) { + return(acc & FINAL)!=0; + } + public static boolean isInterface(int acc) { + return(acc & INTERFACE)!=0; + } + public static boolean isNative(int acc) { + return(acc & NATIVE)!=0; + } + public static boolean isPrivate(int acc) { + return(acc & PRIVATE)!=0; + } + public static boolean isProtected(int acc) { + return(acc & PROTECTED)!=0; + } + public static boolean isPublic(int acc) { + return(acc & PUBLIC)!=0; + } + public static boolean isStatic(int acc) { + return(acc & STATIC)!=0; + } + public static boolean isStrict(int acc) { + return(acc & STRICT)!=0; + } + public static boolean isSuper(int acc) { + return(acc & SUPER)!=0; + } + public static boolean isSynchronized(int acc) { + return(acc & SYNCHRONIZED)!=0; + } + public static boolean isSynthetic(int acc) { + return(acc & SYNTHETIC)!=0; + } + public static boolean isTransient(int acc) { + return(acc & TRANSIENT)!=0; + } + public static boolean isVarargs(int acc) { + return(acc & VARARGS)!=0; + } + public static boolean isVolatile(int acc) { + return(acc & VOLATILE)!=0; + } // Access creation public static int createAccess(int... acArgs) { int access = 0; diff --git a/src/me/coley/recaf/asm/AsmUtil.java b/src/me/coley/recaf/asm/AsmUtil.java index 2cfda2dc4..cc9f9c776 100644 --- a/src/me/coley/recaf/asm/AsmUtil.java +++ b/src/me/coley/recaf/asm/AsmUtil.java @@ -16,108 +16,108 @@ import me.coley.recaf.util.StreamUtil; public class AsmUtil { - private final Recaf recaf = Recaf.getInstance(); + private final Recaf recaf = Recaf.getInstance(); - /** - * Reads the classes of the given jar into a map. - * - * @param jarPath Path to jarfile to read classes from. - * @return Map of classes from the specified jarfile. - * @throws IOException If an error was encountered while reading the - * jarfile. - */ - public Map readClasses(String jarPath) throws IOException { - Map map = new HashMap<>(); - try (ZipFile file = new ZipFile(jarPath)) { - Enumeration entries = file.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if (entry.isDirectory() || !entry.getName().endsWith(".class")) { - continue; - } - String name = null; - try (InputStream is = file.getInputStream(entry)) { - ClassReader cr = new PluginClassReader(is); - name = cr.getClassName(); - map.put(cr.getClassName(), getNode(cr)); - } catch (IndexOutOfBoundsException ioobe) { - if (name == null) { - recaf.window.displayError(new RuntimeException("Failed reading class from: " + entry.getName(), - ioobe)); - } else { - recaf.window.displayError(new RuntimeException("Failed reading into node structure: " + name, ioobe)); - } - } - } - } - return map; - } + /** + * Reads the classes of the given jar into a map. + * + * @param jarPath Path to jarfile to read classes from. + * @return Map of classes from the specified jarfile. + * @throws IOException If an error was encountered while reading the + * jarfile. + */ + public Map readClasses(String jarPath) throws IOException { + Map map = new HashMap<>(); + try (ZipFile file = new ZipFile(jarPath)) { + Enumeration entries = file.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (entry.isDirectory() || !entry.getName().endsWith(".class")) { + continue; + } + String name = null; + try (InputStream is = file.getInputStream(entry)) { + ClassReader cr = new PluginClassReader(is); + name = cr.getClassName(); + map.put(cr.getClassName(), getNode(cr)); + } catch (IndexOutOfBoundsException ioobe) { + if (name == null) { + recaf.window.displayError(new RuntimeException("Failed reading class from: " + entry.getName(), + ioobe)); + } else { + recaf.window.displayError(new RuntimeException("Failed reading into node structure: " + name, ioobe)); + } + } + } + } + return map; + } - /** - * Reads non-classes from the given jar. - * - * @param jarPath Path to jarfile to read non-classes from. - * @return Map of non-classes from the specified jarfile. - * @throws IOException If an error was encountered while reading the - * jarfile. - */ - public Map readNonClasses(String jarPath) throws IOException { - Map map = new HashMap<>(); - try (ZipFile file = new ZipFile(jarPath)) { - Enumeration entries = file.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if (entry.isDirectory() || entry.getName().contains(".class")) { - continue; - } - try (InputStream is = file.getInputStream(entry)) { - map.put(entry.getName(), StreamUtil.fromStream(is)); - } - } - } - return map; - } + /** + * Reads non-classes from the given jar. + * + * @param jarPath Path to jarfile to read non-classes from. + * @return Map of non-classes from the specified jarfile. + * @throws IOException If an error was encountered while reading the + * jarfile. + */ + public Map readNonClasses(String jarPath) throws IOException { + Map map = new HashMap<>(); + try (ZipFile file = new ZipFile(jarPath)) { + Enumeration entries = file.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (entry.isDirectory() || entry.getName().contains(".class")) { + continue; + } + try (InputStream is = file.getInputStream(entry)) { + map.put(entry.getName(), StreamUtil.fromStream(is)); + } + } + } + return map; + } - /** - * Creates a ClassNode from the given ClassReader. - * - * @param cr The class read to obtain the node from. - * @return The node obtained from cr. - */ - private ClassNode getNode(ClassReader cr) { - ClassNode cn = new ClassNode(); - cr.accept(cn, recaf.options.classFlagsInput); - return cn; - } + /** + * Creates a ClassNode from the given ClassReader. + * + * @param cr The class read to obtain the node from. + * @return The node obtained from cr. + */ + private ClassNode getNode(ClassReader cr) { + ClassNode cn = new ClassNode(); + cr.accept(cn, recaf.options.classFlagsInput); + return cn; + } - /** - * Creates a ClassNode from the given class. - * - * @param c The target class. - * @return Node generated from c. - * @throws IOException If an error occurs while loading the class. - */ - public ClassNode getNode(Class c) throws IOException { - String name = c.getName(); - String path = name.replace('.', '/') + ".class"; - ClassLoader loader = c.getClassLoader(); - if (loader == null) { - loader = ClassLoader.getSystemClassLoader(); - } - InputStream is = loader.getResourceAsStream(path); - ClassReader cr = new ClassReader(is); - return getNode(cr); - } + /** + * Creates a ClassNode from the given class. + * + * @param c The target class. + * @return Node generated from c. + * @throws IOException If an error occurs while loading the class. + */ + public ClassNode getNode(Class c) throws IOException { + String name = c.getName(); + String path = name.replace('.', '/') + ".class"; + ClassLoader loader = c.getClassLoader(); + if (loader == null) { + loader = ClassLoader.getSystemClassLoader(); + } + InputStream is = loader.getResourceAsStream(path); + ClassReader cr = new ClassReader(is); + return getNode(cr); + } - /** - * Writes a ClassNode to a byte array. - * - * @param cn The target class node. - * @return ByteArray representation of cn. - */ - public byte[] toBytes(ClassNode cn) { - ClassWriter cw = new NonReflectionWriter(recaf.options.classFlagsOutput); - cn.accept(cw); - return cw.toByteArray(); - } + /** + * Writes a ClassNode to a byte array. + * + * @param cn The target class node. + * @return ByteArray representation of cn. + */ + public byte[] toBytes(ClassNode cn) { + ClassWriter cw = new NonReflectionWriter(recaf.options.classFlagsOutput); + cn.accept(cw); + return cw.toByteArray(); + } } diff --git a/src/me/coley/recaf/asm/JarData.java b/src/me/coley/recaf/asm/JarData.java index 1e5f1e626..66f299343 100644 --- a/src/me/coley/recaf/asm/JarData.java +++ b/src/me/coley/recaf/asm/JarData.java @@ -12,31 +12,31 @@ import me.coley.recaf.Recaf; public class JarData { - private final Recaf recaf = Recaf.getInstance(); - public final Map classes; - public final Map resources; + private final Recaf recaf = Recaf.getInstance(); + public final Map classes; + public final Map resources; - public JarData(File jar) throws IOException { - String path = jar.getAbsolutePath(); - classes = recaf.asm.readClasses(path); - resources = recaf.asm.readNonClasses(path); - } + public JarData(File jar) throws IOException { + String path = jar.getAbsolutePath(); + classes = recaf.asm.readClasses(path); + resources = recaf.asm.readNonClasses(path); + } - public void save(File jar) throws IOException { - try (JarOutputStream output = new JarOutputStream(new FileOutputStream(jar))) { - // write classes - for (String name : classes.keySet()) { - byte[] data = recaf.asm.toBytes(classes.get(name)); - output.putNextEntry(new JarEntry(name.replace(".", "/") + ".class")); - output.write(data); - output.closeEntry(); - } - // write resources - for (String name : resources.keySet()) { - output.putNextEntry(new JarEntry(name)); - output.write(resources.get(name)); - output.closeEntry(); - } - } - } + public void save(File jar) throws IOException { + try (JarOutputStream output = new JarOutputStream(new FileOutputStream(jar))) { + // write classes + for (String name : classes.keySet()) { + byte[] data = recaf.asm.toBytes(classes.get(name)); + output.putNextEntry(new JarEntry(name.replace(".", "/") + ".class")); + output.write(data); + output.closeEntry(); + } + // write resources + for (String name : resources.keySet()) { + output.putNextEntry(new JarEntry(name)); + output.write(resources.get(name)); + output.closeEntry(); + } + } + } } diff --git a/src/me/coley/recaf/asm/NonReflectionWriter.java b/src/me/coley/recaf/asm/NonReflectionWriter.java index 616621f45..ff1fdf108 100644 --- a/src/me/coley/recaf/asm/NonReflectionWriter.java +++ b/src/me/coley/recaf/asm/NonReflectionWriter.java @@ -13,95 +13,95 @@ * classpath for determining the common super-class. */ public class NonReflectionWriter extends ClassWriter { - private static final String DEFAULT_PARENT = "java/lang/Object"; - private final Recaf recaf = Recaf.getInstance(); - private final Map nodes; + private static final String DEFAULT_PARENT = "java/lang/Object"; + private final Recaf recaf = Recaf.getInstance(); + private final Map nodes; - public NonReflectionWriter(int flags) { - super(flags); - this.nodes = recaf.jarData.classes; - } + public NonReflectionWriter(int flags) { + super(flags); + this.nodes = recaf.jarData.classes; + } - @Override - protected String getCommonSuperClass(String type1, String type2) { - if (type1 == null || type2 == null) { - return DEFAULT_PARENT; - } - ClassNode node1 = loadNode(type1); - ClassNode node2 = loadNode(type2); - if (node1 == null || node2 == null) { - return DEFAULT_PARENT; - } else if (isAssignableFrom(node1, node2)) { - return type1; - } else if (isAssignableFrom(node2, node1)) { - return type2; - } - do { - node1 = loadNode(node1.superName); - if (node1 == null) { - if (node2.name.equals(type1)) { - return DEFAULT_PARENT; - } - node1 = loadNode(type2); - node2 = loadNode(type1); - } else if (isAssignableFrom(node1, node2)) { - return type1; - } else if (isAssignableFrom(node2, node1)) { - return type2; - } - } while (!isAssignableFrom(node1, node2)); - return DEFAULT_PARENT; - } + @Override + protected String getCommonSuperClass(String type1, String type2) { + if (type1 == null || type2 == null) { + return DEFAULT_PARENT; + } + ClassNode node1 = loadNode(type1); + ClassNode node2 = loadNode(type2); + if (node1 == null || node2 == null) { + return DEFAULT_PARENT; + } else if (isAssignableFrom(node1, node2)) { + return type1; + } else if (isAssignableFrom(node2, node1)) { + return type2; + } + do { + node1 = loadNode(node1.superName); + if (node1 == null) { + if (node2.name.equals(type1)) { + return DEFAULT_PARENT; + } + node1 = loadNode(type2); + node2 = loadNode(type1); + } else if (isAssignableFrom(node1, node2)) { + return type1; + } else if (isAssignableFrom(node2, node1)) { + return type2; + } + } while (!isAssignableFrom(node1, node2)); + return DEFAULT_PARENT; + } - /** - * Checks if the given parent is a superclass or superinterface of the given - * child. - * - * @param parent - * @param child - * @return - */ - private boolean isAssignableFrom(ClassNode parent, ClassNode child) { - while (child.superName != null) { - if (parent.name.equals(child.name) || child.interfaces.contains(parent.name)) { - return true; - } - for (String interfac : child.interfaces) { - if (isAssignableFrom(parent, loadNode(interfac))) { - return true; - } - } - child = loadNode(child.superName); - } - return false; - } + /** + * Checks if the given parent is a superclass or superinterface of the given + * child. + * + * @param parent + * @param child + * @return + */ + private boolean isAssignableFrom(ClassNode parent, ClassNode child) { + while (child.superName != null) { + if (parent.name.equals(child.name) || child.interfaces.contains(parent.name)) { + return true; + } + for (String interfac : child.interfaces) { + if (isAssignableFrom(parent, loadNode(interfac))) { + return true; + } + } + child = loadNode(child.superName); + } + return false; + } - /** - * Load node from the node map. - * - * @param type - * @return - */ - private ClassNode loadNode(String type) { - // Try loading from node list - if (type == null) { - return null; - } else if (nodes.containsKey(type)) { - return nodes.get(type); - } - // Try loading from runtime - String nameStr = type.replace("/", "."); - try { - Class clazz = Class.forName(nameStr); - if (clazz == null) { - return null; - } - return recaf.asm.getNode(clazz); - } catch (IOException e) { - return null; - } catch (ClassNotFoundException e) { - return null; - } - } + /** + * Load node from the node map. + * + * @param type + * @return + */ + private ClassNode loadNode(String type) { + // Try loading from node list + if (type == null) { + return null; + } else if (nodes.containsKey(type)) { + return nodes.get(type); + } + // Try loading from runtime + String nameStr = type.replace("/", "."); + try { + Class clazz = Class.forName(nameStr); + if (clazz == null) { + return null; + } + return recaf.asm.getNode(clazz); + } catch (IOException e) { + return null; + } catch (ClassNotFoundException e) { + return null; + } + } } \ No newline at end of file diff --git a/src/me/coley/recaf/asm/OpcodeUtil.java b/src/me/coley/recaf/asm/OpcodeUtil.java index 542fb21e8..cf327017f 100644 --- a/src/me/coley/recaf/asm/OpcodeUtil.java +++ b/src/me/coley/recaf/asm/OpcodeUtil.java @@ -7,418 +7,427 @@ import org.objectweb.asm.tree.AbstractInsnNode; public class OpcodeUtil implements Opcodes { - private static Map opcodeToName = new HashMap<>(); - private static Map nameToOpcode = new HashMap<>(); - private static Map frameToName = new HashMap<>(); - private static Map nameToFrame = new HashMap<>(); - private static Map tagToName = new HashMap<>(); - private static Map nameToTag = new HashMap<>(); - private static Map insnTypeToCodes = new HashMap<>(); - /** - * Opcodes of INSN type. - */ - public static String[] OPS_INSN = new String[] { "NOP", "ACONST_NULL", "ICONST_M1", "ICONST_0", "ICONST_1", "ICONST_2", - "ICONST_3", "ICONST_4", "ICONST_5", "LCONST_0", "LCONST_1", "FCONST_0", "FCONST_1", "FCONST_2", "DCONST_0", - "DCONST_1", "IALOAD", "LALOAD", "FALOAD", "DALOAD", "AALOAD", "BALOAD", "CALOAD", "SALOAD", "IASTORE", "LASTORE", - "FASTORE", "DASTORE", "AASTORE", "BASTORE", "CASTORE", "SASTORE", "POP", "POP2", "DUP", "DUP_X1", "DUP_X2", "DUP2", - "DUP2_X1", "DUP2_X2", "SWAP", "IADD", "LADD", "FADD", "DADD", "ISUB", "LSUB", "FSUB", "DSUB", "IMUL", "LMUL", "FMUL", - "DMUL", "IDIV", "LDIV", "FDIV", "DDIV", "IREM", "LREM", "FREM", "DREM", "INEG", "LNEG", "FNEG", "DNEG", "ISHL", - "LSHL", "ISHR", "LSHR", "IUSHR", "LUSHR", "IAND", "LAND", "IOR", "LOR", "IXOR", "LXOR", "I2L", "I2F", "I2D", "L2I", - "L2F", "L2D", "F2I", "F2L", "F2D", "D2I", "D2L", "D2F", "I2B", "I2C", "I2S", "LCMP", "FCMPL", "FCMPG", "DCMPL", - "DCMPG", "IRETURN", "LRETURN", "FRETURN", "DRETURN", "ARETURN", "RETURN", "ARRAYLENGTH", "ATHROW", "MONITORENTER", - "MONITOREXIT" }; - /** - * Subset of {@link #OPS_INSN} for constants. - */ - public static String[] OPS_INSN_SUB_CONSTS = new String[] { "ACONST_NULL", "ICONST_M1", "ICONST_0", "ICONST_1", "ICONST_2", - "ICONST_3", "ICONST_4", "ICONST_5", "LCONST_0", "LCONST_1", "FCONST_0", "FCONST_1", "FCONST_2", "DCONST_0", - "DCONST_1" }; - /** - * Subset of {@link #OPS_INSN} for array loads/saves/etc. - */ - public static String[] OPS_INSN_SUB_ARRAY = new String[] { "IALOAD", "LALOAD", "FALOAD", "DALOAD", "AALOAD", "BALOAD", - "CALOAD", "SALOAD", "IASTORE", "LASTORE", "FASTORE", "DASTORE", "AASTORE", "BASTORE", "CASTORE", "SASTORE", - "ARRAYLENGTH" }; - /** - * Subset of {@link #OPS_INSN} for stack management. - */ - public static String[] OPS_INSN_SUB_STACK = new String[] { "POP", "POP2", "DUP", "DUP_X1", "DUP_X2", "DUP2", "DUP2_X1", - "DUP2_X2", "SWAP" }; - /** - * Subset of {@link #OPS_INSN} for math handling. - */ - public static String[] OPS_INSN_SUB_MATH = new String[] { "IADD", "LADD", "FADD", "DADD", "ISUB", "LSUB", "FSUB", "DSUB", - "IMUL", "LMUL", "FMUL", "DMUL", "IDIV", "LDIV", "FDIV", "DDIV", "IREM", "LREM", "FREM", "DREM", "INEG", "LNEG", - "FNEG", "DNEG", "ISHL", "LSHL", "ISHR", "LSHR", "IUSHR", "LUSHR", "IAND", "LAND", "IOR", "LOR", "IXOR" }; - /** - * Subset of {@link #OPS_INSN} for type conversion. - */ - public static String[] OPS_INSN_SUB_CONVERT = new String[] { "I2L", "I2F", "I2D", "L2I", "L2F", "L2D", "F2I", "F2L", "F2D", - "D2I", "D2L", "D2F", "I2B", "I2C", "I2S" }; - /** - * Subset of {@link #OPS_INSN} for primitve comparisons. - */ - public static String[] OPS_INSN_SUB_COMPARE = new String[] { "LCMP", "FCMPL", "FCMPG", "DCMPL", "DCMPG" }; - /** - * Subset of {@link #OPS_INSN} for returns. - */ - public static String[] OPS_INSN_SUB_RETURN = new String[] { "IRETURN", "LRETURN", "FRETURN", "DRETURN", "ARETURN", "RETURN" }; - /** - * Subset of {@link #OPS_INSN} for monitors. - */ - public static String[] OPS_INSN_SUB_MONITOR = new String[] { "MONITORENTER", "MONITOREXIT" }; - /** - * Subset of {@link #OPS_INSN} for exceptions. - */ - public static String[] OPS_INSN_SUB_EXCEPTION = new String[] { "ATHROW" }; - /** - * Opcodes of INT type. - */ - public static String[] OPS_INT = new String[] { "BIPUSH", "SIPUSH", "NEWARRAY" }; - /** - * Opcodes of INT type. - */ - public static String[] OPS_VAR = new String[] { "ILOAD", "LLOAD", "FLOAD", "DLOAD", "ALOAD", "ISTORE", "LSTORE", "FSTORE", - "DSTORE", "ASTORE", "RET" }; - /** - * Opcodes of TYPE type. - */ - public static String[] OPS_TYPE = new String[] { "NEW", "ANEWARRAY", "CHECKCAST", "INSTANCEOF" }; - /** - * Opcodes of FIELD type. - */ - public static String[] OPS_FIELD = new String[] { "GETSTATIC", "PUTSTATIC", "GETFIELD", "PUTFIELD" }; - /** - * Opcodes of METHOD type. - */ - public static String[] OPS_METHOD = new String[] { "INVOKEVIRTUAL", "INVOKESPECIAL", "INVOKESTATIC", "INVOKEINTERFACE" }; - /** - * Opcodes of INDY_METHOD type. - */ - public static String[] OPS_INDY_METHOD = new String[] { "INVOKEDYNAMIC" }; - /** - * Opcodes of JUMP type. - */ - public static String[] OPS_JUMP = new String[] { "IFEQ", "IFNE", "IFLT", "IFGE", "IFGT", "IFLE", "IF_ICMPEQ", "IF_ICMPNE", - "IF_ICMPLT", "IF_ICMPGE", "IF_ICMPGT", "IF_ICMPLE", "IF_ACMPEQ", "IF_ACMPNE", "GOTO", "JSR", "IFNULL", "IFNONNULL" }; - /** - * Opcodes of LDC type. - */ - public static String[] OPS_LDC = new String[] { "LDC" }; - /** - * Opcodes of IINC type. - */ - public static String[] OPS_IINC = new String[] { "IINC" }; - /** - * Opcodes of TABLESWITCH type. - */ - public static String[] OPS_TABLESWITCH = new String[] { "TABLESWITCH" }; - /** - * Opcodes of LOOKUPSWITCH type. - */ - public static String[] OPS_LOOKUPSWITCH = new String[] { "LOOKUPSWITCH" }; - /** - * Opcodes of LOOKUPSWITCH type. - */ - public static String[] OPS_MULTIANEWARRAY = new String[] { "MULTIANEWARRAY" }; - /** - * Opcodes of FRAME type. - */ - public static String[] OPS_FRAME = new String[] { "F_NEW", "F_FULL", "F_APPEND", "F_CHOP", "F_SAME", "F_APPEND", "F_SAME1" }; - /** - * Empty list. - */ - public static String[] OPS_TAG = new String[] { "H_GETFIELD", "H_GETSTATIC", "H_PUTFIELD", "H_PUTSTATIC", "H_INVOKEINTERFACE", - "H_INVOKESPECIAL", "H_INVOKESTATIC", "H_INVOKEVIRTUAL", "H_NEWINVOKESPECIAL" }; - /** - * Opcodes of LABEL type. Also see {@link #OPS_FRAME}[0]. - */ - public static String[] OPS_LABEL = new String[] { "F_NEW" }; - /** - * Opcodes of LABEL type. Also see {@link #OPS_FRAME}[0]. - */ - public static String[] OPS_LINE = new String[] { "F_NEW" }; - /** - * Empty list. - */ - public static String[] OPS_NONE = new String[] {}; + private static Map opcodeToName = new HashMap<>(); + private static Map nameToOpcode = new HashMap<>(); + private static Map frameToName = new HashMap<>(); + private static Map nameToFrame = new HashMap<>(); + private static Map tagToName = new HashMap<>(); + private static Map nameToTag = new HashMap<>(); + private static Map insnTypeToCodes = new HashMap<>(); + /** + * Opcodes of INSN type. + */ + public static String[] OPS_INSN = new String[] { "NOP", "ACONST_NULL", "ICONST_M1", "ICONST_0", "ICONST_1", "ICONST_2", + "ICONST_3", "ICONST_4", "ICONST_5", "LCONST_0", "LCONST_1", "FCONST_0", "FCONST_1", "FCONST_2", "DCONST_0", + "DCONST_1", "IALOAD", "LALOAD", "FALOAD", "DALOAD", "AALOAD", "BALOAD", "CALOAD", "SALOAD", "IASTORE", "LASTORE", + "FASTORE", "DASTORE", "AASTORE", "BASTORE", "CASTORE", "SASTORE", "POP", "POP2", "DUP", "DUP_X1", "DUP_X2", "DUP2", + "DUP2_X1", "DUP2_X2", "SWAP", "IADD", "LADD", "FADD", "DADD", "ISUB", "LSUB", "FSUB", "DSUB", "IMUL", "LMUL", "FMUL", + "DMUL", "IDIV", "LDIV", "FDIV", "DDIV", "IREM", "LREM", "FREM", "DREM", "INEG", "LNEG", "FNEG", "DNEG", "ISHL", + "LSHL", "ISHR", "LSHR", "IUSHR", "LUSHR", "IAND", "LAND", "IOR", "LOR", "IXOR", "LXOR", "I2L", "I2F", "I2D", "L2I", + "L2F", "L2D", "F2I", "F2L", "F2D", "D2I", "D2L", "D2F", "I2B", "I2C", "I2S", "LCMP", "FCMPL", "FCMPG", "DCMPL", + "DCMPG", "IRETURN", "LRETURN", "FRETURN", "DRETURN", "ARETURN", "RETURN", "ARRAYLENGTH", "ATHROW", "MONITORENTER", + "MONITOREXIT" + }; + /** + * Subset of {@link #OPS_INSN} for constants. + */ + public static String[] OPS_INSN_SUB_CONSTS = new String[] { "ACONST_NULL", "ICONST_M1", "ICONST_0", "ICONST_1", "ICONST_2", + "ICONST_3", "ICONST_4", "ICONST_5", "LCONST_0", "LCONST_1", "FCONST_0", "FCONST_1", "FCONST_2", "DCONST_0", + "DCONST_1" + }; + /** + * Subset of {@link #OPS_INSN} for array loads/saves/etc. + */ + public static String[] OPS_INSN_SUB_ARRAY = new String[] { "IALOAD", "LALOAD", "FALOAD", "DALOAD", "AALOAD", "BALOAD", + "CALOAD", "SALOAD", "IASTORE", "LASTORE", "FASTORE", "DASTORE", "AASTORE", "BASTORE", "CASTORE", "SASTORE", + "ARRAYLENGTH" + }; + /** + * Subset of {@link #OPS_INSN} for stack management. + */ + public static String[] OPS_INSN_SUB_STACK = new String[] { "POP", "POP2", "DUP", "DUP_X1", "DUP_X2", "DUP2", "DUP2_X1", + "DUP2_X2", "SWAP" + }; + /** + * Subset of {@link #OPS_INSN} for math handling. + */ + public static String[] OPS_INSN_SUB_MATH = new String[] { "IADD", "LADD", "FADD", "DADD", "ISUB", "LSUB", "FSUB", "DSUB", + "IMUL", "LMUL", "FMUL", "DMUL", "IDIV", "LDIV", "FDIV", "DDIV", "IREM", "LREM", "FREM", "DREM", "INEG", "LNEG", + "FNEG", "DNEG", "ISHL", "LSHL", "ISHR", "LSHR", "IUSHR", "LUSHR", "IAND", "LAND", "IOR", "LOR", "IXOR" + }; + /** + * Subset of {@link #OPS_INSN} for type conversion. + */ + public static String[] OPS_INSN_SUB_CONVERT = new String[] { "I2L", "I2F", "I2D", "L2I", "L2F", "L2D", "F2I", "F2L", "F2D", + "D2I", "D2L", "D2F", "I2B", "I2C", "I2S" + }; + /** + * Subset of {@link #OPS_INSN} for primitve comparisons. + */ + public static String[] OPS_INSN_SUB_COMPARE = new String[] { "LCMP", "FCMPL", "FCMPG", "DCMPL", "DCMPG" }; + /** + * Subset of {@link #OPS_INSN} for returns. + */ + public static String[] OPS_INSN_SUB_RETURN = new String[] { "IRETURN", "LRETURN", "FRETURN", "DRETURN", "ARETURN", "RETURN" }; + /** + * Subset of {@link #OPS_INSN} for monitors. + */ + public static String[] OPS_INSN_SUB_MONITOR = new String[] { "MONITORENTER", "MONITOREXIT" }; + /** + * Subset of {@link #OPS_INSN} for exceptions. + */ + public static String[] OPS_INSN_SUB_EXCEPTION = new String[] { "ATHROW" }; + /** + * Opcodes of INT type. + */ + public static String[] OPS_INT = new String[] { "BIPUSH", "SIPUSH", "NEWARRAY" }; + /** + * Opcodes of INT type. + */ + public static String[] OPS_VAR = new String[] { "ILOAD", "LLOAD", "FLOAD", "DLOAD", "ALOAD", "ISTORE", "LSTORE", "FSTORE", + "DSTORE", "ASTORE", "RET" + }; + /** + * Opcodes of TYPE type. + */ + public static String[] OPS_TYPE = new String[] { "NEW", "ANEWARRAY", "CHECKCAST", "INSTANCEOF" }; + /** + * Opcodes of FIELD type. + */ + public static String[] OPS_FIELD = new String[] { "GETSTATIC", "PUTSTATIC", "GETFIELD", "PUTFIELD" }; + /** + * Opcodes of METHOD type. + */ + public static String[] OPS_METHOD = new String[] { "INVOKEVIRTUAL", "INVOKESPECIAL", "INVOKESTATIC", "INVOKEINTERFACE" }; + /** + * Opcodes of INDY_METHOD type. + */ + public static String[] OPS_INDY_METHOD = new String[] { "INVOKEDYNAMIC" }; + /** + * Opcodes of JUMP type. + */ + public static String[] OPS_JUMP = new String[] { "IFEQ", "IFNE", "IFLT", "IFGE", "IFGT", "IFLE", "IF_ICMPEQ", "IF_ICMPNE", + "IF_ICMPLT", "IF_ICMPGE", "IF_ICMPGT", "IF_ICMPLE", "IF_ACMPEQ", "IF_ACMPNE", "GOTO", "JSR", "IFNULL", "IFNONNULL" + }; + /** + * Opcodes of LDC type. + */ + public static String[] OPS_LDC = new String[] { "LDC" }; + /** + * Opcodes of IINC type. + */ + public static String[] OPS_IINC = new String[] { "IINC" }; + /** + * Opcodes of TABLESWITCH type. + */ + public static String[] OPS_TABLESWITCH = new String[] { "TABLESWITCH" }; + /** + * Opcodes of LOOKUPSWITCH type. + */ + public static String[] OPS_LOOKUPSWITCH = new String[] { "LOOKUPSWITCH" }; + /** + * Opcodes of LOOKUPSWITCH type. + */ + public static String[] OPS_MULTIANEWARRAY = new String[] { "MULTIANEWARRAY" }; + /** + * Opcodes of FRAME type. + */ + public static String[] OPS_FRAME = new String[] { "F_NEW", "F_FULL", "F_APPEND", "F_CHOP", "F_SAME", "F_APPEND", "F_SAME1" }; + /** + * Empty list. + */ + public static String[] OPS_TAG = new String[] { "H_GETFIELD", "H_GETSTATIC", "H_PUTFIELD", "H_PUTSTATIC", "H_INVOKEINTERFACE", + "H_INVOKESPECIAL", "H_INVOKESTATIC", "H_INVOKEVIRTUAL", "H_NEWINVOKESPECIAL" + }; + /** + * Opcodes of LABEL type. Also see {@link #OPS_FRAME}[0]. + */ + public static String[] OPS_LABEL = new String[] { "F_NEW" }; + /** + * Opcodes of LABEL type. Also see {@link #OPS_FRAME}[0]. + */ + public static String[] OPS_LINE = new String[] { "F_NEW" }; + /** + * Empty list. + */ + public static String[] OPS_NONE = new String[] {}; - public static int nameToOpcode(String name) { - return nameToOpcode.get(name); - } + public static int nameToOpcode(String name) { + return nameToOpcode.get(name); + } - public static String opcodeToName(int op) { - return opcodeToName.get(op); - } + public static String opcodeToName(int op) { + return opcodeToName.get(op); + } - public static int nameToFrame(String name) { - return nameToFrame.get(name); - } + public static int nameToFrame(String name) { + return nameToFrame.get(name); + } - public static String frameToName(int op) { - return frameToName.get(op); - } + public static String frameToName(int op) { + return frameToName.get(op); + } - public static int nameToTag(String tag) { - return nameToTag.get(tag); - } + public static int nameToTag(String tag) { + return nameToTag.get(tag); + } - public static String tagToName(int tag) { - return tagToName.get(tag); - } + public static String tagToName(int tag) { + return tagToName.get(tag); + } - public static String[] typeToCodes(int type) { - return insnTypeToCodes.get(type); - } + public static String[] typeToCodes(int type) { + return insnTypeToCodes.get(type); + } - /** - * Return smaller subset of the {@link #OPS_INSN} string array. - * - * @param name The name of the target array. - * @return The desired subset. - * - * TODO: I have no idea what this is, just filling in some stubs - * so JavaDoc is happy. - * - * - Charles - */ - public static String[] getInsnSubset(String name) { - //@formatter:off - String[][] arrays = new String[][] { - OpcodeUtil.OPS_INSN_SUB_ARRAY, - OpcodeUtil.OPS_INSN_SUB_COMPARE, - OpcodeUtil.OPS_INSN_SUB_CONSTS, - OpcodeUtil.OPS_INSN_SUB_CONVERT, - OpcodeUtil.OPS_INSN_SUB_EXCEPTION, - OpcodeUtil.OPS_INSN_SUB_MATH, - OpcodeUtil.OPS_INSN_SUB_MONITOR, - OpcodeUtil.OPS_INSN_SUB_RETURN, - OpcodeUtil.OPS_INSN_SUB_STACK - }; - //@formatter:on - for (String[] array : arrays) { - if (contains(array, name)) { - return array; - } - } - // Just return an empty array - return OPS_NONE; - } + /** + * Return smaller subset of the {@link #OPS_INSN} string array. + * + * @param name The name of the target array. + * @return The desired subset. + * + * TODO: I have no idea what this is, just filling in some stubs + * so JavaDoc is happy. + * + * - Charles + */ + public static String[] getInsnSubset(String name) { + //@formatter:off + String[][] arrays = new String[][] { + OpcodeUtil.OPS_INSN_SUB_ARRAY, + OpcodeUtil.OPS_INSN_SUB_COMPARE, + OpcodeUtil.OPS_INSN_SUB_CONSTS, + OpcodeUtil.OPS_INSN_SUB_CONVERT, + OpcodeUtil.OPS_INSN_SUB_EXCEPTION, + OpcodeUtil.OPS_INSN_SUB_MATH, + OpcodeUtil.OPS_INSN_SUB_MONITOR, + OpcodeUtil.OPS_INSN_SUB_RETURN, + OpcodeUtil.OPS_INSN_SUB_STACK + }; + //@formatter:on + for (String[] array : arrays) { + if (contains(array, name)) { + return array; + } + } + // Just return an empty array + return OPS_NONE; + } - public static boolean contains(String[] array, String key) { - for (String value : array) { - if (value.equals(key)) { - return true; - } - } - return false; - } + public static boolean contains(String[] array, String key) { + for (String value : array) { + if (value.equals(key)) { + return true; + } + } + return false; + } - private static void put(int op, String text) { - nameToOpcode.put(text, op); - opcodeToName.put(op, text); - } + private static void put(int op, String text) { + nameToOpcode.put(text, op); + opcodeToName.put(op, text); + } - private static void putFrame(int op, String text) { - nameToFrame.put(text, op); - frameToName.put(op, text); - } + private static void putFrame(int op, String text) { + nameToFrame.put(text, op); + frameToName.put(op, text); + } - private static void putTag(int op, String text) { - nameToTag.put(text, op); - tagToName.put(op, text); - } + private static void putTag(int op, String text) { + nameToTag.put(text, op); + tagToName.put(op, text); + } - static { - put(F_NEW, "F_NEW"); - put(NOP, "NOP"); - put(ACONST_NULL, "ACONST_NULL"); - put(ICONST_M1, "ICONST_M1"); - put(ICONST_0, "ICONST_0"); - put(ICONST_1, "ICONST_1"); - put(ICONST_2, "ICONST_2"); - put(ICONST_3, "ICONST_3"); - put(ICONST_4, "ICONST_4"); - put(ICONST_5, "ICONST_5"); - put(LCONST_0, "LCONST_0"); - put(LCONST_1, "LCONST_1"); - put(FCONST_0, "FCONST_0"); - put(FCONST_1, "FCONST_1"); - put(FCONST_2, "FCONST_2"); - put(DCONST_0, "DCONST_0"); - put(DCONST_1, "DCONST_1"); - put(BIPUSH, "BIPUSH"); - put(SIPUSH, "SIPUSH"); - put(LDC, "LDC"); - put(ILOAD, "ILOAD"); - put(LLOAD, "LLOAD"); - put(FLOAD, "FLOAD"); - put(DLOAD, "DLOAD"); - put(ALOAD, "ALOAD"); - put(IALOAD, "IALOAD"); - put(LALOAD, "LALOAD"); - put(FALOAD, "FALOAD"); - put(DALOAD, "DALOAD"); - put(AALOAD, "AALOAD"); - put(BALOAD, "BALOAD"); - put(CALOAD, "CALOAD"); - put(SALOAD, "SALOAD"); - put(ISTORE, "ISTORE"); - put(LSTORE, "LSTORE"); - put(FSTORE, "FSTORE"); - put(DSTORE, "DSTORE"); - put(ASTORE, "ASTORE"); - put(IASTORE, "IASTORE"); - put(LASTORE, "LASTORE"); - put(FASTORE, "FASTORE"); - put(DASTORE, "DASTORE"); - put(AASTORE, "AASTORE"); - put(BASTORE, "BASTORE"); - put(CASTORE, "CASTORE"); - put(SASTORE, "SASTORE"); - put(POP, "POP"); - put(POP2, "POP2"); - put(DUP, "DUP"); - put(DUP_X1, "DUP_X1"); - put(DUP_X2, "DUP_X2"); - put(DUP2, "DUP2"); - put(DUP2_X1, "DUP2_X1"); - put(DUP2_X2, "DUP2_X2"); - put(SWAP, "SWAP"); - put(IADD, "IADD"); - put(LADD, "LADD"); - put(FADD, "FADD"); - put(DADD, "DADD"); - put(ISUB, "ISUB"); - put(LSUB, "LSUB"); - put(FSUB, "FSUB"); - put(DSUB, "DSUB"); - put(IMUL, "IMUL"); - put(LMUL, "LMUL"); - put(FMUL, "FMUL"); - put(DMUL, "DMUL"); - put(IDIV, "IDIV"); - put(LDIV, "LDIV"); - put(FDIV, "FDIV"); - put(DDIV, "DDIV"); - put(IREM, "IREM"); - put(LREM, "LREM"); - put(FREM, "FREM"); - put(DREM, "DREM"); - put(INEG, "INEG"); - put(LNEG, "LNEG"); - put(FNEG, "FNEG"); - put(DNEG, "DNEG"); - put(ISHL, "ISHL"); - put(LSHL, "LSHL"); - put(ISHR, "ISHR"); - put(LSHR, "LSHR"); - put(IUSHR, "IUSHR"); - put(LUSHR, "LUSHR"); - put(IAND, "IAND"); - put(LAND, "LAND"); - put(IOR, "IOR"); - put(LOR, "LOR"); - put(IXOR, "IXOR"); - put(LXOR, "LXOR"); - put(IINC, "IINC"); - put(I2L, "I2L"); - put(I2F, "I2F"); - put(I2D, "I2D"); - put(L2I, "L2I"); - put(L2F, "L2F"); - put(L2D, "L2D"); - put(F2I, "F2I"); - put(F2L, "F2L"); - put(F2D, "F2D"); - put(D2I, "D2I"); - put(D2L, "D2L"); - put(D2F, "D2F"); - put(I2B, "I2B"); - put(I2C, "I2C"); - put(I2S, "I2S"); - put(LCMP, "LCMP"); - put(FCMPL, "FCMPL"); - put(FCMPG, "FCMPG"); - put(DCMPL, "DCMPL"); - put(DCMPG, "DCMPG"); - put(IFEQ, "IFEQ"); - put(IFNE, "IFNE"); - put(IFLT, "IFLT"); - put(IFGE, "IFGE"); - put(IFGT, "IFGT"); - put(IFLE, "IFLE"); - put(IF_ICMPEQ, "IF_ICMPEQ"); - put(IF_ICMPNE, "IF_ICMPNE"); - put(IF_ICMPLT, "IF_ICMPLT"); - put(IF_ICMPGE, "IF_ICMPGE"); - put(IF_ICMPGT, "IF_ICMPGT"); - put(IF_ICMPLE, "IF_ICMPLE"); - put(IF_ACMPEQ, "IF_ACMPEQ"); - put(IF_ACMPNE, "IF_ACMPNE"); - put(GOTO, "GOTO"); - put(JSR, "JSR"); - put(RET, "RET"); - put(TABLESWITCH, "TABLESWITCH"); - put(LOOKUPSWITCH, "LOOKUPSWITCH"); - put(IRETURN, "IRETURN"); - put(LRETURN, "LRETURN"); - put(FRETURN, "FRETURN"); - put(DRETURN, "DRETURN"); - put(ARETURN, "ARETURN"); - put(RETURN, "RETURN"); - put(GETSTATIC, "GETSTATIC"); - put(PUTSTATIC, "PUTSTATIC"); - put(GETFIELD, "GETFIELD"); - put(PUTFIELD, "PUTFIELD"); - put(INVOKEVIRTUAL, "INVOKEVIRTUAL"); - put(INVOKESPECIAL, "INVOKESPECIAL"); - put(INVOKESTATIC, "INVOKESTATIC"); - put(INVOKEINTERFACE, "INVOKEINTERFACE"); - put(INVOKEDYNAMIC, "INVOKEDYNAMIC"); - put(NEW, "NEW"); - put(NEWARRAY, "NEWARRAY"); - put(ANEWARRAY, "ANEWARRAY"); - put(ARRAYLENGTH, "ARRAYLENGTH"); - put(ATHROW, "ATHROW"); - put(CHECKCAST, "CHECKCAST"); - put(INSTANCEOF, "INSTANCEOF"); - put(MONITORENTER, "MONITORENTER"); - put(MONITOREXIT, "MONITOREXIT"); - put(MULTIANEWARRAY, "MULTIANEWARRAY"); - put(IFNULL, "IFNULL"); - put(IFNONNULL, "IFNONNULL"); - putFrame(F_NEW, "F_NEW"); - putFrame(F_FULL, "F_FULL"); - putFrame(F_APPEND, "F_APPEND"); - putFrame(F_CHOP, "F_CHOP"); - putFrame(F_SAME, "F_SAME"); - putFrame(F_APPEND, "F_APPEND"); - putFrame(F_SAME1, "F_SAME1"); - putTag(Opcodes.H_GETFIELD, "H_GETFIELD"); - putTag(Opcodes.H_GETSTATIC, "H_GETSTATIC"); - putTag(Opcodes.H_PUTFIELD, "H_PUTFIELD"); - putTag(Opcodes.H_PUTSTATIC, "H_PUTSTATIC"); - putTag(Opcodes.H_INVOKEINTERFACE, "H_INVOKEINTERFACE"); - putTag(Opcodes.H_INVOKESPECIAL, "H_INVOKESPECIAL"); - putTag(Opcodes.H_INVOKESTATIC, "H_INVOKESTATIC"); - putTag(Opcodes.H_INVOKEVIRTUAL, "H_INVOKEVIRTUAL"); - putTag(Opcodes.H_NEWINVOKESPECIAL, "H_NEWINVOKESPECIAL"); - insnTypeToCodes.put(AbstractInsnNode.FIELD_INSN, OpcodeUtil.OPS_FIELD); - insnTypeToCodes.put(AbstractInsnNode.FRAME, OpcodeUtil.OPS_FRAME); - insnTypeToCodes.put(AbstractInsnNode.IINC_INSN, OpcodeUtil.OPS_IINC); - insnTypeToCodes.put(AbstractInsnNode.INSN, OpcodeUtil.OPS_INSN); - insnTypeToCodes.put(AbstractInsnNode.INT_INSN, OpcodeUtil.OPS_INT); - insnTypeToCodes.put(AbstractInsnNode.INVOKE_DYNAMIC_INSN, OpcodeUtil.OPS_INDY_METHOD); - insnTypeToCodes.put(AbstractInsnNode.JUMP_INSN, OpcodeUtil.OPS_JUMP); - insnTypeToCodes.put(AbstractInsnNode.LABEL, OpcodeUtil.OPS_LABEL); - insnTypeToCodes.put(AbstractInsnNode.LDC_INSN, OpcodeUtil.OPS_LDC); - insnTypeToCodes.put(AbstractInsnNode.LINE, OpcodeUtil.OPS_LINE); - insnTypeToCodes.put(AbstractInsnNode.LOOKUPSWITCH_INSN, OpcodeUtil.OPS_LOOKUPSWITCH); - insnTypeToCodes.put(AbstractInsnNode.METHOD_INSN, OpcodeUtil.OPS_METHOD); - insnTypeToCodes.put(AbstractInsnNode.MULTIANEWARRAY_INSN, OpcodeUtil.OPS_MULTIANEWARRAY); - insnTypeToCodes.put(AbstractInsnNode.TABLESWITCH_INSN, OpcodeUtil.OPS_TABLESWITCH); - insnTypeToCodes.put(AbstractInsnNode.TYPE_INSN, OpcodeUtil.OPS_TYPE); - insnTypeToCodes.put(AbstractInsnNode.VAR_INSN, OpcodeUtil.OPS_VAR); - } + static { + put(F_NEW, "F_NEW"); + put(NOP, "NOP"); + put(ACONST_NULL, "ACONST_NULL"); + put(ICONST_M1, "ICONST_M1"); + put(ICONST_0, "ICONST_0"); + put(ICONST_1, "ICONST_1"); + put(ICONST_2, "ICONST_2"); + put(ICONST_3, "ICONST_3"); + put(ICONST_4, "ICONST_4"); + put(ICONST_5, "ICONST_5"); + put(LCONST_0, "LCONST_0"); + put(LCONST_1, "LCONST_1"); + put(FCONST_0, "FCONST_0"); + put(FCONST_1, "FCONST_1"); + put(FCONST_2, "FCONST_2"); + put(DCONST_0, "DCONST_0"); + put(DCONST_1, "DCONST_1"); + put(BIPUSH, "BIPUSH"); + put(SIPUSH, "SIPUSH"); + put(LDC, "LDC"); + put(ILOAD, "ILOAD"); + put(LLOAD, "LLOAD"); + put(FLOAD, "FLOAD"); + put(DLOAD, "DLOAD"); + put(ALOAD, "ALOAD"); + put(IALOAD, "IALOAD"); + put(LALOAD, "LALOAD"); + put(FALOAD, "FALOAD"); + put(DALOAD, "DALOAD"); + put(AALOAD, "AALOAD"); + put(BALOAD, "BALOAD"); + put(CALOAD, "CALOAD"); + put(SALOAD, "SALOAD"); + put(ISTORE, "ISTORE"); + put(LSTORE, "LSTORE"); + put(FSTORE, "FSTORE"); + put(DSTORE, "DSTORE"); + put(ASTORE, "ASTORE"); + put(IASTORE, "IASTORE"); + put(LASTORE, "LASTORE"); + put(FASTORE, "FASTORE"); + put(DASTORE, "DASTORE"); + put(AASTORE, "AASTORE"); + put(BASTORE, "BASTORE"); + put(CASTORE, "CASTORE"); + put(SASTORE, "SASTORE"); + put(POP, "POP"); + put(POP2, "POP2"); + put(DUP, "DUP"); + put(DUP_X1, "DUP_X1"); + put(DUP_X2, "DUP_X2"); + put(DUP2, "DUP2"); + put(DUP2_X1, "DUP2_X1"); + put(DUP2_X2, "DUP2_X2"); + put(SWAP, "SWAP"); + put(IADD, "IADD"); + put(LADD, "LADD"); + put(FADD, "FADD"); + put(DADD, "DADD"); + put(ISUB, "ISUB"); + put(LSUB, "LSUB"); + put(FSUB, "FSUB"); + put(DSUB, "DSUB"); + put(IMUL, "IMUL"); + put(LMUL, "LMUL"); + put(FMUL, "FMUL"); + put(DMUL, "DMUL"); + put(IDIV, "IDIV"); + put(LDIV, "LDIV"); + put(FDIV, "FDIV"); + put(DDIV, "DDIV"); + put(IREM, "IREM"); + put(LREM, "LREM"); + put(FREM, "FREM"); + put(DREM, "DREM"); + put(INEG, "INEG"); + put(LNEG, "LNEG"); + put(FNEG, "FNEG"); + put(DNEG, "DNEG"); + put(ISHL, "ISHL"); + put(LSHL, "LSHL"); + put(ISHR, "ISHR"); + put(LSHR, "LSHR"); + put(IUSHR, "IUSHR"); + put(LUSHR, "LUSHR"); + put(IAND, "IAND"); + put(LAND, "LAND"); + put(IOR, "IOR"); + put(LOR, "LOR"); + put(IXOR, "IXOR"); + put(LXOR, "LXOR"); + put(IINC, "IINC"); + put(I2L, "I2L"); + put(I2F, "I2F"); + put(I2D, "I2D"); + put(L2I, "L2I"); + put(L2F, "L2F"); + put(L2D, "L2D"); + put(F2I, "F2I"); + put(F2L, "F2L"); + put(F2D, "F2D"); + put(D2I, "D2I"); + put(D2L, "D2L"); + put(D2F, "D2F"); + put(I2B, "I2B"); + put(I2C, "I2C"); + put(I2S, "I2S"); + put(LCMP, "LCMP"); + put(FCMPL, "FCMPL"); + put(FCMPG, "FCMPG"); + put(DCMPL, "DCMPL"); + put(DCMPG, "DCMPG"); + put(IFEQ, "IFEQ"); + put(IFNE, "IFNE"); + put(IFLT, "IFLT"); + put(IFGE, "IFGE"); + put(IFGT, "IFGT"); + put(IFLE, "IFLE"); + put(IF_ICMPEQ, "IF_ICMPEQ"); + put(IF_ICMPNE, "IF_ICMPNE"); + put(IF_ICMPLT, "IF_ICMPLT"); + put(IF_ICMPGE, "IF_ICMPGE"); + put(IF_ICMPGT, "IF_ICMPGT"); + put(IF_ICMPLE, "IF_ICMPLE"); + put(IF_ACMPEQ, "IF_ACMPEQ"); + put(IF_ACMPNE, "IF_ACMPNE"); + put(GOTO, "GOTO"); + put(JSR, "JSR"); + put(RET, "RET"); + put(TABLESWITCH, "TABLESWITCH"); + put(LOOKUPSWITCH, "LOOKUPSWITCH"); + put(IRETURN, "IRETURN"); + put(LRETURN, "LRETURN"); + put(FRETURN, "FRETURN"); + put(DRETURN, "DRETURN"); + put(ARETURN, "ARETURN"); + put(RETURN, "RETURN"); + put(GETSTATIC, "GETSTATIC"); + put(PUTSTATIC, "PUTSTATIC"); + put(GETFIELD, "GETFIELD"); + put(PUTFIELD, "PUTFIELD"); + put(INVOKEVIRTUAL, "INVOKEVIRTUAL"); + put(INVOKESPECIAL, "INVOKESPECIAL"); + put(INVOKESTATIC, "INVOKESTATIC"); + put(INVOKEINTERFACE, "INVOKEINTERFACE"); + put(INVOKEDYNAMIC, "INVOKEDYNAMIC"); + put(NEW, "NEW"); + put(NEWARRAY, "NEWARRAY"); + put(ANEWARRAY, "ANEWARRAY"); + put(ARRAYLENGTH, "ARRAYLENGTH"); + put(ATHROW, "ATHROW"); + put(CHECKCAST, "CHECKCAST"); + put(INSTANCEOF, "INSTANCEOF"); + put(MONITORENTER, "MONITORENTER"); + put(MONITOREXIT, "MONITOREXIT"); + put(MULTIANEWARRAY, "MULTIANEWARRAY"); + put(IFNULL, "IFNULL"); + put(IFNONNULL, "IFNONNULL"); + putFrame(F_NEW, "F_NEW"); + putFrame(F_FULL, "F_FULL"); + putFrame(F_APPEND, "F_APPEND"); + putFrame(F_CHOP, "F_CHOP"); + putFrame(F_SAME, "F_SAME"); + putFrame(F_APPEND, "F_APPEND"); + putFrame(F_SAME1, "F_SAME1"); + putTag(Opcodes.H_GETFIELD, "H_GETFIELD"); + putTag(Opcodes.H_GETSTATIC, "H_GETSTATIC"); + putTag(Opcodes.H_PUTFIELD, "H_PUTFIELD"); + putTag(Opcodes.H_PUTSTATIC, "H_PUTSTATIC"); + putTag(Opcodes.H_INVOKEINTERFACE, "H_INVOKEINTERFACE"); + putTag(Opcodes.H_INVOKESPECIAL, "H_INVOKESPECIAL"); + putTag(Opcodes.H_INVOKESTATIC, "H_INVOKESTATIC"); + putTag(Opcodes.H_INVOKEVIRTUAL, "H_INVOKEVIRTUAL"); + putTag(Opcodes.H_NEWINVOKESPECIAL, "H_NEWINVOKESPECIAL"); + insnTypeToCodes.put(AbstractInsnNode.FIELD_INSN, OpcodeUtil.OPS_FIELD); + insnTypeToCodes.put(AbstractInsnNode.FRAME, OpcodeUtil.OPS_FRAME); + insnTypeToCodes.put(AbstractInsnNode.IINC_INSN, OpcodeUtil.OPS_IINC); + insnTypeToCodes.put(AbstractInsnNode.INSN, OpcodeUtil.OPS_INSN); + insnTypeToCodes.put(AbstractInsnNode.INT_INSN, OpcodeUtil.OPS_INT); + insnTypeToCodes.put(AbstractInsnNode.INVOKE_DYNAMIC_INSN, OpcodeUtil.OPS_INDY_METHOD); + insnTypeToCodes.put(AbstractInsnNode.JUMP_INSN, OpcodeUtil.OPS_JUMP); + insnTypeToCodes.put(AbstractInsnNode.LABEL, OpcodeUtil.OPS_LABEL); + insnTypeToCodes.put(AbstractInsnNode.LDC_INSN, OpcodeUtil.OPS_LDC); + insnTypeToCodes.put(AbstractInsnNode.LINE, OpcodeUtil.OPS_LINE); + insnTypeToCodes.put(AbstractInsnNode.LOOKUPSWITCH_INSN, OpcodeUtil.OPS_LOOKUPSWITCH); + insnTypeToCodes.put(AbstractInsnNode.METHOD_INSN, OpcodeUtil.OPS_METHOD); + insnTypeToCodes.put(AbstractInsnNode.MULTIANEWARRAY_INSN, OpcodeUtil.OPS_MULTIANEWARRAY); + insnTypeToCodes.put(AbstractInsnNode.TABLESWITCH_INSN, OpcodeUtil.OPS_TABLESWITCH); + insnTypeToCodes.put(AbstractInsnNode.TYPE_INSN, OpcodeUtil.OPS_TYPE); + insnTypeToCodes.put(AbstractInsnNode.VAR_INSN, OpcodeUtil.OPS_VAR); + } } diff --git a/src/me/coley/recaf/asm/PluginClassReader.java b/src/me/coley/recaf/asm/PluginClassReader.java index 7bce581e4..e1f871192 100644 --- a/src/me/coley/recaf/asm/PluginClassReader.java +++ b/src/me/coley/recaf/asm/PluginClassReader.java @@ -13,8 +13,8 @@ */ public class PluginClassReader extends ClassReader { - public PluginClassReader(InputStream is) throws IOException { - super(is); - } + public PluginClassReader(InputStream is) throws IOException { + super(is); + } } diff --git a/src/me/coley/recaf/cfr/CFRResourceLookup.java b/src/me/coley/recaf/cfr/CFRResourceLookup.java index 9a08c1267..515d4fd4b 100644 --- a/src/me/coley/recaf/cfr/CFRResourceLookup.java +++ b/src/me/coley/recaf/cfr/CFRResourceLookup.java @@ -11,38 +11,38 @@ * inner classes and such. */ public class CFRResourceLookup { - private final Recaf program; - private final ClassNode override; - - public CFRResourceLookup(Recaf program) { - this(program, null); - } - - public CFRResourceLookup(Recaf program, ClassNode override) { - this.program = program; - this.override = override; - } - - public byte[] get(String path) { - byte[] bytes = null; - try { - if (override != null && path.equals(override.name)) { - bytes = program.asm.toBytes(override); - } else { - Map classes = program.jarData.classes; - if (classes.containsKey(path)) { - bytes = program.asm.toBytes(classes.get(path)); - } else { - ClassNode runtime = program.asm.getNode(Class.forName(path.replace("/", "."))); - if (runtime != null) { - bytes = program.asm.toBytes(runtime); - } - } - } - } catch (Exception e) { - program.window.displayError(e); - } - return bytes; - } + private final Recaf program; + private final ClassNode override; + + public CFRResourceLookup(Recaf program) { + this(program, null); + } + + public CFRResourceLookup(Recaf program, ClassNode override) { + this.program = program; + this.override = override; + } + + public byte[] get(String path) { + byte[] bytes = null; + try { + if (override != null && path.equals(override.name)) { + bytes = program.asm.toBytes(override); + } else { + Map classes = program.jarData.classes; + if (classes.containsKey(path)) { + bytes = program.asm.toBytes(classes.get(path)); + } else { + ClassNode runtime = program.asm.getNode(Class.forName(path.replace("/", "."))); + if (runtime != null) { + bytes = program.asm.toBytes(runtime); + } + } + } + } catch (Exception e) { + program.window.displayError(e); + } + return bytes; + } } diff --git a/src/me/coley/recaf/cfr/CFRSetting.java b/src/me/coley/recaf/cfr/CFRSetting.java index 8426936c2..0148ca18f 100644 --- a/src/me/coley/recaf/cfr/CFRSetting.java +++ b/src/me/coley/recaf/cfr/CFRSetting.java @@ -7,97 +7,97 @@ * Credit: * Samczung - * + * */ public enum CFRSetting { - //@formatter:off - DECODE_ENUM_SWITCH("decodeenumswitch", "Decode Enum Switch", true), - SUGAR_ENUMS("sugarenums", "SugarEnums", true), - DECODE_STRING_SWITCH("decodestringswitch", "Decode String Switch", true), - ARRAYITER("arrayiter", "Arrayiter", true), - COLLECTIONITER("collectioniter", "Collectioniter", true), - INNER_CLASSES("innerclasses", "Inner Classes", false), - REMOVE_BOILER_PLATE("removeboilerplate", "Remove Boiler Plate", true), - REMOVE_INNER_CLASS_SYNTHETICS("removeinnerclasssynthetics", "Remove Inner Class Synthetics", true), - DECODE_LAMBDAS("decodelambdas", "Decode Lambdas", true), - HIDE_BRIDGE_METHODS("hidebridgemethods", "Hide Bridge Methods", false), - LIFT_CONSTRUCTOR_INIT("liftconstructorinit", "Lift Constructor Init", true), - REMOVE_DEAD_METHODS("removedeadmethods", "Remove Dead Methods", false), - REMOVE_BAD_GENERICS("removebadgenerics", "Remove Bad Generics", true), - SUGAR_ASSERTS("sugarasserts", "Sugar Asserts", true), - SUGAR_BOXING("sugarboxing", "Sugar Boxing", true), - SHOW_VERSION("showversion", "Show Version"), - DECODE_FINALLY("decodefinally", "Decode Finally", true), - TIDY_MONITORS("tidymonitors", "Tidy Monitors", true), - LENIENT("lenient", "Lenient", true), - DUMP_CLASS_PATH("dumpclasspath", "Dump Classpath"), - COMMENTS("comments", "Comments"), - FORCE_TOP_SORT("forcetopsort", "Force Top Sort", true), - FORCE_TOP_SORT_AGGRESSIVE("forcetopsortaggress", "Force Top Sort Aggressive", true), - STRINGBUFFER("stringbuffer", "StringBuffer"), - STRINGBUILDER("stringbuilder", "StringBuilder", true), - SILENT("silent", "Silent", true), - RECOVER("recover", "Recover", true), - ECLIPSE("eclipse", "Eclipse", true), - OVERRIDE("override", "Override", true), - SHOW_INFERRABLE("showinferrable", "Show Inferrable", false), - FORCE_AGGRESSIVE_EXCEPTION_AGG("aexagg", "Force Aggressive Exception Aggregation", true), - FORCE_COND_PROPAGATE("forcecondpropagate", "Force Conditional Propogation", true), - HIDE_UTF("hideutf", "Hide UTF", true), - HIDE_LONG_STRINGS("hidelongstrings", "Hide Long Strings"), - COMMENT_MONITORS("commentmonitors", "Comment Monitors"), - ALLOW_CORRECTING("allowcorrecting", "Allow Correcting", true), - LABELLED_BLOCKS("labelledblocks", "Labelled Blocks", true), - J14_CLASS_OBJ("j14classobj", "Java 1.4 Class Objects"), - HIDE_LANG_IMPORTS("hidelangimports", "Hide Lang Imports", true), - RECOVER_TYPE_CLASH("recovertypeclash", "Recover Type Clash", true), - RECOVER_TYPE_HINTS("recovertypehints", "Recover Type Hints", true), - FORCE_RETURNING_IFS("forcereturningifs", "Force Returning Ifs", true), - FOR_LOOP_AGG_CAPTURE("forloopaggcapture", "For Loop Aggressive Capture", true), - RENAME_ILLEGAL_IDENTIFIERS("renameillegalidents", "Rename illegal identifiers", false), - RENAME_DUPE_MEMBERS("renamedupmembers", "Rename duplicated member names", false); - //@formatter:on + //@formatter:off + DECODE_ENUM_SWITCH("decodeenumswitch", "Decode Enum Switch", true), + SUGAR_ENUMS("sugarenums", "SugarEnums", true), + DECODE_STRING_SWITCH("decodestringswitch", "Decode String Switch", true), + ARRAYITER("arrayiter", "Arrayiter", true), + COLLECTIONITER("collectioniter", "Collectioniter", true), + INNER_CLASSES("innerclasses", "Inner Classes", false), + REMOVE_BOILER_PLATE("removeboilerplate", "Remove Boiler Plate", true), + REMOVE_INNER_CLASS_SYNTHETICS("removeinnerclasssynthetics", "Remove Inner Class Synthetics", true), + DECODE_LAMBDAS("decodelambdas", "Decode Lambdas", true), + HIDE_BRIDGE_METHODS("hidebridgemethods", "Hide Bridge Methods", false), + LIFT_CONSTRUCTOR_INIT("liftconstructorinit", "Lift Constructor Init", true), + REMOVE_DEAD_METHODS("removedeadmethods", "Remove Dead Methods", false), + REMOVE_BAD_GENERICS("removebadgenerics", "Remove Bad Generics", true), + SUGAR_ASSERTS("sugarasserts", "Sugar Asserts", true), + SUGAR_BOXING("sugarboxing", "Sugar Boxing", true), + SHOW_VERSION("showversion", "Show Version"), + DECODE_FINALLY("decodefinally", "Decode Finally", true), + TIDY_MONITORS("tidymonitors", "Tidy Monitors", true), + LENIENT("lenient", "Lenient", true), + DUMP_CLASS_PATH("dumpclasspath", "Dump Classpath"), + COMMENTS("comments", "Comments"), + FORCE_TOP_SORT("forcetopsort", "Force Top Sort", true), + FORCE_TOP_SORT_AGGRESSIVE("forcetopsortaggress", "Force Top Sort Aggressive", true), + STRINGBUFFER("stringbuffer", "StringBuffer"), + STRINGBUILDER("stringbuilder", "StringBuilder", true), + SILENT("silent", "Silent", true), + RECOVER("recover", "Recover", true), + ECLIPSE("eclipse", "Eclipse", true), + OVERRIDE("override", "Override", true), + SHOW_INFERRABLE("showinferrable", "Show Inferrable", false), + FORCE_AGGRESSIVE_EXCEPTION_AGG("aexagg", "Force Aggressive Exception Aggregation", true), + FORCE_COND_PROPAGATE("forcecondpropagate", "Force Conditional Propogation", true), + HIDE_UTF("hideutf", "Hide UTF", true), + HIDE_LONG_STRINGS("hidelongstrings", "Hide Long Strings"), + COMMENT_MONITORS("commentmonitors", "Comment Monitors"), + ALLOW_CORRECTING("allowcorrecting", "Allow Correcting", true), + LABELLED_BLOCKS("labelledblocks", "Labelled Blocks", true), + J14_CLASS_OBJ("j14classobj", "Java 1.4 Class Objects"), + HIDE_LANG_IMPORTS("hidelangimports", "Hide Lang Imports", true), + RECOVER_TYPE_CLASH("recovertypeclash", "Recover Type Clash", true), + RECOVER_TYPE_HINTS("recovertypehints", "Recover Type Hints", true), + FORCE_RETURNING_IFS("forcereturningifs", "Force Returning Ifs", true), + FOR_LOOP_AGG_CAPTURE("forloopaggcapture", "For Loop Aggressive Capture", true), + RENAME_ILLEGAL_IDENTIFIERS("renameillegalidents", "Rename illegal identifiers", false), + RENAME_DUPE_MEMBERS("renamedupmembers", "Rename duplicated member names", false); + //@formatter:on - private final String name; - private final String param; - private boolean on; + private final String name; + private final String param; + private boolean on; - CFRSetting(String param, String name) { - this(param, name, false); - } + CFRSetting(String param, String name) { + this(param, name, false); + } - CFRSetting(String param, String name, boolean on) { - this.name = name; - this.param = param; - this.on = on; - } + CFRSetting(String param, String name, boolean on) { + this.name = name; + this.param = param; + this.on = on; + } - public String getParam() { - return param; - } + public String getParam() { + return param; + } - public String getText() { - return name; - } + public String getText() { + return name; + } - public boolean isEnabled() { - return on; - } + public boolean isEnabled() { + return on; + } - public void setEnabled(boolean enabled) { - this.on = enabled; - } + public void setEnabled(boolean enabled) { + this.on = enabled; + } - /** Obtain repreesntation of the CFR settings as a string map. - * - * @return <String, String(of boolean)> map of the settings and their - * current status. - */ - public static Map toStringMap() { - Map options = new HashMap<>(); - for (CFRSetting setting : CFRSetting.values()) { - options.put(setting.getParam(), String.valueOf(setting.isEnabled())); - } - return options; - } + /** Obtain repreesntation of the CFR settings as a string map. + * + * @return <String, String(of boolean)> map of the settings and their + * current status. + */ + public static Map toStringMap() { + Map options = new HashMap<>(); + for (CFRSetting setting : CFRSetting.values()) { + options.put(setting.getParam(), String.valueOf(setting.isEnabled())); + } + return options; + } } diff --git a/src/me/coley/recaf/cfr/CFRSourceImpl.java b/src/me/coley/recaf/cfr/CFRSourceImpl.java index dc2a79c0b..8bd2f5a57 100644 --- a/src/me/coley/recaf/cfr/CFRSourceImpl.java +++ b/src/me/coley/recaf/cfr/CFRSourceImpl.java @@ -6,31 +6,31 @@ import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; public class CFRSourceImpl implements ClassFileSource { - /** - * Lookup assistor for inner classes and other references. - */ - private final CFRResourceLookup resources; + /** + * Lookup assistor for inner classes and other references. + */ + private final CFRResourceLookup resources; - public CFRSourceImpl(CFRResourceLookup resources) { - this.resources = resources; - } + public CFRSourceImpl(CFRResourceLookup resources) { + this.resources = resources; + } - @Override - public void informAnalysisRelativePathDetail(String s, String s1) {} + @Override + public void informAnalysisRelativePathDetail(String s, String s1) {} - @Override - public Collection addJar(String s) { - throw new UnsupportedOperationException("Return paths of all classfiles in jar."); - } + @Override + public Collection addJar(String s) { + throw new UnsupportedOperationException("Return paths of all classfiles in jar."); + } - @Override - public String getPossiblyRenamedPath(String s) { - return s; - } + @Override + public String getPossiblyRenamedPath(String s) { + return s; + } - @Override - public Pair getClassFileContent(String pathOrName) throws IOException { - pathOrName = pathOrName.substring(0, pathOrName.length() - ".class".length()); - return Pair.make(resources.get(pathOrName), pathOrName); - } + @Override + public Pair getClassFileContent(String pathOrName) throws IOException { + pathOrName = pathOrName.substring(0, pathOrName.length() - ".class".length()); + return Pair.make(resources.get(pathOrName), pathOrName); + } } diff --git a/src/me/coley/recaf/ui/FileChoosers.java b/src/me/coley/recaf/ui/FileChoosers.java index 54f82ea77..748914f45 100644 --- a/src/me/coley/recaf/ui/FileChoosers.java +++ b/src/me/coley/recaf/ui/FileChoosers.java @@ -6,52 +6,52 @@ import javax.swing.filechooser.FileNameExtensionFilter; public class FileChoosers { - private JFileChooser fileChooser; + private JFileChooser fileChooser; - /** - * @return The file chooser. If it is null it is instantiated and set to the - * working directory with a filter for jar files. - */ - public JFileChooser getFileChooser() { - return getFileChooser("Java Archives", "jar"); - } + /** + * @return The file chooser. If it is null it is instantiated and set to the + * working directory with a filter for jar files. + */ + public JFileChooser getFileChooser() { + return getFileChooser("Java Archives", "jar"); + } - /** - * @return The file chooser. If it is null it is instantiated and set to the - * working directory with a filter for the given file type. To allow any - * type, have the parameters be null. - * - * @param fileType Name of the type of file - * @param extension Actual file extension. - */ - public JFileChooser getFileChooser(String fileType, String extension) { - if (fileChooser == null) { - fileChooser = new JFileChooser(); - String dir = System.getProperty("user.dir"); - File fileDir = new File(dir); - fileChooser.setDialogTitle("Open File"); - fileChooser.setCurrentDirectory(fileDir); - } - if (fileType == null || extension == null) { - fileChooser.setFileFilter(null); - } else { - FileNameExtensionFilter filter = new FileNameExtensionFilter(fileType, extension); - fileChooser.setFileFilter(filter); - } - return fileChooser; - } + /** + * @return The file chooser. If it is null it is instantiated and set to the + * working directory with a filter for the given file type. To allow any + * type, have the parameters be null. + * + * @param fileType Name of the type of file + * @param extension Actual file extension. + */ + public JFileChooser getFileChooser(String fileType, String extension) { + if (fileChooser == null) { + fileChooser = new JFileChooser(); + String dir = System.getProperty("user.dir"); + File fileDir = new File(dir); + fileChooser.setDialogTitle("Open File"); + fileChooser.setCurrentDirectory(fileDir); + } + if (fileType == null || extension == null) { + fileChooser.setFileFilter(null); + } else { + FileNameExtensionFilter filter = new FileNameExtensionFilter(fileType, extension); + fileChooser.setFileFilter(filter); + } + return fileChooser; + } - /** - * Creates and returns a file chooser set in the working directory. - * - * @return The file chooser. - */ - public JFileChooser createFileSaver() { - JFileChooser fileSaver = new JFileChooser(); - String dir = System.getProperty("user.dir"); - File fileDir = new File(dir); - fileSaver.setCurrentDirectory(fileDir); - fileSaver.setDialogTitle("Save to File"); - return fileSaver; - } + /** + * Creates and returns a file chooser set in the working directory. + * + * @return The file chooser. + */ + public JFileChooser createFileSaver() { + JFileChooser fileSaver = new JFileChooser(); + String dir = System.getProperty("user.dir"); + File fileDir = new File(dir); + fileSaver.setCurrentDirectory(fileDir); + fileSaver.setDialogTitle("Save to File"); + return fileSaver; + } } diff --git a/src/me/coley/recaf/ui/FontUtil.java b/src/me/coley/recaf/ui/FontUtil.java index 84b42447d..e26def715 100644 --- a/src/me/coley/recaf/ui/FontUtil.java +++ b/src/me/coley/recaf/ui/FontUtil.java @@ -8,36 +8,36 @@ /** * Quick font utilities regarding fonts. - * + * * @author Matt */ public class FontUtil { - private static final AffineTransform affinetransform = new AffineTransform(); - private static final FontRenderContext frc = new FontRenderContext(affinetransform, true, true); - public static final Font monospace; - static { - String consolas = null; - String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); - for (String font : fonts) { - if (font.toLowerCase().contains("consolas")) { - consolas = font; - } - } - if (consolas == null) { - monospace = new Font(Font.MONOSPACED, Font.TRUETYPE_FONT, 12); - } else { - monospace = new Font(consolas, Font.TRUETYPE_FONT, 12); - } - } + private static final AffineTransform affinetransform = new AffineTransform(); + private static final FontRenderContext frc = new FontRenderContext(affinetransform, true, true); + public static final Font monospace; + static { + String consolas = null; + String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + for (String font : fonts) { + if (font.toLowerCase().contains("consolas")) { + consolas = font; + } + } + if (consolas == null) { + monospace = new Font(Font.MONOSPACED, Font.TRUETYPE_FONT, 12); + } else { + monospace = new Font(consolas, Font.TRUETYPE_FONT, 12); + } + } - /** - * Create a bounding box for the visual representation of the given text. - * - * @param text The text. - * @param font The font in which to render the text. - * @return The bounding box. - */ - public static Rectangle2D getStringBounds(String text, Font font) { - return font.getStringBounds(text, frc); - } + /** + * Create a bounding box for the visual representation of the given text. + * + * @param text The text. + * @param font The font in which to render the text. + * @return The bounding box. + */ + public static Rectangle2D getStringBounds(String text, Font font) { + return font.getStringBounds(text, frc); + } } diff --git a/src/me/coley/recaf/ui/Gui.java b/src/me/coley/recaf/ui/Gui.java index 749dbbe0b..0a3560d7f 100644 --- a/src/me/coley/recaf/ui/Gui.java +++ b/src/me/coley/recaf/ui/Gui.java @@ -34,216 +34,216 @@ import java.util.List; public class Gui { - private final Recaf recaf = Recaf.getInstance(); - private JFrame frame; - private JarFileTree treeFiles; - private TabbedPanel tabbedContent; - private JMenu mnSearch; - - public Gui() { - initialize(); - } - - /** - * Initialize the contents of the frame. - */ - @SuppressWarnings("serial") - private void initialize() { - frame = new JFrame("Recaf: Java Bytecode Editor"); - frame.setBounds(100, 100, 1200, 730); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - JMenuBar menuBar = new JMenuBar(); - frame.setJMenuBar(menuBar); - - JMenu mnFile = new JMenu("File"); - menuBar.add(mnFile); - - JMenuItem mntmOpenJar = new JMenuItem("Open Jar"); - mntmOpenJar.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JFileChooser chooser = recaf.fileChoosers.getFileChooser(); - int val = chooser.showOpenDialog(null); - if (val == JFileChooser.APPROVE_OPTION) { - try { - recaf.openFile(chooser.getSelectedFile()); - } catch (Exception e1) { - displayError(e1); - } - } - } - - }); - mnFile.add(mntmOpenJar); - - JMenuItem mntmSaveJar = new JMenuItem("Save Jar"); - mntmSaveJar.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JFileChooser chooser = recaf.fileChoosers.createFileSaver(); - int val = chooser.showOpenDialog(null); - if (val == JFileChooser.APPROVE_OPTION) { - try { - recaf.saveFile(chooser.getSelectedFile()); - } catch (Exception e1) { - displayError(e1); - } - } - } - - }); - mnFile.add(mntmSaveJar); - - /* - * JMenu mnEdit = new JMenu("Edit"); JMenuItem mntmUndo = new - * JMenuItem("Undo"); mntmUndo.addActionListener(new ActionListener() { - * - * @Override public void actionPerformed(ActionEvent e) { - * recaf.history.undoLast(); } }); mnEdit.add(mntmUndo); - * menuBar.add(mnEdit); - */ - - JMenu mnOptions = new JMenu("Options"); - mnOptions.add(new ActionCheckBox("Show jump hints", recaf.options.opcodeShowJumpHelp,b -> recaf.options.opcodeShowJumpHelp = b)); - mnOptions.add(new ActionCheckBox("Simplify type descriptors", recaf.options.opcodeSimplifyDescriptors,b -> recaf.options.opcodeSimplifyDescriptors = b)); - mnOptions.add(new ActionCheckBox("Advanced Variable Table", recaf.options.showVariableSignatureInTable,b -> recaf.options.showVariableSignatureInTable = b)); - mnOptions.add(new ActionCheckBox("Confirm deletions", recaf.options.confirmDeletions,b -> recaf.options.confirmDeletions = b)); - mnOptions.add(new ActionMenuItem("ASM flags", () -> { - openTab("ASM Flags", new AsmFlagsPanel()); - })); - menuBar.add(mnOptions); - - mnSearch = new JMenu("Search"); - mnSearch.setEnabled(false); - JMenuItem mntmSearch1 = new ActionMenuItem("Strings", () -> openTab("Search: Strings", new SearchPanel(SearchPanel.S_STRINGS))); - JMenuItem mntmSearch2 = new ActionMenuItem("Fields", () -> openTab("Search: Fields", new SearchPanel(SearchPanel.S_FIELD))); - JMenuItem mntmSearch3 = new ActionMenuItem("Methods", () -> openTab("Search: Methods", new SearchPanel(SearchPanel.S_METHOD))); - JMenuItem mntmSearch4 = new ActionMenuItem("Class Name", () -> openTab("Search: Class", new SearchPanel(SearchPanel.S_CLASS_NAME))); - JMenuItem mntmSearch5 = new ActionMenuItem("Class References", () -> openTab("Search: Class References", new SearchPanel(SearchPanel.S_CLASS_REF))); - mnSearch.add(mntmSearch1); - mnSearch.add(mntmSearch2); - mnSearch.add(mntmSearch3); - mnSearch.add(mntmSearch4); - mnSearch.add(mntmSearch5); - menuBar.add(mnSearch); - - frame.getContentPane().setLayout(new BorderLayout(0, 0)); - - JSplitPane splitPane = new JSplitPane(); - splitPane.setResizeWeight(0.1); - splitPane.setOneTouchExpandable(true); - frame.getContentPane().add(splitPane, BorderLayout.CENTER); - - treeFiles = new JarFileTree(); - splitPane.setLeftComponent(treeFiles); - treeFiles.setDropTarget(new DropTarget() { - @Override - public final void drop(final DropTargetDropEvent event) { - try { - event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); - Object transferData = event.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); - if (transferData == null) { - return; - } - @SuppressWarnings("unchecked") - List ls = (List) transferData; - File file = ls.get(0); - if (ls.size() > 1) { - JOptionPane.showMessageDialog(null, "Only one file can be accepted. Going with: " + file); - } - if (file.getName().toLowerCase().endsWith(".jar")) { - recaf.openFile(file); - } else { - JOptionPane.showMessageDialog(null, "Input was not a java archive (jar)."); - } - } catch (UnsupportedFlavorException ex) { - JOptionPane.showMessageDialog(null, "Input was not a java archive (jar)."); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - }); - - tabbedContent = new TabbedPanel(); - splitPane.setRightComponent(tabbedContent); - - } - - /** - * Creates a new tab with the text of the exception. - * - * @param e The exception. - */ - public void displayError(Throwable e) { - JTextArea text = new JTextArea(); - text.setEditable(false); - text.append(e.getClass().getSimpleName() + ":\n"); - text.append("Message: " + e.getMessage() + "\n"); - text.append("Trace: \n"); - for (StackTraceElement element : e.getStackTrace()) { - text.append(element.toString() + "\n"); - } - - // TODO: Logging of cause - // text.append("Cause: " + e.getCause() + "\n"); - - tabbedContent.addTab("Error: " + e.getClass().getSimpleName(), new JScrollPane(text)); - tabbedContent.setSelectedTab(tabbedContent.getTabCount() - 1); - } - - /** - * Opens up a class tab for the given class-node, or opens an existing page - * if one is found. - * - * @param node The node. - */ - public void addClassView(ClassNode node) { - if (tabbedContent.hasCached(node.name)) { - tabbedContent.setSelectedTab(tabbedContent.getCachedIndex(node.name)); - } else { - tabbedContent.addTab(node.name, new JScrollPane(new ClassDisplayPanel(node))); - tabbedContent.setSelectedTab(tabbedContent.getTabCount() - 1); - int i = tabbedContent.getCachedIndex(node.name); - if (i == -1) { - i = tabbedContent.getTabCount() - 1; - } - tabbedContent.setSelectedTab(i); - } - } - - /** - * Opens up a tab for the given component, or opens an existing page if one - * is found. - * - * @param title - * Title of tab. - * @param component - * Content of tab. - */ - public void openTab(String title, Component component) { - if (tabbedContent.hasCached(title)) { - tabbedContent.setSelectedTab(tabbedContent.getCachedIndex(title)); - } else { - tabbedContent.addTab(title, component); - int i = tabbedContent.getCachedIndex(title); - if (i == -1) { - i = tabbedContent.getTabCount() - 1; - } - tabbedContent.setSelectedTab(i); - } - } - - /** - * Refreshes the tree to display the current jar file. - */ - public void updateTree() { - mnSearch.setEnabled(true); - treeFiles.refresh(); - } - - public JFrame getFrame() { - return frame; - } + private final Recaf recaf = Recaf.getInstance(); + private JFrame frame; + private JarFileTree treeFiles; + private TabbedPanel tabbedContent; + private JMenu mnSearch; + + public Gui() { + initialize(); + } + + /** + * Initialize the contents of the frame. + */ + @SuppressWarnings("serial") + private void initialize() { + frame = new JFrame("Recaf: Java Bytecode Editor"); + frame.setBounds(100, 100, 1200, 730); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JMenuBar menuBar = new JMenuBar(); + frame.setJMenuBar(menuBar); + + JMenu mnFile = new JMenu("File"); + menuBar.add(mnFile); + + JMenuItem mntmOpenJar = new JMenuItem("Open Jar"); + mntmOpenJar.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser chooser = recaf.fileChoosers.getFileChooser(); + int val = chooser.showOpenDialog(null); + if (val == JFileChooser.APPROVE_OPTION) { + try { + recaf.openFile(chooser.getSelectedFile()); + } catch (Exception e1) { + displayError(e1); + } + } + } + + }); + mnFile.add(mntmOpenJar); + + JMenuItem mntmSaveJar = new JMenuItem("Save Jar"); + mntmSaveJar.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser chooser = recaf.fileChoosers.createFileSaver(); + int val = chooser.showOpenDialog(null); + if (val == JFileChooser.APPROVE_OPTION) { + try { + recaf.saveFile(chooser.getSelectedFile()); + } catch (Exception e1) { + displayError(e1); + } + } + } + + }); + mnFile.add(mntmSaveJar); + + /* + * JMenu mnEdit = new JMenu("Edit"); JMenuItem mntmUndo = new + * JMenuItem("Undo"); mntmUndo.addActionListener(new ActionListener() { + * + * @Override public void actionPerformed(ActionEvent e) { + * recaf.history.undoLast(); } }); mnEdit.add(mntmUndo); + * menuBar.add(mnEdit); + */ + + JMenu mnOptions = new JMenu("Options"); + mnOptions.add(new ActionCheckBox("Show jump hints", recaf.options.opcodeShowJumpHelp,b -> recaf.options.opcodeShowJumpHelp = b)); + mnOptions.add(new ActionCheckBox("Simplify type descriptors", recaf.options.opcodeSimplifyDescriptors,b -> recaf.options.opcodeSimplifyDescriptors = b)); + mnOptions.add(new ActionCheckBox("Advanced Variable Table", recaf.options.showVariableSignatureInTable,b -> recaf.options.showVariableSignatureInTable = b)); + mnOptions.add(new ActionCheckBox("Confirm deletions", recaf.options.confirmDeletions,b -> recaf.options.confirmDeletions = b)); + mnOptions.add(new ActionMenuItem("ASM flags", () -> { + openTab("ASM Flags", new AsmFlagsPanel()); + })); + menuBar.add(mnOptions); + + mnSearch = new JMenu("Search"); + mnSearch.setEnabled(false); + JMenuItem mntmSearch1 = new ActionMenuItem("Strings", () -> openTab("Search: Strings", new SearchPanel(SearchPanel.S_STRINGS))); + JMenuItem mntmSearch2 = new ActionMenuItem("Fields", () -> openTab("Search: Fields", new SearchPanel(SearchPanel.S_FIELD))); + JMenuItem mntmSearch3 = new ActionMenuItem("Methods", () -> openTab("Search: Methods", new SearchPanel(SearchPanel.S_METHOD))); + JMenuItem mntmSearch4 = new ActionMenuItem("Class Name", () -> openTab("Search: Class", new SearchPanel(SearchPanel.S_CLASS_NAME))); + JMenuItem mntmSearch5 = new ActionMenuItem("Class References", () -> openTab("Search: Class References", new SearchPanel(SearchPanel.S_CLASS_REF))); + mnSearch.add(mntmSearch1); + mnSearch.add(mntmSearch2); + mnSearch.add(mntmSearch3); + mnSearch.add(mntmSearch4); + mnSearch.add(mntmSearch5); + menuBar.add(mnSearch); + + frame.getContentPane().setLayout(new BorderLayout(0, 0)); + + JSplitPane splitPane = new JSplitPane(); + splitPane.setResizeWeight(0.1); + splitPane.setOneTouchExpandable(true); + frame.getContentPane().add(splitPane, BorderLayout.CENTER); + + treeFiles = new JarFileTree(); + splitPane.setLeftComponent(treeFiles); + treeFiles.setDropTarget(new DropTarget() { + @Override + public final void drop(final DropTargetDropEvent event) { + try { + event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); + Object transferData = event.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); + if (transferData == null) { + return; + } + @SuppressWarnings("unchecked") + List ls = (List) transferData; + File file = ls.get(0); + if (ls.size() > 1) { + JOptionPane.showMessageDialog(null, "Only one file can be accepted. Going with: " + file); + } + if (file.getName().toLowerCase().endsWith(".jar")) { + recaf.openFile(file); + } else { + JOptionPane.showMessageDialog(null, "Input was not a java archive (jar)."); + } + } catch (UnsupportedFlavorException ex) { + JOptionPane.showMessageDialog(null, "Input was not a java archive (jar)."); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }); + + tabbedContent = new TabbedPanel(); + splitPane.setRightComponent(tabbedContent); + + } + + /** + * Creates a new tab with the text of the exception. + * + * @param e The exception. + */ + public void displayError(Throwable e) { + JTextArea text = new JTextArea(); + text.setEditable(false); + text.append(e.getClass().getSimpleName() + ":\n"); + text.append("Message: " + e.getMessage() + "\n"); + text.append("Trace: \n"); + for (StackTraceElement element : e.getStackTrace()) { + text.append(element.toString() + "\n"); + } + + // TODO: Logging of cause + // text.append("Cause: " + e.getCause() + "\n"); + + tabbedContent.addTab("Error: " + e.getClass().getSimpleName(), new JScrollPane(text)); + tabbedContent.setSelectedTab(tabbedContent.getTabCount() - 1); + } + + /** + * Opens up a class tab for the given class-node, or opens an existing page + * if one is found. + * + * @param node The node. + */ + public void addClassView(ClassNode node) { + if (tabbedContent.hasCached(node.name)) { + tabbedContent.setSelectedTab(tabbedContent.getCachedIndex(node.name)); + } else { + tabbedContent.addTab(node.name, new JScrollPane(new ClassDisplayPanel(node))); + tabbedContent.setSelectedTab(tabbedContent.getTabCount() - 1); + int i = tabbedContent.getCachedIndex(node.name); + if (i == -1) { + i = tabbedContent.getTabCount() - 1; + } + tabbedContent.setSelectedTab(i); + } + } + + /** + * Opens up a tab for the given component, or opens an existing page if one + * is found. + * + * @param title + * Title of tab. + * @param component + * Content of tab. + */ + public void openTab(String title, Component component) { + if (tabbedContent.hasCached(title)) { + tabbedContent.setSelectedTab(tabbedContent.getCachedIndex(title)); + } else { + tabbedContent.addTab(title, component); + int i = tabbedContent.getCachedIndex(title); + if (i == -1) { + i = tabbedContent.getTabCount() - 1; + } + tabbedContent.setSelectedTab(i); + } + } + + /** + * Refreshes the tree to display the current jar file. + */ + public void updateTree() { + mnSearch.setEnabled(true); + treeFiles.refresh(); + } + + public JFrame getFrame() { + return frame; + } } diff --git a/src/me/coley/recaf/ui/HtmlRenderer.java b/src/me/coley/recaf/ui/HtmlRenderer.java index 57b309cd5..172d170b5 100644 --- a/src/me/coley/recaf/ui/HtmlRenderer.java +++ b/src/me/coley/recaf/ui/HtmlRenderer.java @@ -5,110 +5,110 @@ import me.coley.recaf.Options; public interface HtmlRenderer { - final String colBlueDark = "#193049"; - final String colTealDark = "#154234"; - final String colGreenDark = "#184216"; - final String colRedDark = "#351717"; - final String colGray = "#555555"; + final String colBlueDark = "#193049"; + final String colTealDark = "#154234"; + final String colGreenDark = "#184216"; + final String colRedDark = "#351717"; + final String colGray = "#555555"; - /** - * HTML escape '&', '<' and '>'. - * - * @param s Text to escape - * @return Text with amp, lt, and gt escaped correctly. - */ - default String escape(String s) { - return s.replace("&", "&").replace("<", "<").replace(">", ">"); - } + /** + * HTML escape '&', '<' and '>'. + * + * @param s Text to escape + * @return Text with amp, lt, and gt escaped correctly. + */ +default String escape(String s) { + return s.replace("&", "&").replace("<", "<").replace(">", ">"); + } - /** - * Converts a given type to a string. - * - * @param type The type object. - * @return String representation of the type object. - */ - default String getTypeStr(Type type) { - return getTypeStr(type, null); - } + /** + * Converts a given type to a string. + * + * @param type The type object. + * @return String representation of the type object. + */ +default String getTypeStr(Type type) { + return getTypeStr(type, null); + } - /** - * Converts a given type to a string. Output will be simplified if - * enabled in passed options. - * - * TODO: this javadoc should either link to documentation for the - * Options class, or document how to use it correctly in this context. - * - * - Charles - * - * @param type The type object. - * @param options Options object. - * @return String representation of the type object. - */ - default String getTypeStr(Type type, Options options) { - String s = ""; - if (type.getDescriptor().length() == 1) { - switch (type.getDescriptor().charAt(0)) { - case 'Z': - return "boolean"; - case 'I': - return "int"; - case 'J': - return "long"; - case 'D': - return "double"; - case 'F': - return "float"; - case 'B': - return "byte"; - case 'C': - return "char"; - case 'S': - return "short"; - case 'V': - return "void"; - default: - return type.getDescriptor(); - } - } else { - s += type.getInternalName(); - } - if (options != null && options.opcodeSimplifyDescriptors && s.contains("/")) { - s = s.substring(s.lastIndexOf("/") + 1); - if (s.endsWith(";")) { - s = s.substring(0, s.length() - 1); - } - } - return s; - } + /** + * Converts a given type to a string. Output will be simplified if + * enabled in passed options. + * + * TODO: this javadoc should either link to documentation for the + * Options class, or document how to use it correctly in this context. + * + * - Charles + * + * @param type The type object. + * @param options Options object. + * @return String representation of the type object. + */ +default String getTypeStr(Type type, Options options) { + String s = ""; + if (type.getDescriptor().length() == 1) { + switch (type.getDescriptor().charAt(0)) { + case 'Z': + return "boolean"; + case 'I': + return "int"; + case 'J': + return "long"; + case 'D': + return "double"; + case 'F': + return "float"; + case 'B': + return "byte"; + case 'C': + return "char"; + case 'S': + return "short"; + case 'V': + return "void"; + default: + return type.getDescriptor(); + } + } else { + s += type.getInternalName(); + } + if (options != null && options.opcodeSimplifyDescriptors && s.contains("/")) { + s = s.substring(s.lastIndexOf("/") + 1); + if (s.endsWith(";")) { + s = s.substring(0, s.length() - 1); + } + } + return s; + } - /** - * Italicize the given text. - * - * @param input Text to italicize. - * @return HTML markup to italicize the text. - */ - default String italic(String input) { - return "" + input + ""; - } + /** + * Italicize the given text. + * + * @param input Text to italicize. + * @return HTML markup to italicize the text. + */ +default String italic(String input) { + return "" + input + ""; + } - /** - * Bold the given text. - * - * @param input Text to bold. - * @return HTML markup with the text bolded. - */ - default String bold(String input) { - return "" + input + ""; - } + /** + * Bold the given text. + * + * @param input Text to bold. + * @return HTML markup with the text bolded. + */ +default String bold(String input) { + return "" + input + ""; + } - /** - * Color the given text. - * - * @param color The color to turn the text, must be a valid HTML color. - * @param input The text to color. - * @return HTML markup with the text colored appropriately. - */ - default String color(String color, String input) { - return "" + input + ""; - } + /** + * Color the given text. + * + * @param color The color to turn the text, must be a valid HTML color. + * @param input The text to color. + * @return HTML markup with the text colored appropriately. + */ +default String color(String color, String input) { + return "" + input + ""; + } } diff --git a/src/me/coley/recaf/ui/Icons.java b/src/me/coley/recaf/ui/Icons.java index 31624ba23..76c47c52b 100644 --- a/src/me/coley/recaf/ui/Icons.java +++ b/src/me/coley/recaf/ui/Icons.java @@ -4,67 +4,67 @@ import javax.swing.ImageIcon; public class Icons { - // Class access - public static final Icon CL_CLASS; - public static final Icon CL_INTERFACE; - public static final Icon CL_ENUM; - public static final Icon CL_ANNOTATION; - // Field access - public static final Icon FL_PUBLIC; - public static final Icon FL_PROTECTED; - public static final Icon FL_PRIVATE; - public static final Icon FL_DEFAULT; - // Method access - public static final Icon ML_PUBLIC; - public static final Icon ML_PROTECTED; - public static final Icon ML_PRIVATE; - public static final Icon ML_DEFAULT; - // General modifiers - public static final Icon MOD_STATIC; - public static final Icon MOD_VOLATILE; - public static final Icon MOD_TRANSIENT; - public static final Icon MOD_SYNTHETIC; - public static final Icon MOD_NATIVE; - public static final Icon MOD_ABSTRACT; - public static final Icon MOD_FINAL; - // Misc - public static final Icon MISC_PACKAGE; - public static final Icon MISC_RESULT; + // Class access + public static final Icon CL_CLASS; + public static final Icon CL_INTERFACE; + public static final Icon CL_ENUM; + public static final Icon CL_ANNOTATION; + // Field access + public static final Icon FL_PUBLIC; + public static final Icon FL_PROTECTED; + public static final Icon FL_PRIVATE; + public static final Icon FL_DEFAULT; + // Method access + public static final Icon ML_PUBLIC; + public static final Icon ML_PROTECTED; + public static final Icon ML_PRIVATE; + public static final Icon ML_DEFAULT; + // General modifiers + public static final Icon MOD_STATIC; + public static final Icon MOD_VOLATILE; + public static final Icon MOD_TRANSIENT; + public static final Icon MOD_SYNTHETIC; + public static final Icon MOD_NATIVE; + public static final Icon MOD_ABSTRACT; + public static final Icon MOD_FINAL; + // Misc + public static final Icon MISC_PACKAGE; + public static final Icon MISC_RESULT; - static { - // - CL_CLASS = load("class.png"); - CL_INTERFACE = load("interface.png"); - CL_ENUM = load("enum.png"); - CL_ANNOTATION = load("annotation.png"); - // - FL_PUBLIC = load("field_public.png"); - FL_PROTECTED = load("field_protected.png"); - FL_PRIVATE = load("field_private.png"); - FL_DEFAULT = load("field_default.png"); - // - ML_PUBLIC = load("method_public.png"); - ML_PROTECTED = load("method_protected.png"); - ML_PRIVATE = load("method_private.png"); - ML_DEFAULT = load("method_default.png"); - // - MOD_STATIC = load("static.png"); - MOD_VOLATILE = load("volatile.png"); - MOD_TRANSIENT = load("transient.png"); - MOD_SYNTHETIC = load("synthetic.png"); - MOD_NATIVE = load("native.png"); - MOD_ABSTRACT = load("abstract.png"); - MOD_FINAL = load("final.png"); - // - MISC_PACKAGE = load("package.png"); - MISC_RESULT = load("result.png"); - } + static { + // + CL_CLASS = load("class.png"); + CL_INTERFACE = load("interface.png"); + CL_ENUM = load("enum.png"); + CL_ANNOTATION = load("annotation.png"); + // + FL_PUBLIC = load("field_public.png"); + FL_PROTECTED = load("field_protected.png"); + FL_PRIVATE = load("field_private.png"); + FL_DEFAULT = load("field_default.png"); + // + ML_PUBLIC = load("method_public.png"); + ML_PROTECTED = load("method_protected.png"); + ML_PRIVATE = load("method_private.png"); + ML_DEFAULT = load("method_default.png"); + // + MOD_STATIC = load("static.png"); + MOD_VOLATILE = load("volatile.png"); + MOD_TRANSIENT = load("transient.png"); + MOD_SYNTHETIC = load("synthetic.png"); + MOD_NATIVE = load("native.png"); + MOD_ABSTRACT = load("abstract.png"); + MOD_FINAL = load("final.png"); + // + MISC_PACKAGE = load("package.png"); + MISC_RESULT = load("result.png"); + } - private static Icon load(String url) { - // TODO: Why does File.separator force non-relative path names but this - // works fine? - String prefix = "/resources/"; - String file = prefix + url; - return new ImageIcon(Icons.class.getResource(file)); - } + private static Icon load(String url) { + // TODO: Why does File.separator force non-relative path names but this + // works fine? + String prefix = "/resources/"; + String file = prefix + url; + return new ImageIcon(Icons.class.getResource(file)); + } } diff --git a/src/me/coley/recaf/ui/component/LabeledComponent.java b/src/me/coley/recaf/ui/component/LabeledComponent.java index 33f296bf2..c6cc0a2f9 100644 --- a/src/me/coley/recaf/ui/component/LabeledComponent.java +++ b/src/me/coley/recaf/ui/component/LabeledComponent.java @@ -8,18 +8,18 @@ /** * Basic wrapper for: - * + * *
  * Label[text] : Component
  * 
- * + * * @author Matt */ @SuppressWarnings("serial") public class LabeledComponent extends JPanel { - public LabeledComponent(String label, JComponent component) { - setLayout(new BorderLayout()); - add(new JLabel(label), BorderLayout.WEST); - add(component, BorderLayout.CENTER); - } + public LabeledComponent(String label, JComponent component) { + setLayout(new BorderLayout()); + add(new JLabel(label), BorderLayout.WEST); + add(component, BorderLayout.CENTER); + } } diff --git a/src/me/coley/recaf/ui/component/ReleaseListener.java b/src/me/coley/recaf/ui/component/ReleaseListener.java index 45f068e94..1df1f017a 100644 --- a/src/me/coley/recaf/ui/component/ReleaseListener.java +++ b/src/me/coley/recaf/ui/component/ReleaseListener.java @@ -7,19 +7,19 @@ * Interface with defaults for all but release. Makes things implementing mouse * listener look a little cleaner (Since the stub event receivers won't need * to be declared) - * + * * @author Matt */ public interface ReleaseListener extends MouseListener { - @Override - default void mouseClicked(MouseEvent e) {} + @Override +default void mouseClicked(MouseEvent e) {} - @Override - default void mousePressed(MouseEvent e) {} + @Override +default void mousePressed(MouseEvent e) {} - @Override - default void mouseEntered(MouseEvent e) {} + @Override +default void mouseEntered(MouseEvent e) {} - @Override - default void mouseExited(MouseEvent e) {} + @Override +default void mouseExited(MouseEvent e) {} } diff --git a/src/me/coley/recaf/ui/component/action/ActionButton.java b/src/me/coley/recaf/ui/component/action/ActionButton.java index b3ec9501b..a7c0f44ea 100644 --- a/src/me/coley/recaf/ui/component/action/ActionButton.java +++ b/src/me/coley/recaf/ui/component/action/ActionButton.java @@ -7,13 +7,13 @@ @SuppressWarnings("serial") public class ActionButton extends JButton { - public ActionButton(String text, Runnable r) { - super(text); - addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - r.run(); - } - }); - } + public ActionButton(String text, Runnable r) { + super(text); + addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + r.run(); + } + }); + } } diff --git a/src/me/coley/recaf/ui/component/action/ActionCheckBox.java b/src/me/coley/recaf/ui/component/action/ActionCheckBox.java index 7ea61f22f..998f39d38 100644 --- a/src/me/coley/recaf/ui/component/action/ActionCheckBox.java +++ b/src/me/coley/recaf/ui/component/action/ActionCheckBox.java @@ -8,13 +8,13 @@ @SuppressWarnings("serial") public class ActionCheckBox extends JCheckBox { - public ActionCheckBox(String text, boolean defaultValue, Consumer r) { - super(text, defaultValue); - addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - r.accept(isSelected()); - } - }); - } + public ActionCheckBox(String text, boolean defaultValue, Consumer r) { + super(text, defaultValue); + addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + r.accept(isSelected()); + } + }); + } } diff --git a/src/me/coley/recaf/ui/component/action/ActionMenuItem.java b/src/me/coley/recaf/ui/component/action/ActionMenuItem.java index b1802ddb2..5901f9a78 100644 --- a/src/me/coley/recaf/ui/component/action/ActionMenuItem.java +++ b/src/me/coley/recaf/ui/component/action/ActionMenuItem.java @@ -8,18 +8,18 @@ @SuppressWarnings("serial") public class ActionMenuItem extends JMenuItem { - public ActionMenuItem(String text, Runnable action) { - this(text, new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - action.run(); - } - }); - } + public ActionMenuItem(String text, Runnable action) { + this(text, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + action.run(); + } + }); + } - public ActionMenuItem(String text, ActionListener action) { - super(text); - addActionListener(action); - } + public ActionMenuItem(String text, ActionListener action) { + super(text); + addActionListener(action); + } } diff --git a/src/me/coley/recaf/ui/component/action/ActionTextField.java b/src/me/coley/recaf/ui/component/action/ActionTextField.java index c0dbd306c..e1933c3e3 100644 --- a/src/me/coley/recaf/ui/component/action/ActionTextField.java +++ b/src/me/coley/recaf/ui/component/action/ActionTextField.java @@ -9,31 +9,31 @@ @SuppressWarnings("serial") public class ActionTextField extends JTextField { - public ActionTextField(Object content, Consumer textAction) { - this(content.toString(), textAction); - } + public ActionTextField(Object content, Consumer textAction) { + this(content.toString(), textAction); + } - public ActionTextField(String content, Consumer textAction) { - super(resolve(content)); - setFont(FontUtil.monospace); - addKeyListener(new KeyListener() { - @Override - public void keyTyped(KeyEvent e) {} + public ActionTextField(String content, Consumer textAction) { + super(resolve(content)); + setFont(FontUtil.monospace); + addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) {} - @Override - public void keyPressed(KeyEvent e) {} + @Override + public void keyPressed(KeyEvent e) {} - @Override - public void keyReleased(KeyEvent e) { - textAction.accept(getText()); - } - }); - } + @Override + public void keyReleased(KeyEvent e) { + textAction.accept(getText()); + } + }); + } - private static String resolve(String content) { - if (content == null) { - return ""; - } - return content; - } + private static String resolve(String content) { + if (content == null) { + return ""; + } + return content; + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/AccessBox.java b/src/me/coley/recaf/ui/component/internalframe/AccessBox.java index 2295cdc42..bff00334e 100644 --- a/src/me/coley/recaf/ui/component/internalframe/AccessBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/AccessBox.java @@ -13,23 +13,23 @@ @SuppressWarnings("serial") public class AccessBox extends BasicFrame { - public AccessBox(Object value, JComponent owner) throws Exception { - AccessPanel panel = createPanel(value, owner); - setLayout(new BorderLayout()); - add(panel, BorderLayout.CENTER); - setTitle(panel.getTitle()); - setVisible(true); - } - - private static AccessPanel createPanel(Object value, JComponent owner) throws Exception { - if (value instanceof ClassNode) { - return new AccessPanel((ClassNode) value, owner); - } else if (value instanceof FieldNode) { - return new AccessPanel((FieldNode) value, owner); - } else if (value instanceof MethodNode) { - return new AccessPanel((MethodNode) value, owner); - } - return null; - } + public AccessBox(Object value, JComponent owner) throws Exception { + AccessPanel panel = createPanel(value, owner); + setLayout(new BorderLayout()); + add(panel, BorderLayout.CENTER); + setTitle(panel.getTitle()); + setVisible(true); + } + + private static AccessPanel createPanel(Object value, JComponent owner) throws Exception { + if (value instanceof ClassNode) { + return new AccessPanel((ClassNode) value, owner); + } else if (value instanceof FieldNode) { + return new AccessPanel((FieldNode) value, owner); + } else if (value instanceof MethodNode) { + return new AccessPanel((MethodNode) value, owner); + } + return null; + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/BasicFrame.java b/src/me/coley/recaf/ui/component/internalframe/BasicFrame.java index 830a18653..847b8415e 100644 --- a/src/me/coley/recaf/ui/component/internalframe/BasicFrame.java +++ b/src/me/coley/recaf/ui/component/internalframe/BasicFrame.java @@ -6,24 +6,24 @@ @SuppressWarnings("serial") public class BasicFrame extends JInternalFrame { - protected int padding = 12; - - public BasicFrame() { - this(""); - } - - public BasicFrame(String title) { - super(title); - setMaximumSize(new Dimension(400, 400)); - setResizable(true); - setIconifiable(true); - setClosable(true); - } + protected int padding = 12; - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - pack(); - setSize(getWidth() + padding, getHeight() + padding); - } + public BasicFrame() { + this(""); + } + + public BasicFrame(String title) { + super(title); + setMaximumSize(new Dimension(400, 400)); + setResizable(true); + setIconifiable(true); + setClosable(true); + } + + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + pack(); + setSize(getWidth() + padding, getHeight() + padding); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/DecompileBox.java b/src/me/coley/recaf/ui/component/internalframe/DecompileBox.java index 74e099523..208b9a849 100644 --- a/src/me/coley/recaf/ui/component/internalframe/DecompileBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/DecompileBox.java @@ -5,11 +5,11 @@ @SuppressWarnings("serial") public class DecompileBox extends BasicFrame { - public DecompileBox(DecompilePanel value) throws Exception { - setLayout(new BorderLayout()); - add(value, BorderLayout.CENTER); - setMaximumSize(null); - setTitle(value.getTitle()); - setVisible(true); - } + public DecompileBox(DecompilePanel value) throws Exception { + setLayout(new BorderLayout()); + add(value, BorderLayout.CENTER); + setMaximumSize(null); + setTitle(value.getTitle()); + setVisible(true); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/DefaultValueBox.java b/src/me/coley/recaf/ui/component/internalframe/DefaultValueBox.java index b5bf4a3d2..509ab7018 100644 --- a/src/me/coley/recaf/ui/component/internalframe/DefaultValueBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/DefaultValueBox.java @@ -8,11 +8,11 @@ @SuppressWarnings("serial") public class DefaultValueBox extends BasicFrame { - public DefaultValueBox(String fieldName, Object init, Consumer action) throws Exception { - super("Default Value: " + fieldName); - setLayout(new BorderLayout()); - String value = init == null ? "" : init.toString(); - add(new LabeledComponent("Default Value: ", new ActionTextField(value, action)), BorderLayout.CENTER); - setVisible(true); - } + public DefaultValueBox(String fieldName, Object init, Consumer action) throws Exception { + super("Default Value: " + fieldName); + setLayout(new BorderLayout()); + String value = init == null ? "" : init.toString(); + add(new LabeledComponent("Default Value: ", new ActionTextField(value, action)), BorderLayout.CENTER); + setVisible(true); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/EditBox.java b/src/me/coley/recaf/ui/component/internalframe/EditBox.java index e3e83fa39..e2c0e6146 100644 --- a/src/me/coley/recaf/ui/component/internalframe/EditBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/EditBox.java @@ -9,36 +9,36 @@ // Not extending BasicFrame is intentional. @SuppressWarnings("serial") public class EditBox extends JInternalFrame { - private boolean hasContent; - - public EditBox(String title) { - super(title); - setResizable(true); - setIconifiable(true); - setClosable(true); - setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); - } - - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - if (visible) { - pack(); - // setMinimumSize(getSize()); - } - } - - @Override - public Component add(Component comp) { - // Don't count internal swing components - if (!(comp instanceof BasicInternalFrameTitlePane)) { - hasContent = true; - } - return super.add(comp); - } - - public boolean hasContent() { - return hasContent; - } + private boolean hasContent; + + public EditBox(String title) { + super(title); + setResizable(true); + setIconifiable(true); + setClosable(true); + setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); + } + + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + if (visible) { + pack(); + // setMinimumSize(getSize()); + } + } + + @Override + public Component add(Component comp) { + // Don't count internal swing components + if (!(comp instanceof BasicInternalFrameTitlePane)) { + hasContent = true; + } + return super.add(comp); + } + + public boolean hasContent() { + return hasContent; + } } \ No newline at end of file diff --git a/src/me/coley/recaf/ui/component/internalframe/ExceptionsListBox.java b/src/me/coley/recaf/ui/component/internalframe/ExceptionsListBox.java index f61dea093..82bf07bdc 100644 --- a/src/me/coley/recaf/ui/component/internalframe/ExceptionsListBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/ExceptionsListBox.java @@ -14,43 +14,43 @@ @SuppressWarnings("serial") public class ExceptionsListBox extends BasicFrame { - private static final Color bg = new Color(166, 166, 166); + private static final Color bg = new Color(166, 166, 166); - public ExceptionsListBox(MethodNode mn) { - super("Exceptions: " + mn.name); - setBackground(bg); - setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS)); - update(mn); - setVisible(true); - } + public ExceptionsListBox(MethodNode mn) { + super("Exceptions: " + mn.name); + setBackground(bg); + setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS)); + update(mn); + setVisible(true); + } - private void update(MethodNode mn) { - getContentPane().removeAll(); - for (int i = 0; i < mn.exceptions.size(); i++) { - final int j = i; - String ex = mn.exceptions.get(i); - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - panel.add(new ActionButton("Delete", () -> { - mn.exceptions.remove(j); - update(mn); - }), BorderLayout.WEST); - panel.add(new ActionTextField(ex, s -> mn.exceptions.set(j, s)), BorderLayout.CENTER); - add(panel); - } - JPanel panel = new JPanel(); - { - final JTextField text = new JTextField(); - panel.setLayout(new BorderLayout()); - panel.add(new ActionButton("Add", () -> { - mn.exceptions.add(text.getText()); - setSize(getWidth(), getHeight() + 30); - update(mn); - }), BorderLayout.WEST); - panel.add(text, BorderLayout.CENTER); - add(panel); - } - getContentPane().repaint(); - getContentPane().validate(); - } + private void update(MethodNode mn) { + getContentPane().removeAll(); + for (int i = 0; i < mn.exceptions.size(); i++) { + final int j = i; + String ex = mn.exceptions.get(i); + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.add(new ActionButton("Delete", () -> { + mn.exceptions.remove(j); + update(mn); + }), BorderLayout.WEST); + panel.add(new ActionTextField(ex, s -> mn.exceptions.set(j, s)), BorderLayout.CENTER); + add(panel); + } + JPanel panel = new JPanel(); + { + final JTextField text = new JTextField(); + panel.setLayout(new BorderLayout()); + panel.add(new ActionButton("Add", () -> { + mn.exceptions.add(text.getText()); + setSize(getWidth(), getHeight() + 30); + update(mn); + }), BorderLayout.WEST); + panel.add(text, BorderLayout.CENTER); + add(panel); + } + getContentPane().repaint(); + getContentPane().validate(); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/MemberDefinitionBox.java b/src/me/coley/recaf/ui/component/internalframe/MemberDefinitionBox.java index 1ab2be825..439e26bc6 100644 --- a/src/me/coley/recaf/ui/component/internalframe/MemberDefinitionBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/MemberDefinitionBox.java @@ -13,47 +13,47 @@ @SuppressWarnings("serial") public class MemberDefinitionBox extends BasicFrame { - public MemberDefinitionBox(FieldNode fn, JList list) { - super("Definition: " + fn.name); - setup(fn.name, n -> { - fn.name = n; - list.repaint(); - }, fn.desc, d -> { - fn.desc = d; - list.repaint(); - }, fn.signature, s -> { - if (s.isEmpty()) { - fn.signature = null; - } else { - fn.signature = s; - } - }); - } - - public MemberDefinitionBox(MethodNode mn, JList list) { - super("Definition: " + mn.name); - setup(mn.name, n -> { - mn.name = n; - list.repaint(); - }, mn.desc, d -> { - mn.desc = d; - list.repaint(); - }, mn.signature, s -> { - if (s.isEmpty()) { - mn.signature = null; - } else { - mn.signature = s; - } - }); - } - - private void setup(String name, Consumer nameConsumer, String desc, Consumer descConsumer, String signature, - Consumer signatureConsumer) { - setLayout(new GridLayout(3, 1)); - add(new LabeledComponent("Name: ", new ActionTextField(name, nameConsumer))); - add(new LabeledComponent("Descriptor: ", new ActionTextField(desc, descConsumer))); - add(new LabeledComponent("Signature: ", new ActionTextField(signature == null ? "" : signature, signatureConsumer))); - setVisible(true); - } + public MemberDefinitionBox(FieldNode fn, JList list) { + super("Definition: " + fn.name); + setup(fn.name, n -> { + fn.name = n; + list.repaint(); + }, fn.desc, d -> { + fn.desc = d; + list.repaint(); + }, fn.signature, s -> { + if (s.isEmpty()) { + fn.signature = null; + } else { + fn.signature = s; + } + }); + } + + public MemberDefinitionBox(MethodNode mn, JList list) { + super("Definition: " + mn.name); + setup(mn.name, n -> { + mn.name = n; + list.repaint(); + }, mn.desc, d -> { + mn.desc = d; + list.repaint(); + }, mn.signature, s -> { + if (s.isEmpty()) { + mn.signature = null; + } else { + mn.signature = s; + } + }); + } + + private void setup(String name, Consumer nameConsumer, String desc, Consumer descConsumer, String signature, + Consumer signatureConsumer) { + setLayout(new GridLayout(3, 1)); + add(new LabeledComponent("Name: ", new ActionTextField(name, nameConsumer))); + add(new LabeledComponent("Descriptor: ", new ActionTextField(desc, descConsumer))); + add(new LabeledComponent("Signature: ", new ActionTextField(signature == null ? "" : signature, signatureConsumer))); + setVisible(true); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java b/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java index 9d626cef8..ddfb178e5 100644 --- a/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java @@ -26,273 +26,273 @@ @SuppressWarnings("serial") public class OpcodeCreationBox extends BasicFrame { - private static final Map nameToType = new HashMap<>(); - private final Map> typeToOpcodeSelector = new HashMap<>(); - private final Map> typeToMapOfThings = new HashMap<>(); - private String currentType; + private static final Map nameToType = new HashMap<>(); + private final Map> typeToOpcodeSelector = new HashMap<>(); + private final Map> typeToMapOfThings = new HashMap<>(); + private String currentType; - public OpcodeCreationBox(boolean insertBefore, OpcodeList list, MethodNode method, AbstractInsnNode target) { - super("Create Opcode"); - setLayout(new BorderLayout()); - // Setting up center of the border panel to be a inner card-layout - // panel. - JPanel content = new JPanel(); - JComboBox comboCard = new JComboBox<>(from(nameToType.keySet())); - comboCard.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent evt) { - String item = (String) evt.getItem(); - currentType = item; - CardLayout cl = (CardLayout) (content.getLayout()); - cl.show(content, item); - } - }); - content.setLayout(new CardLayout()); - // Creating cards per opcode-type. - for (String key : nameToType.keySet()) { - Map map = new HashMap<>(); - typeToMapOfThings.put(key, map); - JPanel card = new JPanel(); - card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS)); - int type = nameToType.get(key); - content.add(card, key); - // Adding content to cards - String[] codes = OpcodeUtil.typeToCodes(type); - JComboBox comboCodes = new JComboBox<>(codes); - if (codes.length > 1) { - card.add(new LabeledComponent("Opcode: ", comboCodes)); - } - typeToOpcodeSelector.put(key, comboCodes); - // Type specific content - switch (type) { - case AbstractInsnNode.LDC_INSN: - case AbstractInsnNode.INT_INSN: { - JTextField text = new JTextField(); - card.add(new LabeledComponent("Value: ", text)); - map.put("value", text); - break; - } - case AbstractInsnNode.IINC_INSN: { - card.add(new JScrollPane(VariableTable.create(list, method))); - JTextField var = new JTextField(); - JTextField text = new JTextField(); - card.add(new LabeledComponent("Variable: ", var)); - card.add(new LabeledComponent("Increment: ", text)); - map.put("var", var); - map.put("inc", text); - break; - } - case AbstractInsnNode.VAR_INSN: { - card.add(new JScrollPane(VariableTable.create(list, method))); - JTextField var = new JTextField(); - card.add(new LabeledComponent("Variable: ", var)); - map.put("var", var); - break; - } - case AbstractInsnNode.TYPE_INSN: { - JTextField text = new JTextField(); - card.add(new LabeledComponent("Type: ", text)); - map.put("value", text); - break; - } - case AbstractInsnNode.FIELD_INSN: - case AbstractInsnNode.METHOD_INSN: { - JTextField owner = new JTextField(); - JTextField name = new JTextField(); - JTextField desc = new JTextField(); - card.add(new LabeledComponent("Owner: ", owner)); - card.add(new LabeledComponent("Name: ", name)); - card.add(new LabeledComponent("Desc: ", desc)); - map.put("owner", owner); - map.put("name", name); - map.put("desc", desc); - break; - } - case AbstractInsnNode.MULTIANEWARRAY_INSN: { - JTextField desc = new JTextField(); - JTextField dim = new JTextField(); - card.add(new LabeledComponent("Desc: ", desc)); - card.add(new LabeledComponent("Dimensions: ", dim)); - map.put("desc", desc); - map.put("dims", dim); - break; - } - case AbstractInsnNode.LINE: { - JTextField text = new JTextField(); - card.add(new LabeledComponent("Line: ", text)); - map.put("value", text); - break; - } - // TODO: The rest of these - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - break; - case AbstractInsnNode.JUMP_INSN: - break; - case AbstractInsnNode.LABEL: - break; - case AbstractInsnNode.TABLESWITCH_INSN: - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - break; - case AbstractInsnNode.FRAME: - break; - } - } - // Action for adding opcode. - ActionButton btn = new ActionButton("Add Opcode", () -> { - AbstractInsnNode ain = create(); - if (ain != null) { - // Insert - if (insertBefore) { - method.instructions.insertBefore(target, ain); - } else { - method.instructions.insert(target, ain); - } - list.repopulate(); - // Close window - try { - setClosed(true); - } catch (PropertyVetoException e) { - e.printStackTrace(); - } - } else { - // Couldn't make insn, show error. - setTitle("Error: Check inputs!"); - } - }); - add(content, BorderLayout.CENTER); - add(btn, BorderLayout.SOUTH); - add(comboCard, BorderLayout.NORTH); - setVisible(true); - pack(); - } + public OpcodeCreationBox(boolean insertBefore, OpcodeList list, MethodNode method, AbstractInsnNode target) { + super("Create Opcode"); + setLayout(new BorderLayout()); + // Setting up center of the border panel to be a inner card-layout + // panel. + JPanel content = new JPanel(); + JComboBox comboCard = new JComboBox<>(from(nameToType.keySet())); + comboCard.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent evt) { + String item = (String) evt.getItem(); + currentType = item; + CardLayout cl = (CardLayout) (content.getLayout()); + cl.show(content, item); + } + }); + content.setLayout(new CardLayout()); + // Creating cards per opcode-type. + for (String key : nameToType.keySet()) { + Map map = new HashMap<>(); + typeToMapOfThings.put(key, map); + JPanel card = new JPanel(); + card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS)); + int type = nameToType.get(key); + content.add(card, key); + // Adding content to cards + String[] codes = OpcodeUtil.typeToCodes(type); + JComboBox comboCodes = new JComboBox<>(codes); + if (codes.length > 1) { + card.add(new LabeledComponent("Opcode: ", comboCodes)); + } + typeToOpcodeSelector.put(key, comboCodes); + // Type specific content + switch (type) { + case AbstractInsnNode.LDC_INSN: + case AbstractInsnNode.INT_INSN: { + JTextField text = new JTextField(); + card.add(new LabeledComponent("Value: ", text)); + map.put("value", text); + break; + } + case AbstractInsnNode.IINC_INSN: { + card.add(new JScrollPane(VariableTable.create(list, method))); + JTextField var = new JTextField(); + JTextField text = new JTextField(); + card.add(new LabeledComponent("Variable: ", var)); + card.add(new LabeledComponent("Increment: ", text)); + map.put("var", var); + map.put("inc", text); + break; + } + case AbstractInsnNode.VAR_INSN: { + card.add(new JScrollPane(VariableTable.create(list, method))); + JTextField var = new JTextField(); + card.add(new LabeledComponent("Variable: ", var)); + map.put("var", var); + break; + } + case AbstractInsnNode.TYPE_INSN: { + JTextField text = new JTextField(); + card.add(new LabeledComponent("Type: ", text)); + map.put("value", text); + break; + } + case AbstractInsnNode.FIELD_INSN: + case AbstractInsnNode.METHOD_INSN: { + JTextField owner = new JTextField(); + JTextField name = new JTextField(); + JTextField desc = new JTextField(); + card.add(new LabeledComponent("Owner: ", owner)); + card.add(new LabeledComponent("Name: ", name)); + card.add(new LabeledComponent("Desc: ", desc)); + map.put("owner", owner); + map.put("name", name); + map.put("desc", desc); + break; + } + case AbstractInsnNode.MULTIANEWARRAY_INSN: { + JTextField desc = new JTextField(); + JTextField dim = new JTextField(); + card.add(new LabeledComponent("Desc: ", desc)); + card.add(new LabeledComponent("Dimensions: ", dim)); + map.put("desc", desc); + map.put("dims", dim); + break; + } + case AbstractInsnNode.LINE: { + JTextField text = new JTextField(); + card.add(new LabeledComponent("Line: ", text)); + map.put("value", text); + break; + } + // TODO: The rest of these + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + break; + case AbstractInsnNode.JUMP_INSN: + break; + case AbstractInsnNode.LABEL: + break; + case AbstractInsnNode.TABLESWITCH_INSN: + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + break; + case AbstractInsnNode.FRAME: + break; + } + } + // Action for adding opcode. + ActionButton btn = new ActionButton("Add Opcode", () -> { + AbstractInsnNode ain = create(); + if (ain != null) { + // Insert + if (insertBefore) { + method.instructions.insertBefore(target, ain); + } else { + method.instructions.insert(target, ain); + } + list.repopulate(); + // Close window + try { + setClosed(true); + } catch (PropertyVetoException e) { + e.printStackTrace(); + } + } else { + // Couldn't make insn, show error. + setTitle("Error: Check inputs!"); + } + }); + add(content, BorderLayout.CENTER); + add(btn, BorderLayout.SOUTH); + add(comboCard, BorderLayout.NORTH); + setVisible(true); + pack(); + } - /** - * Create an opcode from the current open card. If there's an input - * error no node is returned. - * - * @return The opcode created. - */ - public AbstractInsnNode create() { - try { - switch (nameToType.get(currentType)) { - case AbstractInsnNode.INSN: - return new InsnNode(getOpcode()); - case AbstractInsnNode.INT_INSN: - return new IntInsnNode(getOpcode(), getInt("value")); - case AbstractInsnNode.VAR_INSN: - return new VarInsnNode(getOpcode(), getInt("var")); - case AbstractInsnNode.TYPE_INSN: - return new TypeInsnNode(getOpcode(), getString("value")); - case AbstractInsnNode.FIELD_INSN: - return new FieldInsnNode(getOpcode(), getString("owner"), getString("name"), getString("desc")); - case AbstractInsnNode.METHOD_INSN: - return new MethodInsnNode(getOpcode(), getString("owner"), getString("name"), getString("desc"), - getOpcode() == Opcodes.INVOKEINTERFACE); - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - break; - case AbstractInsnNode.LABEL: - return new LabelNode(); - case AbstractInsnNode.LDC_INSN: - return new LdcInsnNode(get("value")); - case AbstractInsnNode.IINC_INSN: - return new IincInsnNode(getInt("var"), getInt("inc")); - case AbstractInsnNode.LINE: - return new LineNumberNode(getInt("value"), new LabelNode()); - case AbstractInsnNode.MULTIANEWARRAY_INSN: - return new MultiANewArrayInsnNode(getString("desc"), getInt("dims")); - case AbstractInsnNode.JUMP_INSN: - break; - case AbstractInsnNode.TABLESWITCH_INSN: - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - break; - case AbstractInsnNode.FRAME: - break; - } - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + /** + * Create an opcode from the current open card. If there's an input + * error no node is returned. + * + * @return The opcode created. + */ + public AbstractInsnNode create() { + try { + switch (nameToType.get(currentType)) { + case AbstractInsnNode.INSN: + return new InsnNode(getOpcode()); + case AbstractInsnNode.INT_INSN: + return new IntInsnNode(getOpcode(), getInt("value")); + case AbstractInsnNode.VAR_INSN: + return new VarInsnNode(getOpcode(), getInt("var")); + case AbstractInsnNode.TYPE_INSN: + return new TypeInsnNode(getOpcode(), getString("value")); + case AbstractInsnNode.FIELD_INSN: + return new FieldInsnNode(getOpcode(), getString("owner"), getString("name"), getString("desc")); + case AbstractInsnNode.METHOD_INSN: + return new MethodInsnNode(getOpcode(), getString("owner"), getString("name"), getString("desc"), + getOpcode() == Opcodes.INVOKEINTERFACE); + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + break; + case AbstractInsnNode.LABEL: + return new LabelNode(); + case AbstractInsnNode.LDC_INSN: + return new LdcInsnNode(get("value")); + case AbstractInsnNode.IINC_INSN: + return new IincInsnNode(getInt("var"), getInt("inc")); + case AbstractInsnNode.LINE: + return new LineNumberNode(getInt("value"), new LabelNode()); + case AbstractInsnNode.MULTIANEWARRAY_INSN: + return new MultiANewArrayInsnNode(getString("desc"), getInt("dims")); + case AbstractInsnNode.JUMP_INSN: + break; + case AbstractInsnNode.TABLESWITCH_INSN: + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + break; + case AbstractInsnNode.FRAME: + break; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } - /** - * Get selected opcode. - * - * @return - */ - private int getOpcode() { - return OpcodeUtil.nameToOpcode(typeToOpcodeSelector.get(currentType).getSelectedItem().toString()); - } + /** + * Get selected opcode. + * + * @return + */ + private int getOpcode() { + return OpcodeUtil.nameToOpcode(typeToOpcodeSelector.get(currentType).getSelectedItem().toString()); + } - /** - * Get value for the current card pertaining to the given key as a String. - * - * @param key - * Label associated with an input. - * @return - */ - private String getString(String key) { - return get(key).toString(); - } + /** + * Get value for the current card pertaining to the given key as a String. + * + * @param key + * Label associated with an input. + * @return + */ + private String getString(String key) { + return get(key).toString(); + } - /** - * Get value for the current card pertaining to the given key as an integer. - * - * @param key - * Label associated with an input. - * @return - */ - private int getInt(String key) { - return Integer.parseInt(get(key).toString()); - } + /** + * Get value for the current card pertaining to the given key as an integer. + * + * @param key + * Label associated with an input. + * @return + */ + private int getInt(String key) { + return Integer.parseInt(get(key).toString()); + } - /** - * Get value for the current card pertaining to the given key. - * - * @param key - * Label associated with an input. - * @return - */ - private Object get(String key) { - JTextField field = typeToMapOfThings.get(currentType).get(key); - if (field != null) { - return field.getText(); - } - return null; - } + /** + * Get value for the current card pertaining to the given key. + * + * @param key + * Label associated with an input. + * @return + */ + private Object get(String key) { + JTextField field = typeToMapOfThings.get(currentType).get(key); + if (field != null) { + return field.getText(); + } + return null; + } - /** - * Set to array. - * - * @param set - * @return - */ - private static String[] from(Set set) { - String[] s = new String[set.size()]; - int i = 0; - for (String ss : set) { - s[i++] = ss; - } - return s; - } + /** + * Set to array. + * + * @param set + * @return + */ + private static String[] from(Set set) { + String[] s = new String[set.size()]; + int i = 0; + for (String ss : set) { + s[i++] = ss; + } + return s; + } - static { - // Commenting out the lines that would add cards for unsupported insn - // types. When they're supported they'll be uncommented. - nameToType.put("Insn", AbstractInsnNode.INSN); - nameToType.put("Field", AbstractInsnNode.FIELD_INSN); - // nameToType.put("Frame", AbstractInsnNode.FRAME); - nameToType.put("Increment", AbstractInsnNode.IINC_INSN); - nameToType.put("Integer", AbstractInsnNode.INT_INSN); - // nameToType.put("Jump", AbstractInsnNode.JUMP_INSN); - nameToType.put("Ldc", AbstractInsnNode.LDC_INSN); - // nameToType.put("Line", AbstractInsnNode.LINE); - // nameToType.put("LookupSwitch", AbstractInsnNode.LOOKUPSWITCH_INSN); - nameToType.put("Method", AbstractInsnNode.METHOD_INSN); - // nameToType.put("MethodIndy", AbstractInsnNode.INVOKE_DYNAMIC_INSN); - nameToType.put("MultiANewArray", AbstractInsnNode.MULTIANEWARRAY_INSN); - // nameToType.put("TableSwitch", AbstractInsnNode.TABLESWITCH_INSN); - nameToType.put("Type", AbstractInsnNode.TYPE_INSN); - nameToType.put("Variable", AbstractInsnNode.VAR_INSN); - } + static { + // Commenting out the lines that would add cards for unsupported insn + // types. When they're supported they'll be uncommented. + nameToType.put("Insn", AbstractInsnNode.INSN); + nameToType.put("Field", AbstractInsnNode.FIELD_INSN); + // nameToType.put("Frame", AbstractInsnNode.FRAME); + nameToType.put("Increment", AbstractInsnNode.IINC_INSN); + nameToType.put("Integer", AbstractInsnNode.INT_INSN); + // nameToType.put("Jump", AbstractInsnNode.JUMP_INSN); + nameToType.put("Ldc", AbstractInsnNode.LDC_INSN); + // nameToType.put("Line", AbstractInsnNode.LINE); + // nameToType.put("LookupSwitch", AbstractInsnNode.LOOKUPSWITCH_INSN); + nameToType.put("Method", AbstractInsnNode.METHOD_INSN); + // nameToType.put("MethodIndy", AbstractInsnNode.INVOKE_DYNAMIC_INSN); + nameToType.put("MultiANewArray", AbstractInsnNode.MULTIANEWARRAY_INSN); + // nameToType.put("TableSwitch", AbstractInsnNode.TABLESWITCH_INSN); + nameToType.put("Type", AbstractInsnNode.TYPE_INSN); + nameToType.put("Variable", AbstractInsnNode.VAR_INSN); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/OpcodeListBox.java b/src/me/coley/recaf/ui/component/internalframe/OpcodeListBox.java index 5e03d1cdc..e740728f8 100644 --- a/src/me/coley/recaf/ui/component/internalframe/OpcodeListBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/OpcodeListBox.java @@ -12,15 +12,15 @@ @SuppressWarnings("serial") public class OpcodeListBox extends BasicFrame { - private static final Color bg = new Color(166, 166, 166); + private static final Color bg = new Color(166, 166, 166); - public OpcodeListBox(ClassDisplayPanel display, MethodNode mn) throws Exception { - super("Opcodes: " + mn.name); - setBackground(bg); - setLayout(new BorderLayout()); - setMaximumSize(new Dimension(900, 900)); - // Opcodes list - add(new JScrollPane(new OpcodeList(display, mn)), BorderLayout.CENTER); - setVisible(true); - } + public OpcodeListBox(ClassDisplayPanel display, MethodNode mn) throws Exception { + super("Opcodes: " + mn.name); + setBackground(bg); + setLayout(new BorderLayout()); + setMaximumSize(new Dimension(900, 900)); + // Opcodes list + add(new JScrollPane(new OpcodeList(display, mn)), BorderLayout.CENTER); + setVisible(true); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/TryCatchBox.java b/src/me/coley/recaf/ui/component/internalframe/TryCatchBox.java index 7f5a5eccb..6deebb9f6 100644 --- a/src/me/coley/recaf/ui/component/internalframe/TryCatchBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/TryCatchBox.java @@ -23,65 +23,65 @@ @SuppressWarnings("serial") public class TryCatchBox extends BasicFrame { - private static final Color bg = new Color(166, 166, 166); - private final JScrollPane scroll = new JScrollPane(); + private static final Color bg = new Color(166, 166, 166); + private final JScrollPane scroll = new JScrollPane(); - public TryCatchBox(MethodNode mn) { - super("Try-Catches: " + mn.name); - setBackground(bg); - setLayout(new BorderLayout()); - add(scroll, BorderLayout.CENTER); - update(mn); - int k = 162; - int s = Math.min(k * 2, k * mn.tryCatchBlocks.size()); - scroll.setPreferredSize(new Dimension(350, s)); - setVisible(true); - } + public TryCatchBox(MethodNode mn) { + super("Try-Catches: " + mn.name); + setBackground(bg); + setLayout(new BorderLayout()); + add(scroll, BorderLayout.CENTER); + update(mn); + int k = 162; + int s = Math.min(k * 2, k * mn.tryCatchBlocks.size()); + scroll.setPreferredSize(new Dimension(350, s)); + setVisible(true); + } - private void update(MethodNode mn) { - JPanel content = new JPanel(); - content.setLayout(new GridLayout(0, 1)); - for (int i = 0; i <= mn.tryCatchBlocks.size(); i++) { - content.add(make(i, mn)); - } - scroll.setViewportView(content); - } + private void update(MethodNode mn) { + JPanel content = new JPanel(); + content.setLayout(new GridLayout(0, 1)); + for (int i = 0; i <= mn.tryCatchBlocks.size(); i++) { + content.add(make(i, mn)); + } + scroll.setViewportView(content); + } - private JPanel make(final int i, MethodNode mn) { - boolean isNew = i >= mn.tryCatchBlocks.size(); - JPanel panel = new JPanel(); - panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); - panel.setBorder(BorderFactory.createEtchedBorder()); - TryCatchBlockNode block; - if (isNew) { - block = new TryCatchBlockNode(null, null, null, ""); - } else { - block = mn.tryCatchBlocks.get(i); - } - List comps = new ArrayList<>(); - comps.add(new LabeledComponent("Start: ", new LabelSwitcherPanel(mn, block.start, l -> block.start = l))); - comps.add(new LabeledComponent("End: ", new LabelSwitcherPanel(mn, block.end, l -> block.end = l))); - comps.add(new LabeledComponent("Handler: ", new LabelSwitcherPanel(mn, block.handler, - l -> block.handler = l))); - comps.add(new LabeledComponent("Type: ", new ActionTextField(block.type, s -> block.type = s))); - if (isNew) { - comps.add(new ActionButton("Insert", () -> { - if (block.start == null || block.end == null || block.handler == null) { - return; - } - mn.tryCatchBlocks.add(block); - update(mn); - })); - } else { - comps.add(new ActionButton("Remove", () -> { - mn.tryCatchBlocks.remove(i); - update(mn); - })); - } - for (JComponent c : comps) { - c.setAlignmentX(JComponent.LEFT_ALIGNMENT); - panel.add(c); - } - return panel; - } + private JPanel make(final int i, MethodNode mn) { + boolean isNew = i >= mn.tryCatchBlocks.size(); + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBorder(BorderFactory.createEtchedBorder()); + TryCatchBlockNode block; + if (isNew) { + block = new TryCatchBlockNode(null, null, null, ""); + } else { + block = mn.tryCatchBlocks.get(i); + } + List comps = new ArrayList<>(); + comps.add(new LabeledComponent("Start: ", new LabelSwitcherPanel(mn, block.start, l -> block.start = l))); + comps.add(new LabeledComponent("End: ", new LabelSwitcherPanel(mn, block.end, l -> block.end = l))); + comps.add(new LabeledComponent("Handler: ", new LabelSwitcherPanel(mn, block.handler, + l -> block.handler = l))); + comps.add(new LabeledComponent("Type: ", new ActionTextField(block.type, s -> block.type = s))); + if (isNew) { + comps.add(new ActionButton("Insert", () -> { + if (block.start == null || block.end == null || block.handler == null) { + return; + } + mn.tryCatchBlocks.add(block); + update(mn); + })); + } else { + comps.add(new ActionButton("Remove", () -> { + mn.tryCatchBlocks.remove(i); + update(mn); + })); + } + for (JComponent c : comps) { + c.setAlignmentX(JComponent.LEFT_ALIGNMENT); + panel.add(c); + } + return panel; + } } diff --git a/src/me/coley/recaf/ui/component/list/MemberNodeClickListener.java b/src/me/coley/recaf/ui/component/list/MemberNodeClickListener.java index 252c120c9..9c40a62d6 100644 --- a/src/me/coley/recaf/ui/component/list/MemberNodeClickListener.java +++ b/src/me/coley/recaf/ui/component/list/MemberNodeClickListener.java @@ -31,207 +31,207 @@ /** * Click listener for ClassNode members (Fields / Methods). Used for * generation context menus and such. - * + * * @author Matt */ public class MemberNodeClickListener implements ReleaseListener { - private final Recaf recaf = Recaf.getInstance(); - private final ClassDisplayPanel display; - private final JList list; - private final ClassNode node; + private final Recaf recaf = Recaf.getInstance(); + private final ClassDisplayPanel display; + private final JList list; + private final ClassNode node; - public MemberNodeClickListener(ClassDisplayPanel display, ClassNode node, JList list) { - this.list = list; - this.node = node; - this.display = display; - } + public MemberNodeClickListener(ClassDisplayPanel display, ClassNode node, JList list) { + this.list = list; + this.node = node; + this.display = display; + } - @Override - public void mouseReleased(MouseEvent e) { - int button = e.getButton(); - // If not left-click, enforce selection at the given location - if (button != MouseEvent.BUTTON1) { - int index = list.locationToIndex(e.getPoint()); - list.setSelectedIndex(index); - } - Object value = list.getSelectedValue(); - if (value == null) { - return; - } - // Middle-click to open editor - // Right-click to open context menu - if (button == MouseEvent.BUTTON2) { - // TODO: Allow users to choose custom middle-click actions - if (value instanceof FieldNode) { - openDefaultValue((FieldNode) value); - } else if (value instanceof MethodNode) { - openOpcodes((MethodNode) value); - } - } else if (button == MouseEvent.BUTTON3) { - createContextMenu(value, e.getX(), e.getY()); - } - } + @Override + public void mouseReleased(MouseEvent e) { + int button = e.getButton(); + // If not left-click, enforce selection at the given location + if (button != MouseEvent.BUTTON1) { + int index = list.locationToIndex(e.getPoint()); + list.setSelectedIndex(index); + } + Object value = list.getSelectedValue(); + if (value == null) { + return; + } + // Middle-click to open editor + // Right-click to open context menu + if (button == MouseEvent.BUTTON2) { + // TODO: Allow users to choose custom middle-click actions + if (value instanceof FieldNode) { + openDefaultValue((FieldNode) value); + } else if (value instanceof MethodNode) { + openOpcodes((MethodNode) value); + } + } else if (button == MouseEvent.BUTTON3) { + createContextMenu(value, e.getX(), e.getY()); + } + } - private void createContextMenu(Object value, int x, int y) { - JPopupMenu popup = new JPopupMenu(); - // Field/Method only actions - if (value instanceof FieldNode) { - FieldNode fn = (FieldNode) value; - if (fn.desc.length() == 1 || fn.desc.equals("Ljava/lang/String;")) { - popup.add(new ActionMenuItem("Edit DefaultValue", () -> openDefaultValue((FieldNode) value))); - } - } else { - MethodNode mn = (MethodNode) value; - if (!Access.isAbstract(mn.access)) { - popup.add(new ActionMenuItem("Edit Opcodes", () -> openOpcodes(mn))); - } - if (mn.exceptions != null) { - popup.add(new ActionMenuItem("Edit Exceptions", () -> openExceptions(mn))); - } - if (mn.tryCatchBlocks != null && !mn.tryCatchBlocks.isEmpty()) { - popup.add(new ActionMenuItem("Edit Try-Catch Blocks", () -> openTryCatchBlocks(mn))); - } - if (mn.instructions.size() > 0) { - popup.add(new ActionMenuItem("Show Decompilation", () -> decompile(node, mn))); - } - } - // General actions - ActionMenuItem itemDefine = new ActionMenuItem("Edit Definition", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - try { - if (value instanceof FieldNode) { - FieldNode fn = (FieldNode) value; - display.addWindow(new MemberDefinitionBox(fn, list)); - } else if (value instanceof MethodNode) { - MethodNode mn = (MethodNode) value; - display.addWindow(new MemberDefinitionBox(mn, list)); - } - } catch (Exception e1) { - display.exception(e1); - } - } - })); - ActionMenuItem itemAccess = new ActionMenuItem("Edit Access", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - try { - if (value instanceof FieldNode) { - FieldNode fn = (FieldNode) value; - display.addWindow(new AccessBox(fn, list)); - } else if (value instanceof MethodNode) { - MethodNode mn = (MethodNode) value; - display.addWindow(new AccessBox(mn, list)); - } - } catch (Exception e1) { - display.exception(e1); - } - } - })); - ActionMenuItem itemDeletThis = new ActionMenuItem("Remove", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - // Show confirmation - if (recaf.options.confirmDeletions) { - int dialogResult = JOptionPane.showConfirmDialog(null, "You sure you want to delete that member?", "Warning", - JOptionPane.YES_NO_OPTION); - if (dialogResult != JOptionPane.YES_OPTION) { - return; - } - } - // remove from class node - if (value instanceof FieldNode) { - node.fields.remove(value); - } else { - node.methods.remove(value); - } - // remove from list - DefaultListModel model = (DefaultListModel) list.getModel(); - model.removeElement(value); + private void createContextMenu(Object value, int x, int y) { + JPopupMenu popup = new JPopupMenu(); + // Field/Method only actions + if (value instanceof FieldNode) { + FieldNode fn = (FieldNode) value; + if (fn.desc.length() == 1 || fn.desc.equals("Ljava/lang/String;")) { + popup.add(new ActionMenuItem("Edit DefaultValue", () -> openDefaultValue((FieldNode) value))); + } + } else { + MethodNode mn = (MethodNode) value; + if (!Access.isAbstract(mn.access)) { + popup.add(new ActionMenuItem("Edit Opcodes", () -> openOpcodes(mn))); + } + if (mn.exceptions != null) { + popup.add(new ActionMenuItem("Edit Exceptions", () -> openExceptions(mn))); + } + if (mn.tryCatchBlocks != null && !mn.tryCatchBlocks.isEmpty()) { + popup.add(new ActionMenuItem("Edit Try-Catch Blocks", () -> openTryCatchBlocks(mn))); + } + if (mn.instructions.size() > 0) { + popup.add(new ActionMenuItem("Show Decompilation", () -> decompile(node, mn))); + } + } + // General actions + ActionMenuItem itemDefine = new ActionMenuItem("Edit Definition", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + if (value instanceof FieldNode) { + FieldNode fn = (FieldNode) value; + display.addWindow(new MemberDefinitionBox(fn, list)); + } else if (value instanceof MethodNode) { + MethodNode mn = (MethodNode) value; + display.addWindow(new MemberDefinitionBox(mn, list)); + } + } catch (Exception e1) { + display.exception(e1); + } + } + })); + ActionMenuItem itemAccess = new ActionMenuItem("Edit Access", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + if (value instanceof FieldNode) { + FieldNode fn = (FieldNode) value; + display.addWindow(new AccessBox(fn, list)); + } else if (value instanceof MethodNode) { + MethodNode mn = (MethodNode) value; + display.addWindow(new AccessBox(mn, list)); + } + } catch (Exception e1) { + display.exception(e1); + } + } + })); + ActionMenuItem itemDeletThis = new ActionMenuItem("Remove", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Show confirmation + if (recaf.options.confirmDeletions) { + int dialogResult = JOptionPane.showConfirmDialog(null, "You sure you want to delete that member?", "Warning", + JOptionPane.YES_NO_OPTION); + if (dialogResult != JOptionPane.YES_OPTION) { + return; + } + } + // remove from class node + if (value instanceof FieldNode) { + node.fields.remove(value); + } else { + node.methods.remove(value); + } + // remove from list + DefaultListModel model = (DefaultListModel) list.getModel(); + model.removeElement(value); - } - })); - popup.add(itemDefine); - popup.add(itemAccess); - popup.add(itemDeletThis); - // Display popup - popup.show(list, x, y); - } + } + })); + popup.add(itemDefine); + popup.add(itemAccess); + popup.add(itemDeletThis); + // Display popup + popup.show(list, x, y); + } - /** - * Opens a window showing the decompiled method belonging to the given - * class. - * - * @param cn - * @param mn - */ - private void decompile(ClassNode cn, MethodNode mn) { - try { - display.addWindow(new DecompileBox(new DecompilePanel(cn, mn))); - } catch (Exception e) { - display.exception(e); - } - } + /** + * Opens a window showing the decompiled method belonging to the given + * class. + * + * @param cn + * @param mn + */ + private void decompile(ClassNode cn, MethodNode mn) { + try { + display.addWindow(new DecompileBox(new DecompilePanel(cn, mn))); + } catch (Exception e) { + display.exception(e); + } + } - /** - * Open window for modifying default value of a field. - * - * @param field - */ - private void openDefaultValue(FieldNode field) { - try { - display.addWindow(new DefaultValueBox(field.name, field.value, value -> { - if (field.desc.length() == 1) { - // Convert string value to int. - if (Misc.isInt(value)) { - field.value = Integer.parseInt(value); - } - } else { - // Just set value as string - field.value = value; - } - })); - } catch (Exception e) { - display.exception(e); - } - } + /** + * Open window for modifying default value of a field. + * + * @param field + */ + private void openDefaultValue(FieldNode field) { + try { + display.addWindow(new DefaultValueBox(field.name, field.value, value -> { + if (field.desc.length() == 1) { + // Convert string value to int. + if (Misc.isInt(value)) { + field.value = Integer.parseInt(value); + } + } else { + // Just set value as string + field.value = value; + } + })); + } catch (Exception e) { + display.exception(e); + } + } - /** - * Open window for modifying method opcodes. - * - * @param method - */ - private void openOpcodes(MethodNode method) { - try { - display.addWindow(new OpcodeListBox(display, method)); - } catch (Exception e) { - display.exception(e); - } - } + /** + * Open window for modifying method opcodes. + * + * @param method + */ + private void openOpcodes(MethodNode method) { + try { + display.addWindow(new OpcodeListBox(display, method)); + } catch (Exception e) { + display.exception(e); + } + } - /** - * Open window for modifying method exceptions. - * - * @param method - */ - private void openExceptions(MethodNode method) { - try { - display.addWindow(new ExceptionsListBox(method)); - } catch (Exception e) { - display.exception(e); - } - } + /** + * Open window for modifying method exceptions. + * + * @param method + */ + private void openExceptions(MethodNode method) { + try { + display.addWindow(new ExceptionsListBox(method)); + } catch (Exception e) { + display.exception(e); + } + } - /** - * Open window for modifying method try-catch blocks. - * - * @param method - */ - private void openTryCatchBlocks(MethodNode method) { - try { - display.addWindow(new TryCatchBox(method)); - } catch (Exception e) { - display.exception(e); - } - } + /** + * Open window for modifying method try-catch blocks. + * + * @param method + */ + private void openTryCatchBlocks(MethodNode method) { + try { + display.addWindow(new TryCatchBox(method)); + } catch (Exception e) { + display.exception(e); + } + } } diff --git a/src/me/coley/recaf/ui/component/list/MemberNodeRenderer.java b/src/me/coley/recaf/ui/component/list/MemberNodeRenderer.java index 6940805c7..82043da1a 100644 --- a/src/me/coley/recaf/ui/component/list/MemberNodeRenderer.java +++ b/src/me/coley/recaf/ui/component/list/MemberNodeRenderer.java @@ -27,116 +27,116 @@ /** * Member node renderer. - * + * * @author Matt */ public class MemberNodeRenderer implements HtmlRenderer, ListCellRenderer { - private static final Color bg = new Color(200, 200, 200); - private static final Color bg2 = new Color(166, 166, 166); - private final Options options; + private static final Color bg = new Color(200, 200, 200); + private static final Color bg2 = new Color(166, 166, 166); + private final Options options; - public MemberNodeRenderer(Options options) { - this.options = options; - } + public MemberNodeRenderer(Options options) { + this.options = options; + } - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, - boolean cellHasFocus) { - list.setBackground(bg2); - String display = value.toString(); - int access = -1; - boolean method = false; - if (value instanceof MethodNode) { - MethodNode node = (MethodNode) value; - display = formatMethod(node); - access = node.access; - method = true; - } else if (value instanceof FieldNode) { - FieldNode node = (FieldNode) value; - display = formatField(node); - access = node.access; - } - JPanel content = new JPanel(); - content.setBackground(bg2); - content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS)); - JLabel label = new JLabel("" + display + ""); - label.setFont(FontUtil.monospace); - formatComponent(label, isSelected); - content.add(label); - addAccess(content, access, method, isSelected); - return content; - } + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + list.setBackground(bg2); + String display = value.toString(); + int access = -1; + boolean method = false; + if (value instanceof MethodNode) { + MethodNode node = (MethodNode) value; + display = formatMethod(node); + access = node.access; + method = true; + } else if (value instanceof FieldNode) { + FieldNode node = (FieldNode) value; + display = formatField(node); + access = node.access; + } + JPanel content = new JPanel(); + content.setBackground(bg2); + content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS)); + JLabel label = new JLabel("" + display + ""); + label.setFont(FontUtil.monospace); + formatComponent(label, isSelected); + content.add(label); + addAccess(content, access, method, isSelected); + return content; + } - private void addAccess(JPanel content, int access, boolean method, boolean selected) { - if (Access.isPublic(access)) { - add(content, selected, method ? Icons.ML_PUBLIC : Icons.FL_PUBLIC); - } else if (Access.isProtected(access)) { - add(content, selected, method ? Icons.ML_PROTECTED : Icons.FL_PROTECTED); - } else if (Access.isPrivate(access)) { - add(content, selected, method ? Icons.ML_PRIVATE : Icons.FL_PRIVATE); - } else if (Access.isPrivate(access)) { - add(content, selected, method ? Icons.ML_PRIVATE : Icons.FL_PRIVATE); - } else { - add(content, selected, method ? Icons.ML_DEFAULT : Icons.FL_DEFAULT); - } - if (Access.isAbstract(access)) { - add(content, selected, MOD_ABSTRACT); - } - if (Access.isFinal(access)) { - add(content, selected, MOD_FINAL); - } - if (Access.isNative(access)) { - add(content, selected, MOD_NATIVE); - } - if (Access.isStatic(access)) { - add(content, selected, MOD_STATIC); - } - if (Access.isTransient(access)) { - add(content, selected, MOD_TRANSIENT); - } - if (Access.isVolatile(access)) { - add(content, selected, MOD_VOLATILE); - } - if (Access.isSynthetic(access) || Access.isBridge(access)) { - add(content, selected, MOD_SYNTHETIC); - } - } + private void addAccess(JPanel content, int access, boolean method, boolean selected) { + if (Access.isPublic(access)) { + add(content, selected, method ? Icons.ML_PUBLIC : Icons.FL_PUBLIC); + } else if (Access.isProtected(access)) { + add(content, selected, method ? Icons.ML_PROTECTED : Icons.FL_PROTECTED); + } else if (Access.isPrivate(access)) { + add(content, selected, method ? Icons.ML_PRIVATE : Icons.FL_PRIVATE); + } else if (Access.isPrivate(access)) { + add(content, selected, method ? Icons.ML_PRIVATE : Icons.FL_PRIVATE); + } else { + add(content, selected, method ? Icons.ML_DEFAULT : Icons.FL_DEFAULT); + } + if (Access.isAbstract(access)) { + add(content, selected, MOD_ABSTRACT); + } + if (Access.isFinal(access)) { + add(content, selected, MOD_FINAL); + } + if (Access.isNative(access)) { + add(content, selected, MOD_NATIVE); + } + if (Access.isStatic(access)) { + add(content, selected, MOD_STATIC); + } + if (Access.isTransient(access)) { + add(content, selected, MOD_TRANSIENT); + } + if (Access.isVolatile(access)) { + add(content, selected, MOD_VOLATILE); + } + if (Access.isSynthetic(access) || Access.isBridge(access)) { + add(content, selected, MOD_SYNTHETIC); + } + } - private void add(JPanel content, boolean selected, Icon icon) { - JLabel lbl = new JLabel(icon); - lbl.setPreferredSize(new Dimension(18,16)); - formatComponent(lbl, selected); - content.add(lbl); - } + private void add(JPanel content, boolean selected, Icon icon) { + JLabel lbl = new JLabel(icon); + lbl.setPreferredSize(new Dimension(18,16)); + formatComponent(lbl, selected); + content.add(lbl); + } - private void formatComponent(JComponent component, boolean selected) { - component.setOpaque(true); - component.setBorder(BorderFactory.createEtchedBorder()); - if (selected) { - component.setBackground(Color.white); - } else { - component.setBackground(bg); - } - } + private void formatComponent(JComponent component, boolean selected) { + component.setOpaque(true); + component.setBorder(BorderFactory.createEtchedBorder()); + if (selected) { + component.setBackground(Color.white); + } else { + component.setBackground(bg); + } + } - private String formatField(FieldNode node) { - return italic(color(colBlueDark, getTypeStr(Type.getType(node.desc), options))) + " " + escape(node.name); - } + private String formatField(FieldNode node) { + return italic(color(colBlueDark, getTypeStr(Type.getType(node.desc), options))) + " " + escape(node.name); + } - private String formatMethod(MethodNode node) { - Type typeMethod = Type.getMethodType(node.desc); - // Args string - String args = ""; - for (Type t : typeMethod.getArgumentTypes()) { - args += getTypeStr(t, options) + ", "; - } - if (args.endsWith(", ")) { - args = args.substring(0, args.length() - 2); - } - String s = italic(color(colBlueDark, getTypeStr(typeMethod.getReturnType(), options))) + " "; - s += color(colRedDark, escape(node.name)) + "("; - s += color(colTealDark, args); - s += ")"; - return s; - } + private String formatMethod(MethodNode node) { + Type typeMethod = Type.getMethodType(node.desc); + // Args string + String args = ""; + for (Type t : typeMethod.getArgumentTypes()) { + args += getTypeStr(t, options) + ", "; + } + if (args.endsWith(", ")) { + args = args.substring(0, args.length() - 2); + } + String s = italic(color(colBlueDark, getTypeStr(typeMethod.getReturnType(), options))) + " "; + s += color(colRedDark, escape(node.name)) + "("; + s += color(colTealDark, args); + s += ")"; + return s; + } } diff --git a/src/me/coley/recaf/ui/component/list/OpcodeCellRenderer.java b/src/me/coley/recaf/ui/component/list/OpcodeCellRenderer.java index d7abed08a..70a976eaa 100644 --- a/src/me/coley/recaf/ui/component/list/OpcodeCellRenderer.java +++ b/src/me/coley/recaf/ui/component/list/OpcodeCellRenderer.java @@ -19,235 +19,271 @@ import me.coley.recaf.ui.HtmlRenderer; public class OpcodeCellRenderer implements HtmlRenderer, ListCellRenderer, Opcodes { - private final MethodNode method; - private final Options options; + private final MethodNode method; + private final Options options; - public OpcodeCellRenderer(MethodNode method, Options options) { - this.method = method; - this.options = options; - } + public OpcodeCellRenderer(MethodNode method, Options options) { + this.method = method; + this.options = options; + } - @Override - public Component getListCellRendererComponent(JList list, AbstractInsnNode value, int index, - boolean isSelected, boolean cellHasFocus) { - OpcodeList opcodeCastedList = (OpcodeList) list; - JLabel label = new JLabel(getOpcodeText(opcodeCastedList, value)); - label.setFont(FontUtil.monospace); - label.setOpaque(true); - label.setBorder(BorderFactory.createEtchedBorder()); - if (isSelected) { - label.setBackground(Color.white); - } else { - label.setBackground(opcodeCastedList.getColorFor(index, value)); - } - return label; - } + @Override + public Component getListCellRendererComponent(JList list, AbstractInsnNode value, int index, + boolean isSelected, boolean cellHasFocus) { + OpcodeList opcodeCastedList = (OpcodeList) list; + JLabel label = new JLabel(getOpcodeText(opcodeCastedList, value)); + label.setFont(FontUtil.monospace); + label.setOpaque(true); + label.setBorder(BorderFactory.createEtchedBorder()); + if (isSelected) { + label.setBackground(Color.white); + } else { + label.setBackground(opcodeCastedList.getColorFor(index, value)); + } + return label; + } - public String getOpcodeText(OpcodeList list, AbstractInsnNode ain) { - int ainIndex = method.instructions.indexOf(ain); - int zeros = String.valueOf(method.instructions.size()).length() - String.valueOf(ainIndex).length() + 1; - String ss = ""; - for (int i = 0; i < zeros; i++) { - ss += " "; - } - String s = "" + color(colGray, ainIndex + ".") + ss + "" + OpcodeUtil.opcodeToName(ain.getOpcode()) + ""; - switch (ain.getType()) { - case AbstractInsnNode.INT_INSN: - // Add int value to string - IntInsnNode insnInt = (IntInsnNode) ain; - s += " " + insnInt.operand; - break; - case AbstractInsnNode.VAR_INSN: - // Add local variable index to string - VarInsnNode insnVar = (VarInsnNode) ain; - s += " " + insnVar.var; - // Add local variable name if possible - if (insnVar.var < method.localVariables.size()) { - LocalVariableNode var = method.localVariables.get(insnVar.var); - String varStr = var.name; - s += color(colBlueDark, italic(" (" + varStr + ") - " + getTypeStr(Type.getType(var.desc), options))); - } else if (insnVar.var == 0 && !Access.isStatic(method.access)) { - // If the local variable doesn't have a name, we can assume at - // index = 0 that it is 'this'. - s += color(colBlueDark, italic(" (this)")); - } - break; - case AbstractInsnNode.TYPE_INSN: - // Add type name to string - TypeInsnNode insnType = (TypeInsnNode) ain; - String typeDeclaredStr = getTypeStr(Type.getType(insnType.desc), options); - s += color(colBlueDark, italic(" " + typeDeclaredStr)); - break; - case AbstractInsnNode.FIELD_INSN: - FieldInsnNode insnField = (FieldInsnNode) ain; - s += " " + italic(color(colBlueDark, getTypeStr(Type.getType(insnField.desc), options))) + " "; - s += color(colRedDark, getTypeStr(Type.getObjectType(insnField.owner), options)) + "." + escape(insnField.name); - break; - case AbstractInsnNode.METHOD_INSN: - MethodInsnNode insnMethod = (MethodInsnNode) ain; - Type typeMethod = Type.getMethodType(insnMethod.desc); - // Args string - String args = ""; - for (Type t : typeMethod.getArgumentTypes()) { - args += getTypeStr(t, options) + ", "; - } - if (args.endsWith(", ")) { - args = args.substring(0, args.length() - 2); - } - s += " " + italic(color(colBlueDark, getTypeStr(typeMethod.getReturnType(), options))) + " "; - s += color(colRedDark, getTypeStr(Type.getObjectType(insnMethod.owner), options)) + "." + escape(insnMethod.name) - + "("; - s += color(colTealDark, args); - s += ")"; - break; - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - InvokeDynamicInsnNode insnIndy = (InvokeDynamicInsnNode) ain; - if (insnIndy.bsmArgs.length >= 2 && insnIndy.bsmArgs[1] instanceof Handle) { - Handle handle = (Handle) insnIndy.bsmArgs[1]; - Type typeIndyOwner = Type.getObjectType(handle.getOwner()); - Type typeIndyDesc = Type.getMethodType(handle.getDesc()); - // args string - String argsIndy = ""; - for (Type t : typeIndyDesc.getArgumentTypes()) { - argsIndy += getTypeStr(t, options) + ", "; - } - if (argsIndy.endsWith(", ")) { - argsIndy = argsIndy.substring(0, argsIndy.length() - 2); - } - s += " " + italic(color(colBlueDark, getTypeStr(typeIndyDesc.getReturnType(), options))) + " "; - s += color(colRedDark, getTypeStr(typeIndyOwner, options)) + "." + escape(handle.getName()) + "("; - s += color(colTealDark, argsIndy); - s += ")"; - } else { - s += " " + italic(color(colGray, "(unknown indy format)")); - } - break; - case AbstractInsnNode.JUMP_INSN: - JumpInsnNode insnJump = (JumpInsnNode) ain; - if (insnJump.label != null) { - s += " " + method.instructions.indexOf(insnJump.label); - } - if (options.opcodeShowJumpHelp) { - //@formatter:off - String z = ""; - switch (ain.getOpcode()) { - case IFEQ : z = "($0 == 0 -> offset)"; break; - case IFNE : z = "($0 != 0 -> offset)"; break; - case IFLE : z = "($0 <= 0 -> offset)"; break; - case IFLT : z = "($0 < 0 -> offset)"; break; - case IFGE : z = "($0 >= 0 -> offset)"; break; - case IFGT : z = "($0 > 0 -> offset)"; break; - case IF_ACMPNE: z = "($1 != $0 -> offset)"; break; - case IF_ACMPEQ: z = "($1 == $0 -> offset)"; break; - case IF_ICMPEQ: z = "($1 == $0 -> offset)"; break; - case IF_ICMPNE: z = "($1 != $0 -> offset)"; break; - case IF_ICMPLE: z = "($1 <= $0 -> offset)"; break; - case IF_ICMPLT: z = "($1 < $0 -> offset)"; break; - case IF_ICMPGE: z = "($1 >= $0 -> offset)"; break; - case IF_ICMPGT: z = "($1 > $0 -> offset)"; break; - case GOTO : z = "(-> offset)"; break; - case JSR : z = "(-> offset, +address)";break; - case IFNULL : z = "($0 == null -> offset)";break; - case IFNONNULL: z = "($0 != null -> offset)";break; - } - //@formatter:on - s += " " + italic(color(colGray, escape(z))); - } - break; - case AbstractInsnNode.LDC_INSN: - LdcInsnNode insnLdc = (LdcInsnNode) ain; - String v = escape(insnLdc.cst.toString()); - boolean extended = false; - if (v.length() > options.ldcMaxLength) { - v = v.substring(0, options.ldcMaxLength); - extended = true; - } - String x = italic(color(colGreenDark, v)); - if (insnLdc.cst instanceof String) { - x = "\"" + x; - if (extended) { - x += italic(color(colGray, " (too long)")); - } - x += "\""; - } - s += " " + x; - break; - case AbstractInsnNode.IINC_INSN: - // Add local variable index to string - IincInsnNode insnIinc = (IincInsnNode) ain; - s += " " + insnIinc.var; - // Add local variable name if possible - if (insnIinc.var < method.localVariables.size()) { - LocalVariableNode var = method.localVariables.get(insnIinc.var); - String varStr = var.name; - s += color(colBlueDark, italic(" (" + varStr + ") ")); - } else if (insnIinc.var == 0 && !Access.isStatic(method.access)) { - // If the local variable doesn't have a name, we can assume at - // index = 0 that it is 'this'. - s += color(colBlueDark, italic(" (this) ")); - } - if (insnIinc.incr > 0) { - s += color(colRedDark, "+" + insnIinc.incr); - } else { - s += color(colRedDark, "-" + insnIinc.incr); - } - break; - case AbstractInsnNode.TABLESWITCH_INSN: - TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; - String o = ""; - for (LabelNode label : insnTableSwitch.labels) { - o += method.instructions.indexOf(label) + ", "; - } - if (o.endsWith(", ")) { - o = o.substring(0, o.length() - 2); - } - int tableDefaultOffset = method.instructions.indexOf(insnTableSwitch.dflt); - s += color(colGray, " range[" + insnTableSwitch.min + "-" + insnTableSwitch.max + "] offsets:[" + o + "] default:" - + tableDefaultOffset); - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; - String u = ""; - for (int i = 0; i < insnLookupSwitch.keys.size(); i++) { - int offset = method.instructions.indexOf(insnLookupSwitch.labels.get(i)); - u += insnLookupSwitch.keys.get(i) + "->" + offset + ", "; - } - if (insnLookupSwitch.dflt != null) { - int offset = method.instructions.indexOf(insnLookupSwitch.dflt); - u += "default:" + offset; - } - if (u.endsWith(", ")) { - u = u.substring(0, u.length() - 2); - } - s += color(colGray, italic(" (" + u + ")")); - break; - case AbstractInsnNode.MULTIANEWARRAY_INSN: - // MultiANewArrayInsnNode insnArray = (MultiANewArrayInsnNode) ain; - // TODO - break; - case AbstractInsnNode.FRAME: - FrameNode fn = (FrameNode) ain; - s = s.replaceAll("F_NEW", OpcodeUtil.opcodeToName(fn.type)); - break; - case AbstractInsnNode.LABEL: - if (options.opcodeSimplifyDescriptors) { - s = s.replace("F_NEW", ""); - } else { - s += " "; - } - s += color(colGray, italic("Label " + bold(list.getLabelName(ain)))); - break; - case AbstractInsnNode.LINE: - LineNumberNode line = (LineNumberNode) ain; - if (options.opcodeSimplifyDescriptors) { - s = s.replace("F_NEW", ""); - } else { - s += " "; - } - s += color(colGray, italic("line #" + line.line)); - break; + public String getOpcodeText(OpcodeList list, AbstractInsnNode ain) { + int ainIndex = method.instructions.indexOf(ain); + int zeros = String.valueOf(method.instructions.size()).length() - String.valueOf(ainIndex).length() + 1; + String ss = ""; + for (int i = 0; i < zeros; i++) { + ss += " "; + } + String s = "" + color(colGray, ainIndex + ".") + ss + "" + OpcodeUtil.opcodeToName(ain.getOpcode()) + ""; + switch (ain.getType()) { + case AbstractInsnNode.INT_INSN: + // Add int value to string + IntInsnNode insnInt = (IntInsnNode) ain; + s += " " + insnInt.operand; + break; + case AbstractInsnNode.VAR_INSN: + // Add local variable index to string + VarInsnNode insnVar = (VarInsnNode) ain; + s += " " + insnVar.var; + // Add local variable name if possible + if (insnVar.var < method.localVariables.size()) { + LocalVariableNode var = method.localVariables.get(insnVar.var); + String varStr = var.name; + s += color(colBlueDark, italic(" (" + varStr + ") - " + getTypeStr(Type.getType(var.desc), options))); + } else if (insnVar.var == 0 && !Access.isStatic(method.access)) { + // If the local variable doesn't have a name, we can assume at + // index = 0 that it is 'this'. + s += color(colBlueDark, italic(" (this)")); + } + break; + case AbstractInsnNode.TYPE_INSN: + // Add type name to string + TypeInsnNode insnType = (TypeInsnNode) ain; + String typeDeclaredStr = getTypeStr(Type.getType(insnType.desc), options); + s += color(colBlueDark, italic(" " + typeDeclaredStr)); + break; + case AbstractInsnNode.FIELD_INSN: + FieldInsnNode insnField = (FieldInsnNode) ain; + s += " " + italic(color(colBlueDark, getTypeStr(Type.getType(insnField.desc), options))) + " "; + s += color(colRedDark, getTypeStr(Type.getObjectType(insnField.owner), options)) + "." + escape(insnField.name); + break; + case AbstractInsnNode.METHOD_INSN: + MethodInsnNode insnMethod = (MethodInsnNode) ain; + Type typeMethod = Type.getMethodType(insnMethod.desc); + // Args string + String args = ""; + for (Type t : typeMethod.getArgumentTypes()) { + args += getTypeStr(t, options) + ", "; + } + if (args.endsWith(", ")) { + args = args.substring(0, args.length() - 2); + } + s += " " + italic(color(colBlueDark, getTypeStr(typeMethod.getReturnType(), options))) + " "; + s += color(colRedDark, getTypeStr(Type.getObjectType(insnMethod.owner), options)) + "." + escape(insnMethod.name) + + "("; + s += color(colTealDark, args); + s += ")"; + break; + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + InvokeDynamicInsnNode insnIndy = (InvokeDynamicInsnNode) ain; + if (insnIndy.bsmArgs.length >= 2 && insnIndy.bsmArgs[1] instanceof Handle) { + Handle handle = (Handle) insnIndy.bsmArgs[1]; + Type typeIndyOwner = Type.getObjectType(handle.getOwner()); + Type typeIndyDesc = Type.getMethodType(handle.getDesc()); + // args string + String argsIndy = ""; + for (Type t : typeIndyDesc.getArgumentTypes()) { + argsIndy += getTypeStr(t, options) + ", "; + } + if (argsIndy.endsWith(", ")) { + argsIndy = argsIndy.substring(0, argsIndy.length() - 2); + } + s += " " + italic(color(colBlueDark, getTypeStr(typeIndyDesc.getReturnType(), options))) + " "; + s += color(colRedDark, getTypeStr(typeIndyOwner, options)) + "." + escape(handle.getName()) + "("; + s += color(colTealDark, argsIndy); + s += ")"; + } else { + s += " " + italic(color(colGray, "(unknown indy format)")); + } + break; + case AbstractInsnNode.JUMP_INSN: + JumpInsnNode insnJump = (JumpInsnNode) ain; + if (insnJump.label != null) { + s += " " + method.instructions.indexOf(insnJump.label); + } + if (options.opcodeShowJumpHelp) { + //@formatter:off + String z = ""; + switch (ain.getOpcode()) { + case IFEQ : + z = "($0 == 0 -> offset)"; + break; + case IFNE : + z = "($0 != 0 -> offset)"; + break; + case IFLE : + z = "($0 <= 0 -> offset)"; + break; + case IFLT : + z = "($0 < 0 -> offset)"; + break; + case IFGE : + z = "($0 >= 0 -> offset)"; + break; + case IFGT : + z = "($0 > 0 -> offset)"; + break; + case IF_ACMPNE: + z = "($1 != $0 -> offset)"; + break; + case IF_ACMPEQ: + z = "($1 == $0 -> offset)"; + break; + case IF_ICMPEQ: + z = "($1 == $0 -> offset)"; + break; + case IF_ICMPNE: + z = "($1 != $0 -> offset)"; + break; + case IF_ICMPLE: + z = "($1 <= $0 -> offset)"; + break; + case IF_ICMPLT: + z = "($1 < $0 -> offset)"; + break; + case IF_ICMPGE: + z = "($1 >= $0 -> offset)"; + break; + case IF_ICMPGT: + z = "($1 > $0 -> offset)"; + break; + case GOTO : + z = "(-> offset)"; + break; + case JSR : + z = "(-> offset, +address)"; + break; + case IFNULL : + z = "($0 == null -> offset)"; + break; + case IFNONNULL: + z = "($0 != null -> offset)"; + break; + } + //@formatter:on + s += " " + italic(color(colGray, escape(z))); + } + break; + case AbstractInsnNode.LDC_INSN: + LdcInsnNode insnLdc = (LdcInsnNode) ain; + String v = escape(insnLdc.cst.toString()); + boolean extended = false; + if (v.length() > options.ldcMaxLength) { + v = v.substring(0, options.ldcMaxLength); + extended = true; + } + String x = italic(color(colGreenDark, v)); + if (insnLdc.cst instanceof String) { + x = "\"" + x; + if (extended) { + x += italic(color(colGray, " (too long)")); + } + x += "\""; + } + s += " " + x; + break; + case AbstractInsnNode.IINC_INSN: + // Add local variable index to string + IincInsnNode insnIinc = (IincInsnNode) ain; + s += " " + insnIinc.var; + // Add local variable name if possible + if (insnIinc.var < method.localVariables.size()) { + LocalVariableNode var = method.localVariables.get(insnIinc.var); + String varStr = var.name; + s += color(colBlueDark, italic(" (" + varStr + ") ")); + } else if (insnIinc.var == 0 && !Access.isStatic(method.access)) { + // If the local variable doesn't have a name, we can assume at + // index = 0 that it is 'this'. + s += color(colBlueDark, italic(" (this) ")); + } + if (insnIinc.incr > 0) { + s += color(colRedDark, "+" + insnIinc.incr); + } else { + s += color(colRedDark, "-" + insnIinc.incr); + } + break; + case AbstractInsnNode.TABLESWITCH_INSN: + TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; + String o = ""; + for (LabelNode label : insnTableSwitch.labels) { + o += method.instructions.indexOf(label) + ", "; + } + if (o.endsWith(", ")) { + o = o.substring(0, o.length() - 2); + } + int tableDefaultOffset = method.instructions.indexOf(insnTableSwitch.dflt); + s += color(colGray, " range[" + insnTableSwitch.min + "-" + insnTableSwitch.max + "] offsets:[" + o + "] default:" + + tableDefaultOffset); + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; + String u = ""; + for (int i = 0; i < insnLookupSwitch.keys.size(); i++) { + int offset = method.instructions.indexOf(insnLookupSwitch.labels.get(i)); + u += insnLookupSwitch.keys.get(i) + "->" + offset + ", "; + } + if (insnLookupSwitch.dflt != null) { + int offset = method.instructions.indexOf(insnLookupSwitch.dflt); + u += "default:" + offset; + } + if (u.endsWith(", ")) { + u = u.substring(0, u.length() - 2); + } + s += color(colGray, italic(" (" + u + ")")); + break; + case AbstractInsnNode.MULTIANEWARRAY_INSN: + // MultiANewArrayInsnNode insnArray = (MultiANewArrayInsnNode) ain; + // TODO + break; + case AbstractInsnNode.FRAME: + FrameNode fn = (FrameNode) ain; + s = s.replaceAll("F_NEW", OpcodeUtil.opcodeToName(fn.type)); + break; + case AbstractInsnNode.LABEL: + if (options.opcodeSimplifyDescriptors) { + s = s.replace("F_NEW", ""); + } else { + s += " "; + } + s += color(colGray, italic("Label " + bold(list.getLabelName(ain)))); + break; + case AbstractInsnNode.LINE: + LineNumberNode line = (LineNumberNode) ain; + if (options.opcodeSimplifyDescriptors) { + s = s.replace("F_NEW", ""); + } else { + s += " "; + } + s += color(colGray, italic("line #" + line.line)); + break; - } - return s + color(colGray, italic(list.getAppendFor(ainIndex, ain))) + ""; - } + } + return s + color(colGray, italic(list.getAppendFor(ainIndex, ain))) + ""; + } } diff --git a/src/me/coley/recaf/ui/component/list/OpcodeKeyListener.java b/src/me/coley/recaf/ui/component/list/OpcodeKeyListener.java index bfd82a7a6..60a77864c 100644 --- a/src/me/coley/recaf/ui/component/list/OpcodeKeyListener.java +++ b/src/me/coley/recaf/ui/component/list/OpcodeKeyListener.java @@ -4,38 +4,38 @@ import java.awt.event.KeyListener; public class OpcodeKeyListener implements KeyListener { - private final OpcodeList list; - private boolean control, shift; - - public OpcodeKeyListener(OpcodeList list) { - this.list = list; - } - - @Override - public void keyTyped(KeyEvent e) {} - - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_CONTROL) { - control = true; - } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) { - shift = true; - } - update(); - } - - @Override - public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_CONTROL) { - control = false; - } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) { - shift = false; - } - update(); - } - - private void update() { - list.setModifiers(control, shift); - } + private final OpcodeList list; + private boolean control, shift; + + public OpcodeKeyListener(OpcodeList list) { + this.list = list; + } + + @Override + public void keyTyped(KeyEvent e) {} + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_CONTROL) { + control = true; + } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) { + shift = true; + } + update(); + } + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_CONTROL) { + control = false; + } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) { + shift = false; + } + update(); + } + + private void update() { + list.setModifiers(control, shift); + } } diff --git a/src/me/coley/recaf/ui/component/list/OpcodeList.java b/src/me/coley/recaf/ui/component/list/OpcodeList.java index 522c34b5b..c64273b85 100644 --- a/src/me/coley/recaf/ui/component/list/OpcodeList.java +++ b/src/me/coley/recaf/ui/component/list/OpcodeList.java @@ -17,143 +17,143 @@ @SuppressWarnings("serial") public class OpcodeList extends JList { - private final Recaf recaf = Recaf.getInstance(); - private static final Color colEntryBG = new Color(200, 200, 200); - private static final Color colListBG = new Color(166, 166, 166); - /** - * The method being viewed. - */ - private final MethodNode method; - /** - * Map of background-color overrides to be drawn by the cell renderer. - */ - private Map colorMap = new HashMap<>(); - /** - * Map of label opcodes to some label name. - */ - private final Map labels = new HashMap<>(); - /** - * Map of appended text to be added to the cell renderer. - */ - private Map appendMap = new HashMap<>(); - /** - * Key modifiers - */ - public boolean controlDown, shiftDown; + private final Recaf recaf = Recaf.getInstance(); + private static final Color colEntryBG = new Color(200, 200, 200); + private static final Color colListBG = new Color(166, 166, 166); + /** + * The method being viewed. + */ + private final MethodNode method; + /** + * Map of background-color overrides to be drawn by the cell renderer. + */ + private Map colorMap = new HashMap<>(); + /** + * Map of label opcodes to some label name. + */ + private final Map labels = new HashMap<>(); + /** + * Map of appended text to be added to the cell renderer. + */ + private Map appendMap = new HashMap<>(); + /** + * Key modifiers + */ + public boolean controlDown, shiftDown; - public OpcodeList(ClassDisplayPanel display, MethodNode method) { - this.method = method; - setBackground(colListBG); - setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - DefaultListModel model = new DefaultListModel<>(); - for (AbstractInsnNode ain : method.instructions.toArray()) { - model.addElement(ain); - } - setModel(model); - setCellRenderer(new OpcodeCellRenderer(method, recaf.options)); - addListSelectionListener(new OpcodeSelectionListener()); - addMouseListener(new OpcodeMouseListener(method, display, this)); - addKeyListener(new OpcodeKeyListener(this)); - int i = 1; - for (AbstractInsnNode ain : method.instructions.toArray()) { - if (ain.getType() == AbstractInsnNode.LABEL) { - labels.put(ain, Integer.toHexString(i++)); - } - } - } + public OpcodeList(ClassDisplayPanel display, MethodNode method) { + this.method = method; + setBackground(colListBG); + setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + DefaultListModel model = new DefaultListModel<>(); + for (AbstractInsnNode ain : method.instructions.toArray()) { + model.addElement(ain); + } + setModel(model); + setCellRenderer(new OpcodeCellRenderer(method, recaf.options)); + addListSelectionListener(new OpcodeSelectionListener()); + addMouseListener(new OpcodeMouseListener(method, display, this)); + addKeyListener(new OpcodeKeyListener(this)); + int i = 1; + for (AbstractInsnNode ain : method.instructions.toArray()) { + if (ain.getType() == AbstractInsnNode.LABEL) { + labels.put(ain, Integer.toHexString(i++)); + } + } + } - /** - * Re-populate the model. - */ - public void repopulate() { - DefaultListModel model = (DefaultListModel) getModel(); - model.clear(); - for (AbstractInsnNode ain : method.instructions.toArray()) { - model.addElement(ain); - } - setModel(model); - } + /** + * Re-populate the model. + */ + public void repopulate() { + DefaultListModel model = (DefaultListModel) getModel(); + model.clear(); + for (AbstractInsnNode ain : method.instructions.toArray()) { + model.addElement(ain); + } + setModel(model); + } - /** - * Get the background color for the given opcode. - * - * @param index Opcode index. - * @param value Opcode value. - * @return Background color. - */ - public Color getColorFor(int index, AbstractInsnNode value) { - if (colorMap.containsKey(value)) { - return colorMap.get(value); - } - return colEntryBG; - } + /** + * Get the background color for the given opcode. + * + * @param index Opcode index. + * @param value Opcode value. + * @return Background color. + */ + public Color getColorFor(int index, AbstractInsnNode value) { + if (colorMap.containsKey(value)) { + return colorMap.get(value); + } + return colEntryBG; + } - /** - * Get the appended text for the given opcode. - * - * @param index Opcode index. - * @param value Opcode value. - * @return appended text. - */ - public String getAppendFor(int index, AbstractInsnNode value) { - if (appendMap.containsKey(value)) { - return appendMap.get(value); - } - return ""; - } + /** + * Get the appended text for the given opcode. + * + * @param index Opcode index. + * @param value Opcode value. + * @return appended text. + */ + public String getAppendFor(int index, AbstractInsnNode value) { + if (appendMap.containsKey(value)) { + return appendMap.get(value); + } + return ""; + } - /** - * Get the arbitrary label identifier for the given label opcode. - * - * @param ain Label opcode. - * @return label identifier. - */ - public String getLabelName(AbstractInsnNode ain) { - return labels.getOrDefault(ain, "(New Label)"); - } + /** + * Get the arbitrary label identifier for the given label opcode. + * + * @param ain Label opcode. + * @return label identifier. + */ + public String getLabelName(AbstractInsnNode ain) { + return labels.getOrDefault(ain, "(New Label)"); + } - /** - * Get the method node associated with the list. - * - * @return the method node. - */ - public MethodNode getMethod() { - return method; - } + /** + * Get the method node associated with the list. + * + * @return the method node. + */ + public MethodNode getMethod() { + return method; + } - /** - * Getter for {@link #colorMap}. - * - * @return Map associating AbstractInsnNode instances with their - * colors. - */ - public Map getColorMap() { - return colorMap; - } + /** + * Getter for {@link #colorMap}. + * + * @return Map associating AbstractInsnNode instances with their + * colors. + */ + public Map getColorMap() { + return colorMap; + } - /** - * Getter for {@link #appendMap}. - * - * @return Map associated AbstractInsnNode instances with their - * appended text. - */ - public Map getAppendMap() { - return appendMap; - } + /** + * Getter for {@link #appendMap}. + * + * @return Map associated AbstractInsnNode instances with their + * appended text. + */ + public Map getAppendMap() { + return appendMap; + } - /** - * Set key-modifiers. - * - * @param control TODO - * @param shift TODO - * - * TODO: What do control and shift correspond to? What is this method - * for? - * - * - Charles - */ - public void setModifiers(boolean control, boolean shift) { - this.controlDown = control; - this.shiftDown = shift; - } + /** + * Set key-modifiers. + * + * @param control TODO + * @param shift TODO + * + * TODO: What do control and shift correspond to? What is this method + * for? + * + * - Charles + */ + public void setModifiers(boolean control, boolean shift) { + this.controlDown = control; + this.shiftDown = shift; + } } diff --git a/src/me/coley/recaf/ui/component/list/OpcodeMouseListener.java b/src/me/coley/recaf/ui/component/list/OpcodeMouseListener.java index cae7d03f4..82a8d78e8 100644 --- a/src/me/coley/recaf/ui/component/list/OpcodeMouseListener.java +++ b/src/me/coley/recaf/ui/component/list/OpcodeMouseListener.java @@ -31,233 +31,233 @@ import me.coley.recaf.util.Misc; public class OpcodeMouseListener implements ReleaseListener { - private final Recaf recaf = Recaf.getInstance(); - private final MethodNode method; - private final OpcodeList list; - private final ClassDisplayPanel display; + private final Recaf recaf = Recaf.getInstance(); + private final MethodNode method; + private final OpcodeList list; + private final ClassDisplayPanel display; - public OpcodeMouseListener(MethodNode method, ClassDisplayPanel display, OpcodeList list) { - this.method = method; - this.display = display; - this.list = list; - } + public OpcodeMouseListener(MethodNode method, ClassDisplayPanel display, OpcodeList list) { + this.method = method; + this.display = display; + this.list = list; + } - @Override - public void mouseReleased(MouseEvent e) { - int button = e.getButton(); - - if (list.getSelectedIndices().length == 1) { - // If not left-click, enforce selection at the given location - if (button != MouseEvent.BUTTON1) { - int index = list.locationToIndex(e.getPoint()); - list.setSelectedIndex(index); - } - } + @Override + public void mouseReleased(MouseEvent e) { + int button = e.getButton(); - Object value = list.getSelectedValue(); - if (value == null) { - return; - } - if (button == MouseEvent.BUTTON3) { - createContextMenu((AbstractInsnNode) value, e.getX(), e.getY()); - } else if (button == MouseEvent.BUTTON2) { - createEdit((AbstractInsnNode) value, e.getX(), e.getY()); - } - } + if (list.getSelectedIndices().length == 1) { + // If not left-click, enforce selection at the given location + if (button != MouseEvent.BUTTON1) { + int index = list.locationToIndex(e.getPoint()); + list.setSelectedIndex(index); + } + } - private void createContextMenu(AbstractInsnNode ain, int x, int y) { - JPopupMenu popup = new JPopupMenu(); - ActionMenuItem itemEdit = new ActionMenuItem("Edit", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - createEdit(ain, x, y); - } - })); - popup.add(itemEdit); - ActionMenuItem itemNewBefore = new ActionMenuItem("New Opcode Before...", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - display.addWindow(new OpcodeCreationBox(true, list, method, ain)); - } - })); - popup.add(itemNewBefore); - ActionMenuItem itemNewAfter = new ActionMenuItem("New Opcode After...", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - display.addWindow(new OpcodeCreationBox(false, list, method, ain)); - } - })); - popup.add(itemNewAfter); - ActionMenuItem itemRemove = new ActionMenuItem("Remove", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (recaf.options.confirmDeletions) { - int dialogResult = JOptionPane.showConfirmDialog(null, "You sure you want to delete that opcode?", "Warning", - JOptionPane.YES_NO_OPTION); - if (dialogResult != JOptionPane.YES_OPTION) { - return; - } - } - DefaultListModel model = (DefaultListModel) list.getModel(); - int[] descending = new int[list.getSelectedIndices().length]; - if (descending.length > 1) { - // sort the list and remove highest index objects first - for (int i = 0; i < descending.length; i++) { - descending[i] = list.getSelectedIndices()[i]; - } - Arrays.sort(descending); - for (int i = 0; i < descending.length; i++) { - int j = descending[descending.length - 1 - i]; - model.remove(j); - method.instructions.remove(method.instructions.get(j)); - } - } else { - model.remove(list.getSelectedIndex()); - method.instructions.remove(ain); - } + Object value = list.getSelectedValue(); + if (value == null) { + return; + } + if (button == MouseEvent.BUTTON3) { + createContextMenu((AbstractInsnNode) value, e.getX(), e.getY()); + } else if (button == MouseEvent.BUTTON2) { + createEdit((AbstractInsnNode) value, e.getX(), e.getY()); + } + } - } - })); - popup.add(itemRemove); - popup.show(list, x, y); - } + private void createContextMenu(AbstractInsnNode ain, int x, int y) { + JPopupMenu popup = new JPopupMenu(); + ActionMenuItem itemEdit = new ActionMenuItem("Edit", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + createEdit(ain, x, y); + } + })); + popup.add(itemEdit); + ActionMenuItem itemNewBefore = new ActionMenuItem("New Opcode Before...", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + display.addWindow(new OpcodeCreationBox(true, list, method, ain)); + } + })); + popup.add(itemNewBefore); + ActionMenuItem itemNewAfter = new ActionMenuItem("New Opcode After...", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + display.addWindow(new OpcodeCreationBox(false, list, method, ain)); + } + })); + popup.add(itemNewAfter); + ActionMenuItem itemRemove = new ActionMenuItem("Remove", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (recaf.options.confirmDeletions) { + int dialogResult = JOptionPane.showConfirmDialog(null, "You sure you want to delete that opcode?", "Warning", + JOptionPane.YES_NO_OPTION); + if (dialogResult != JOptionPane.YES_OPTION) { + return; + } + } + DefaultListModel model = (DefaultListModel) list.getModel(); + int[] descending = new int[list.getSelectedIndices().length]; + if (descending.length > 1) { + // sort the list and remove highest index objects first + for (int i = 0; i < descending.length; i++) { + descending[i] = list.getSelectedIndices()[i]; + } + Arrays.sort(descending); + for (int i = 0; i < descending.length; i++) { + int j = descending[descending.length - 1 - i]; + model.remove(j); + method.instructions.remove(method.instructions.get(j)); + } + } else { + model.remove(list.getSelectedIndex()); + method.instructions.remove(ain); + } - private void createEdit(AbstractInsnNode ain, int x, int y) { - EditBox frame = new EditBox("Opcode: " + OpcodeUtil.opcodeToName(ain.getOpcode())); - switch (ain.getType()) { - case AbstractInsnNode.INT_INSN: - IntInsnNode insnInt = (IntInsnNode) ain; - frame.add(new LabeledComponent("Value: ", new ActionTextField(insnInt.operand, s -> { - if (Misc.isInt(s)) { - insnInt.operand = Integer.parseInt(s); - } - }))); - break; - case AbstractInsnNode.VAR_INSN: - VarInsnNode insnVar = (VarInsnNode) ain; - frame.add(new JScrollPane(VariableTable.create(list, method))); - frame.add(new LabeledComponent("Variable Index: ", new ActionTextField(insnVar.var, s -> { - if (Misc.isInt(s)) { - insnVar.var = Integer.parseInt(s); - } - }))); - break; - case AbstractInsnNode.TYPE_INSN: - TypeInsnNode insnType = (TypeInsnNode) ain; - frame.add(new LabeledComponent("Type: ", new ActionTextField(insnType.desc, s -> insnType.desc = s))); - break; - case AbstractInsnNode.FIELD_INSN: - FieldInsnNode insnField = (FieldInsnNode) ain; - frame.add(new LabeledComponent("Owner: ", new ActionTextField(insnField.owner, s -> insnField.owner = s))); - frame.add(new LabeledComponent("Name: ", new ActionTextField(insnField.name, s -> insnField.name = s))); - frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnField.desc, s -> insnField.desc = s))); - break; - case AbstractInsnNode.METHOD_INSN: - MethodInsnNode insnMethod = (MethodInsnNode) ain; - frame.add(new LabeledComponent("Owner: ", new ActionTextField(insnMethod.owner, s -> insnMethod.owner = s))); - frame.add(new LabeledComponent("Name: ", new ActionTextField(insnMethod.name, s -> insnMethod.name = s))); - frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnMethod.desc, s -> insnMethod.desc = s))); - // ITF is labeled so it's not a centered checkbox. - frame.add(new LabeledComponent("", new ActionCheckBox("Owner is Interface (ITF)", insnMethod.itf, - b -> insnMethod.itf = b))); - break; - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - InvokeDynamicInsnNode insnIndy = (InvokeDynamicInsnNode) ain; - if (insnIndy.bsmArgs.length > 2 && insnIndy.bsmArgs[1] instanceof Handle) { - Handle h = (Handle) insnIndy.bsmArgs[1]; - frame.add(new LabeledComponent("Name: ", new ActionTextField(h.getName(), s -> Misc.set(h, "name", s)))); - frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(h.getDesc(), s -> Misc.set(h, "desc", s)))); - frame.add(new LabeledComponent("Owner: ", new ActionTextField(h.getOwner(), s -> Misc.set(h, "owner", s)))); - frame.add(new LabeledComponent("IsInterface: ", new ActionTextField(h.isInterface(), s -> Misc.setBoolean( - insnIndy.bsm, "itf", s)))); - frame.add(new TagTypeSwitchPanel(list, h)); - } - break; - case AbstractInsnNode.JUMP_INSN: - JumpInsnNode insnJump = (JumpInsnNode) ain; - frame.add(new LabelSwitcherPanel(list, method, insnJump.label, l -> insnJump.label = l)); - break; - case AbstractInsnNode.LDC_INSN: - LdcInsnNode insnLdc = (LdcInsnNode) ain; - frame.add(new LabeledComponent("Value: ", new ActionTextField(insnLdc.cst, s -> { - if (insnLdc.cst instanceof String) { - insnLdc.cst = s; - } else if (Misc.isInt(s)) { - insnLdc.cst = Integer.parseInt(s); - } - }))); - break; - case AbstractInsnNode.IINC_INSN: - IincInsnNode insnIinc = (IincInsnNode) ain; - frame.add(new JScrollPane(VariableTable.create(list, method))); - frame.add(new LabeledComponent("Variable Index: ", new ActionTextField(insnIinc.var, s -> { - if (Misc.isInt(s)) { - insnIinc.var = Integer.parseInt(s); - } - }))); - break; - case AbstractInsnNode.TABLESWITCH_INSN: - TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; - frame.add(new LabeledComponent("Default: ", new LabelSwitcherPanel(list, method, insnTableSwitch.dflt, - l -> insnTableSwitch.dflt = l))); - for (int i = 0; i < insnTableSwitch.labels.size(); i++) { - final int fi = i; - LabelNode label = insnTableSwitch.labels.get(i); - int j = insnTableSwitch.min + i; - frame.add(new LabeledComponent(j + ": ", new LabelSwitcherPanel(list, method, label, l -> insnTableSwitch.labels - .set(fi, l)))); - } - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; - frame.add(new LabeledComponent("Default: ", new LabelSwitcherPanel(list, method, insnLookupSwitch.dflt, - l -> insnLookupSwitch.dflt = l))); - for (int i = 0; i < insnLookupSwitch.labels.size(); i++) { - final int fi = i; - LabelNode label = insnLookupSwitch.labels.get(i); - int j = insnLookupSwitch.keys.get(i); - frame.add(new LabeledComponent(j + ": ", new LabelSwitcherPanel(list, method, label, l -> insnLookupSwitch.labels - .set(fi, l)))); - } - break; - case AbstractInsnNode.MULTIANEWARRAY_INSN: - MultiANewArrayInsnNode insnArray = (MultiANewArrayInsnNode) ain; - frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnArray.desc, s -> insnArray.desc = s))); - frame.add(new LabeledComponent("Dimensions: ", new ActionTextField(insnArray.dims, s -> { - if (Misc.isInt(s)) { - insnArray.dims = Integer.parseInt(s); - } - }))); - break; - case AbstractInsnNode.FRAME: - // TODO - FrameNode insnFrame = (FrameNode) ain; - break; - case AbstractInsnNode.LINE: - LineNumberNode insnLine = (LineNumberNode) ain; - frame.add(new LabeledComponent("Line: ", new ActionTextField(insnLine.line, s -> { - if (Misc.isInt(s)) { - insnLine.line = Integer.parseInt(s); - } - }))); - frame.add(new LabeledComponent("Start: ", new LabelSwitcherPanel(list, method, insnLine.start, - l -> insnLine.start = l))); - break; - } - OpcodeTypeSwitchPanel opSelector = new OpcodeTypeSwitchPanel(list, ain); - if (opSelector.getOptionCount() > 0) { - frame.add(opSelector); - } - // Tell the user the empty box is intentional. - if (!frame.hasContent()) { - JLabel nothing = new JLabel("Nothing to edit"); - nothing.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - frame.add(nothing); - } - display.addWindow(frame); - // TODO: Reliable way of positioning frame in a reasonable place (near - // the mouse) - // frame.setLocation(x, y); - frame.setVisible(true); - } + } + })); + popup.add(itemRemove); + popup.show(list, x, y); + } + + private void createEdit(AbstractInsnNode ain, int x, int y) { + EditBox frame = new EditBox("Opcode: " + OpcodeUtil.opcodeToName(ain.getOpcode())); + switch (ain.getType()) { + case AbstractInsnNode.INT_INSN: + IntInsnNode insnInt = (IntInsnNode) ain; + frame.add(new LabeledComponent("Value: ", new ActionTextField(insnInt.operand, s -> { + if (Misc.isInt(s)) { + insnInt.operand = Integer.parseInt(s); + } + }))); + break; + case AbstractInsnNode.VAR_INSN: + VarInsnNode insnVar = (VarInsnNode) ain; + frame.add(new JScrollPane(VariableTable.create(list, method))); + frame.add(new LabeledComponent("Variable Index: ", new ActionTextField(insnVar.var, s -> { + if (Misc.isInt(s)) { + insnVar.var = Integer.parseInt(s); + } + }))); + break; + case AbstractInsnNode.TYPE_INSN: + TypeInsnNode insnType = (TypeInsnNode) ain; + frame.add(new LabeledComponent("Type: ", new ActionTextField(insnType.desc, s -> insnType.desc = s))); + break; + case AbstractInsnNode.FIELD_INSN: + FieldInsnNode insnField = (FieldInsnNode) ain; + frame.add(new LabeledComponent("Owner: ", new ActionTextField(insnField.owner, s -> insnField.owner = s))); + frame.add(new LabeledComponent("Name: ", new ActionTextField(insnField.name, s -> insnField.name = s))); + frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnField.desc, s -> insnField.desc = s))); + break; + case AbstractInsnNode.METHOD_INSN: + MethodInsnNode insnMethod = (MethodInsnNode) ain; + frame.add(new LabeledComponent("Owner: ", new ActionTextField(insnMethod.owner, s -> insnMethod.owner = s))); + frame.add(new LabeledComponent("Name: ", new ActionTextField(insnMethod.name, s -> insnMethod.name = s))); + frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnMethod.desc, s -> insnMethod.desc = s))); + // ITF is labeled so it's not a centered checkbox. + frame.add(new LabeledComponent("", new ActionCheckBox("Owner is Interface (ITF)", insnMethod.itf, + b -> insnMethod.itf = b))); + break; + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + InvokeDynamicInsnNode insnIndy = (InvokeDynamicInsnNode) ain; + if (insnIndy.bsmArgs.length > 2 && insnIndy.bsmArgs[1] instanceof Handle) { + Handle h = (Handle) insnIndy.bsmArgs[1]; + frame.add(new LabeledComponent("Name: ", new ActionTextField(h.getName(), s -> Misc.set(h, "name", s)))); + frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(h.getDesc(), s -> Misc.set(h, "desc", s)))); + frame.add(new LabeledComponent("Owner: ", new ActionTextField(h.getOwner(), s -> Misc.set(h, "owner", s)))); + frame.add(new LabeledComponent("IsInterface: ", new ActionTextField(h.isInterface(), s -> Misc.setBoolean( + insnIndy.bsm, "itf", s)))); + frame.add(new TagTypeSwitchPanel(list, h)); + } + break; + case AbstractInsnNode.JUMP_INSN: + JumpInsnNode insnJump = (JumpInsnNode) ain; + frame.add(new LabelSwitcherPanel(list, method, insnJump.label, l -> insnJump.label = l)); + break; + case AbstractInsnNode.LDC_INSN: + LdcInsnNode insnLdc = (LdcInsnNode) ain; + frame.add(new LabeledComponent("Value: ", new ActionTextField(insnLdc.cst, s -> { + if (insnLdc.cst instanceof String) { + insnLdc.cst = s; + } else if (Misc.isInt(s)) { + insnLdc.cst = Integer.parseInt(s); + } + }))); + break; + case AbstractInsnNode.IINC_INSN: + IincInsnNode insnIinc = (IincInsnNode) ain; + frame.add(new JScrollPane(VariableTable.create(list, method))); + frame.add(new LabeledComponent("Variable Index: ", new ActionTextField(insnIinc.var, s -> { + if (Misc.isInt(s)) { + insnIinc.var = Integer.parseInt(s); + } + }))); + break; + case AbstractInsnNode.TABLESWITCH_INSN: + TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; + frame.add(new LabeledComponent("Default: ", new LabelSwitcherPanel(list, method, insnTableSwitch.dflt, + l -> insnTableSwitch.dflt = l))); + for (int i = 0; i < insnTableSwitch.labels.size(); i++) { + final int fi = i; + LabelNode label = insnTableSwitch.labels.get(i); + int j = insnTableSwitch.min + i; + frame.add(new LabeledComponent(j + ": ", new LabelSwitcherPanel(list, method, label, l -> insnTableSwitch.labels + .set(fi, l)))); + } + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; + frame.add(new LabeledComponent("Default: ", new LabelSwitcherPanel(list, method, insnLookupSwitch.dflt, + l -> insnLookupSwitch.dflt = l))); + for (int i = 0; i < insnLookupSwitch.labels.size(); i++) { + final int fi = i; + LabelNode label = insnLookupSwitch.labels.get(i); + int j = insnLookupSwitch.keys.get(i); + frame.add(new LabeledComponent(j + ": ", new LabelSwitcherPanel(list, method, label, l -> insnLookupSwitch.labels + .set(fi, l)))); + } + break; + case AbstractInsnNode.MULTIANEWARRAY_INSN: + MultiANewArrayInsnNode insnArray = (MultiANewArrayInsnNode) ain; + frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnArray.desc, s -> insnArray.desc = s))); + frame.add(new LabeledComponent("Dimensions: ", new ActionTextField(insnArray.dims, s -> { + if (Misc.isInt(s)) { + insnArray.dims = Integer.parseInt(s); + } + }))); + break; + case AbstractInsnNode.FRAME: + // TODO + FrameNode insnFrame = (FrameNode) ain; + break; + case AbstractInsnNode.LINE: + LineNumberNode insnLine = (LineNumberNode) ain; + frame.add(new LabeledComponent("Line: ", new ActionTextField(insnLine.line, s -> { + if (Misc.isInt(s)) { + insnLine.line = Integer.parseInt(s); + } + }))); + frame.add(new LabeledComponent("Start: ", new LabelSwitcherPanel(list, method, insnLine.start, + l -> insnLine.start = l))); + break; + } + OpcodeTypeSwitchPanel opSelector = new OpcodeTypeSwitchPanel(list, ain); + if (opSelector.getOptionCount() > 0) { + frame.add(opSelector); + } + // Tell the user the empty box is intentional. + if (!frame.hasContent()) { + JLabel nothing = new JLabel("Nothing to edit"); + nothing.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + frame.add(nothing); + } + display.addWindow(frame); + // TODO: Reliable way of positioning frame in a reasonable place (near + // the mouse) + // frame.setLocation(x, y); + frame.setVisible(true); + } } diff --git a/src/me/coley/recaf/ui/component/list/OpcodeSelectionListener.java b/src/me/coley/recaf/ui/component/list/OpcodeSelectionListener.java index 00fbdf2c8..d48414b38 100644 --- a/src/me/coley/recaf/ui/component/list/OpcodeSelectionListener.java +++ b/src/me/coley/recaf/ui/component/list/OpcodeSelectionListener.java @@ -8,96 +8,96 @@ import org.objectweb.asm.tree.*; public class OpcodeSelectionListener implements ListSelectionListener, Opcodes { - // Jumps - private static final Color colJumpFail = new Color(250, 200, 200); - private static final Color colJumpSuccess = new Color(200, 250, 200); - private static final Color colJumpRange = new Color(220, 220, 170); - // Labels - private static final Color colDestinationReference = new Color(247, 255, 191); + // Jumps + private static final Color colJumpFail = new Color(250, 200, 200); + private static final Color colJumpSuccess = new Color(200, 250, 200); + private static final Color colJumpRange = new Color(220, 220, 170); + // Labels + private static final Color colDestinationReference = new Color(247, 255, 191); - - @Override - public void valueChanged(ListSelectionEvent e) { - // TODO: getValueIsAdjusting = true for keyboard up/down - // getValueIsAdjusting = false for mouse press (true release) - // - // Should find a way so this isn't called twice but is instant for both. - /* - * if (e.getValueIsAdjusting()) { return; } - */ - OpcodeList list = (OpcodeList) e.getSource(); - boolean multiple = list.getMaxSelectionIndex() != list.getMinSelectionIndex(); - AbstractInsnNode selected = list.getSelectedValue(); - list.getColorMap().clear(); - list.getAppendMap().clear(); - list.repaint(); - if (!multiple && selected != null) { - int op = selected.getOpcode(); - switch (selected.getType()) { - case AbstractInsnNode.LABEL: - MethodNode method = list.getMethod(); - for (AbstractInsnNode ain : method.instructions.toArray()) { - if (ain.getType() == AbstractInsnNode.JUMP_INSN) { - JumpInsnNode insnJump = (JumpInsnNode) ain; - if (insnJump.label.equals(selected)) { - list.getColorMap().put(insnJump, colDestinationReference); - } - } else if (ain.getType() == AbstractInsnNode.TABLESWITCH_INSN) { - TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; - if (selected.equals(insnTableSwitch.dflt)) { - list.getColorMap().put(insnTableSwitch, colDestinationReference); - } - for (LabelNode ln : insnTableSwitch.labels) { - if (selected.equals(ln)) { - list.getColorMap().put(insnTableSwitch, colDestinationReference); - } - } - } else if (ain.getType() == AbstractInsnNode.LOOKUPSWITCH_INSN) { - LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; - if (selected.equals(insnLookupSwitch.dflt)) { - list.getColorMap().put(insnLookupSwitch, colDestinationReference); - } - for (LabelNode ln : insnLookupSwitch.labels) { - if (selected.equals(ln)) { - list.getColorMap().put(insnLookupSwitch, colDestinationReference); - } - } - } - } - break; - case AbstractInsnNode.JUMP_INSN: - JumpInsnNode insnJump = (JumpInsnNode) selected; - if (op != GOTO && op != JSR) { - list.getColorMap().put(insnJump.getNext(), colJumpFail); - } - list.getColorMap().put(insnJump.label, colJumpSuccess); - break; - case AbstractInsnNode.TABLESWITCH_INSN: - TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) selected; - int diff = insnTableSwitch.max - insnTableSwitch.min; - for (int i = 0; i <= diff; i++) { - int key = i + insnTableSwitch.min; - LabelNode label = insnTableSwitch.labels.get(i); - list.getAppendMap().put(label, " [switch key: " + key + "]"); - list.getColorMap().put(label, colJumpRange); - } - for (LabelNode label : insnTableSwitch.labels) { - list.getColorMap().put(label, colJumpRange); - } - list.getColorMap().put(insnTableSwitch.dflt, colJumpFail); - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) selected; - for (int i = 0; i < insnLookupSwitch.keys.size(); i++) { - int key = insnLookupSwitch.keys.get(i); - LabelNode label = insnLookupSwitch.labels.get(i); - list.getAppendMap().put(label, " [switch key: " + key + "]"); - list.getColorMap().put(label, colJumpRange); - } - list.getColorMap().put(insnLookupSwitch.dflt, colJumpFail); - break; - } - } - } + + @Override + public void valueChanged(ListSelectionEvent e) { + // TODO: getValueIsAdjusting = true for keyboard up/down + // getValueIsAdjusting = false for mouse press (true release) + // + // Should find a way so this isn't called twice but is instant for both. + /* + * if (e.getValueIsAdjusting()) { return; } + */ + OpcodeList list = (OpcodeList) e.getSource(); + boolean multiple = list.getMaxSelectionIndex() != list.getMinSelectionIndex(); + AbstractInsnNode selected = list.getSelectedValue(); + list.getColorMap().clear(); + list.getAppendMap().clear(); + list.repaint(); + if (!multiple && selected != null) { + int op = selected.getOpcode(); + switch (selected.getType()) { + case AbstractInsnNode.LABEL: + MethodNode method = list.getMethod(); + for (AbstractInsnNode ain : method.instructions.toArray()) { + if (ain.getType() == AbstractInsnNode.JUMP_INSN) { + JumpInsnNode insnJump = (JumpInsnNode) ain; + if (insnJump.label.equals(selected)) { + list.getColorMap().put(insnJump, colDestinationReference); + } + } else if (ain.getType() == AbstractInsnNode.TABLESWITCH_INSN) { + TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; + if (selected.equals(insnTableSwitch.dflt)) { + list.getColorMap().put(insnTableSwitch, colDestinationReference); + } + for (LabelNode ln : insnTableSwitch.labels) { + if (selected.equals(ln)) { + list.getColorMap().put(insnTableSwitch, colDestinationReference); + } + } + } else if (ain.getType() == AbstractInsnNode.LOOKUPSWITCH_INSN) { + LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; + if (selected.equals(insnLookupSwitch.dflt)) { + list.getColorMap().put(insnLookupSwitch, colDestinationReference); + } + for (LabelNode ln : insnLookupSwitch.labels) { + if (selected.equals(ln)) { + list.getColorMap().put(insnLookupSwitch, colDestinationReference); + } + } + } + } + break; + case AbstractInsnNode.JUMP_INSN: + JumpInsnNode insnJump = (JumpInsnNode) selected; + if (op != GOTO && op != JSR) { + list.getColorMap().put(insnJump.getNext(), colJumpFail); + } + list.getColorMap().put(insnJump.label, colJumpSuccess); + break; + case AbstractInsnNode.TABLESWITCH_INSN: + TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) selected; + int diff = insnTableSwitch.max - insnTableSwitch.min; + for (int i = 0; i <= diff; i++) { + int key = i + insnTableSwitch.min; + LabelNode label = insnTableSwitch.labels.get(i); + list.getAppendMap().put(label, " [switch key: " + key + "]"); + list.getColorMap().put(label, colJumpRange); + } + for (LabelNode label : insnTableSwitch.labels) { + list.getColorMap().put(label, colJumpRange); + } + list.getColorMap().put(insnTableSwitch.dflt, colJumpFail); + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) selected; + for (int i = 0; i < insnLookupSwitch.keys.size(); i++) { + int key = insnLookupSwitch.keys.get(i); + LabelNode label = insnLookupSwitch.labels.get(i); + list.getAppendMap().put(label, " [switch key: " + key + "]"); + list.getColorMap().put(label, colJumpRange); + } + list.getColorMap().put(insnLookupSwitch.dflt, colJumpFail); + break; + } + } + } } diff --git a/src/me/coley/recaf/ui/component/panel/AccessPanel.java b/src/me/coley/recaf/ui/component/panel/AccessPanel.java index 3fb17e87d..434fb9779 100644 --- a/src/me/coley/recaf/ui/component/panel/AccessPanel.java +++ b/src/me/coley/recaf/ui/component/panel/AccessPanel.java @@ -21,101 +21,101 @@ @SuppressWarnings("serial") public class AccessPanel extends JPanel { - public final static String TITLE_CLASS = "Class Access"; - public final static String TITLE_FIELD = "Field Access"; - public final static String TITLE_METHOD = "Method Access"; - public final static String TITLE_PARAMETER = "Parameter Access"; - private final Map compToAccess = new HashMap<>(); - private final Consumer action; - private final String title; + public final static String TITLE_CLASS = "Class Access"; + public final static String TITLE_FIELD = "Field Access"; + public final static String TITLE_METHOD = "Method Access"; + public final static String TITLE_PARAMETER = "Parameter Access"; + private final Map compToAccess = new HashMap<>(); + private final Consumer action; + private final String title; - public AccessPanel(ClassNode clazz, JComponent owner) throws Exception { - this(AccessPanel.TITLE_CLASS + ": " + clazz.name, clazz.access, acc -> clazz.access = acc, owner); - } + public AccessPanel(ClassNode clazz, JComponent owner) throws Exception { + this(AccessPanel.TITLE_CLASS + ": " + clazz.name, clazz.access, acc -> clazz.access = acc, owner); + } - public AccessPanel(FieldNode field, JComponent owner) throws Exception { - this(AccessPanel.TITLE_FIELD + ": " + field.name, field.access, acc -> field.access = acc, owner); - } + public AccessPanel(FieldNode field, JComponent owner) throws Exception { + this(AccessPanel.TITLE_FIELD + ": " + field.name, field.access, acc -> field.access = acc, owner); + } - public AccessPanel(MethodNode method, JComponent owner) throws Exception { - this(AccessPanel.TITLE_METHOD + ": " + method.name, method.access, acc -> method.access = acc, owner); - } + public AccessPanel(MethodNode method, JComponent owner) throws Exception { + this(AccessPanel.TITLE_METHOD + ": " + method.name, method.access, acc -> method.access = acc, owner); + } - private AccessPanel(String title, int init, Consumer action, JComponent owner) throws Exception { - this.title = title; - this.action = action; - this.setLayout(new GridLayout(0, 3)); - // this.add(comp) - for (Field acc : Access.class.getDeclaredFields()) { - acc.setAccessible(true); - String name = acc.getName(); - // Skip non-modifier value fields - if (name.contains("_")) { - continue; - } - int accValue = acc.getInt(null); - // Skip modifiers that don't apply to the given access - if (title.contains(TITLE_CLASS)) { - // Classes - if (!Access.hasAccess(Access.CLASS_MODIFIERS, accValue)) { - continue; - } - } else if (title.contains(TITLE_FIELD)) { - // fields - if (!Access.hasAccess(Access.FIELD_MODIFIERS, accValue)) { - continue; - } - } else if (title.contains(TITLE_METHOD)) { - if (title.contains(" action, JComponent owner) throws Exception { + this.title = title; + this.action = action; + this.setLayout(new GridLayout(0, 3)); + // this.add(comp) + for (Field acc : Access.class.getDeclaredFields()) { + acc.setAccessible(true); + String name = acc.getName(); + // Skip non-modifier value fields + if (name.contains("_")) { + continue; + } + int accValue = acc.getInt(null); + // Skip modifiers that don't apply to the given access + if (title.contains(TITLE_CLASS)) { + // Classes + if (!Access.hasAccess(Access.CLASS_MODIFIERS, accValue)) { + continue; + } + } else if (title.contains(TITLE_FIELD)) { + // fields + if (!Access.hasAccess(Access.FIELD_MODIFIERS, accValue)) { + continue; + } + } else if (title.contains(TITLE_METHOD)) { + if (title.contains(" entry : compToAccess.entrySet()) { - if (entry.getKey().isSelected()) { - access |= entry.getValue().intValue(); - } - } - this.action.accept(access); - } + public void onUpdate() { + // Create new access + int access = 0; + for (Entry entry : compToAccess.entrySet()) { + if (entry.getKey().isSelected()) { + access |= entry.getValue().intValue(); + } + } + this.action.accept(access); + } - public String getTitle() { - return title; - } + public String getTitle() { + return title; + } } diff --git a/src/me/coley/recaf/ui/component/panel/AsmFlagsPanel.java b/src/me/coley/recaf/ui/component/panel/AsmFlagsPanel.java index 0ada7f93c..935b03458 100644 --- a/src/me/coley/recaf/ui/component/panel/AsmFlagsPanel.java +++ b/src/me/coley/recaf/ui/component/panel/AsmFlagsPanel.java @@ -16,56 +16,56 @@ /** * Panel for selecting ASM flags. - * + * * @author Matt */ @SuppressWarnings("serial") public class AsmFlagsPanel extends JPanel { - private final Options options = Recaf.getInstance().options; - private ActionCheckBox inE, inD, inF, inC, outF, outM; + private final Options options = Recaf.getInstance().options; + private ActionCheckBox inE, inD, inF, inC, outF, outM; - public AsmFlagsPanel() { - //@formatter:off - setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - JPanel p1 = new JPanel(); - p1.setBorder(BorderFactory.createTitledBorder("Input Flags")); - p1.setLayout(new GridLayout(0, 2)); - p1.add(inE = new ActionCheckBox("Expand Frames", Access.hasAccess(options.classFlagsInput, ClassReader.EXPAND_FRAMES), (b) -> update())); - p1.add(inD = new ActionCheckBox("Skip Debug", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_DEBUG), (b) -> update())); - p1.add(inF = new ActionCheckBox("Skip Frames", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_FRAMES), (b) -> update())); - p1.add(inC = new ActionCheckBox("Skip Code", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_CODE), (b) -> update())); - JPanel p2 = new JPanel(); - p2.setBorder(BorderFactory.createTitledBorder("Output Flags")); - p2.setLayout(new GridLayout(0, 2)); - p2.add(outF = new ActionCheckBox("Compute Frames", Access.hasAccess(options.classFlagsOutput, ClassWriter.COMPUTE_FRAMES), (b) -> update())); - p2.add(outM = new ActionCheckBox("Compute Maxs", Access.hasAccess(options.classFlagsOutput, ClassWriter.COMPUTE_MAXS), (b) -> update())); - add(p1); - add(p2); - //@formatter:on - } + public AsmFlagsPanel() { + //@formatter:off + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + JPanel p1 = new JPanel(); + p1.setBorder(BorderFactory.createTitledBorder("Input Flags")); + p1.setLayout(new GridLayout(0, 2)); + p1.add(inE = new ActionCheckBox("Expand Frames", Access.hasAccess(options.classFlagsInput, ClassReader.EXPAND_FRAMES), (b) -> update())); + p1.add(inD = new ActionCheckBox("Skip Debug", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_DEBUG), (b) -> update())); + p1.add(inF = new ActionCheckBox("Skip Frames", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_FRAMES), (b) -> update())); + p1.add(inC = new ActionCheckBox("Skip Code", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_CODE), (b) -> update())); + JPanel p2 = new JPanel(); + p2.setBorder(BorderFactory.createTitledBorder("Output Flags")); + p2.setLayout(new GridLayout(0, 2)); + p2.add(outF = new ActionCheckBox("Compute Frames", Access.hasAccess(options.classFlagsOutput, ClassWriter.COMPUTE_FRAMES), (b) -> update())); + p2.add(outM = new ActionCheckBox("Compute Maxs", Access.hasAccess(options.classFlagsOutput, ClassWriter.COMPUTE_MAXS), (b) -> update())); + add(p1); + add(p2); + //@formatter:on + } - private void update() { - int in = 0; - int out = 0; - if (inE.isSelected()) { - in |= ClassReader.EXPAND_FRAMES; - } - if (inD.isSelected()) { - in |= ClassReader.SKIP_DEBUG; - } - if (inF.isSelected()) { - in |= ClassReader.SKIP_FRAMES; - } - if (inC.isSelected()) { - in |= ClassReader.SKIP_CODE; - } - if (outF.isSelected()) { - out |= ClassWriter.COMPUTE_FRAMES; - } - if (outM.isSelected()) { - out |= ClassWriter.COMPUTE_MAXS; - } - options.classFlagsInput = in; - options.classFlagsOutput = out; - } + private void update() { + int in = 0; + int out = 0; + if (inE.isSelected()) { + in |= ClassReader.EXPAND_FRAMES; + } + if (inD.isSelected()) { + in |= ClassReader.SKIP_DEBUG; + } + if (inF.isSelected()) { + in |= ClassReader.SKIP_FRAMES; + } + if (inC.isSelected()) { + in |= ClassReader.SKIP_CODE; + } + if (outF.isSelected()) { + out |= ClassWriter.COMPUTE_FRAMES; + } + if (outM.isSelected()) { + out |= ClassWriter.COMPUTE_MAXS; + } + options.classFlagsInput = in; + options.classFlagsOutput = out; + } } diff --git a/src/me/coley/recaf/ui/component/panel/ClassDisplayPanel.java b/src/me/coley/recaf/ui/component/panel/ClassDisplayPanel.java index 86eee6887..4ffd9f0a8 100644 --- a/src/me/coley/recaf/ui/component/panel/ClassDisplayPanel.java +++ b/src/me/coley/recaf/ui/component/panel/ClassDisplayPanel.java @@ -27,155 +27,155 @@ @SuppressWarnings("serial") public class ClassDisplayPanel extends JPanel { - private final Recaf recaf = Recaf.getInstance(); - private final Gui gui = recaf.window; - private final JDesktopPane desktopPane = new JDesktopPane(); - private final ClassNode node; + private final Recaf recaf = Recaf.getInstance(); + private final Gui gui = recaf.window; + private final JDesktopPane desktopPane = new JDesktopPane(); + private final ClassNode node; - public ClassDisplayPanel(ClassNode node) { - this.node = node; - setLayout(new BorderLayout(0, 0)); - // Class - JInternalFrame frameClass = setupClassFrame(); - addWindow(frameClass); - // Fields - if (node.fields.size() > 0) { - JInternalFrame frameFields = setupFieldsFrame(); - addWindow(frameFields); - } - // Methods - if (node.methods.size() > 0) { - JInternalFrame frameMethods = setupMethodsFrame(); - addWindow(frameMethods); - } - add(desktopPane); - } + public ClassDisplayPanel(ClassNode node) { + this.node = node; + setLayout(new BorderLayout(0, 0)); + // Class + JInternalFrame frameClass = setupClassFrame(); + addWindow(frameClass); + // Fields + if (node.fields.size() > 0) { + JInternalFrame frameFields = setupFieldsFrame(); + addWindow(frameFields); + } + // Methods + if (node.methods.size() > 0) { + JInternalFrame frameMethods = setupMethodsFrame(); + addWindow(frameMethods); + } + add(desktopPane); + } - private JInternalFrame setupClassFrame() { - JInternalFrame frameClass = new JInternalFrame("Class Data"); - frameClass.setResizable(true); - frameClass.setIconifiable(true); - frameClass.setBounds(10, 11, 240, 276); - frameClass.setVisible(true); - frameClass.setLayout(new BoxLayout(frameClass.getContentPane(), BoxLayout.Y_AXIS)); - //@formatter:off - Misc.addAll(frameClass, - new LabeledComponent("Version: ", new ActionTextField(node.version, s -> { - if (Misc.isInt(s)) { - node.version = Integer.parseInt(s); - } - })), - new LabeledComponent("Source File: ", new ActionTextField(node.sourceFile, s -> { - if (s.isEmpty()) { - node.sourceFile = null; - } else { - node.sourceFile = s; - } - })), - new LabeledComponent("Source Debug: ", new ActionTextField(node.sourceDebug, s -> { - if (s.isEmpty()) { - node.sourceDebug = null; - } else { - node.sourceDebug = s; - } - })), - new LabeledComponent("Signature: ", new ActionTextField(node.signature == null ? "" : node.signature, s -> { - if (s.isEmpty()) { - node.signature = null; - } else { - node.signature = s; - } - })), - new LabeledComponent("Outer Class: ", new ActionTextField(node.outerClass == null ? "" : node.outerClass, s -> { - if (s.isEmpty()) { - node.outerClass = null; - } else { - node.outerClass = s; - } - })), - new LabeledComponent("Outer Method Name: ", new ActionTextField(node.outerMethod == null ? "" : node.outerMethod, s -> { - if (s.isEmpty()) { - node.outerMethod = null; - } else { - node.outerMethod = s; - } - })), - new LabeledComponent("Outer Method Desc: ", new ActionTextField(node.outerMethodDesc == null ? "" : node.outerMethodDesc, s -> { - if (s.isEmpty()) { - node.outerMethodDesc = null; - } else { - node.outerMethodDesc = s; - } - })), - new LabeledComponent("", new ActionButton("Edit Access",() -> { - try { - addWindow(new AccessBox(node, null)); - } catch (Exception e) { - exception(e); - } - })), - new LabeledComponent("", new ActionButton("Decompile", () -> { - try { - addWindow(new DecompileBox(new DecompilePanel(node))); - } catch (Exception e) { - exception(e); - } - })) - ); - //@formatter:on - return frameClass; - } + private JInternalFrame setupClassFrame() { + JInternalFrame frameClass = new JInternalFrame("Class Data"); + frameClass.setResizable(true); + frameClass.setIconifiable(true); + frameClass.setBounds(10, 11, 240, 276); + frameClass.setVisible(true); + frameClass.setLayout(new BoxLayout(frameClass.getContentPane(), BoxLayout.Y_AXIS)); + //@formatter:off + Misc.addAll(frameClass, + new LabeledComponent("Version: ", new ActionTextField(node.version, s -> { + if (Misc.isInt(s)) { + node.version = Integer.parseInt(s); + } + })), + new LabeledComponent("Source File: ", new ActionTextField(node.sourceFile, s -> { + if (s.isEmpty()) { + node.sourceFile = null; + } else { + node.sourceFile = s; + } + })), + new LabeledComponent("Source Debug: ", new ActionTextField(node.sourceDebug, s -> { + if (s.isEmpty()) { + node.sourceDebug = null; + } else { + node.sourceDebug = s; + } + })), + new LabeledComponent("Signature: ", new ActionTextField(node.signature == null ? "" : node.signature, s -> { + if (s.isEmpty()) { + node.signature = null; + } else { + node.signature = s; + } + })), + new LabeledComponent("Outer Class: ", new ActionTextField(node.outerClass == null ? "" : node.outerClass, s -> { + if (s.isEmpty()) { + node.outerClass = null; + } else { + node.outerClass = s; + } + })), + new LabeledComponent("Outer Method Name: ", new ActionTextField(node.outerMethod == null ? "" : node.outerMethod, s -> { + if (s.isEmpty()) { + node.outerMethod = null; + } else { + node.outerMethod = s; + } + })), + new LabeledComponent("Outer Method Desc: ", new ActionTextField(node.outerMethodDesc == null ? "" : node.outerMethodDesc, s -> { + if (s.isEmpty()) { + node.outerMethodDesc = null; + } else { + node.outerMethodDesc = s; + } + })), + new LabeledComponent("", new ActionButton("Edit Access",() -> { + try { + addWindow(new AccessBox(node, null)); + } catch (Exception e) { + exception(e); + } + })), + new LabeledComponent("", new ActionButton("Decompile", () -> { + try { + addWindow(new DecompileBox(new DecompilePanel(node))); + } catch (Exception e) { + exception(e); + } + })) + ); + //@formatter:on + return frameClass; + } - private JInternalFrame setupFieldsFrame() { - JInternalFrame frameFields = new JInternalFrame("Fields"); - frameFields.setResizable(true); - frameFields.setIconifiable(true); - frameFields.setBounds(260, 11, 180, 140); - frameFields.setVisible(true); - frameFields.setLayout(new BorderLayout()); - JList fields = new JList<>(); - fields.setCellRenderer(new MemberNodeRenderer(recaf.options)); - fields.addMouseListener(new MemberNodeClickListener(this, node, fields)); - DefaultListModel model = new DefaultListModel<>(); - for (FieldNode fn : node.fields) { - model.addElement(fn); - } - fields.setModel(model); - frameFields.add(new JScrollPane(fields), BorderLayout.CENTER); - frameFields.pack(); - return frameFields; - } + private JInternalFrame setupFieldsFrame() { + JInternalFrame frameFields = new JInternalFrame("Fields"); + frameFields.setResizable(true); + frameFields.setIconifiable(true); + frameFields.setBounds(260, 11, 180, 140); + frameFields.setVisible(true); + frameFields.setLayout(new BorderLayout()); + JList fields = new JList<>(); + fields.setCellRenderer(new MemberNodeRenderer(recaf.options)); + fields.addMouseListener(new MemberNodeClickListener(this, node, fields)); + DefaultListModel model = new DefaultListModel<>(); + for (FieldNode fn : node.fields) { + model.addElement(fn); + } + fields.setModel(model); + frameFields.add(new JScrollPane(fields), BorderLayout.CENTER); + frameFields.pack(); + return frameFields; + } - private JInternalFrame setupMethodsFrame() { - JInternalFrame frameMethods = new JInternalFrame("Methods"); - frameMethods.setResizable(true); - frameMethods.setIconifiable(true); - frameMethods.setBounds(445, 11, 180, 120); - frameMethods.setVisible(true); - frameMethods.setLayout(new BorderLayout()); + private JInternalFrame setupMethodsFrame() { + JInternalFrame frameMethods = new JInternalFrame("Methods"); + frameMethods.setResizable(true); + frameMethods.setIconifiable(true); + frameMethods.setBounds(445, 11, 180, 120); + frameMethods.setVisible(true); + frameMethods.setLayout(new BorderLayout()); - JList methods = new JList<>(); - methods.setCellRenderer(new MemberNodeRenderer(recaf.options)); - methods.addMouseListener(new MemberNodeClickListener(this, node, methods)); - DefaultListModel model = new DefaultListModel<>(); - for (MethodNode mn : node.methods) { - model.addElement(mn); - } - methods.setModel(model); - frameMethods.add(new JScrollPane(methods), BorderLayout.CENTER); - // TODO: Switch to table - // frameMethods.add(new JScrollPane(MemberTable.create(node.methods)), - // BorderLayout.CENTER); - frameMethods.pack(); - return frameMethods; - } + JList methods = new JList<>(); + methods.setCellRenderer(new MemberNodeRenderer(recaf.options)); + methods.addMouseListener(new MemberNodeClickListener(this, node, methods)); + DefaultListModel model = new DefaultListModel<>(); + for (MethodNode mn : node.methods) { + model.addElement(mn); + } + methods.setModel(model); + frameMethods.add(new JScrollPane(methods), BorderLayout.CENTER); + // TODO: Switch to table + // frameMethods.add(new JScrollPane(MemberTable.create(node.methods)), + // BorderLayout.CENTER); + frameMethods.pack(); + return frameMethods; + } - public void addWindow(JInternalFrame frame) { - desktopPane.add(frame); - desktopPane.moveToFront(frame); - } + public void addWindow(JInternalFrame frame) { + desktopPane.add(frame); + desktopPane.moveToFront(frame); + } - public void exception(Exception e) { - gui.displayError(e); - } + public void exception(Exception e) { + gui.displayError(e); + } } diff --git a/src/me/coley/recaf/ui/component/panel/DecompilePanel.java b/src/me/coley/recaf/ui/component/panel/DecompilePanel.java index 5c7a75681..cebc103b0 100644 --- a/src/me/coley/recaf/ui/component/panel/DecompilePanel.java +++ b/src/me/coley/recaf/ui/component/panel/DecompilePanel.java @@ -18,79 +18,79 @@ @SuppressWarnings("serial") public class DecompilePanel extends JPanel { - private final RSyntaxTextArea textArea = new RSyntaxTextArea(25, 70); - private final RTextScrollPane scrollText = new RTextScrollPane(textArea); - private final ClassNode classNode; - private final MethodNode methodNode; - private final CFRResourceLookup lookupHelper; + private final RSyntaxTextArea textArea = new RSyntaxTextArea(25, 70); + private final RTextScrollPane scrollText = new RTextScrollPane(textArea); + private final ClassNode classNode; + private final MethodNode methodNode; + private final CFRResourceLookup lookupHelper; - public DecompilePanel(ClassNode cn) { - this(cn, null); - } + public DecompilePanel(ClassNode cn) { + this(cn, null); + } - public DecompilePanel(ClassNode cn, MethodNode mn) { - this.classNode = cn; - this.methodNode = mn; - if (mn != null) { - this.lookupHelper = new CFRResourceLookup(Recaf.getInstance(), getIsolatedMethodClass()); - } else { - this.lookupHelper = new CFRResourceLookup(Recaf.getInstance()); - } - // - textArea.setCaretPosition(0); - textArea.requestFocusInWindow(); - textArea.setMarkOccurrences(true); - textArea.setClearWhitespaceLinesEnabled(false); - textArea.setEditable(false); - textArea.setAntiAliasingEnabled(true); - textArea.setCodeFoldingEnabled(true); - textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); - textArea.setComponentPopupMenu(null); - textArea.setPopupMenu(null); - // - setLayout(new BorderLayout()); - add(scrollText, BorderLayout.CENTER); - // - decompile(); - } + public DecompilePanel(ClassNode cn, MethodNode mn) { + this.classNode = cn; + this.methodNode = mn; + if (mn != null) { + this.lookupHelper = new CFRResourceLookup(Recaf.getInstance(), getIsolatedMethodClass()); + } else { + this.lookupHelper = new CFRResourceLookup(Recaf.getInstance()); + } + // + textArea.setCaretPosition(0); + textArea.requestFocusInWindow(); + textArea.setMarkOccurrences(true); + textArea.setClearWhitespaceLinesEnabled(false); + textArea.setEditable(false); + textArea.setAntiAliasingEnabled(true); + textArea.setCodeFoldingEnabled(true); + textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + textArea.setComponentPopupMenu(null); + textArea.setPopupMenu(null); + // + setLayout(new BorderLayout()); + add(scrollText, BorderLayout.CENTER); + // + decompile(); + } - /** - * Returns a title for the containing parent to access (Groupbox / - * InternalWindow). - * - * @return The title. - */ - public String getTitle() { - String s = "CFR: " + classNode.name; - if (methodNode != null) { - s += "#" + methodNode.name + methodNode.desc; - } - return s; - } + /** + * Returns a title for the containing parent to access (Groupbox / + * InternalWindow). + * + * @return The title. + */ + public String getTitle() { + String s = "CFR: " + classNode.name; + if (methodNode != null) { + s += "#" + methodNode.name + methodNode.desc; + } + return s; + } - private ClassNode getIsolatedMethodClass() { - ClassNode copy = new ClassNode(); - copy.visit(classNode.version, classNode.access, classNode.name, classNode.signature, classNode.superName, - classNode.interfaces.stream().toArray(String[]::new)); - // I initially though sharing method nodes would be bad, - // but copying it is even more of a pain. - copy.methods.add(methodNode); - return copy; - } + private ClassNode getIsolatedMethodClass() { + ClassNode copy = new ClassNode(); + copy.visit(classNode.version, classNode.access, classNode.name, classNode.signature, classNode.superName, + classNode.interfaces.stream().toArray(String[]::new)); + // I initially though sharing method nodes would be bad, + // but copying it is even more of a pain. + copy.methods.add(methodNode); + return copy; + } - /** - * Decompiled the class. - */ - private void decompile() { - String name = classNode.name; - String text = new PluginRunner(CFRSetting.toStringMap(), new CFRSourceImpl(lookupHelper)).getDecompilationFor(name); - // Hack to substring the first indent (Where the isolated method begins) - // to the end of the class, minus one (so it substrings to the method's - // closing brace) - if (methodNode != null) { - text = text.substring(text.indexOf(" "), text.lastIndexOf("}") - 1); - } - textArea.setText(text); - textArea.moveCaretPosition(0); - } + /** + * Decompiled the class. + */ + private void decompile() { + String name = classNode.name; + String text = new PluginRunner(CFRSetting.toStringMap(), new CFRSourceImpl(lookupHelper)).getDecompilationFor(name); + // Hack to substring the first indent (Where the isolated method begins) + // to the end of the class, minus one (so it substrings to the method's + // closing brace) + if (methodNode != null) { + text = text.substring(text.indexOf(" "), text.lastIndexOf("}") - 1); + } + textArea.setText(text); + textArea.moveCaretPosition(0); + } } diff --git a/src/me/coley/recaf/ui/component/panel/LabelSwitcherPanel.java b/src/me/coley/recaf/ui/component/panel/LabelSwitcherPanel.java index f7d803b17..c9509045f 100644 --- a/src/me/coley/recaf/ui/component/panel/LabelSwitcherPanel.java +++ b/src/me/coley/recaf/ui/component/panel/LabelSwitcherPanel.java @@ -19,74 +19,74 @@ /** * JPanel for updating label values. - * + * * @author Matt */ @SuppressWarnings("serial") public class LabelSwitcherPanel extends JPanel implements Opcodes { - /** - * Map of strings to labels. - */ - private final Map labels = new LinkedHashMap<>(); - /** - * Initial label value. - */ - private final LabelNode initial; - /** - * Callback to the label setter. - */ - private final Consumer updater; - /** - * Reference so list can be re-painted. - */ - private final OpcodeList list; - /** - * Combobox containing label node indices. - */ - private final JComboBox combo = new JComboBox<>(); + /** + * Map of strings to labels. + */ + private final Map labels = new LinkedHashMap<>(); + /** + * Initial label value. + */ + private final LabelNode initial; + /** + * Callback to the label setter. + */ + private final Consumer updater; + /** + * Reference so list can be re-painted. + */ + private final OpcodeList list; + /** + * Combobox containing label node indices. + */ + private final JComboBox combo = new JComboBox<>(); - public LabelSwitcherPanel(MethodNode method, LabelNode initial, Consumer updater) { - this(null, method, initial, updater); - } + public LabelSwitcherPanel(MethodNode method, LabelNode initial, Consumer updater) { + this(null, method, initial, updater); + } - public LabelSwitcherPanel(OpcodeList list, MethodNode method, LabelNode initial, Consumer updater) { - this.initial = initial; - this.updater = updater; - this.list = list; - setLayout(new BorderLayout()); - populate(method.instructions); - add(combo, BorderLayout.CENTER); - } + public LabelSwitcherPanel(OpcodeList list, MethodNode method, LabelNode initial, Consumer updater) { + this.initial = initial; + this.updater = updater; + this.list = list; + setLayout(new BorderLayout()); + populate(method.instructions); + add(combo, BorderLayout.CENTER); + } - private void populate(InsnList opcodes) { - int selected = -1, labelCount = 0;; - DefaultComboBoxModel model = new DefaultComboBoxModel<>(); - for (int i = 0; i < opcodes.size(); i++) { - AbstractInsnNode ain = opcodes.get(i); - if (ain.getType() == AbstractInsnNode.LABEL) { - LabelNode label = (LabelNode) ain; - String s = i + "."; - if (list != null) { - s += " : " + list.getLabelName(ain); - } - labels.put(s, label); - model.addElement(s); - if (label.equals(initial)) { - selected = labelCount; - } - labelCount++; - } - } - combo.setModel(model); - combo.setSelectedIndex(selected); - combo.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - updater.accept(labels.get(e.getItem())); - if (list != null) { - list.repaint(); - } - } - }); - } + private void populate(InsnList opcodes) { + int selected = -1, labelCount = 0;; + DefaultComboBoxModel model = new DefaultComboBoxModel<>(); + for (int i = 0; i < opcodes.size(); i++) { + AbstractInsnNode ain = opcodes.get(i); + if (ain.getType() == AbstractInsnNode.LABEL) { + LabelNode label = (LabelNode) ain; + String s = i + "."; + if (list != null) { + s += " : " + list.getLabelName(ain); + } + labels.put(s, label); + model.addElement(s); + if (label.equals(initial)) { + selected = labelCount; + } + labelCount++; + } + } + combo.setModel(model); + combo.setSelectedIndex(selected); + combo.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + updater.accept(labels.get(e.getItem())); + if (list != null) { + list.repaint(); + } + } + }); + } } diff --git a/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java b/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java index 3f8e84379..7f1854b98 100644 --- a/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java +++ b/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java @@ -20,180 +20,180 @@ /** * JPanel for opcode switcher for AbstractInsnNode. - * + * * @author Matt */ @SuppressWarnings("serial") public class OpcodeTypeSwitchPanel extends JPanel implements Opcodes { - /** - * Map of radio buttons to possible opcodes. - */ - private final Map compToOpcode = new HashMap<>(); - /** - * Opcode node being modified. - */ - private final AbstractInsnNode opcode; - /** - * Reference so list can be re-painted. - */ - private final JList list; - /** - * Content wrapper. - */ - private final JPanel content = new JPanel(); - - public OpcodeTypeSwitchPanel(JList list, AbstractInsnNode opcode) { - this.list = list; - this.opcode = opcode; - // setMaximumSize(new Dimension(900, 200)); - // content.setMaximumSize(new Dimension(900, 300)); - // scroll.setMaximumSize(new Dimension(900, 300)); - populate(); - setLayout(new BorderLayout()); - JScrollPane scroll = new JScrollPane(content); - add(scroll, BorderLayout.CENTER); - } - - private void populate() { - switch (opcode.getType()) { - case AbstractInsnNode.INSN: - populate(OpcodeUtil.getInsnSubset(OpcodeUtil.opcodeToName(opcode.getOpcode()))); - break; - case AbstractInsnNode.INT_INSN: - populate(OpcodeUtil.OPS_INT); - break; - case AbstractInsnNode.VAR_INSN: - populate(OpcodeUtil.OPS_VAR); - break; - case AbstractInsnNode.TYPE_INSN: - populate(OpcodeUtil.OPS_TYPE); - break; - case AbstractInsnNode.FIELD_INSN: - populate(OpcodeUtil.OPS_FIELD); - break; - case AbstractInsnNode.METHOD_INSN: - populate(OpcodeUtil.OPS_METHOD); - break; - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - populate(OpcodeUtil.OPS_INDY_METHOD); - break; - case AbstractInsnNode.JUMP_INSN: - populate(OpcodeUtil.OPS_JUMP); - break; - case AbstractInsnNode.LDC_INSN: - populate(OpcodeUtil.OPS_LDC); - break; - case AbstractInsnNode.IINC_INSN: - populate(OpcodeUtil.OPS_IINC); - break; - case AbstractInsnNode.TABLESWITCH_INSN: - populate(OpcodeUtil.OPS_TABLESWITCH); - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - populate(OpcodeUtil.OPS_LOOKUPSWITCH); - break; - case AbstractInsnNode.MULTIANEWARRAY_INSN: - populate(OpcodeUtil.OPS_MULTIANEWARRAY); - break; - case AbstractInsnNode.LABEL: - case AbstractInsnNode.LINE: - break; - case AbstractInsnNode.FRAME: - populateFrames(OpcodeUtil.OPS_FRAME); - break; - } - } - - private void populate(String[] opcodes) { - populate(opcodes, s -> OpcodeUtil.nameToOpcode(s)); - - } - - private void populateFrames(String[] opcodes) { - populate(opcodes, s -> OpcodeUtil.nameToFrame(s)); - } - - private void populate(String[] opcodes, Function getter) { - // don't bother showing the option to change if there are no other - // options - if (opcodes.length == 1) { - return; - } - // Set layout based on number of options - setLayout(opcodes.length); - // Add options - for (String op : opcodes) { - int value = getter.apply(op);; - JRadioButton btn = new JRadioButton(op); - if (value == opcode.getOpcode()) { - btn.setSelected(true); - } - btn.addActionListener(new RadioListener(btn)); - compToOpcode.put(btn, value); - content.add(btn); - } - } - - /** - * Update {@link #opcode} value. - * - * @param value - */ - private void setValue(int value) { - try { - Field op = AbstractInsnNode.class.getDeclaredField("opcode"); - op.setAccessible(true); - op.set(opcode, value); - list.repaint(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Sets layout depending on the content size. - * - * @param size - */ - private void setLayout(int size) { - if (size % 6 == 0 || size % 3 == 0) { - content.setLayout(new GridLayout(0, 3)); - } else if (size % 2 == 0) { - content.setLayout(new GridLayout(0, 2)); - } else { - content.setLayout(new GridLayout(0, 3)); - } - } - - /** - * @return the number of radio buttons. - - */ - public int getOptionCount() { - return compToOpcode.keySet().size(); - } - - /** - * Listener for disabling other radio buttons. - * - * @author Matt - */ - private class RadioListener implements ActionListener { - private final JRadioButton btn; - - public RadioListener(JRadioButton btn) { - this.btn = btn; - } - - @Override - public void actionPerformed(ActionEvent e) { - for (JRadioButton comp : compToOpcode.keySet()) { - if (comp != btn && comp.isSelected()) { - comp.setSelected(false); - } else if (comp == btn) { - setValue(compToOpcode.get(comp)); - } - } - } - } + /** + * Map of radio buttons to possible opcodes. + */ + private final Map compToOpcode = new HashMap<>(); + /** + * Opcode node being modified. + */ + private final AbstractInsnNode opcode; + /** + * Reference so list can be re-painted. + */ + private final JList list; + /** + * Content wrapper. + */ + private final JPanel content = new JPanel(); + + public OpcodeTypeSwitchPanel(JList list, AbstractInsnNode opcode) { + this.list = list; + this.opcode = opcode; + // setMaximumSize(new Dimension(900, 200)); + // content.setMaximumSize(new Dimension(900, 300)); + // scroll.setMaximumSize(new Dimension(900, 300)); + populate(); + setLayout(new BorderLayout()); + JScrollPane scroll = new JScrollPane(content); + add(scroll, BorderLayout.CENTER); + } + + private void populate() { + switch (opcode.getType()) { + case AbstractInsnNode.INSN: + populate(OpcodeUtil.getInsnSubset(OpcodeUtil.opcodeToName(opcode.getOpcode()))); + break; + case AbstractInsnNode.INT_INSN: + populate(OpcodeUtil.OPS_INT); + break; + case AbstractInsnNode.VAR_INSN: + populate(OpcodeUtil.OPS_VAR); + break; + case AbstractInsnNode.TYPE_INSN: + populate(OpcodeUtil.OPS_TYPE); + break; + case AbstractInsnNode.FIELD_INSN: + populate(OpcodeUtil.OPS_FIELD); + break; + case AbstractInsnNode.METHOD_INSN: + populate(OpcodeUtil.OPS_METHOD); + break; + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + populate(OpcodeUtil.OPS_INDY_METHOD); + break; + case AbstractInsnNode.JUMP_INSN: + populate(OpcodeUtil.OPS_JUMP); + break; + case AbstractInsnNode.LDC_INSN: + populate(OpcodeUtil.OPS_LDC); + break; + case AbstractInsnNode.IINC_INSN: + populate(OpcodeUtil.OPS_IINC); + break; + case AbstractInsnNode.TABLESWITCH_INSN: + populate(OpcodeUtil.OPS_TABLESWITCH); + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + populate(OpcodeUtil.OPS_LOOKUPSWITCH); + break; + case AbstractInsnNode.MULTIANEWARRAY_INSN: + populate(OpcodeUtil.OPS_MULTIANEWARRAY); + break; + case AbstractInsnNode.LABEL: + case AbstractInsnNode.LINE: + break; + case AbstractInsnNode.FRAME: + populateFrames(OpcodeUtil.OPS_FRAME); + break; + } + } + + private void populate(String[] opcodes) { + populate(opcodes, s -> OpcodeUtil.nameToOpcode(s)); + + } + + private void populateFrames(String[] opcodes) { + populate(opcodes, s -> OpcodeUtil.nameToFrame(s)); + } + + private void populate(String[] opcodes, Function getter) { + // don't bother showing the option to change if there are no other + // options + if (opcodes.length == 1) { + return; + } + // Set layout based on number of options + setLayout(opcodes.length); + // Add options + for (String op : opcodes) { + int value = getter.apply(op);; + JRadioButton btn = new JRadioButton(op); + if (value == opcode.getOpcode()) { + btn.setSelected(true); + } + btn.addActionListener(new RadioListener(btn)); + compToOpcode.put(btn, value); + content.add(btn); + } + } + + /** + * Update {@link #opcode} value. + * + * @param value + */ + private void setValue(int value) { + try { + Field op = AbstractInsnNode.class.getDeclaredField("opcode"); + op.setAccessible(true); + op.set(opcode, value); + list.repaint(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Sets layout depending on the content size. + * + * @param size + */ + private void setLayout(int size) { + if (size % 6 == 0 || size % 3 == 0) { + content.setLayout(new GridLayout(0, 3)); + } else if (size % 2 == 0) { + content.setLayout(new GridLayout(0, 2)); + } else { + content.setLayout(new GridLayout(0, 3)); + } + } + + /** + * @return the number of radio buttons. + + */ + public int getOptionCount() { + return compToOpcode.keySet().size(); + } + + /** + * Listener for disabling other radio buttons. + * + * @author Matt + */ + private class RadioListener implements ActionListener { + private final JRadioButton btn; + + public RadioListener(JRadioButton btn) { + this.btn = btn; + } + + @Override + public void actionPerformed(ActionEvent e) { + for (JRadioButton comp : compToOpcode.keySet()) { + if (comp != btn && comp.isSelected()) { + comp.setSelected(false); + } else if (comp == btn) { + setValue(compToOpcode.get(comp)); + } + } + } + } } diff --git a/src/me/coley/recaf/ui/component/panel/SearchPanel.java b/src/me/coley/recaf/ui/component/panel/SearchPanel.java index 98212fc99..52f320ad0 100644 --- a/src/me/coley/recaf/ui/component/panel/SearchPanel.java +++ b/src/me/coley/recaf/ui/component/panel/SearchPanel.java @@ -34,211 +34,211 @@ @SuppressWarnings("serial") public class SearchPanel extends JPanel { - public static final int S_STRINGS = 0; - public static final int S_FIELD = 10; - public static final int S_METHOD = 20; - public static final int S_CLASS_NAME = 30, S_CLASS_REF = 31; - private final Recaf recaf = Recaf.getInstance(); - private final JTree tree = new JTree(new String[] {}); + public static final int S_STRINGS = 0; + public static final int S_FIELD = 10; + public static final int S_METHOD = 20; + public static final int S_CLASS_NAME = 30, S_CLASS_REF = 31; + private final Recaf recaf = Recaf.getInstance(); + private final JTree tree = new JTree(new String[] {}); - public SearchPanel(int type) { - setLayout(new BorderLayout()); - JPanel pnlInput = new JPanel(), pnlOutput = new JPanel(); - pnlInput.setLayout(new BoxLayout(pnlInput, BoxLayout.Y_AXIS)); - pnlOutput.setLayout(new BorderLayout()); - JScrollPane scrollTree = new JScrollPane(tree); - pnlOutput.add(scrollTree, BorderLayout.CENTER); - tree.setCellRenderer(new JavaTreeRenderer()); - JavaTreeListener sel = new JavaTreeListener(); - tree.addTreeSelectionListener(sel); - tree.addMouseListener(sel); - tree.addTreeExpansionListener(sel); - JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pnlInput, pnlOutput); - split.setResizeWeight(0.67); - switch (type) { - case S_STRINGS: { - JTextField text; - JCheckBox caseSense; - pnlInput.add(new LabeledComponent("String", text = new JTextField(""))); - pnlInput.add(caseSense = new JCheckBox("Case sensitive")); - pnlInput.add(new ActionButton("Search", () -> searchString(text.getText(), caseSense.isSelected()))); - break; - } - case S_FIELD: { - JTextField name, desc; - pnlInput.add(new LabeledComponent("Field name", name = new JTextField(""))); - pnlInput.add(new LabeledComponent("Field desc", desc = new JTextField(""))); - pnlInput.add(new ActionButton("Search", () -> searchField(name.getText(), desc.getText()))); - break; - } - case S_METHOD: { - JTextField name, desc; - pnlInput.add(new LabeledComponent("Method name", name = new JTextField(""))); - pnlInput.add(new LabeledComponent("Method desc", desc = new JTextField(""))); - pnlInput.add(new ActionButton("Search", () -> searchMethod(name.getText(), desc.getText()))); - break; - } - case S_CLASS_NAME: { - JTextField clazz; - JCheckBox ex; - pnlInput.add(new LabeledComponent("Class name", clazz = new JTextField(""))); - pnlInput.add(ex = new JCheckBox("Exact match")); - pnlInput.add(new ActionButton("Search", () -> searchClass(clazz.getText(), ex.isSelected()))); - break; - } - case S_CLASS_REF: { - JTextField clazz, name, desc; - JCheckBox ex; - pnlInput.add(new LabeledComponent("Class owner", clazz = new JTextField(""))); - pnlInput.add(new LabeledComponent("Member name", name = new JTextField(""))); - pnlInput.add(new LabeledComponent("Member desc", desc = new JTextField(""))); - pnlInput.add(ex = new JCheckBox("Exact match")); - pnlInput.add(new ActionButton("Search", () -> searchClassRef(clazz.getText(), name.getText(), desc.getText(), ex.isSelected()))); - break; - } - } - add(split, BorderLayout.CENTER); - } + public SearchPanel(int type) { + setLayout(new BorderLayout()); + JPanel pnlInput = new JPanel(), pnlOutput = new JPanel(); + pnlInput.setLayout(new BoxLayout(pnlInput, BoxLayout.Y_AXIS)); + pnlOutput.setLayout(new BorderLayout()); + JScrollPane scrollTree = new JScrollPane(tree); + pnlOutput.add(scrollTree, BorderLayout.CENTER); + tree.setCellRenderer(new JavaTreeRenderer()); + JavaTreeListener sel = new JavaTreeListener(); + tree.addTreeSelectionListener(sel); + tree.addMouseListener(sel); + tree.addTreeExpansionListener(sel); + JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pnlInput, pnlOutput); + split.setResizeWeight(0.67); + switch (type) { + case S_STRINGS: { + JTextField text; + JCheckBox caseSense; + pnlInput.add(new LabeledComponent("String", text = new JTextField(""))); + pnlInput.add(caseSense = new JCheckBox("Case sensitive")); + pnlInput.add(new ActionButton("Search", () -> searchString(text.getText(), caseSense.isSelected()))); + break; + } + case S_FIELD: { + JTextField name, desc; + pnlInput.add(new LabeledComponent("Field name", name = new JTextField(""))); + pnlInput.add(new LabeledComponent("Field desc", desc = new JTextField(""))); + pnlInput.add(new ActionButton("Search", () -> searchField(name.getText(), desc.getText()))); + break; + } + case S_METHOD: { + JTextField name, desc; + pnlInput.add(new LabeledComponent("Method name", name = new JTextField(""))); + pnlInput.add(new LabeledComponent("Method desc", desc = new JTextField(""))); + pnlInput.add(new ActionButton("Search", () -> searchMethod(name.getText(), desc.getText()))); + break; + } + case S_CLASS_NAME: { + JTextField clazz; + JCheckBox ex; + pnlInput.add(new LabeledComponent("Class name", clazz = new JTextField(""))); + pnlInput.add(ex = new JCheckBox("Exact match")); + pnlInput.add(new ActionButton("Search", () -> searchClass(clazz.getText(), ex.isSelected()))); + break; + } + case S_CLASS_REF: { + JTextField clazz, name, desc; + JCheckBox ex; + pnlInput.add(new LabeledComponent("Class owner", clazz = new JTextField(""))); + pnlInput.add(new LabeledComponent("Member name", name = new JTextField(""))); + pnlInput.add(new LabeledComponent("Member desc", desc = new JTextField(""))); + pnlInput.add(ex = new JCheckBox("Exact match")); + pnlInput.add(new ActionButton("Search", () -> searchClassRef(clazz.getText(), name.getText(), desc.getText(), ex.isSelected()))); + break; + } + } + add(split, BorderLayout.CENTER); + } - private void searchString(String text, boolean caseSensitive) { - DefaultTreeModel model = setup(); - - search((n) -> { - for (MethodNode m : n.methods) { - for (AbstractInsnNode ain : m.instructions.toArray()) { - if (ain.getType() == AbstractInsnNode.LDC_INSN) { - LdcInsnNode ldc = (LdcInsnNode) ain; - String s = ldc.cst.toString(); - if ((caseSensitive && s.contains(text)) || (!caseSensitive && (s.toLowerCase().contains(text.toLowerCase())))) { - // Get tree node for class - ASMTreeNode genClass = Misc.getOrCreateNode(model, n); + private void searchString(String text, boolean caseSensitive) { + DefaultTreeModel model = setup(); - // Get or create tree node for method - ASMTreeNode genMethod = genClass.getChild(m.name); - if (genMethod == null) { - genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); - genClass.add(genMethod); - } - // Add opcode node to method tree node - genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": '" + s + "'", n, m, ain)); - } - } - } - } - }); - tree.setModel(model); - } + search((n) -> { + for (MethodNode m : n.methods) { + for (AbstractInsnNode ain : m.instructions.toArray()) { + if (ain.getType() == AbstractInsnNode.LDC_INSN) { + LdcInsnNode ldc = (LdcInsnNode) ain; + String s = ldc.cst.toString(); + if ((caseSensitive && s.contains(text)) || (!caseSensitive && (s.toLowerCase().contains(text.toLowerCase())))) { + // Get tree node for class + ASMTreeNode genClass = Misc.getOrCreateNode(model, n); - private void searchField(String name, String desc) { - DefaultTreeModel model = setup(); - search((n) -> { - for (FieldNode f : n.fields) { - if (f.name.contains(name) && f.desc.contains(desc)) { - ASMTreeNode genClass = Misc.getOrCreateNode(model, n); - ASMTreeNode genMethod = genClass.getChild(f.name); - if (genMethod == null) { - genMethod = new ASMFieldTreeNode(f.desc + " " + f.name, n, f); - } - genClass.add(genMethod); - } - } - }); - tree.setModel(model); - } + // Get or create tree node for method + ASMTreeNode genMethod = genClass.getChild(m.name); + if (genMethod == null) { + genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); + genClass.add(genMethod); + } + // Add opcode node to method tree node + genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": '" + s + "'", n, m, ain)); + } + } + } + } + }); + tree.setModel(model); + } - private void searchMethod(String name, String desc) { - DefaultTreeModel model = setup(); - search((n) -> { - for (MethodNode m : n.methods) { - if (m.name.contains(name) && m.desc.contains(desc)) { - ASMTreeNode genClass = Misc.getOrCreateNode(model, n); - ASMTreeNode genMethod = genClass.getChild(m.name); - if (genMethod == null) { - genMethod = new ASMMethodTreeNode(m.name + m.desc, n,m); - } - genClass.add(genMethod); - } - } - }); - tree.setModel(model); - } + private void searchField(String name, String desc) { + DefaultTreeModel model = setup(); + search((n) -> { + for (FieldNode f : n.fields) { + if (f.name.contains(name) && f.desc.contains(desc)) { + ASMTreeNode genClass = Misc.getOrCreateNode(model, n); + ASMTreeNode genMethod = genClass.getChild(f.name); + if (genMethod == null) { + genMethod = new ASMFieldTreeNode(f.desc + " " + f.name, n, f); + } + genClass.add(genMethod); + } + } + }); + tree.setModel(model); + } - private void searchClass(String text, boolean exact) { - DefaultTreeModel model = setup(); - search((n) -> { - if (exact ? n.name.equals(text) : n.name.contains(text)) { - Misc.getOrCreateNode(model, n); - } - }); - tree.setModel(model); - } + private void searchMethod(String name, String desc) { + DefaultTreeModel model = setup(); + search((n) -> { + for (MethodNode m : n.methods) { + if (m.name.contains(name) && m.desc.contains(desc)) { + ASMTreeNode genClass = Misc.getOrCreateNode(model, n); + ASMTreeNode genMethod = genClass.getChild(m.name); + if (genMethod == null) { + genMethod = new ASMMethodTreeNode(m.name + m.desc, n,m); + } + genClass.add(genMethod); + } + } + }); + tree.setModel(model); + } - private void searchClassRef(String owner, String name, String desc, boolean exact) { - DefaultTreeModel model = setup(); - search((n) -> { - for (MethodNode m : n.methods) { - for (AbstractInsnNode ain : m.instructions.toArray()) { - if (ain.getType() == AbstractInsnNode.FIELD_INSN) { - FieldInsnNode fin = (FieldInsnNode) ain; - if ((exact && (fin.owner.equals(owner) && fin.name.equals(name) && fin.desc.equals(desc))) || - (!exact && (fin.owner.contains(owner) && fin.name.contains(name) && fin.desc.contains(desc)))) { - System.out.println("A"); - ASMTreeNode genClass = Misc.getOrCreateNode(model, n); - // Get or create tree node for method - ASMTreeNode genMethod = genClass.getChild(m.name); - if (genMethod == null) { - genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); - genClass.add(genMethod); - } - // Add opcode node to method tree node - genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": " + fin.name, n, m, ain)); - } - } else if (ain.getType() == AbstractInsnNode.METHOD_INSN) { - MethodInsnNode min = (MethodInsnNode) ain; - if ((exact && (min.owner.equals(owner) && min.name.equals(name) && min.desc.equals(desc))) || - (!exact && (min.owner.contains(owner) && min.name.contains(name) && min.desc.contains(desc)))) { - // Get tree node for class - ASMTreeNode genClass = Misc.getOrCreateNode(model, n); - // Get or create tree node for method - ASMTreeNode genMethod = genClass.getChild(m.name); - if (genMethod == null) { - genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); - genClass.add(genMethod); - } - // Add opcode node to method tree node - genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": " + min.name, n, m, ain)); - } - } - } - } - }); - tree.setModel(model); - } + private void searchClass(String text, boolean exact) { + DefaultTreeModel model = setup(); + search((n) -> { + if (exact ? n.name.equals(text) : n.name.contains(text)) { + Misc.getOrCreateNode(model, n); + } + }); + tree.setModel(model); + } - /** - * Setup and return the tree model for a search. - * - * @return - */ - private DefaultTreeModel setup() { - String jarName = recaf.currentJar.getName(); - ASMTreeNode root = new ASMTreeNode(jarName, null); - DefaultTreeModel model = new DefaultTreeModel(root); - model.setRoot(root); - return model; - } + private void searchClassRef(String owner, String name, String desc, boolean exact) { + DefaultTreeModel model = setup(); + search((n) -> { + for (MethodNode m : n.methods) { + for (AbstractInsnNode ain : m.instructions.toArray()) { + if (ain.getType() == AbstractInsnNode.FIELD_INSN) { + FieldInsnNode fin = (FieldInsnNode) ain; + if ((exact && (fin.owner.equals(owner) && fin.name.equals(name) && fin.desc.equals(desc))) || + (!exact && (fin.owner.contains(owner) && fin.name.contains(name) && fin.desc.contains(desc)))) { + System.out.println("A"); + ASMTreeNode genClass = Misc.getOrCreateNode(model, n); + // Get or create tree node for method + ASMTreeNode genMethod = genClass.getChild(m.name); + if (genMethod == null) { + genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); + genClass.add(genMethod); + } + // Add opcode node to method tree node + genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": " + fin.name, n, m, ain)); + } + } else if (ain.getType() == AbstractInsnNode.METHOD_INSN) { + MethodInsnNode min = (MethodInsnNode) ain; + if ((exact && (min.owner.equals(owner) && min.name.equals(name) && min.desc.equals(desc))) || + (!exact && (min.owner.contains(owner) && min.name.contains(name) && min.desc.contains(desc)))) { + // Get tree node for class + ASMTreeNode genClass = Misc.getOrCreateNode(model, n); + // Get or create tree node for method + ASMTreeNode genMethod = genClass.getChild(m.name); + if (genMethod == null) { + genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); + genClass.add(genMethod); + } + // Add opcode node to method tree node + genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": " + min.name, n, m, ain)); + } + } + } + } + }); + tree.setModel(model); + } - /** - * Search and pass classnodes through the given function. - * - * @param model - * @param func - */ - private void search(Consumer func) { - List names = StreamUtil.listOfSortedJavaNames(recaf.jarData.classes.keySet()); - for (String className : names) { - ClassNode node = recaf.jarData.classes.get(className); - func.accept(node); - } - } + /** + * Setup and return the tree model for a search. + * + * @return + */ + private DefaultTreeModel setup() { + String jarName = recaf.currentJar.getName(); + ASMTreeNode root = new ASMTreeNode(jarName, null); + DefaultTreeModel model = new DefaultTreeModel(root); + model.setRoot(root); + return model; + } + + /** + * Search and pass classnodes through the given function. + * + * @param model + * @param func + */ + private void search(Consumer func) { + List names = StreamUtil.listOfSortedJavaNames(recaf.jarData.classes.keySet()); + for (String className : names) { + ClassNode node = recaf.jarData.classes.get(className); + func.accept(node); + } + } } diff --git a/src/me/coley/recaf/ui/component/panel/TabbedPanel.java b/src/me/coley/recaf/ui/component/panel/TabbedPanel.java index b2dd8168f..4f750afb7 100644 --- a/src/me/coley/recaf/ui/component/panel/TabbedPanel.java +++ b/src/me/coley/recaf/ui/component/panel/TabbedPanel.java @@ -19,115 +19,115 @@ */ @SuppressWarnings("serial") public class TabbedPanel extends JPanel { - /** - * Wrapped tabbed pane. - */ - private final JTabbedPane pane; - private final Map children = new HashMap<>(); - private final Map childrenReverse = new HashMap<>(); + /** + * Wrapped tabbed pane. + */ + private final JTabbedPane pane; + private final Map children = new HashMap<>(); + private final Map childrenReverse = new HashMap<>(); - public TabbedPanel() { - setLayout(new BorderLayout()); - pane = new JTabbedPane(JTabbedPane.TOP); - pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); - pane.addMouseListener(new ReleaseListener() { - @Override - public void mouseReleased(MouseEvent e) { - // Only close tabs when middle-clicked - if (e.getButton() != MouseEvent.BUTTON2) { - return; - } - int index = pane.getSelectedIndex(); - if (index >= 0) { - String key = childrenReverse.remove(pane.getSelectedComponent()); - children.remove(key); - pane.remove(index); - } - } - }); - add(pane, BorderLayout.CENTER); - } + public TabbedPanel() { + setLayout(new BorderLayout()); + pane = new JTabbedPane(JTabbedPane.TOP); + pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + pane.addMouseListener(new ReleaseListener() { + @Override + public void mouseReleased(MouseEvent e) { + // Only close tabs when middle-clicked + if (e.getButton() != MouseEvent.BUTTON2) { + return; + } + int index = pane.getSelectedIndex(); + if (index >= 0) { + String key = childrenReverse.remove(pane.getSelectedComponent()); + children.remove(key); + pane.remove(index); + } + } + }); + add(pane, BorderLayout.CENTER); + } - /** - * Adds a tab to the panel. - * - * @param title The tab's title. - * @param component The component. - * - * TODO: What is the component for? - * - * - Charles - */ - public void addTab(String title, Component component) { - pane.add(title, component); - if (!shouldCache(title, component)) { - children.put(title, component); - childrenReverse.put(component, title); - } - } + /** + * Adds a tab to the panel. + * + * @param title The tab's title. + * @param component The component. + * + * TODO: What is the component for? + * + * - Charles + */ + public void addTab(String title, Component component) { + pane.add(title, component); + if (!shouldCache(title, component)) { + children.put(title, component); + childrenReverse.put(component, title); + } + } - /** - * Determines if the tab with the given title and component should - * cached for redirection, instead of duplicating tabs. - * - * @param title The tab's title. - * @param component The component. - * - * TODO: What is the component for? - * - * - Charles - * - * @return true if the tab should be cached. - */ - private boolean shouldCache(String title, Component component) { - return title.contains("Error: "); - } + /** + * Determines if the tab with the given title and component should + * cached for redirection, instead of duplicating tabs. + * + * @param title The tab's title. + * @param component The component. + * + * TODO: What is the component for? + * + * - Charles + * + * @return true if the tab should be cached. + */ + private boolean shouldCache(String title, Component component) { + return title.contains("Error: "); + } - /** - * @return The number of open tabs. + /** + * @return The number of open tabs. - */ - public int getTabCount() { - return pane.getTabCount(); - } + */ + public int getTabCount() { + return pane.getTabCount(); + } - /** - * Set the selected tab. - * - * @param index Index of the tab. - */ - public void setSelectedTab(int index) { - pane.setSelectedIndex(index); - } + /** + * Set the selected tab. + * + * @param index Index of the tab. + */ + public void setSelectedTab(int index) { + pane.setSelectedIndex(index); + } - /** - * Check if a tab by the given title exists and is available for - * redirection. - * - * @param title Title of the tab to check. - * @return true if the tab is available for redirection. - * - * TODO: Is the return accurate? I'm not entirely sure what this does. - * - * - Charles - */ - public boolean hasCached(String title) { - return children.containsKey(title); - } + /** + * Check if a tab by the given title exists and is available for + * redirection. + * + * @param title Title of the tab to check. + * @return true if the tab is available for redirection. + * + * TODO: Is the return accurate? I'm not entirely sure what this does. + * + * - Charles + */ + public boolean hasCached(String title) { + return children.containsKey(title); + } - /** - * Retrieve the index of the cached tab by its title. - * - * @param title The title of the tab. - * @return The tab's index. - */ - public int getCachedIndex(String title) { - for (int i = 0; i < getTabCount(); i++) { - Component component = pane.getComponentAt(i); - if (childrenReverse.get(component).equals(title)) { - return i; - } - } - return -1; - } + /** + * Retrieve the index of the cached tab by its title. + * + * @param title The title of the tab. + * @return The tab's index. + */ + public int getCachedIndex(String title) { + for (int i = 0; i < getTabCount(); i++) { + Component component = pane.getComponentAt(i); + if (childrenReverse.get(component).equals(title)) { + return i; + } + } + return -1; + } } diff --git a/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java b/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java index 315b31d80..1295d9f08 100644 --- a/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java +++ b/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java @@ -22,95 +22,95 @@ /** * JPanel for tag switcher for Handle. - * + * * @author Matt */ @SuppressWarnings("serial") public class TagTypeSwitchPanel extends JPanel implements Opcodes { - /** - * Map of radio buttons to possible tags. - */ - private final Map compToTag = new HashMap<>(); - /** - * InvokeDynamic handle being modified. - */ - private final Handle handle; - /** - * Only stored so the list can be re-painted when the tag is re-chosen. - */ - private final JList list; - /** - * Content wrapper. - */ - private final JPanel content = new JPanel(); + /** + * Map of radio buttons to possible tags. + */ + private final Map compToTag = new HashMap<>(); + /** + * InvokeDynamic handle being modified. + */ + private final Handle handle; + /** + * Only stored so the list can be re-painted when the tag is re-chosen. + */ + private final JList list; + /** + * Content wrapper. + */ + private final JPanel content = new JPanel(); - public TagTypeSwitchPanel(JList list, Handle handle) { - this.list = list; - this.handle = handle; - //setMaximumSize(new Dimension(300, 300)); - // content.setMaximumSize(new Dimension(300, 300)); - // scroll.setMaximumSize(new Dimension(300, 300)); - content.setLayout(new GridLayout(0, 2)); - populate(OpcodeUtil.OPS_TAG, s -> OpcodeUtil.nameToTag(s)); - setLayout(new BorderLayout()); - JScrollPane scroll = new JScrollPane(content); - add(scroll, BorderLayout.CENTER); - } + public TagTypeSwitchPanel(JList list, Handle handle) { + this.list = list; + this.handle = handle; + //setMaximumSize(new Dimension(300, 300)); + // content.setMaximumSize(new Dimension(300, 300)); + // scroll.setMaximumSize(new Dimension(300, 300)); + content.setLayout(new GridLayout(0, 2)); + populate(OpcodeUtil.OPS_TAG, s -> OpcodeUtil.nameToTag(s)); + setLayout(new BorderLayout()); + JScrollPane scroll = new JScrollPane(content); + add(scroll, BorderLayout.CENTER); + } - private void populate(String[] tags, Function getter) { - // Set layout based on number of options - // Add options - for (String op : tags) { - int value = getter.apply(op);; - JRadioButton btn = new JRadioButton(op); - if (value == handle.getTag()) { - btn.setSelected(true); - } - btn.addActionListener(new RadioListener(btn)); - compToTag.put(btn, value); - content.add(btn); - } - } + private void populate(String[] tags, Function getter) { + // Set layout based on number of options + // Add options + for (String op : tags) { + int value = getter.apply(op);; + JRadioButton btn = new JRadioButton(op); + if (value == handle.getTag()) { + btn.setSelected(true); + } + btn.addActionListener(new RadioListener(btn)); + compToTag.put(btn, value); + content.add(btn); + } + } - /** - * Update {@link #handle} value. - * - * @param value - */ - private void setValue(int value) { - Misc.set(handle, "tag", value); - list.repaint(); - } + /** + * Update {@link #handle} value. + * + * @param value + */ + private void setValue(int value) { + Misc.set(handle, "tag", value); + list.repaint(); + } - /** - * @return The number of radio buttons. + /** + * @return The number of radio buttons. - */ - public int getOptionCount() { - return compToTag.keySet().size(); - } + */ + public int getOptionCount() { + return compToTag.keySet().size(); + } - /** - * Listener for disabling other radio buttons. - * - * @author Matt - */ - private class RadioListener implements ActionListener { - private final JRadioButton btn; + /** + * Listener for disabling other radio buttons. + * + * @author Matt + */ + private class RadioListener implements ActionListener { + private final JRadioButton btn; - public RadioListener(JRadioButton btn) { - this.btn = btn; - } + public RadioListener(JRadioButton btn) { + this.btn = btn; + } - @Override - public void actionPerformed(ActionEvent e) { - for (JRadioButton comp : compToTag.keySet()) { - if (comp != btn && comp.isSelected()) { - comp.setSelected(false); - } else if (comp == btn) { - setValue(compToTag.get(comp)); - } - } - } - } + @Override + public void actionPerformed(ActionEvent e) { + for (JRadioButton comp : compToTag.keySet()) { + if (comp != btn && comp.isSelected()) { + comp.setSelected(false); + } else if (comp == btn) { + setValue(compToTag.get(comp)); + } + } + } + } } diff --git a/src/me/coley/recaf/ui/component/table/MemberTable.java b/src/me/coley/recaf/ui/component/table/MemberTable.java index 0d2277ab6..157171dc4 100644 --- a/src/me/coley/recaf/ui/component/table/MemberTable.java +++ b/src/me/coley/recaf/ui/component/table/MemberTable.java @@ -11,75 +11,75 @@ /** * JTable populated by a list of members - * + * * @author Matt */ @SuppressWarnings("serial") public class MemberTable extends JTable { - // TODO: Clean this up and make it a viable alternative to the list display. - // TODO: Male alternative for List - // - // Pros: - // * Sortable - // - // Cons: - // * Usually 2x wider than list display - public static MemberTable create(List methods) { - String column[] = { "Index", "Name", "Descriptor", "Flags" }; - Object data[][] = new Object[methods.size()][4]; - // Determine widths of table - int maxIndexSize = 45; - int maxNameSize = 10; - int maxTypeSize = 10; - int maxAccessSize = 45; - int padding = 1; - for (int i = 0; i < methods.size(); i++) { - MethodNode method = methods.get(i); - data[i][0] = i; - data[i][1] = method.name; - data[i][2] = method.desc; - data[i][3] = method.access; - // Widths detection - int sIndex = (int) (FontUtil.getStringBounds(data[i][0].toString(), FontUtil.monospace).getWidth()); - if (maxIndexSize < sIndex) { - maxIndexSize = sIndex; - } - int sName = (int) (FontUtil.getStringBounds(data[i][1].toString(), FontUtil.monospace).getWidth()); - if (maxNameSize < sName) { - maxNameSize = sName; - } - int sDesc = (int) (FontUtil.getStringBounds(data[i][2].toString(), FontUtil.monospace).getWidth()); - if (maxTypeSize < sDesc) { - maxTypeSize = sDesc; - } - int sAccess = (int) (FontUtil.getStringBounds(data[i][3].toString(), FontUtil.monospace).getWidth()); - if (maxAccessSize < sAccess) { - maxAccessSize = sAccess; - } - } - MemberTable table = new MemberTable(column, data); - table.setFont(FontUtil.monospace); - table.getColumn("Index").setPreferredWidth(maxIndexSize + (padding * 2)); - table.getColumn("Name").setPreferredWidth(maxNameSize + (padding * 3)); - table.getColumn("Descriptor").setPreferredWidth(maxTypeSize + (padding * 4)); - table.getColumn("Flags").setPreferredWidth(maxAccessSize + (padding * 4)); - return table; - } + // TODO: Clean this up and make it a viable alternative to the list display. + // TODO: Male alternative for List + // + // Pros: + // * Sortable + // + // Cons: + // * Usually 2x wider than list display + public static MemberTable create(List methods) { + String column[] = { "Index", "Name", "Descriptor", "Flags" }; + Object data[][] = new Object[methods.size()][4]; + // Determine widths of table + int maxIndexSize = 45; + int maxNameSize = 10; + int maxTypeSize = 10; + int maxAccessSize = 45; + int padding = 1; + for (int i = 0; i < methods.size(); i++) { + MethodNode method = methods.get(i); + data[i][0] = i; + data[i][1] = method.name; + data[i][2] = method.desc; + data[i][3] = method.access; + // Widths detection + int sIndex = (int) (FontUtil.getStringBounds(data[i][0].toString(), FontUtil.monospace).getWidth()); + if (maxIndexSize < sIndex) { + maxIndexSize = sIndex; + } + int sName = (int) (FontUtil.getStringBounds(data[i][1].toString(), FontUtil.monospace).getWidth()); + if (maxNameSize < sName) { + maxNameSize = sName; + } + int sDesc = (int) (FontUtil.getStringBounds(data[i][2].toString(), FontUtil.monospace).getWidth()); + if (maxTypeSize < sDesc) { + maxTypeSize = sDesc; + } + int sAccess = (int) (FontUtil.getStringBounds(data[i][3].toString(), FontUtil.monospace).getWidth()); + if (maxAccessSize < sAccess) { + maxAccessSize = sAccess; + } + } + MemberTable table = new MemberTable(column, data); + table.setFont(FontUtil.monospace); + table.getColumn("Index").setPreferredWidth(maxIndexSize + (padding * 2)); + table.getColumn("Name").setPreferredWidth(maxNameSize + (padding * 3)); + table.getColumn("Descriptor").setPreferredWidth(maxTypeSize + (padding * 4)); + table.getColumn("Flags").setPreferredWidth(maxAccessSize + (padding * 4)); + return table; + } - private MemberTable(String[] column, Object[][] data) { - super(data, column); - } + private MemberTable(String[] column, Object[][] data) { + super(data, column); + } - /** - * Override the getPrefferedScrollableViewportSize to prevent the wrapping - * scroll pane from adding lots of pointless empty space near the bottom of - * the container. - * - * Credits: https://stackoverflow.com/a/42436205/8071915 - */ - @Override - public Dimension getPreferredScrollableViewportSize() { - return new Dimension(super.getPreferredSize().width, getRowHeight() * getRowCount()); - } + /** + * Override the getPrefferedScrollableViewportSize to prevent the wrapping + * scroll pane from adding lots of pointless empty space near the bottom of + * the container. + * + * Credits: https://stackoverflow.com/a/42436205/8071915 + */ + @Override + public Dimension getPreferredScrollableViewportSize() { + return new Dimension(super.getPreferredSize().width, getRowHeight() * getRowCount()); + } } diff --git a/src/me/coley/recaf/ui/component/table/VariableTable.java b/src/me/coley/recaf/ui/component/table/VariableTable.java index f64ef3103..f39449447 100644 --- a/src/me/coley/recaf/ui/component/table/VariableTable.java +++ b/src/me/coley/recaf/ui/component/table/VariableTable.java @@ -22,116 +22,116 @@ */ @SuppressWarnings("serial") public class VariableTable extends JTable { - private static final int INDEX = 0, NAME = 1, DESC = 2, SIGNATURE = 3; - private static final Options options = Recaf.getInstance().options; + private static final int INDEX = 0, NAME = 1, DESC = 2, SIGNATURE = 3; + private static final Options options = Recaf.getInstance().options; - /** - * Construct a local variable table from the given method. - * - * @param list List of opcodes. - * - * @param method The method. - * @return VariableTable containing the local variables for the method. - */ - public static VariableTable create(OpcodeList list, MethodNode method) { - boolean showSignatures = options.showVariableSignatureInTable; - int max = showSignatures ? 4 : 3; - String column[] = { "Index", "Name", "Descriptor", "Signature" }; - if (!showSignatures) { - // If not showing signatures, remove last column. - column = Arrays.copyOf(column, max); - } - int locals = method.localVariables != null ? method.localVariables.size() : method.maxLocals; - String data[][] = new String[locals][max]; - // Determine widths of table - int maxIndexSize = 45; - int maxNameSize = 10; - int maxTypeSize = 10; - int maxSigSize = 10; - int padding = 10; - for (int i = 0; i < locals; i++) { - // Raw indices - data[i][INDEX] = String.valueOf(i); - int sIndex = (int) (FontUtil.getStringBounds(data[i][0], FontUtil.monospace).getWidth()); - if (maxIndexSize < sIndex) { - maxIndexSize = sIndex; - } - // If possible, add data from local variable table. - if (method.localVariables != null && i < method.localVariables.size()) { - LocalVariableNode variable = method.localVariables.get(i); - data[i][NAME] = variable.name; - data[i][DESC] = variable.desc; - int sName = (int) (FontUtil.getStringBounds(data[i][1], FontUtil.monospace).getWidth()); - int sDesc = (int) (FontUtil.getStringBounds(data[i][2], FontUtil.monospace).getWidth()); - if (maxNameSize < sName) { - maxNameSize = sName; - } - if (maxTypeSize < sDesc) { - maxTypeSize = sDesc; - } - // Signature - if (showSignatures) { - data[i][SIGNATURE] = variable.signature == null ? "" : variable.signature; - int sSign = (int) (FontUtil.getStringBounds(data[i][3], FontUtil.monospace).getWidth()); - if (maxSigSize < sSign) { - maxSigSize = sSign; - } - } - } - } - VariableTable table = new VariableTable(column, data); - table.setFont(FontUtil.monospace); - table.getColumn(column[INDEX]).setPreferredWidth(maxIndexSize + (padding * 2)); - table.getColumn(column[NAME]).setPreferredWidth(maxNameSize + (padding * 3)); - table.getColumn(column[DESC]).setPreferredWidth(maxTypeSize + (padding * 4)); - if (showSignatures) { - table.getColumn(column[SIGNATURE]).setPreferredWidth(maxSigSize + (padding * 4)); - } - table.setCellSelectionEnabled(true); - if (method.localVariables != null) { - table.addKeyListener(new KeyAdapter() { - @Override - public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - int row = table.getSelectedRow(); - int col = table.getSelectedColumn(); - String value = table.getValueAt(row, col).toString(); - switch (col) { - case INDEX: - break; - case NAME: - method.localVariables.get(row).name = value; - list.repaint(); - break; - case DESC: - method.localVariables.get(row).desc = value; - list.repaint(); - break; - case SIGNATURE: - method.localVariables.get(row).signature = value; - list.repaint(); - break; - } - } - } - }); - } - return table; - } + /** + * Construct a local variable table from the given method. + * + * @param list List of opcodes. + * + * @param method The method. + * @return VariableTable containing the local variables for the method. + */ + public static VariableTable create(OpcodeList list, MethodNode method) { + boolean showSignatures = options.showVariableSignatureInTable; + int max = showSignatures ? 4 : 3; + String column[] = { "Index", "Name", "Descriptor", "Signature" }; + if (!showSignatures) { + // If not showing signatures, remove last column. + column = Arrays.copyOf(column, max); + } + int locals = method.localVariables != null ? method.localVariables.size() : method.maxLocals; + String data[][] = new String[locals][max]; + // Determine widths of table + int maxIndexSize = 45; + int maxNameSize = 10; + int maxTypeSize = 10; + int maxSigSize = 10; + int padding = 10; + for (int i = 0; i < locals; i++) { + // Raw indices + data[i][INDEX] = String.valueOf(i); + int sIndex = (int) (FontUtil.getStringBounds(data[i][0], FontUtil.monospace).getWidth()); + if (maxIndexSize < sIndex) { + maxIndexSize = sIndex; + } + // If possible, add data from local variable table. + if (method.localVariables != null && i < method.localVariables.size()) { + LocalVariableNode variable = method.localVariables.get(i); + data[i][NAME] = variable.name; + data[i][DESC] = variable.desc; + int sName = (int) (FontUtil.getStringBounds(data[i][1], FontUtil.monospace).getWidth()); + int sDesc = (int) (FontUtil.getStringBounds(data[i][2], FontUtil.monospace).getWidth()); + if (maxNameSize < sName) { + maxNameSize = sName; + } + if (maxTypeSize < sDesc) { + maxTypeSize = sDesc; + } + // Signature + if (showSignatures) { + data[i][SIGNATURE] = variable.signature == null ? "" : variable.signature; + int sSign = (int) (FontUtil.getStringBounds(data[i][3], FontUtil.monospace).getWidth()); + if (maxSigSize < sSign) { + maxSigSize = sSign; + } + } + } + } + VariableTable table = new VariableTable(column, data); + table.setFont(FontUtil.monospace); + table.getColumn(column[INDEX]).setPreferredWidth(maxIndexSize + (padding * 2)); + table.getColumn(column[NAME]).setPreferredWidth(maxNameSize + (padding * 3)); + table.getColumn(column[DESC]).setPreferredWidth(maxTypeSize + (padding * 4)); + if (showSignatures) { + table.getColumn(column[SIGNATURE]).setPreferredWidth(maxSigSize + (padding * 4)); + } + table.setCellSelectionEnabled(true); + if (method.localVariables != null) { + table.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + int row = table.getSelectedRow(); + int col = table.getSelectedColumn(); + String value = table.getValueAt(row, col).toString(); + switch (col) { + case INDEX: + break; + case NAME: + method.localVariables.get(row).name = value; + list.repaint(); + break; + case DESC: + method.localVariables.get(row).desc = value; + list.repaint(); + break; + case SIGNATURE: + method.localVariables.get(row).signature = value; + list.repaint(); + break; + } + } + } + }); + } + return table; + } - private VariableTable(String[] column, String[][] data) { - super(data, column); - } + private VariableTable(String[] column, String[][] data) { + super(data, column); + } - /** - * Override the getPrefferedScrollableViewportSize to prevent the wrapping - * scroll pane from adding lots of pointless empty space near the bottom of - * the container. - * - * Credits: https://stackoverflow.com/a/42436205/8071915 - */ - @Override - public Dimension getPreferredScrollableViewportSize() { - return new Dimension(super.getPreferredSize().width, getRowHeight() * getRowCount()); - } + /** + * Override the getPrefferedScrollableViewportSize to prevent the wrapping + * scroll pane from adding lots of pointless empty space near the bottom of + * the container. + * + * Credits: https://stackoverflow.com/a/42436205/8071915 + */ + @Override + public Dimension getPreferredScrollableViewportSize() { + return new Dimension(super.getPreferredSize().width, getRowHeight() * getRowCount()); + } } diff --git a/src/me/coley/recaf/ui/component/tree/ASMFieldTreeNode.java b/src/me/coley/recaf/ui/component/tree/ASMFieldTreeNode.java index 44e2f9d99..e24c2eb44 100644 --- a/src/me/coley/recaf/ui/component/tree/ASMFieldTreeNode.java +++ b/src/me/coley/recaf/ui/component/tree/ASMFieldTreeNode.java @@ -5,19 +5,19 @@ /** * Tree node containing ClassNode and FieldNode data. - * + * * @author Matt */ @SuppressWarnings("serial") public class ASMFieldTreeNode extends ASMTreeNode { - private final FieldNode field; + private final FieldNode field; - public ASMFieldTreeNode(String title, ClassNode node, FieldNode field) { - super(title, node); - this.field = field; - } + public ASMFieldTreeNode(String title, ClassNode node, FieldNode field) { + super(title, node); + this.field = field; + } - public FieldNode getField() { - return field; - } + public FieldNode getField() { + return field; + } } diff --git a/src/me/coley/recaf/ui/component/tree/ASMInsnTreeNode.java b/src/me/coley/recaf/ui/component/tree/ASMInsnTreeNode.java index 7732de6ff..4c3f256f0 100644 --- a/src/me/coley/recaf/ui/component/tree/ASMInsnTreeNode.java +++ b/src/me/coley/recaf/ui/component/tree/ASMInsnTreeNode.java @@ -6,19 +6,19 @@ /** * Tree node containing ClassNode, MethodNode, and AbstractInsnNode data. - * + * * @author Matt */ @SuppressWarnings("serial") public class ASMInsnTreeNode extends ASMMethodTreeNode { - private final AbstractInsnNode ain; + private final AbstractInsnNode ain; - public ASMInsnTreeNode(String title, ClassNode node, MethodNode method, AbstractInsnNode ain) { - super(title, node, method); - this.ain = ain; - } + public ASMInsnTreeNode(String title, ClassNode node, MethodNode method, AbstractInsnNode ain) { + super(title, node, method); + this.ain = ain; + } - public AbstractInsnNode getInsn() { - return ain; - } + public AbstractInsnNode getInsn() { + return ain; + } } diff --git a/src/me/coley/recaf/ui/component/tree/ASMMethodTreeNode.java b/src/me/coley/recaf/ui/component/tree/ASMMethodTreeNode.java index 2017d0c96..6bb0f1e76 100644 --- a/src/me/coley/recaf/ui/component/tree/ASMMethodTreeNode.java +++ b/src/me/coley/recaf/ui/component/tree/ASMMethodTreeNode.java @@ -5,19 +5,19 @@ /** * Tree node containing ClassNode and MethodNode data. - * + * * @author Matt */ @SuppressWarnings("serial") public class ASMMethodTreeNode extends ASMTreeNode { - private final MethodNode method; + private final MethodNode method; - public ASMMethodTreeNode(String title, ClassNode node, MethodNode method) { - super(title, node); - this.method = method; - } + public ASMMethodTreeNode(String title, ClassNode node, MethodNode method) { + super(title, node); + this.method = method; + } - public MethodNode getMethod() { - return method; - } + public MethodNode getMethod() { + return method; + } } diff --git a/src/me/coley/recaf/ui/component/tree/ASMTreeNode.java b/src/me/coley/recaf/ui/component/tree/ASMTreeNode.java index cad8dd1fe..a1cef5241 100644 --- a/src/me/coley/recaf/ui/component/tree/ASMTreeNode.java +++ b/src/me/coley/recaf/ui/component/tree/ASMTreeNode.java @@ -9,28 +9,28 @@ /** * Tree node containing ClassNode data. - * + * * @author Matt */ @SuppressWarnings("serial") public class ASMTreeNode extends DefaultMutableTreeNode { - private final Map children = new HashMap<>(); - private final ClassNode node; + private final Map children = new HashMap<>(); + private final ClassNode node; - public ASMTreeNode(String title, ClassNode node) { - super(title); - this.node = node; - } + public ASMTreeNode(String title, ClassNode node) { + super(title); + this.node = node; + } - public ASMTreeNode getChild(String name) { - return children.get(name); - } + public ASMTreeNode getChild(String name) { + return children.get(name); + } - public void addChild(String name, ASMTreeNode node) { - children.put(name, node); - } + public void addChild(String name, ASMTreeNode node) { + children.put(name, node); + } - public final ClassNode getNode() { - return node; - } + public final ClassNode getNode() { + return node; + } } diff --git a/src/me/coley/recaf/ui/component/tree/JarFileTree.java b/src/me/coley/recaf/ui/component/tree/JarFileTree.java index 0f46b991f..79d87493f 100644 --- a/src/me/coley/recaf/ui/component/tree/JarFileTree.java +++ b/src/me/coley/recaf/ui/component/tree/JarFileTree.java @@ -18,53 +18,53 @@ /** * JTree wrapper for displaying the contents of a jar file. - * + * * @author Matt * */ @SuppressWarnings("serial") public class JarFileTree extends JPanel { - private final Recaf recaf = Recaf.getInstance(); - private final JTree tree = new JTree(new String[] { "Open a jar" }); - private final JScrollPane scrollTree = new JScrollPane(tree); + private final Recaf recaf = Recaf.getInstance(); + private final JTree tree = new JTree(new String[] { "Open a jar" }); + private final JScrollPane scrollTree = new JScrollPane(tree); - public JarFileTree() { - try { - tree.setCellRenderer(new JavaTreeRenderer()); - JavaTreeListener listener = new JavaTreeListener(); - tree.addTreeExpansionListener(listener); - tree.addTreeSelectionListener(listener); - tree.addMouseListener(listener); - } catch (Exception e) { - e.printStackTrace(); - } - setLayout(new BorderLayout()); - add(scrollTree, BorderLayout.CENTER); - } + public JarFileTree() { + try { + tree.setCellRenderer(new JavaTreeRenderer()); + JavaTreeListener listener = new JavaTreeListener(); + tree.addTreeExpansionListener(listener); + tree.addTreeSelectionListener(listener); + tree.addMouseListener(listener); + } catch (Exception e) { + e.printStackTrace(); + } + setLayout(new BorderLayout()); + add(scrollTree, BorderLayout.CENTER); + } - /** - * Updates the JTree with class files loaded from the current jar. - */ - public void refresh() { - JarData read = recaf.jarData; - // Root node - String jarName = recaf.currentJar.getName(); - ASMTreeNode root = new ASMTreeNode(jarName, null); - DefaultTreeModel model = new DefaultTreeModel(root); - tree.setModel(model); - // Iterate classes - List names = StreamUtil.listOfSortedJavaNames(read.classes.keySet()); - for (String className : names) { - if (!read.classes.containsKey(className)) { - continue; - } - ClassNode node = read.classes.get(className); - // Create directory path based on current node name. - ArrayList dirPath = new ArrayList(Arrays.asList(node.name.split("/"))); - // Create directory of nodes - Misc.generateTreePath(root, dirPath, node, model); - } - model.setRoot(root); + /** + * Updates the JTree with class files loaded from the current jar. + */ + public void refresh() { + JarData read = recaf.jarData; + // Root node + String jarName = recaf.currentJar.getName(); + ASMTreeNode root = new ASMTreeNode(jarName, null); + DefaultTreeModel model = new DefaultTreeModel(root); + tree.setModel(model); + // Iterate classes + List names = StreamUtil.listOfSortedJavaNames(read.classes.keySet()); + for (String className : names) { + if (!read.classes.containsKey(className)) { + continue; + } + ClassNode node = read.classes.get(className); + // Create directory path based on current node name. + ArrayList dirPath = new ArrayList(Arrays.asList(node.name.split("/"))); + // Create directory of nodes + Misc.generateTreePath(root, dirPath, node, model); + } + model.setRoot(root); - } + } } diff --git a/src/me/coley/recaf/ui/component/tree/JavaTreeListener.java b/src/me/coley/recaf/ui/component/tree/JavaTreeListener.java index f724a01e5..8fedfddb1 100644 --- a/src/me/coley/recaf/ui/component/tree/JavaTreeListener.java +++ b/src/me/coley/recaf/ui/component/tree/JavaTreeListener.java @@ -14,62 +14,62 @@ /** * Selection/Mouse listener for double-click actions related to the selected * ClassNode. - * + * * @author Matt */ public class JavaTreeListener implements TreeSelectionListener, MouseListener, TreeExpansionListener { - private final Recaf recaf = Recaf.getInstance(); - private ASMTreeNode lastSelected; - private JTree tree; + private final Recaf recaf = Recaf.getInstance(); + private ASMTreeNode lastSelected; + private JTree tree; - @Override - public void valueChanged(TreeSelectionEvent e) { - tree = (JTree) e.getSource(); - } + @Override + public void valueChanged(TreeSelectionEvent e) { + tree = (JTree) e.getSource(); + } - @Override - public void treeExpanded(TreeExpansionEvent e) { - // Reset selection, prevents expansion from opening the contained value. - lastSelected = null; - } + @Override + public void treeExpanded(TreeExpansionEvent e) { + // Reset selection, prevents expansion from opening the contained value. + lastSelected = null; + } - @Override - public void treeCollapsed(TreeExpansionEvent e) { - // Reset selection, prevents collapsing from opening the contained - // value. - lastSelected = null; - } + @Override + public void treeCollapsed(TreeExpansionEvent e) { + // Reset selection, prevents collapsing from opening the contained + // value. + lastSelected = null; + } - @Override - public void mousePressed(MouseEvent e) { - // Skip if nothing selected (tree null) or not a left click - if (tree == null || e.getButton() != MouseEvent.BUTTON1) { - return; - } - // Skip if the press did not occur in the selection's bounds - if (tree.getSelectionPath() == null || !tree.getPathBounds(tree.getSelectionPath()).contains(e.getX(), e.getY())) { - return; - } - // Update selection, open if double clicked. - Object selection = tree.getLastSelectedPathComponent(); - if (selection instanceof ASMTreeNode) { - ASMTreeNode node = (ASMTreeNode) selection; - if (node != null && node == lastSelected && node.getNode() != null) { - recaf.selectClass(node.getNode()); - } - lastSelected = node; - } - } + @Override + public void mousePressed(MouseEvent e) { + // Skip if nothing selected (tree null) or not a left click + if (tree == null || e.getButton() != MouseEvent.BUTTON1) { + return; + } + // Skip if the press did not occur in the selection's bounds + if (tree.getSelectionPath() == null || !tree.getPathBounds(tree.getSelectionPath()).contains(e.getX(), e.getY())) { + return; + } + // Update selection, open if double clicked. + Object selection = tree.getLastSelectedPathComponent(); + if (selection instanceof ASMTreeNode) { + ASMTreeNode node = (ASMTreeNode) selection; + if (node != null && node == lastSelected && node.getNode() != null) { + recaf.selectClass(node.getNode()); + } + lastSelected = node; + } + } - @Override - public void mouseClicked(MouseEvent e) {} + @Override + public void mouseClicked(MouseEvent e) {} - @Override - public void mouseReleased(MouseEvent e) {} + @Override + public void mouseReleased(MouseEvent e) {} - @Override - public void mouseEntered(MouseEvent e) {} + @Override + public void mouseEntered(MouseEvent e) {} - @Override - public void mouseExited(MouseEvent e) {} + @Override + public void mouseExited(MouseEvent e) {} } diff --git a/src/me/coley/recaf/ui/component/tree/JavaTreeRenderer.java b/src/me/coley/recaf/ui/component/tree/JavaTreeRenderer.java index 66aa34e81..c7e02d26d 100644 --- a/src/me/coley/recaf/ui/component/tree/JavaTreeRenderer.java +++ b/src/me/coley/recaf/ui/component/tree/JavaTreeRenderer.java @@ -13,75 +13,75 @@ /** * TreeCellRenderer for the contents of a jar file/java bin. - * + * * @author Matt */ @SuppressWarnings("serial") public class JavaTreeRenderer extends DefaultTreeCellRenderer { - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, - boolean hasFocus) { - super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; - if (node instanceof ASMInsnTreeNode) { - setIcon(MISC_RESULT); - } else if (node instanceof ASMMethodTreeNode) { - int acc = ((ASMMethodTreeNode) node).getMethod().access; - if (Access.isPublic(acc)) { - setIcon(ML_PUBLIC); - } else if (Access.isProtected(acc)) { - setIcon(ML_PROTECTED); - } else if (Access.isPrivate(acc)) { - setIcon(ML_PRIVATE); - } else { - setIcon(ML_DEFAULT); - } - } else if (node instanceof ASMFieldTreeNode) { - int acc = ((ASMFieldTreeNode) node).getField().access; - if (Access.isPublic(acc)) { - setIcon(FL_PUBLIC); - } else if (Access.isProtected(acc)) { - setIcon(FL_PROTECTED); - } else if (Access.isPrivate(acc)) { - setIcon(FL_PRIVATE); - } else { - setIcon(FL_DEFAULT); - } - } else if (node instanceof ASMTreeNode) { - ASMTreeNode mtNode = (ASMTreeNode) node; - if (mtNode.getNode() == null) { - // The root node of the tree has no node. - // The root isn't DefaultMutableTreeNode because otherwise - // it makes the code for generating the tree a uglier. This - // if statement is the exchange. - if (node.getChildCount() > 0) { - // Tis a package. - setIcon(MISC_PACKAGE); - } else { - setIcon(MISC_RESULT); - } - } else { - // Get the classnode, determine icon by access - ClassNode cn = mtNode.getNode(); - int acc = cn.access; - if (Access.isInterface(acc)) { - setIcon(CL_INTERFACE); - } else if (Access.isEnum(acc)) { - setIcon(CL_ENUM); - } else if (Access.isAnnotation(acc)) { - setIcon(CL_ANNOTATION); - } else { - setIcon(CL_CLASS); - } - } - } else if (node.getChildCount() > 0) { - // Tis a package. - setIcon(MISC_PACKAGE); - } else { - setIcon(MISC_RESULT); - } + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, + boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; + if (node instanceof ASMInsnTreeNode) { + setIcon(MISC_RESULT); + } else if (node instanceof ASMMethodTreeNode) { + int acc = ((ASMMethodTreeNode) node).getMethod().access; + if (Access.isPublic(acc)) { + setIcon(ML_PUBLIC); + } else if (Access.isProtected(acc)) { + setIcon(ML_PROTECTED); + } else if (Access.isPrivate(acc)) { + setIcon(ML_PRIVATE); + } else { + setIcon(ML_DEFAULT); + } + } else if (node instanceof ASMFieldTreeNode) { + int acc = ((ASMFieldTreeNode) node).getField().access; + if (Access.isPublic(acc)) { + setIcon(FL_PUBLIC); + } else if (Access.isProtected(acc)) { + setIcon(FL_PROTECTED); + } else if (Access.isPrivate(acc)) { + setIcon(FL_PRIVATE); + } else { + setIcon(FL_DEFAULT); + } + } else if (node instanceof ASMTreeNode) { + ASMTreeNode mtNode = (ASMTreeNode) node; + if (mtNode.getNode() == null) { + // The root node of the tree has no node. + // The root isn't DefaultMutableTreeNode because otherwise + // it makes the code for generating the tree a uglier. This + // if statement is the exchange. + if (node.getChildCount() > 0) { + // Tis a package. + setIcon(MISC_PACKAGE); + } else { + setIcon(MISC_RESULT); + } + } else { + // Get the classnode, determine icon by access + ClassNode cn = mtNode.getNode(); + int acc = cn.access; + if (Access.isInterface(acc)) { + setIcon(CL_INTERFACE); + } else if (Access.isEnum(acc)) { + setIcon(CL_ENUM); + } else if (Access.isAnnotation(acc)) { + setIcon(CL_ANNOTATION); + } else { + setIcon(CL_CLASS); + } + } + } else if (node.getChildCount() > 0) { + // Tis a package. + setIcon(MISC_PACKAGE); + } else { + setIcon(MISC_RESULT); + } - return this; - } + return this; + } } \ No newline at end of file diff --git a/src/me/coley/recaf/util/JavaNameSorter.java b/src/me/coley/recaf/util/JavaNameSorter.java index 66afc7934..5d08c38e6 100644 --- a/src/me/coley/recaf/util/JavaNameSorter.java +++ b/src/me/coley/recaf/util/JavaNameSorter.java @@ -4,29 +4,29 @@ /** * Sorter of java names. - * + * * @author Matt */ public class JavaNameSorter implements Comparator { - @Override - public int compare(String s1, String s2) { - String[] split1 = s1.split("/"); - String[] split2 = s2.split("/"); - int l1 = split1.length; - int l2 = split2.length; - int len = Math.min(l1, l2); - for (int i = 0; i < len; i++) { - String p1 = split1[i]; - String p2 = split2[i]; - if (i == len - 1 && l1 != l2) { - return (l1 > l2) ? -1 : 1; - } - int cmp = p1.compareTo(p2); - if (cmp != 0) { - return cmp; - } - } - return 0; - } + @Override + public int compare(String s1, String s2) { + String[] split1 = s1.split("/"); + String[] split2 = s2.split("/"); + int l1 = split1.length; + int l2 = split2.length; + int len = Math.min(l1, l2); + for (int i = 0; i < len; i++) { + String p1 = split1[i]; + String p2 = split2[i]; + if (i == len - 1 && l1 != l2) { + return (l1 > l2) ? -1 : 1; + } + int cmp = p1.compareTo(p2); + if (cmp != 0) { + return cmp; + } + } + return 0; + } } \ No newline at end of file diff --git a/src/me/coley/recaf/util/Misc.java b/src/me/coley/recaf/util/Misc.java index 415c80464..70e2520c3 100644 --- a/src/me/coley/recaf/util/Misc.java +++ b/src/me/coley/recaf/util/Misc.java @@ -22,139 +22,139 @@ */ public class Misc { - public static boolean isInt(String s) { - if (s.length() == 0) { - return false; - } - try { - Integer.parseInt(s); - return true; - } catch (Exception e) { - return false; - } - } - - public static boolean isBoolean(String s) { - if (s.length() == 0) { - return false; - } - try { - Boolean.parseBoolean(s); - return true; - } catch (Exception e) { - return false; - } - } - - public static void addAll(JInternalFrame owner, JComponent... components) { - for (JComponent component : components) { - owner.add(component); - } - } - - public static void setBoolean(Object owner, String fieldName, Object value) { - String vts = value.toString(); - if (Misc.isBoolean(vts)) { - set(owner, fieldName, Boolean.parseBoolean(vts)); - } - } - - public static void setInt(Object owner, String fieldName, Object value) { - String vts = value.toString(); - if (Misc.isInt(vts)) { - set(owner, fieldName, Integer.parseInt(vts)); - } - } - - public static void set(Object owner, String fieldName, Object value) { - // Ok, so this is mostly used in lambdas, which can't handle - // exceptions.... - // so just try-catch it. Ugly, but hey it'll have to do. - try { - Field field = owner.getClass().getDeclaredField(fieldName); - if (!field.isAccessible()) { - field.setAccessible(true); - } - field.set(owner, value); - } catch (Exception e) {} - } - - public static String readFile(String path) throws IOException { - return new String(Files.readAllBytes(Paths.get(path)), Charset.forName("utf-8")); - } - - public static void writeFile(String path, String content) throws IOException { - Files.write(Paths.get(path), content.getBytes("utf-8")); - } - - /** - * Adds a path to a given parent node. Also updates the given model. - * - * @param parent The parent node. - * @param dirPath TODO - * @param cn Class - * @param model Model to add node to - * - * TODO: document dirPath param; I'm not sure what it's for. - * - * - Charles - */ - public static ASMTreeNode generateTreePath(ASMTreeNode parent, List dirPath, ClassNode cn, DefaultTreeModel model) { - ASMTreeNode ret = null; - while (dirPath.size() > 0) { - String section = dirPath.get(0); - ASMTreeNode node; - // Create child if it doesn't exist. - if ((node = parent.getChild(section)) == null) { - ASMTreeNode newDir = ret = new ASMTreeNode(section, dirPath.size() == 1 ? cn : null); - parent.addChild(section, newDir); - parent.add(newDir); - // update model - model.nodesWereInserted(parent, new int[] { parent.getIndex(newDir) }); - node = newDir; - } - parent = node; - dirPath.remove(0); - } - return ret; - } - - /** - * Adds a path to a given parent node. Also updates the given model. - * - * @param parent The parent node - * @param dirPath TODO - * - * TODO: document dirPath param; I'm not sure what it's for. - * - * - Charles - */ - public static ASMTreeNode getTreePath(ASMTreeNode parent, List dirPath) { - ASMTreeNode node = parent; - while (dirPath.size() > 0) { - node = node.getChild(dirPath.get(0)); - dirPath.remove(0); - } - return node; - } - - /** - * Get or create the tree node for the given class node from the given - * model. - * - * @param model The default tree model to use. - * @param classNode The class node. - * @return The tree node. - */ - public static ASMTreeNode getOrCreateNode(DefaultTreeModel model, ClassNode classNode) { - ASMTreeNode root = (ASMTreeNode) model.getRoot(); - ArrayList dirPath = new ArrayList(Arrays.asList(classNode.name.split("/"))); - ASMTreeNode genClass = generateTreePath(root, dirPath, classNode, model); - if (genClass == null) { - dirPath = new ArrayList(Arrays.asList(classNode.name.split("/"))); - genClass = getTreePath(root, dirPath); - } - return genClass; - } + public static boolean isInt(String s) { + if (s.length() == 0) { + return false; + } + try { + Integer.parseInt(s); + return true; + } catch (Exception e) { + return false; + } + } + + public static boolean isBoolean(String s) { + if (s.length() == 0) { + return false; + } + try { + Boolean.parseBoolean(s); + return true; + } catch (Exception e) { + return false; + } + } + + public static void addAll(JInternalFrame owner, JComponent... components) { + for (JComponent component : components) { + owner.add(component); + } + } + + public static void setBoolean(Object owner, String fieldName, Object value) { + String vts = value.toString(); + if (Misc.isBoolean(vts)) { + set(owner, fieldName, Boolean.parseBoolean(vts)); + } + } + + public static void setInt(Object owner, String fieldName, Object value) { + String vts = value.toString(); + if (Misc.isInt(vts)) { + set(owner, fieldName, Integer.parseInt(vts)); + } + } + + public static void set(Object owner, String fieldName, Object value) { + // Ok, so this is mostly used in lambdas, which can't handle + // exceptions.... + // so just try-catch it. Ugly, but hey it'll have to do. + try { + Field field = owner.getClass().getDeclaredField(fieldName); + if (!field.isAccessible()) { + field.setAccessible(true); + } + field.set(owner, value); + } catch (Exception e) {} + } + + public static String readFile(String path) throws IOException { + return new String(Files.readAllBytes(Paths.get(path)), Charset.forName("utf-8")); + } + + public static void writeFile(String path, String content) throws IOException { + Files.write(Paths.get(path), content.getBytes("utf-8")); + } + + /** + * Adds a path to a given parent node. Also updates the given model. + * + * @param parent The parent node. + * @param dirPath TODO + * @param cn Class + * @param model Model to add node to + * + * TODO: document dirPath param; I'm not sure what it's for. + * + * - Charles + */ + public static ASMTreeNode generateTreePath(ASMTreeNode parent, List dirPath, ClassNode cn, DefaultTreeModel model) { + ASMTreeNode ret = null; + while (dirPath.size() > 0) { + String section = dirPath.get(0); + ASMTreeNode node; + // Create child if it doesn't exist. + if ((node = parent.getChild(section)) == null) { + ASMTreeNode newDir = ret = new ASMTreeNode(section, dirPath.size() == 1 ? cn : null); + parent.addChild(section, newDir); + parent.add(newDir); + // update model + model.nodesWereInserted(parent, new int[] { parent.getIndex(newDir) }); + node = newDir; + } + parent = node; + dirPath.remove(0); + } + return ret; + } + + /** + * Adds a path to a given parent node. Also updates the given model. + * + * @param parent The parent node + * @param dirPath TODO + * + * TODO: document dirPath param; I'm not sure what it's for. + * + * - Charles + */ + public static ASMTreeNode getTreePath(ASMTreeNode parent, List dirPath) { + ASMTreeNode node = parent; + while (dirPath.size() > 0) { + node = node.getChild(dirPath.get(0)); + dirPath.remove(0); + } + return node; + } + + /** + * Get or create the tree node for the given class node from the given + * model. + * + * @param model The default tree model to use. + * @param classNode The class node. + * @return The tree node. + */ + public static ASMTreeNode getOrCreateNode(DefaultTreeModel model, ClassNode classNode) { + ASMTreeNode root = (ASMTreeNode) model.getRoot(); + ArrayList dirPath = new ArrayList(Arrays.asList(classNode.name.split("/"))); + ASMTreeNode genClass = generateTreePath(root, dirPath, classNode, model); + if (genClass == null) { + dirPath = new ArrayList(Arrays.asList(classNode.name.split("/"))); + genClass = getTreePath(root, dirPath); + } + return genClass; + } } diff --git a/src/me/coley/recaf/util/StreamUtil.java b/src/me/coley/recaf/util/StreamUtil.java index 2b4a1defb..6bb25abcd 100644 --- a/src/me/coley/recaf/util/StreamUtil.java +++ b/src/me/coley/recaf/util/StreamUtil.java @@ -9,55 +9,55 @@ import java.util.stream.Stream; public class StreamUtil { - private final static int BUFF_SIZE = (int) Math.pow(128, 2); + private final static int BUFF_SIZE = (int) Math.pow(128, 2); - /** - * Creates a DataInputStream from byte[]. - * - * @param data byte[] to convert to DataInputStream. - * @return The data input stream. - */ - public static IndexableDataStream fromBytes(byte[] data) { - return new IndexableDataStream(data); - } + /** + * Creates a DataInputStream from byte[]. + * + * @param data byte[] to convert to DataInputStream. + * @return The data input stream. + */ + public static IndexableDataStream fromBytes(byte[] data) { + return new IndexableDataStream(data); + } - /** - * Reads the bytes from the inputstream into a byte array. - * - * @param is InputStream to read from. - * @return byt earray representation of the input stream. - * @throws IOException Thrown if the given input stream cannot be read - * from. - */ - public static byte[] fromStream(InputStream is) throws IOException { - try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { - int r; - byte[] data = new byte[BUFF_SIZE]; - while ((r = is.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, r); - } - buffer.flush(); - return buffer.toByteArray(); - } - } + /** + * Reads the bytes from the inputstream into a byte array. + * + * @param is InputStream to read from. + * @return byt earray representation of the input stream. + * @throws IOException Thrown if the given input stream cannot be read + * from. + */ + public static byte[] fromStream(InputStream is) throws IOException { + try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { + int r; + byte[] data = new byte[BUFF_SIZE]; + while ((r = is.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, r); + } + buffer.flush(); + return buffer.toByteArray(); + } + } - /** - * Sorts the stream of java names. - * - * @param stream Stream of names. - * @return The stream, sorted. - */ - public static Stream sortJavaNames(Stream stream) { - return stream.sorted(new JavaNameSorter()); - } + /** + * Sorts the stream of java names. + * + * @param stream Stream of names. + * @return The stream, sorted. + */ + public static Stream sortJavaNames(Stream stream) { + return stream.sorted(new JavaNameSorter()); + } - /** - * Creates a list of sorted java names from a given collection. - * - * @param names Collection of names. - * @return The collection, sorted and converted to a list. - */ - public static List listOfSortedJavaNames(Collection names) { - return sortJavaNames(names.stream()).collect(Collectors.toList()); - } + /** + * Creates a list of sorted java names from a given collection. + * + * @param names Collection of names. + * @return The collection, sorted and converted to a list. + */ + public static List listOfSortedJavaNames(Collection names) { + return sortJavaNames(names.stream()).collect(Collectors.toList()); + } } From 55718fc527f4730af8bd5ffa99471a875d77a924 Mon Sep 17 00:00:00 2001 From: Charles Daniels Date: Sat, 14 Oct 2017 19:26:35 -0400 Subject: [PATCH 4/6] Re-ran astyle with --indent=force-tab=4 --- src/me/coley/recaf/Options.java | 200 ++--- src/me/coley/recaf/Recaf.java | 100 +-- src/me/coley/recaf/asm/Access.java | 220 ++--- src/me/coley/recaf/asm/AsmUtil.java | 198 ++--- src/me/coley/recaf/asm/JarData.java | 50 +- .../coley/recaf/asm/NonReflectionWriter.java | 172 ++-- src/me/coley/recaf/asm/OpcodeUtil.java | 820 +++++++++--------- src/me/coley/recaf/asm/PluginClassReader.java | 6 +- src/me/coley/recaf/cfr/CFRResourceLookup.java | 66 +- src/me/coley/recaf/cfr/CFRSetting.java | 164 ++-- src/me/coley/recaf/cfr/CFRSourceImpl.java | 44 +- src/me/coley/recaf/ui/FileChoosers.java | 90 +- src/me/coley/recaf/ui/FontUtil.java | 54 +- src/me/coley/recaf/ui/Gui.java | 422 ++++----- src/me/coley/recaf/ui/HtmlRenderer.java | 188 ++-- src/me/coley/recaf/ui/Icons.java | 122 +-- .../recaf/ui/component/LabeledComponent.java | 10 +- .../recaf/ui/component/ReleaseListener.java | 8 +- .../ui/component/action/ActionButton.java | 18 +- .../ui/component/action/ActionCheckBox.java | 18 +- .../ui/component/action/ActionMenuItem.java | 24 +- .../ui/component/action/ActionTextField.java | 46 +- .../ui/component/internalframe/AccessBox.java | 36 +- .../component/internalframe/BasicFrame.java | 34 +- .../component/internalframe/DecompileBox.java | 14 +- .../internalframe/DefaultValueBox.java | 14 +- .../ui/component/internalframe/EditBox.java | 62 +- .../internalframe/ExceptionsListBox.java | 74 +- .../internalframe/MemberDefinitionBox.java | 84 +- .../internalframe/OpcodeCreationBox.java | 522 +++++------ .../internalframe/OpcodeListBox.java | 20 +- .../component/internalframe/TryCatchBox.java | 116 +-- .../list/MemberNodeClickListener.java | 380 ++++---- .../ui/component/list/MemberNodeRenderer.java | 202 ++--- .../ui/component/list/OpcodeCellRenderer.java | 526 +++++------ .../ui/component/list/OpcodeKeyListener.java | 66 +- .../recaf/ui/component/list/OpcodeList.java | 260 +++--- .../component/list/OpcodeMouseListener.java | 444 +++++----- .../list/OpcodeSelectionListener.java | 178 ++-- .../recaf/ui/component/panel/AccessPanel.java | 182 ++-- .../ui/component/panel/AsmFlagsPanel.java | 90 +- .../ui/component/panel/ClassDisplayPanel.java | 288 +++--- .../ui/component/panel/DecompilePanel.java | 140 +-- .../component/panel/LabelSwitcherPanel.java | 124 +-- .../panel/OpcodeTypeSwitchPanel.java | 342 ++++---- .../recaf/ui/component/panel/SearchPanel.java | 394 ++++----- .../recaf/ui/component/panel/TabbedPanel.java | 206 ++--- .../component/panel/TagTypeSwitchPanel.java | 156 ++-- .../recaf/ui/component/table/MemberTable.java | 126 +-- .../ui/component/table/VariableTable.java | 218 ++--- .../ui/component/tree/ASMFieldTreeNode.java | 16 +- .../ui/component/tree/ASMInsnTreeNode.java | 16 +- .../ui/component/tree/ASMMethodTreeNode.java | 16 +- .../recaf/ui/component/tree/ASMTreeNode.java | 30 +- .../recaf/ui/component/tree/JarFileTree.java | 80 +- .../ui/component/tree/JavaTreeListener.java | 92 +- .../ui/component/tree/JavaTreeRenderer.java | 128 +-- .../coley/recaf/util/IndexableDataStream.java | 56 +- src/me/coley/recaf/util/JavaNameSorter.java | 40 +- src/me/coley/recaf/util/Misc.java | 268 +++--- src/me/coley/recaf/util/StreamUtil.java | 94 +- 61 files changed, 4587 insertions(+), 4587 deletions(-) diff --git a/src/me/coley/recaf/Options.java b/src/me/coley/recaf/Options.java index 179467f33..595bbe8f9 100644 --- a/src/me/coley/recaf/Options.java +++ b/src/me/coley/recaf/Options.java @@ -14,108 +14,108 @@ import me.coley.recaf.util.Misc; public class Options { - /** - * File to store config in. - */ - private final static File optionsFile = new File("rcoptions.json"); - /** - * Show confirmation prompt on doing potentially dangerous things. - */ - public boolean confirmDeletions = true; - /** - * Show extra jump information. - */ - public boolean opcodeShowJumpHelp = true; - /** - * Simplify descriptor displays on the opcode list. - */ - public boolean opcodeSimplifyDescriptors = true; - /** - * Display variable's signature in the opcode edit window for variable - * opcodes. Allows editing of signatures (Generic types) and - * significantly increases the edit window size. - */ - public boolean showVariableSignatureInTable; - /** - * Flags for reading in classes. - */ - public int classFlagsInput = ClassReader.EXPAND_FRAMES; - /** - * Flags for writing classes. - */ - public int classFlagsOutput = ClassWriter.COMPUTE_FRAMES; - /** - * Max length for text in ldc opcodes to be displayed. - */ - public int ldcMaxLength = 125; + /** + * File to store config in. + */ + private final static File optionsFile = new File("rcoptions.json"); + /** + * Show confirmation prompt on doing potentially dangerous things. + */ + public boolean confirmDeletions = true; + /** + * Show extra jump information. + */ + public boolean opcodeShowJumpHelp = true; + /** + * Simplify descriptor displays on the opcode list. + */ + public boolean opcodeSimplifyDescriptors = true; + /** + * Display variable's signature in the opcode edit window for variable + * opcodes. Allows editing of signatures (Generic types) and + * significantly increases the edit window size. + */ + public boolean showVariableSignatureInTable; + /** + * Flags for reading in classes. + */ + public int classFlagsInput = ClassReader.EXPAND_FRAMES; + /** + * Flags for writing classes. + */ + public int classFlagsOutput = ClassWriter.COMPUTE_FRAMES; + /** + * Max length for text in ldc opcodes to be displayed. + */ + public int ldcMaxLength = 125; - public Options() { - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - save(); - } - }); - } + public Options() { + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + save(); + } + }); + } - /** - * Load from configuration. - */ - public void load() { - if (!optionsFile.exists()) { - return; - } - try { - JsonObject json = Json.parse(Misc.readFile(optionsFile.getAbsolutePath())).asObject(); - for (Field field : Options.class.getDeclaredFields()) { - String name = field.getName(); - JsonValue value = json.get(name); - if (value == null) { - continue; - } - field.setAccessible(true); - if (value.isBoolean()) { - field.set(this, value.asBoolean()); - } else if (value.isNumber()) { - field.set(this, value.asInt()); - } else if (value.isString()) { - field.set(this, value.asString()); - } - } - } catch (Exception e) { - // TODO: Propper logging - e.printStackTrace(); - } - } + /** + * Load from configuration. + */ + public void load() { + if (!optionsFile.exists()) { + return; + } + try { + JsonObject json = Json.parse(Misc.readFile(optionsFile.getAbsolutePath())).asObject(); + for (Field field : Options.class.getDeclaredFields()) { + String name = field.getName(); + JsonValue value = json.get(name); + if (value == null) { + continue; + } + field.setAccessible(true); + if (value.isBoolean()) { + field.set(this, value.asBoolean()); + } else if (value.isNumber()) { + field.set(this, value.asInt()); + } else if (value.isString()) { + field.set(this, value.asString()); + } + } + } catch (Exception e) { + // TODO: Propper logging + e.printStackTrace(); + } + } - /** - * Save current settings to configuration. - */ - public void save() { - try { - if (!optionsFile.exists()) { - optionsFile.createNewFile(); - } - JsonObject json = Json.object(); - for (Field field : Options.class.getDeclaredFields()) { - field.setAccessible(true); - String name = field.getName(); - Object value = field.get(this); - if (value instanceof Boolean) { - json.set(name, (boolean) value); - } else if (value instanceof Integer) { - json.set(name, (int) value); - } else if (value instanceof String) { - json.set(name, (String) value); - } - } - StringWriter w = new StringWriter(); - json.writeTo(w, WriterConfig.PRETTY_PRINT); - Misc.writeFile(optionsFile.getAbsolutePath(), w.toString()); - } catch (Exception e) { - // TODO: Propper logging - e.getMessage(); - } - } + /** + * Save current settings to configuration. + */ + public void save() { + try { + if (!optionsFile.exists()) { + optionsFile.createNewFile(); + } + JsonObject json = Json.object(); + for (Field field : Options.class.getDeclaredFields()) { + field.setAccessible(true); + String name = field.getName(); + Object value = field.get(this); + if (value instanceof Boolean) { + json.set(name, (boolean) value); + } else if (value instanceof Integer) { + json.set(name, (int) value); + } else if (value instanceof String) { + json.set(name, (String) value); + } + } + StringWriter w = new StringWriter(); + json.writeTo(w, WriterConfig.PRETTY_PRINT); + Misc.writeFile(optionsFile.getAbsolutePath(), w.toString()); + } catch (Exception e) { + // TODO: Propper logging + e.getMessage(); + } + } } diff --git a/src/me/coley/recaf/Recaf.java b/src/me/coley/recaf/Recaf.java index 7e464c735..71af8e847 100644 --- a/src/me/coley/recaf/Recaf.java +++ b/src/me/coley/recaf/Recaf.java @@ -14,62 +14,62 @@ import me.coley.recaf.ui.Gui; public class Recaf { - private static Recaf instance; - public Gui window; - public File currentJar; - public JarData jarData; - public FileChoosers fileChoosers; - public Options options; - public AsmUtil asm; + private static Recaf instance; + public Gui window; + public File currentJar; + public JarData jarData; + public FileChoosers fileChoosers; + public Options options; + public AsmUtil asm; - public Recaf() { - instance = this; - fileChoosers = new FileChoosers(); - options = new Options(); - options.load(); - asm = new AsmUtil(); - } + public Recaf() { + instance = this; + fileChoosers = new FileChoosers(); + options = new Options(); + options.load(); + asm = new AsmUtil(); + } - public void openFile(File file) throws IOException { - this.currentJar = file; - this.jarData = new JarData(file); - this.window.updateTree(); - this.window.getFrame().setTitle("Recaf: " + file.getName()); - } + public void openFile(File file) throws IOException { + this.currentJar = file; + this.jarData = new JarData(file); + this.window.updateTree(); + this.window.getFrame().setTitle("Recaf: " + file.getName()); + } - public void saveFile(File file) throws IOException { - this.jarData.save(file); - } + public void saveFile(File file) throws IOException { + this.jarData.save(file); + } - public void selectClass(ClassNode node) { - this.window.addClassView(node); - } + public void selectClass(ClassNode node) { + this.window.addClassView(node); + } - public void showGui() { - EventQueue.invokeLater(new Runnable() { - public void run() { - try { - window = new Gui(); - window.getFrame().setVisible(true); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } + public void showGui() { + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + window = new Gui(); + window.getFrame().setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } - public static Recaf getInstance() { - return instance; - } + public static Recaf getInstance() { + return instance; + } - public static void main(String[] args) { - try { - UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); - } catch (Exception e) { - e.printStackTrace(); - } - Recaf program = new Recaf(); - program.showGui(); + public static void main(String[] args) { + try { + UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); + } catch (Exception e) { + e.printStackTrace(); + } + Recaf program = new Recaf(); + program.showGui(); - } + } } diff --git a/src/me/coley/recaf/asm/Access.java b/src/me/coley/recaf/asm/Access.java index 84dde6c03..e979600c4 100644 --- a/src/me/coley/recaf/asm/Access.java +++ b/src/me/coley/recaf/asm/Access.java @@ -6,114 +6,114 @@ * @author Matt */ public class Access { - // @formatter:off - // Modifiers - Public - public static final int PUBLIC = 0x00001; - public static final int PRIVATE = 0x00002; - public static final int PROTECTED = 0x00004; - public static final int STATIC = 0x00008; - public static final int FINAL = 0x00010; - public static final int SYNCHRONIZED = 0x00020; - public static final int VOLATILE = 0x00040; - public static final int TRANSIENT = 0x00080; - public static final int NATIVE = 0x00100; - public static final int INTERFACE = 0x00200; - public static final int ABSTRACT = 0x00400; - public static final int STRICT = 0x00800; - // Modifiers - Non-Public - public static final int BRIDGE = 0x00040; - public static final int VARARGS = 0x00080; - public static final int SYNTHETIC = 0x01000; - public static final int ANNOTATION = 0x02000; - public static final int ENUM = 0x04000; - public static final int MANDATED = 0x08000; - public static final int SUPER = 0x00020; - // Modifier sets - public static final int CLASS_MODIFIERS = - PUBLIC | PRIVATE | FINAL | - STATIC | ANNOTATION | ENUM | - SYNTHETIC | INTERFACE | SUPER | - ABSTRACT | STRICT; - public static final int INTERFACE_MODIFIERS = - PUBLIC | PROTECTED | PRIVATE | - ABSTRACT | STATIC | STRICT | - SYNTHETIC; - public static final int CONSTRUCTOR_MODIFIERS = - PUBLIC | PROTECTED | PRIVATE | - BRIDGE | SYNTHETIC | VARARGS; - public static final int METHOD_MODIFIERS = - PUBLIC | PROTECTED | PRIVATE | - ABSTRACT | STATIC | FINAL | - SYNCHRONIZED | NATIVE | STRICT | - SYNTHETIC | BRIDGE | VARARGS; - public static final int FIELD_MODIFIERS = - PUBLIC | PROTECTED | PRIVATE | - STATIC | TRANSIENT | FINAL | - VOLATILE | SYNTHETIC; - // Access checking - public static boolean isAbstract(int acc) { - return(acc & ABSTRACT)!=0; - } - public static boolean isAnnotation(int acc) { - return(acc & ANNOTATION)!=0; - } - public static boolean isBridge(int acc) { - return(acc & BRIDGE)!=0; - } - public static boolean isEnum(int acc) { - return(acc & ENUM)!=0; - } - public static boolean isFinal(int acc) { - return(acc & FINAL)!=0; - } - public static boolean isInterface(int acc) { - return(acc & INTERFACE)!=0; - } - public static boolean isNative(int acc) { - return(acc & NATIVE)!=0; - } - public static boolean isPrivate(int acc) { - return(acc & PRIVATE)!=0; - } - public static boolean isProtected(int acc) { - return(acc & PROTECTED)!=0; - } - public static boolean isPublic(int acc) { - return(acc & PUBLIC)!=0; - } - public static boolean isStatic(int acc) { - return(acc & STATIC)!=0; - } - public static boolean isStrict(int acc) { - return(acc & STRICT)!=0; - } - public static boolean isSuper(int acc) { - return(acc & SUPER)!=0; - } - public static boolean isSynchronized(int acc) { - return(acc & SYNCHRONIZED)!=0; - } - public static boolean isSynthetic(int acc) { - return(acc & SYNTHETIC)!=0; - } - public static boolean isTransient(int acc) { - return(acc & TRANSIENT)!=0; - } - public static boolean isVarargs(int acc) { - return(acc & VARARGS)!=0; - } - public static boolean isVolatile(int acc) { - return(acc & VOLATILE)!=0; - } - // Access creation - public static int createAccess(int... acArgs) { - int access = 0; - for (int acArg : acArgs) access |= acArg; - return access; - } - public static boolean hasAccess(int access, int... acArgs) { - for (int acArg : acArgs) - if ((access & acArg) == 0) return false; - return true; - } + // @formatter:off + // Modifiers - Public + public static final int PUBLIC = 0x00001; + public static final int PRIVATE = 0x00002; + public static final int PROTECTED = 0x00004; + public static final int STATIC = 0x00008; + public static final int FINAL = 0x00010; + public static final int SYNCHRONIZED = 0x00020; + public static final int VOLATILE = 0x00040; + public static final int TRANSIENT = 0x00080; + public static final int NATIVE = 0x00100; + public static final int INTERFACE = 0x00200; + public static final int ABSTRACT = 0x00400; + public static final int STRICT = 0x00800; + // Modifiers - Non-Public + public static final int BRIDGE = 0x00040; + public static final int VARARGS = 0x00080; + public static final int SYNTHETIC = 0x01000; + public static final int ANNOTATION = 0x02000; + public static final int ENUM = 0x04000; + public static final int MANDATED = 0x08000; + public static final int SUPER = 0x00020; + // Modifier sets + public static final int CLASS_MODIFIERS = + PUBLIC | PRIVATE | FINAL | + STATIC | ANNOTATION | ENUM | + SYNTHETIC | INTERFACE | SUPER | + ABSTRACT | STRICT; + public static final int INTERFACE_MODIFIERS = + PUBLIC | PROTECTED | PRIVATE | + ABSTRACT | STATIC | STRICT | + SYNTHETIC; + public static final int CONSTRUCTOR_MODIFIERS = + PUBLIC | PROTECTED | PRIVATE | + BRIDGE | SYNTHETIC | VARARGS; + public static final int METHOD_MODIFIERS = + PUBLIC | PROTECTED | PRIVATE | + ABSTRACT | STATIC | FINAL | + SYNCHRONIZED | NATIVE | STRICT | + SYNTHETIC | BRIDGE | VARARGS; + public static final int FIELD_MODIFIERS = + PUBLIC | PROTECTED | PRIVATE | + STATIC | TRANSIENT | FINAL | + VOLATILE | SYNTHETIC; + // Access checking + public static boolean isAbstract(int acc) { + return(acc & ABSTRACT)!=0; + } + public static boolean isAnnotation(int acc) { + return(acc & ANNOTATION)!=0; + } + public static boolean isBridge(int acc) { + return(acc & BRIDGE)!=0; + } + public static boolean isEnum(int acc) { + return(acc & ENUM)!=0; + } + public static boolean isFinal(int acc) { + return(acc & FINAL)!=0; + } + public static boolean isInterface(int acc) { + return(acc & INTERFACE)!=0; + } + public static boolean isNative(int acc) { + return(acc & NATIVE)!=0; + } + public static boolean isPrivate(int acc) { + return(acc & PRIVATE)!=0; + } + public static boolean isProtected(int acc) { + return(acc & PROTECTED)!=0; + } + public static boolean isPublic(int acc) { + return(acc & PUBLIC)!=0; + } + public static boolean isStatic(int acc) { + return(acc & STATIC)!=0; + } + public static boolean isStrict(int acc) { + return(acc & STRICT)!=0; + } + public static boolean isSuper(int acc) { + return(acc & SUPER)!=0; + } + public static boolean isSynchronized(int acc) { + return(acc & SYNCHRONIZED)!=0; + } + public static boolean isSynthetic(int acc) { + return(acc & SYNTHETIC)!=0; + } + public static boolean isTransient(int acc) { + return(acc & TRANSIENT)!=0; + } + public static boolean isVarargs(int acc) { + return(acc & VARARGS)!=0; + } + public static boolean isVolatile(int acc) { + return(acc & VOLATILE)!=0; + } + // Access creation + public static int createAccess(int... acArgs) { + int access = 0; + for (int acArg : acArgs) access |= acArg; + return access; + } + public static boolean hasAccess(int access, int... acArgs) { + for (int acArg : acArgs) + if ((access & acArg) == 0) return false; + return true; + } } diff --git a/src/me/coley/recaf/asm/AsmUtil.java b/src/me/coley/recaf/asm/AsmUtil.java index cc9f9c776..96b84edc8 100644 --- a/src/me/coley/recaf/asm/AsmUtil.java +++ b/src/me/coley/recaf/asm/AsmUtil.java @@ -16,108 +16,108 @@ import me.coley.recaf.util.StreamUtil; public class AsmUtil { - private final Recaf recaf = Recaf.getInstance(); + private final Recaf recaf = Recaf.getInstance(); - /** - * Reads the classes of the given jar into a map. - * - * @param jarPath Path to jarfile to read classes from. - * @return Map of classes from the specified jarfile. - * @throws IOException If an error was encountered while reading the - * jarfile. - */ - public Map readClasses(String jarPath) throws IOException { - Map map = new HashMap<>(); - try (ZipFile file = new ZipFile(jarPath)) { - Enumeration entries = file.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if (entry.isDirectory() || !entry.getName().endsWith(".class")) { - continue; - } - String name = null; - try (InputStream is = file.getInputStream(entry)) { - ClassReader cr = new PluginClassReader(is); - name = cr.getClassName(); - map.put(cr.getClassName(), getNode(cr)); - } catch (IndexOutOfBoundsException ioobe) { - if (name == null) { - recaf.window.displayError(new RuntimeException("Failed reading class from: " + entry.getName(), - ioobe)); - } else { - recaf.window.displayError(new RuntimeException("Failed reading into node structure: " + name, ioobe)); - } - } - } - } - return map; - } + /** + * Reads the classes of the given jar into a map. + * + * @param jarPath Path to jarfile to read classes from. + * @return Map of classes from the specified jarfile. + * @throws IOException If an error was encountered while reading the + * jarfile. + */ + public Map readClasses(String jarPath) throws IOException { + Map map = new HashMap<>(); + try (ZipFile file = new ZipFile(jarPath)) { + Enumeration entries = file.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (entry.isDirectory() || !entry.getName().endsWith(".class")) { + continue; + } + String name = null; + try (InputStream is = file.getInputStream(entry)) { + ClassReader cr = new PluginClassReader(is); + name = cr.getClassName(); + map.put(cr.getClassName(), getNode(cr)); + } catch (IndexOutOfBoundsException ioobe) { + if (name == null) { + recaf.window.displayError(new RuntimeException("Failed reading class from: " + entry.getName(), + ioobe)); + } else { + recaf.window.displayError(new RuntimeException("Failed reading into node structure: " + name, ioobe)); + } + } + } + } + return map; + } - /** - * Reads non-classes from the given jar. - * - * @param jarPath Path to jarfile to read non-classes from. - * @return Map of non-classes from the specified jarfile. - * @throws IOException If an error was encountered while reading the - * jarfile. - */ - public Map readNonClasses(String jarPath) throws IOException { - Map map = new HashMap<>(); - try (ZipFile file = new ZipFile(jarPath)) { - Enumeration entries = file.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if (entry.isDirectory() || entry.getName().contains(".class")) { - continue; - } - try (InputStream is = file.getInputStream(entry)) { - map.put(entry.getName(), StreamUtil.fromStream(is)); - } - } - } - return map; - } + /** + * Reads non-classes from the given jar. + * + * @param jarPath Path to jarfile to read non-classes from. + * @return Map of non-classes from the specified jarfile. + * @throws IOException If an error was encountered while reading the + * jarfile. + */ + public Map readNonClasses(String jarPath) throws IOException { + Map map = new HashMap<>(); + try (ZipFile file = new ZipFile(jarPath)) { + Enumeration entries = file.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (entry.isDirectory() || entry.getName().contains(".class")) { + continue; + } + try (InputStream is = file.getInputStream(entry)) { + map.put(entry.getName(), StreamUtil.fromStream(is)); + } + } + } + return map; + } - /** - * Creates a ClassNode from the given ClassReader. - * - * @param cr The class read to obtain the node from. - * @return The node obtained from cr. - */ - private ClassNode getNode(ClassReader cr) { - ClassNode cn = new ClassNode(); - cr.accept(cn, recaf.options.classFlagsInput); - return cn; - } + /** + * Creates a ClassNode from the given ClassReader. + * + * @param cr The class read to obtain the node from. + * @return The node obtained from cr. + */ + private ClassNode getNode(ClassReader cr) { + ClassNode cn = new ClassNode(); + cr.accept(cn, recaf.options.classFlagsInput); + return cn; + } - /** - * Creates a ClassNode from the given class. - * - * @param c The target class. - * @return Node generated from c. - * @throws IOException If an error occurs while loading the class. - */ - public ClassNode getNode(Class c) throws IOException { - String name = c.getName(); - String path = name.replace('.', '/') + ".class"; - ClassLoader loader = c.getClassLoader(); - if (loader == null) { - loader = ClassLoader.getSystemClassLoader(); - } - InputStream is = loader.getResourceAsStream(path); - ClassReader cr = new ClassReader(is); - return getNode(cr); - } + /** + * Creates a ClassNode from the given class. + * + * @param c The target class. + * @return Node generated from c. + * @throws IOException If an error occurs while loading the class. + */ + public ClassNode getNode(Class c) throws IOException { + String name = c.getName(); + String path = name.replace('.', '/') + ".class"; + ClassLoader loader = c.getClassLoader(); + if (loader == null) { + loader = ClassLoader.getSystemClassLoader(); + } + InputStream is = loader.getResourceAsStream(path); + ClassReader cr = new ClassReader(is); + return getNode(cr); + } - /** - * Writes a ClassNode to a byte array. - * - * @param cn The target class node. - * @return ByteArray representation of cn. - */ - public byte[] toBytes(ClassNode cn) { - ClassWriter cw = new NonReflectionWriter(recaf.options.classFlagsOutput); - cn.accept(cw); - return cw.toByteArray(); - } + /** + * Writes a ClassNode to a byte array. + * + * @param cn The target class node. + * @return ByteArray representation of cn. + */ + public byte[] toBytes(ClassNode cn) { + ClassWriter cw = new NonReflectionWriter(recaf.options.classFlagsOutput); + cn.accept(cw); + return cw.toByteArray(); + } } diff --git a/src/me/coley/recaf/asm/JarData.java b/src/me/coley/recaf/asm/JarData.java index 66f299343..1e5f1e626 100644 --- a/src/me/coley/recaf/asm/JarData.java +++ b/src/me/coley/recaf/asm/JarData.java @@ -12,31 +12,31 @@ import me.coley.recaf.Recaf; public class JarData { - private final Recaf recaf = Recaf.getInstance(); - public final Map classes; - public final Map resources; + private final Recaf recaf = Recaf.getInstance(); + public final Map classes; + public final Map resources; - public JarData(File jar) throws IOException { - String path = jar.getAbsolutePath(); - classes = recaf.asm.readClasses(path); - resources = recaf.asm.readNonClasses(path); - } + public JarData(File jar) throws IOException { + String path = jar.getAbsolutePath(); + classes = recaf.asm.readClasses(path); + resources = recaf.asm.readNonClasses(path); + } - public void save(File jar) throws IOException { - try (JarOutputStream output = new JarOutputStream(new FileOutputStream(jar))) { - // write classes - for (String name : classes.keySet()) { - byte[] data = recaf.asm.toBytes(classes.get(name)); - output.putNextEntry(new JarEntry(name.replace(".", "/") + ".class")); - output.write(data); - output.closeEntry(); - } - // write resources - for (String name : resources.keySet()) { - output.putNextEntry(new JarEntry(name)); - output.write(resources.get(name)); - output.closeEntry(); - } - } - } + public void save(File jar) throws IOException { + try (JarOutputStream output = new JarOutputStream(new FileOutputStream(jar))) { + // write classes + for (String name : classes.keySet()) { + byte[] data = recaf.asm.toBytes(classes.get(name)); + output.putNextEntry(new JarEntry(name.replace(".", "/") + ".class")); + output.write(data); + output.closeEntry(); + } + // write resources + for (String name : resources.keySet()) { + output.putNextEntry(new JarEntry(name)); + output.write(resources.get(name)); + output.closeEntry(); + } + } + } } diff --git a/src/me/coley/recaf/asm/NonReflectionWriter.java b/src/me/coley/recaf/asm/NonReflectionWriter.java index ff1fdf108..3c352faa4 100644 --- a/src/me/coley/recaf/asm/NonReflectionWriter.java +++ b/src/me/coley/recaf/asm/NonReflectionWriter.java @@ -13,95 +13,95 @@ * classpath for determining the common super-class. */ public class NonReflectionWriter extends ClassWriter { - private static final String DEFAULT_PARENT = "java/lang/Object"; - private final Recaf recaf = Recaf.getInstance(); - private final Map nodes; + private static final String DEFAULT_PARENT = "java/lang/Object"; + private final Recaf recaf = Recaf.getInstance(); + private final Map nodes; - public NonReflectionWriter(int flags) { - super(flags); - this.nodes = recaf.jarData.classes; - } + public NonReflectionWriter(int flags) { + super(flags); + this.nodes = recaf.jarData.classes; + } - @Override - protected String getCommonSuperClass(String type1, String type2) { - if (type1 == null || type2 == null) { - return DEFAULT_PARENT; - } - ClassNode node1 = loadNode(type1); - ClassNode node2 = loadNode(type2); - if (node1 == null || node2 == null) { - return DEFAULT_PARENT; - } else if (isAssignableFrom(node1, node2)) { - return type1; - } else if (isAssignableFrom(node2, node1)) { - return type2; - } - do { - node1 = loadNode(node1.superName); - if (node1 == null) { - if (node2.name.equals(type1)) { - return DEFAULT_PARENT; - } - node1 = loadNode(type2); - node2 = loadNode(type1); - } else if (isAssignableFrom(node1, node2)) { - return type1; - } else if (isAssignableFrom(node2, node1)) { - return type2; - } - } while (!isAssignableFrom(node1, node2)); - return DEFAULT_PARENT; - } + @Override + protected String getCommonSuperClass(String type1, String type2) { + if (type1 == null || type2 == null) { + return DEFAULT_PARENT; + } + ClassNode node1 = loadNode(type1); + ClassNode node2 = loadNode(type2); + if (node1 == null || node2 == null) { + return DEFAULT_PARENT; + } else if (isAssignableFrom(node1, node2)) { + return type1; + } else if (isAssignableFrom(node2, node1)) { + return type2; + } + do { + node1 = loadNode(node1.superName); + if (node1 == null) { + if (node2.name.equals(type1)) { + return DEFAULT_PARENT; + } + node1 = loadNode(type2); + node2 = loadNode(type1); + } else if (isAssignableFrom(node1, node2)) { + return type1; + } else if (isAssignableFrom(node2, node1)) { + return type2; + } + } while (!isAssignableFrom(node1, node2)); + return DEFAULT_PARENT; + } - /** - * Checks if the given parent is a superclass or superinterface of the given - * child. - * - * @param parent - * @param child - * @return - */ - private boolean isAssignableFrom(ClassNode parent, ClassNode child) { - while (child.superName != null) { - if (parent.name.equals(child.name) || child.interfaces.contains(parent.name)) { - return true; - } - for (String interfac : child.interfaces) { - if (isAssignableFrom(parent, loadNode(interfac))) { - return true; - } - } - child = loadNode(child.superName); - } - return false; - } + /** + * Checks if the given parent is a superclass or superinterface of the given + * child. + * + * @param parent + * @param child + * @return + */ + private boolean isAssignableFrom(ClassNode parent, ClassNode child) { + while (child.superName != null) { + if (parent.name.equals(child.name) || child.interfaces.contains(parent.name)) { + return true; + } + for (String interfac : child.interfaces) { + if (isAssignableFrom(parent, loadNode(interfac))) { + return true; + } + } + child = loadNode(child.superName); + } + return false; + } - /** - * Load node from the node map. - * - * @param type - * @return - */ - private ClassNode loadNode(String type) { - // Try loading from node list - if (type == null) { - return null; - } else if (nodes.containsKey(type)) { - return nodes.get(type); - } - // Try loading from runtime - String nameStr = type.replace("/", "."); - try { - Class clazz = Class.forName(nameStr); - if (clazz == null) { - return null; - } - return recaf.asm.getNode(clazz); - } catch (IOException e) { - return null; - } catch (ClassNotFoundException e) { - return null; - } - } + /** + * Load node from the node map. + * + * @param type + * @return + */ + private ClassNode loadNode(String type) { + // Try loading from node list + if (type == null) { + return null; + } else if (nodes.containsKey(type)) { + return nodes.get(type); + } + // Try loading from runtime + String nameStr = type.replace("/", "."); + try { + Class clazz = Class.forName(nameStr); + if (clazz == null) { + return null; + } + return recaf.asm.getNode(clazz); + } catch (IOException e) { + return null; + } catch (ClassNotFoundException e) { + return null; + } + } } \ No newline at end of file diff --git a/src/me/coley/recaf/asm/OpcodeUtil.java b/src/me/coley/recaf/asm/OpcodeUtil.java index cf327017f..69c7eb313 100644 --- a/src/me/coley/recaf/asm/OpcodeUtil.java +++ b/src/me/coley/recaf/asm/OpcodeUtil.java @@ -7,427 +7,427 @@ import org.objectweb.asm.tree.AbstractInsnNode; public class OpcodeUtil implements Opcodes { - private static Map opcodeToName = new HashMap<>(); - private static Map nameToOpcode = new HashMap<>(); - private static Map frameToName = new HashMap<>(); - private static Map nameToFrame = new HashMap<>(); - private static Map tagToName = new HashMap<>(); - private static Map nameToTag = new HashMap<>(); - private static Map insnTypeToCodes = new HashMap<>(); - /** - * Opcodes of INSN type. - */ - public static String[] OPS_INSN = new String[] { "NOP", "ACONST_NULL", "ICONST_M1", "ICONST_0", "ICONST_1", "ICONST_2", - "ICONST_3", "ICONST_4", "ICONST_5", "LCONST_0", "LCONST_1", "FCONST_0", "FCONST_1", "FCONST_2", "DCONST_0", - "DCONST_1", "IALOAD", "LALOAD", "FALOAD", "DALOAD", "AALOAD", "BALOAD", "CALOAD", "SALOAD", "IASTORE", "LASTORE", - "FASTORE", "DASTORE", "AASTORE", "BASTORE", "CASTORE", "SASTORE", "POP", "POP2", "DUP", "DUP_X1", "DUP_X2", "DUP2", - "DUP2_X1", "DUP2_X2", "SWAP", "IADD", "LADD", "FADD", "DADD", "ISUB", "LSUB", "FSUB", "DSUB", "IMUL", "LMUL", "FMUL", - "DMUL", "IDIV", "LDIV", "FDIV", "DDIV", "IREM", "LREM", "FREM", "DREM", "INEG", "LNEG", "FNEG", "DNEG", "ISHL", - "LSHL", "ISHR", "LSHR", "IUSHR", "LUSHR", "IAND", "LAND", "IOR", "LOR", "IXOR", "LXOR", "I2L", "I2F", "I2D", "L2I", - "L2F", "L2D", "F2I", "F2L", "F2D", "D2I", "D2L", "D2F", "I2B", "I2C", "I2S", "LCMP", "FCMPL", "FCMPG", "DCMPL", - "DCMPG", "IRETURN", "LRETURN", "FRETURN", "DRETURN", "ARETURN", "RETURN", "ARRAYLENGTH", "ATHROW", "MONITORENTER", - "MONITOREXIT" - }; - /** - * Subset of {@link #OPS_INSN} for constants. - */ - public static String[] OPS_INSN_SUB_CONSTS = new String[] { "ACONST_NULL", "ICONST_M1", "ICONST_0", "ICONST_1", "ICONST_2", - "ICONST_3", "ICONST_4", "ICONST_5", "LCONST_0", "LCONST_1", "FCONST_0", "FCONST_1", "FCONST_2", "DCONST_0", - "DCONST_1" - }; - /** - * Subset of {@link #OPS_INSN} for array loads/saves/etc. - */ - public static String[] OPS_INSN_SUB_ARRAY = new String[] { "IALOAD", "LALOAD", "FALOAD", "DALOAD", "AALOAD", "BALOAD", - "CALOAD", "SALOAD", "IASTORE", "LASTORE", "FASTORE", "DASTORE", "AASTORE", "BASTORE", "CASTORE", "SASTORE", - "ARRAYLENGTH" - }; - /** - * Subset of {@link #OPS_INSN} for stack management. - */ - public static String[] OPS_INSN_SUB_STACK = new String[] { "POP", "POP2", "DUP", "DUP_X1", "DUP_X2", "DUP2", "DUP2_X1", - "DUP2_X2", "SWAP" - }; - /** - * Subset of {@link #OPS_INSN} for math handling. - */ - public static String[] OPS_INSN_SUB_MATH = new String[] { "IADD", "LADD", "FADD", "DADD", "ISUB", "LSUB", "FSUB", "DSUB", - "IMUL", "LMUL", "FMUL", "DMUL", "IDIV", "LDIV", "FDIV", "DDIV", "IREM", "LREM", "FREM", "DREM", "INEG", "LNEG", - "FNEG", "DNEG", "ISHL", "LSHL", "ISHR", "LSHR", "IUSHR", "LUSHR", "IAND", "LAND", "IOR", "LOR", "IXOR" - }; - /** - * Subset of {@link #OPS_INSN} for type conversion. - */ - public static String[] OPS_INSN_SUB_CONVERT = new String[] { "I2L", "I2F", "I2D", "L2I", "L2F", "L2D", "F2I", "F2L", "F2D", - "D2I", "D2L", "D2F", "I2B", "I2C", "I2S" - }; - /** - * Subset of {@link #OPS_INSN} for primitve comparisons. - */ - public static String[] OPS_INSN_SUB_COMPARE = new String[] { "LCMP", "FCMPL", "FCMPG", "DCMPL", "DCMPG" }; - /** - * Subset of {@link #OPS_INSN} for returns. - */ - public static String[] OPS_INSN_SUB_RETURN = new String[] { "IRETURN", "LRETURN", "FRETURN", "DRETURN", "ARETURN", "RETURN" }; - /** - * Subset of {@link #OPS_INSN} for monitors. - */ - public static String[] OPS_INSN_SUB_MONITOR = new String[] { "MONITORENTER", "MONITOREXIT" }; - /** - * Subset of {@link #OPS_INSN} for exceptions. - */ - public static String[] OPS_INSN_SUB_EXCEPTION = new String[] { "ATHROW" }; - /** - * Opcodes of INT type. - */ - public static String[] OPS_INT = new String[] { "BIPUSH", "SIPUSH", "NEWARRAY" }; - /** - * Opcodes of INT type. - */ - public static String[] OPS_VAR = new String[] { "ILOAD", "LLOAD", "FLOAD", "DLOAD", "ALOAD", "ISTORE", "LSTORE", "FSTORE", - "DSTORE", "ASTORE", "RET" - }; - /** - * Opcodes of TYPE type. - */ - public static String[] OPS_TYPE = new String[] { "NEW", "ANEWARRAY", "CHECKCAST", "INSTANCEOF" }; - /** - * Opcodes of FIELD type. - */ - public static String[] OPS_FIELD = new String[] { "GETSTATIC", "PUTSTATIC", "GETFIELD", "PUTFIELD" }; - /** - * Opcodes of METHOD type. - */ - public static String[] OPS_METHOD = new String[] { "INVOKEVIRTUAL", "INVOKESPECIAL", "INVOKESTATIC", "INVOKEINTERFACE" }; - /** - * Opcodes of INDY_METHOD type. - */ - public static String[] OPS_INDY_METHOD = new String[] { "INVOKEDYNAMIC" }; - /** - * Opcodes of JUMP type. - */ - public static String[] OPS_JUMP = new String[] { "IFEQ", "IFNE", "IFLT", "IFGE", "IFGT", "IFLE", "IF_ICMPEQ", "IF_ICMPNE", - "IF_ICMPLT", "IF_ICMPGE", "IF_ICMPGT", "IF_ICMPLE", "IF_ACMPEQ", "IF_ACMPNE", "GOTO", "JSR", "IFNULL", "IFNONNULL" - }; - /** - * Opcodes of LDC type. - */ - public static String[] OPS_LDC = new String[] { "LDC" }; - /** - * Opcodes of IINC type. - */ - public static String[] OPS_IINC = new String[] { "IINC" }; - /** - * Opcodes of TABLESWITCH type. - */ - public static String[] OPS_TABLESWITCH = new String[] { "TABLESWITCH" }; - /** - * Opcodes of LOOKUPSWITCH type. - */ - public static String[] OPS_LOOKUPSWITCH = new String[] { "LOOKUPSWITCH" }; - /** - * Opcodes of LOOKUPSWITCH type. - */ - public static String[] OPS_MULTIANEWARRAY = new String[] { "MULTIANEWARRAY" }; - /** - * Opcodes of FRAME type. - */ - public static String[] OPS_FRAME = new String[] { "F_NEW", "F_FULL", "F_APPEND", "F_CHOP", "F_SAME", "F_APPEND", "F_SAME1" }; - /** - * Empty list. - */ - public static String[] OPS_TAG = new String[] { "H_GETFIELD", "H_GETSTATIC", "H_PUTFIELD", "H_PUTSTATIC", "H_INVOKEINTERFACE", - "H_INVOKESPECIAL", "H_INVOKESTATIC", "H_INVOKEVIRTUAL", "H_NEWINVOKESPECIAL" - }; - /** - * Opcodes of LABEL type. Also see {@link #OPS_FRAME}[0]. - */ - public static String[] OPS_LABEL = new String[] { "F_NEW" }; - /** - * Opcodes of LABEL type. Also see {@link #OPS_FRAME}[0]. - */ - public static String[] OPS_LINE = new String[] { "F_NEW" }; - /** - * Empty list. - */ - public static String[] OPS_NONE = new String[] {}; + private static Map opcodeToName = new HashMap<>(); + private static Map nameToOpcode = new HashMap<>(); + private static Map frameToName = new HashMap<>(); + private static Map nameToFrame = new HashMap<>(); + private static Map tagToName = new HashMap<>(); + private static Map nameToTag = new HashMap<>(); + private static Map insnTypeToCodes = new HashMap<>(); + /** + * Opcodes of INSN type. + */ + public static String[] OPS_INSN = new String[] { "NOP", "ACONST_NULL", "ICONST_M1", "ICONST_0", "ICONST_1", "ICONST_2", + "ICONST_3", "ICONST_4", "ICONST_5", "LCONST_0", "LCONST_1", "FCONST_0", "FCONST_1", "FCONST_2", "DCONST_0", + "DCONST_1", "IALOAD", "LALOAD", "FALOAD", "DALOAD", "AALOAD", "BALOAD", "CALOAD", "SALOAD", "IASTORE", "LASTORE", + "FASTORE", "DASTORE", "AASTORE", "BASTORE", "CASTORE", "SASTORE", "POP", "POP2", "DUP", "DUP_X1", "DUP_X2", "DUP2", + "DUP2_X1", "DUP2_X2", "SWAP", "IADD", "LADD", "FADD", "DADD", "ISUB", "LSUB", "FSUB", "DSUB", "IMUL", "LMUL", "FMUL", + "DMUL", "IDIV", "LDIV", "FDIV", "DDIV", "IREM", "LREM", "FREM", "DREM", "INEG", "LNEG", "FNEG", "DNEG", "ISHL", + "LSHL", "ISHR", "LSHR", "IUSHR", "LUSHR", "IAND", "LAND", "IOR", "LOR", "IXOR", "LXOR", "I2L", "I2F", "I2D", "L2I", + "L2F", "L2D", "F2I", "F2L", "F2D", "D2I", "D2L", "D2F", "I2B", "I2C", "I2S", "LCMP", "FCMPL", "FCMPG", "DCMPL", + "DCMPG", "IRETURN", "LRETURN", "FRETURN", "DRETURN", "ARETURN", "RETURN", "ARRAYLENGTH", "ATHROW", "MONITORENTER", + "MONITOREXIT" + }; + /** + * Subset of {@link #OPS_INSN} for constants. + */ + public static String[] OPS_INSN_SUB_CONSTS = new String[] { "ACONST_NULL", "ICONST_M1", "ICONST_0", "ICONST_1", "ICONST_2", + "ICONST_3", "ICONST_4", "ICONST_5", "LCONST_0", "LCONST_1", "FCONST_0", "FCONST_1", "FCONST_2", "DCONST_0", + "DCONST_1" + }; + /** + * Subset of {@link #OPS_INSN} for array loads/saves/etc. + */ + public static String[] OPS_INSN_SUB_ARRAY = new String[] { "IALOAD", "LALOAD", "FALOAD", "DALOAD", "AALOAD", "BALOAD", + "CALOAD", "SALOAD", "IASTORE", "LASTORE", "FASTORE", "DASTORE", "AASTORE", "BASTORE", "CASTORE", "SASTORE", + "ARRAYLENGTH" + }; + /** + * Subset of {@link #OPS_INSN} for stack management. + */ + public static String[] OPS_INSN_SUB_STACK = new String[] { "POP", "POP2", "DUP", "DUP_X1", "DUP_X2", "DUP2", "DUP2_X1", + "DUP2_X2", "SWAP" + }; + /** + * Subset of {@link #OPS_INSN} for math handling. + */ + public static String[] OPS_INSN_SUB_MATH = new String[] { "IADD", "LADD", "FADD", "DADD", "ISUB", "LSUB", "FSUB", "DSUB", + "IMUL", "LMUL", "FMUL", "DMUL", "IDIV", "LDIV", "FDIV", "DDIV", "IREM", "LREM", "FREM", "DREM", "INEG", "LNEG", + "FNEG", "DNEG", "ISHL", "LSHL", "ISHR", "LSHR", "IUSHR", "LUSHR", "IAND", "LAND", "IOR", "LOR", "IXOR" + }; + /** + * Subset of {@link #OPS_INSN} for type conversion. + */ + public static String[] OPS_INSN_SUB_CONVERT = new String[] { "I2L", "I2F", "I2D", "L2I", "L2F", "L2D", "F2I", "F2L", "F2D", + "D2I", "D2L", "D2F", "I2B", "I2C", "I2S" + }; + /** + * Subset of {@link #OPS_INSN} for primitve comparisons. + */ + public static String[] OPS_INSN_SUB_COMPARE = new String[] { "LCMP", "FCMPL", "FCMPG", "DCMPL", "DCMPG" }; + /** + * Subset of {@link #OPS_INSN} for returns. + */ + public static String[] OPS_INSN_SUB_RETURN = new String[] { "IRETURN", "LRETURN", "FRETURN", "DRETURN", "ARETURN", "RETURN" }; + /** + * Subset of {@link #OPS_INSN} for monitors. + */ + public static String[] OPS_INSN_SUB_MONITOR = new String[] { "MONITORENTER", "MONITOREXIT" }; + /** + * Subset of {@link #OPS_INSN} for exceptions. + */ + public static String[] OPS_INSN_SUB_EXCEPTION = new String[] { "ATHROW" }; + /** + * Opcodes of INT type. + */ + public static String[] OPS_INT = new String[] { "BIPUSH", "SIPUSH", "NEWARRAY" }; + /** + * Opcodes of INT type. + */ + public static String[] OPS_VAR = new String[] { "ILOAD", "LLOAD", "FLOAD", "DLOAD", "ALOAD", "ISTORE", "LSTORE", "FSTORE", + "DSTORE", "ASTORE", "RET" + }; + /** + * Opcodes of TYPE type. + */ + public static String[] OPS_TYPE = new String[] { "NEW", "ANEWARRAY", "CHECKCAST", "INSTANCEOF" }; + /** + * Opcodes of FIELD type. + */ + public static String[] OPS_FIELD = new String[] { "GETSTATIC", "PUTSTATIC", "GETFIELD", "PUTFIELD" }; + /** + * Opcodes of METHOD type. + */ + public static String[] OPS_METHOD = new String[] { "INVOKEVIRTUAL", "INVOKESPECIAL", "INVOKESTATIC", "INVOKEINTERFACE" }; + /** + * Opcodes of INDY_METHOD type. + */ + public static String[] OPS_INDY_METHOD = new String[] { "INVOKEDYNAMIC" }; + /** + * Opcodes of JUMP type. + */ + public static String[] OPS_JUMP = new String[] { "IFEQ", "IFNE", "IFLT", "IFGE", "IFGT", "IFLE", "IF_ICMPEQ", "IF_ICMPNE", + "IF_ICMPLT", "IF_ICMPGE", "IF_ICMPGT", "IF_ICMPLE", "IF_ACMPEQ", "IF_ACMPNE", "GOTO", "JSR", "IFNULL", "IFNONNULL" + }; + /** + * Opcodes of LDC type. + */ + public static String[] OPS_LDC = new String[] { "LDC" }; + /** + * Opcodes of IINC type. + */ + public static String[] OPS_IINC = new String[] { "IINC" }; + /** + * Opcodes of TABLESWITCH type. + */ + public static String[] OPS_TABLESWITCH = new String[] { "TABLESWITCH" }; + /** + * Opcodes of LOOKUPSWITCH type. + */ + public static String[] OPS_LOOKUPSWITCH = new String[] { "LOOKUPSWITCH" }; + /** + * Opcodes of LOOKUPSWITCH type. + */ + public static String[] OPS_MULTIANEWARRAY = new String[] { "MULTIANEWARRAY" }; + /** + * Opcodes of FRAME type. + */ + public static String[] OPS_FRAME = new String[] { "F_NEW", "F_FULL", "F_APPEND", "F_CHOP", "F_SAME", "F_APPEND", "F_SAME1" }; + /** + * Empty list. + */ + public static String[] OPS_TAG = new String[] { "H_GETFIELD", "H_GETSTATIC", "H_PUTFIELD", "H_PUTSTATIC", "H_INVOKEINTERFACE", + "H_INVOKESPECIAL", "H_INVOKESTATIC", "H_INVOKEVIRTUAL", "H_NEWINVOKESPECIAL" + }; + /** + * Opcodes of LABEL type. Also see {@link #OPS_FRAME}[0]. + */ + public static String[] OPS_LABEL = new String[] { "F_NEW" }; + /** + * Opcodes of LABEL type. Also see {@link #OPS_FRAME}[0]. + */ + public static String[] OPS_LINE = new String[] { "F_NEW" }; + /** + * Empty list. + */ + public static String[] OPS_NONE = new String[] {}; - public static int nameToOpcode(String name) { - return nameToOpcode.get(name); - } + public static int nameToOpcode(String name) { + return nameToOpcode.get(name); + } - public static String opcodeToName(int op) { - return opcodeToName.get(op); - } + public static String opcodeToName(int op) { + return opcodeToName.get(op); + } - public static int nameToFrame(String name) { - return nameToFrame.get(name); - } + public static int nameToFrame(String name) { + return nameToFrame.get(name); + } - public static String frameToName(int op) { - return frameToName.get(op); - } + public static String frameToName(int op) { + return frameToName.get(op); + } - public static int nameToTag(String tag) { - return nameToTag.get(tag); - } + public static int nameToTag(String tag) { + return nameToTag.get(tag); + } - public static String tagToName(int tag) { - return tagToName.get(tag); - } + public static String tagToName(int tag) { + return tagToName.get(tag); + } - public static String[] typeToCodes(int type) { - return insnTypeToCodes.get(type); - } + public static String[] typeToCodes(int type) { + return insnTypeToCodes.get(type); + } - /** - * Return smaller subset of the {@link #OPS_INSN} string array. - * - * @param name The name of the target array. - * @return The desired subset. - * - * TODO: I have no idea what this is, just filling in some stubs - * so JavaDoc is happy. - * - * - Charles - */ - public static String[] getInsnSubset(String name) { - //@formatter:off - String[][] arrays = new String[][] { - OpcodeUtil.OPS_INSN_SUB_ARRAY, - OpcodeUtil.OPS_INSN_SUB_COMPARE, - OpcodeUtil.OPS_INSN_SUB_CONSTS, - OpcodeUtil.OPS_INSN_SUB_CONVERT, - OpcodeUtil.OPS_INSN_SUB_EXCEPTION, - OpcodeUtil.OPS_INSN_SUB_MATH, - OpcodeUtil.OPS_INSN_SUB_MONITOR, - OpcodeUtil.OPS_INSN_SUB_RETURN, - OpcodeUtil.OPS_INSN_SUB_STACK - }; - //@formatter:on - for (String[] array : arrays) { - if (contains(array, name)) { - return array; - } - } - // Just return an empty array - return OPS_NONE; - } + /** + * Return smaller subset of the {@link #OPS_INSN} string array. + * + * @param name The name of the target array. + * @return The desired subset. + * + * TODO: I have no idea what this is, just filling in some stubs + * so JavaDoc is happy. + * + * - Charles + */ + public static String[] getInsnSubset(String name) { + //@formatter:off + String[][] arrays = new String[][] { + OpcodeUtil.OPS_INSN_SUB_ARRAY, + OpcodeUtil.OPS_INSN_SUB_COMPARE, + OpcodeUtil.OPS_INSN_SUB_CONSTS, + OpcodeUtil.OPS_INSN_SUB_CONVERT, + OpcodeUtil.OPS_INSN_SUB_EXCEPTION, + OpcodeUtil.OPS_INSN_SUB_MATH, + OpcodeUtil.OPS_INSN_SUB_MONITOR, + OpcodeUtil.OPS_INSN_SUB_RETURN, + OpcodeUtil.OPS_INSN_SUB_STACK + }; + //@formatter:on + for (String[] array : arrays) { + if (contains(array, name)) { + return array; + } + } + // Just return an empty array + return OPS_NONE; + } - public static boolean contains(String[] array, String key) { - for (String value : array) { - if (value.equals(key)) { - return true; - } - } - return false; - } + public static boolean contains(String[] array, String key) { + for (String value : array) { + if (value.equals(key)) { + return true; + } + } + return false; + } - private static void put(int op, String text) { - nameToOpcode.put(text, op); - opcodeToName.put(op, text); - } + private static void put(int op, String text) { + nameToOpcode.put(text, op); + opcodeToName.put(op, text); + } - private static void putFrame(int op, String text) { - nameToFrame.put(text, op); - frameToName.put(op, text); - } + private static void putFrame(int op, String text) { + nameToFrame.put(text, op); + frameToName.put(op, text); + } - private static void putTag(int op, String text) { - nameToTag.put(text, op); - tagToName.put(op, text); - } + private static void putTag(int op, String text) { + nameToTag.put(text, op); + tagToName.put(op, text); + } - static { - put(F_NEW, "F_NEW"); - put(NOP, "NOP"); - put(ACONST_NULL, "ACONST_NULL"); - put(ICONST_M1, "ICONST_M1"); - put(ICONST_0, "ICONST_0"); - put(ICONST_1, "ICONST_1"); - put(ICONST_2, "ICONST_2"); - put(ICONST_3, "ICONST_3"); - put(ICONST_4, "ICONST_4"); - put(ICONST_5, "ICONST_5"); - put(LCONST_0, "LCONST_0"); - put(LCONST_1, "LCONST_1"); - put(FCONST_0, "FCONST_0"); - put(FCONST_1, "FCONST_1"); - put(FCONST_2, "FCONST_2"); - put(DCONST_0, "DCONST_0"); - put(DCONST_1, "DCONST_1"); - put(BIPUSH, "BIPUSH"); - put(SIPUSH, "SIPUSH"); - put(LDC, "LDC"); - put(ILOAD, "ILOAD"); - put(LLOAD, "LLOAD"); - put(FLOAD, "FLOAD"); - put(DLOAD, "DLOAD"); - put(ALOAD, "ALOAD"); - put(IALOAD, "IALOAD"); - put(LALOAD, "LALOAD"); - put(FALOAD, "FALOAD"); - put(DALOAD, "DALOAD"); - put(AALOAD, "AALOAD"); - put(BALOAD, "BALOAD"); - put(CALOAD, "CALOAD"); - put(SALOAD, "SALOAD"); - put(ISTORE, "ISTORE"); - put(LSTORE, "LSTORE"); - put(FSTORE, "FSTORE"); - put(DSTORE, "DSTORE"); - put(ASTORE, "ASTORE"); - put(IASTORE, "IASTORE"); - put(LASTORE, "LASTORE"); - put(FASTORE, "FASTORE"); - put(DASTORE, "DASTORE"); - put(AASTORE, "AASTORE"); - put(BASTORE, "BASTORE"); - put(CASTORE, "CASTORE"); - put(SASTORE, "SASTORE"); - put(POP, "POP"); - put(POP2, "POP2"); - put(DUP, "DUP"); - put(DUP_X1, "DUP_X1"); - put(DUP_X2, "DUP_X2"); - put(DUP2, "DUP2"); - put(DUP2_X1, "DUP2_X1"); - put(DUP2_X2, "DUP2_X2"); - put(SWAP, "SWAP"); - put(IADD, "IADD"); - put(LADD, "LADD"); - put(FADD, "FADD"); - put(DADD, "DADD"); - put(ISUB, "ISUB"); - put(LSUB, "LSUB"); - put(FSUB, "FSUB"); - put(DSUB, "DSUB"); - put(IMUL, "IMUL"); - put(LMUL, "LMUL"); - put(FMUL, "FMUL"); - put(DMUL, "DMUL"); - put(IDIV, "IDIV"); - put(LDIV, "LDIV"); - put(FDIV, "FDIV"); - put(DDIV, "DDIV"); - put(IREM, "IREM"); - put(LREM, "LREM"); - put(FREM, "FREM"); - put(DREM, "DREM"); - put(INEG, "INEG"); - put(LNEG, "LNEG"); - put(FNEG, "FNEG"); - put(DNEG, "DNEG"); - put(ISHL, "ISHL"); - put(LSHL, "LSHL"); - put(ISHR, "ISHR"); - put(LSHR, "LSHR"); - put(IUSHR, "IUSHR"); - put(LUSHR, "LUSHR"); - put(IAND, "IAND"); - put(LAND, "LAND"); - put(IOR, "IOR"); - put(LOR, "LOR"); - put(IXOR, "IXOR"); - put(LXOR, "LXOR"); - put(IINC, "IINC"); - put(I2L, "I2L"); - put(I2F, "I2F"); - put(I2D, "I2D"); - put(L2I, "L2I"); - put(L2F, "L2F"); - put(L2D, "L2D"); - put(F2I, "F2I"); - put(F2L, "F2L"); - put(F2D, "F2D"); - put(D2I, "D2I"); - put(D2L, "D2L"); - put(D2F, "D2F"); - put(I2B, "I2B"); - put(I2C, "I2C"); - put(I2S, "I2S"); - put(LCMP, "LCMP"); - put(FCMPL, "FCMPL"); - put(FCMPG, "FCMPG"); - put(DCMPL, "DCMPL"); - put(DCMPG, "DCMPG"); - put(IFEQ, "IFEQ"); - put(IFNE, "IFNE"); - put(IFLT, "IFLT"); - put(IFGE, "IFGE"); - put(IFGT, "IFGT"); - put(IFLE, "IFLE"); - put(IF_ICMPEQ, "IF_ICMPEQ"); - put(IF_ICMPNE, "IF_ICMPNE"); - put(IF_ICMPLT, "IF_ICMPLT"); - put(IF_ICMPGE, "IF_ICMPGE"); - put(IF_ICMPGT, "IF_ICMPGT"); - put(IF_ICMPLE, "IF_ICMPLE"); - put(IF_ACMPEQ, "IF_ACMPEQ"); - put(IF_ACMPNE, "IF_ACMPNE"); - put(GOTO, "GOTO"); - put(JSR, "JSR"); - put(RET, "RET"); - put(TABLESWITCH, "TABLESWITCH"); - put(LOOKUPSWITCH, "LOOKUPSWITCH"); - put(IRETURN, "IRETURN"); - put(LRETURN, "LRETURN"); - put(FRETURN, "FRETURN"); - put(DRETURN, "DRETURN"); - put(ARETURN, "ARETURN"); - put(RETURN, "RETURN"); - put(GETSTATIC, "GETSTATIC"); - put(PUTSTATIC, "PUTSTATIC"); - put(GETFIELD, "GETFIELD"); - put(PUTFIELD, "PUTFIELD"); - put(INVOKEVIRTUAL, "INVOKEVIRTUAL"); - put(INVOKESPECIAL, "INVOKESPECIAL"); - put(INVOKESTATIC, "INVOKESTATIC"); - put(INVOKEINTERFACE, "INVOKEINTERFACE"); - put(INVOKEDYNAMIC, "INVOKEDYNAMIC"); - put(NEW, "NEW"); - put(NEWARRAY, "NEWARRAY"); - put(ANEWARRAY, "ANEWARRAY"); - put(ARRAYLENGTH, "ARRAYLENGTH"); - put(ATHROW, "ATHROW"); - put(CHECKCAST, "CHECKCAST"); - put(INSTANCEOF, "INSTANCEOF"); - put(MONITORENTER, "MONITORENTER"); - put(MONITOREXIT, "MONITOREXIT"); - put(MULTIANEWARRAY, "MULTIANEWARRAY"); - put(IFNULL, "IFNULL"); - put(IFNONNULL, "IFNONNULL"); - putFrame(F_NEW, "F_NEW"); - putFrame(F_FULL, "F_FULL"); - putFrame(F_APPEND, "F_APPEND"); - putFrame(F_CHOP, "F_CHOP"); - putFrame(F_SAME, "F_SAME"); - putFrame(F_APPEND, "F_APPEND"); - putFrame(F_SAME1, "F_SAME1"); - putTag(Opcodes.H_GETFIELD, "H_GETFIELD"); - putTag(Opcodes.H_GETSTATIC, "H_GETSTATIC"); - putTag(Opcodes.H_PUTFIELD, "H_PUTFIELD"); - putTag(Opcodes.H_PUTSTATIC, "H_PUTSTATIC"); - putTag(Opcodes.H_INVOKEINTERFACE, "H_INVOKEINTERFACE"); - putTag(Opcodes.H_INVOKESPECIAL, "H_INVOKESPECIAL"); - putTag(Opcodes.H_INVOKESTATIC, "H_INVOKESTATIC"); - putTag(Opcodes.H_INVOKEVIRTUAL, "H_INVOKEVIRTUAL"); - putTag(Opcodes.H_NEWINVOKESPECIAL, "H_NEWINVOKESPECIAL"); - insnTypeToCodes.put(AbstractInsnNode.FIELD_INSN, OpcodeUtil.OPS_FIELD); - insnTypeToCodes.put(AbstractInsnNode.FRAME, OpcodeUtil.OPS_FRAME); - insnTypeToCodes.put(AbstractInsnNode.IINC_INSN, OpcodeUtil.OPS_IINC); - insnTypeToCodes.put(AbstractInsnNode.INSN, OpcodeUtil.OPS_INSN); - insnTypeToCodes.put(AbstractInsnNode.INT_INSN, OpcodeUtil.OPS_INT); - insnTypeToCodes.put(AbstractInsnNode.INVOKE_DYNAMIC_INSN, OpcodeUtil.OPS_INDY_METHOD); - insnTypeToCodes.put(AbstractInsnNode.JUMP_INSN, OpcodeUtil.OPS_JUMP); - insnTypeToCodes.put(AbstractInsnNode.LABEL, OpcodeUtil.OPS_LABEL); - insnTypeToCodes.put(AbstractInsnNode.LDC_INSN, OpcodeUtil.OPS_LDC); - insnTypeToCodes.put(AbstractInsnNode.LINE, OpcodeUtil.OPS_LINE); - insnTypeToCodes.put(AbstractInsnNode.LOOKUPSWITCH_INSN, OpcodeUtil.OPS_LOOKUPSWITCH); - insnTypeToCodes.put(AbstractInsnNode.METHOD_INSN, OpcodeUtil.OPS_METHOD); - insnTypeToCodes.put(AbstractInsnNode.MULTIANEWARRAY_INSN, OpcodeUtil.OPS_MULTIANEWARRAY); - insnTypeToCodes.put(AbstractInsnNode.TABLESWITCH_INSN, OpcodeUtil.OPS_TABLESWITCH); - insnTypeToCodes.put(AbstractInsnNode.TYPE_INSN, OpcodeUtil.OPS_TYPE); - insnTypeToCodes.put(AbstractInsnNode.VAR_INSN, OpcodeUtil.OPS_VAR); - } + static { + put(F_NEW, "F_NEW"); + put(NOP, "NOP"); + put(ACONST_NULL, "ACONST_NULL"); + put(ICONST_M1, "ICONST_M1"); + put(ICONST_0, "ICONST_0"); + put(ICONST_1, "ICONST_1"); + put(ICONST_2, "ICONST_2"); + put(ICONST_3, "ICONST_3"); + put(ICONST_4, "ICONST_4"); + put(ICONST_5, "ICONST_5"); + put(LCONST_0, "LCONST_0"); + put(LCONST_1, "LCONST_1"); + put(FCONST_0, "FCONST_0"); + put(FCONST_1, "FCONST_1"); + put(FCONST_2, "FCONST_2"); + put(DCONST_0, "DCONST_0"); + put(DCONST_1, "DCONST_1"); + put(BIPUSH, "BIPUSH"); + put(SIPUSH, "SIPUSH"); + put(LDC, "LDC"); + put(ILOAD, "ILOAD"); + put(LLOAD, "LLOAD"); + put(FLOAD, "FLOAD"); + put(DLOAD, "DLOAD"); + put(ALOAD, "ALOAD"); + put(IALOAD, "IALOAD"); + put(LALOAD, "LALOAD"); + put(FALOAD, "FALOAD"); + put(DALOAD, "DALOAD"); + put(AALOAD, "AALOAD"); + put(BALOAD, "BALOAD"); + put(CALOAD, "CALOAD"); + put(SALOAD, "SALOAD"); + put(ISTORE, "ISTORE"); + put(LSTORE, "LSTORE"); + put(FSTORE, "FSTORE"); + put(DSTORE, "DSTORE"); + put(ASTORE, "ASTORE"); + put(IASTORE, "IASTORE"); + put(LASTORE, "LASTORE"); + put(FASTORE, "FASTORE"); + put(DASTORE, "DASTORE"); + put(AASTORE, "AASTORE"); + put(BASTORE, "BASTORE"); + put(CASTORE, "CASTORE"); + put(SASTORE, "SASTORE"); + put(POP, "POP"); + put(POP2, "POP2"); + put(DUP, "DUP"); + put(DUP_X1, "DUP_X1"); + put(DUP_X2, "DUP_X2"); + put(DUP2, "DUP2"); + put(DUP2_X1, "DUP2_X1"); + put(DUP2_X2, "DUP2_X2"); + put(SWAP, "SWAP"); + put(IADD, "IADD"); + put(LADD, "LADD"); + put(FADD, "FADD"); + put(DADD, "DADD"); + put(ISUB, "ISUB"); + put(LSUB, "LSUB"); + put(FSUB, "FSUB"); + put(DSUB, "DSUB"); + put(IMUL, "IMUL"); + put(LMUL, "LMUL"); + put(FMUL, "FMUL"); + put(DMUL, "DMUL"); + put(IDIV, "IDIV"); + put(LDIV, "LDIV"); + put(FDIV, "FDIV"); + put(DDIV, "DDIV"); + put(IREM, "IREM"); + put(LREM, "LREM"); + put(FREM, "FREM"); + put(DREM, "DREM"); + put(INEG, "INEG"); + put(LNEG, "LNEG"); + put(FNEG, "FNEG"); + put(DNEG, "DNEG"); + put(ISHL, "ISHL"); + put(LSHL, "LSHL"); + put(ISHR, "ISHR"); + put(LSHR, "LSHR"); + put(IUSHR, "IUSHR"); + put(LUSHR, "LUSHR"); + put(IAND, "IAND"); + put(LAND, "LAND"); + put(IOR, "IOR"); + put(LOR, "LOR"); + put(IXOR, "IXOR"); + put(LXOR, "LXOR"); + put(IINC, "IINC"); + put(I2L, "I2L"); + put(I2F, "I2F"); + put(I2D, "I2D"); + put(L2I, "L2I"); + put(L2F, "L2F"); + put(L2D, "L2D"); + put(F2I, "F2I"); + put(F2L, "F2L"); + put(F2D, "F2D"); + put(D2I, "D2I"); + put(D2L, "D2L"); + put(D2F, "D2F"); + put(I2B, "I2B"); + put(I2C, "I2C"); + put(I2S, "I2S"); + put(LCMP, "LCMP"); + put(FCMPL, "FCMPL"); + put(FCMPG, "FCMPG"); + put(DCMPL, "DCMPL"); + put(DCMPG, "DCMPG"); + put(IFEQ, "IFEQ"); + put(IFNE, "IFNE"); + put(IFLT, "IFLT"); + put(IFGE, "IFGE"); + put(IFGT, "IFGT"); + put(IFLE, "IFLE"); + put(IF_ICMPEQ, "IF_ICMPEQ"); + put(IF_ICMPNE, "IF_ICMPNE"); + put(IF_ICMPLT, "IF_ICMPLT"); + put(IF_ICMPGE, "IF_ICMPGE"); + put(IF_ICMPGT, "IF_ICMPGT"); + put(IF_ICMPLE, "IF_ICMPLE"); + put(IF_ACMPEQ, "IF_ACMPEQ"); + put(IF_ACMPNE, "IF_ACMPNE"); + put(GOTO, "GOTO"); + put(JSR, "JSR"); + put(RET, "RET"); + put(TABLESWITCH, "TABLESWITCH"); + put(LOOKUPSWITCH, "LOOKUPSWITCH"); + put(IRETURN, "IRETURN"); + put(LRETURN, "LRETURN"); + put(FRETURN, "FRETURN"); + put(DRETURN, "DRETURN"); + put(ARETURN, "ARETURN"); + put(RETURN, "RETURN"); + put(GETSTATIC, "GETSTATIC"); + put(PUTSTATIC, "PUTSTATIC"); + put(GETFIELD, "GETFIELD"); + put(PUTFIELD, "PUTFIELD"); + put(INVOKEVIRTUAL, "INVOKEVIRTUAL"); + put(INVOKESPECIAL, "INVOKESPECIAL"); + put(INVOKESTATIC, "INVOKESTATIC"); + put(INVOKEINTERFACE, "INVOKEINTERFACE"); + put(INVOKEDYNAMIC, "INVOKEDYNAMIC"); + put(NEW, "NEW"); + put(NEWARRAY, "NEWARRAY"); + put(ANEWARRAY, "ANEWARRAY"); + put(ARRAYLENGTH, "ARRAYLENGTH"); + put(ATHROW, "ATHROW"); + put(CHECKCAST, "CHECKCAST"); + put(INSTANCEOF, "INSTANCEOF"); + put(MONITORENTER, "MONITORENTER"); + put(MONITOREXIT, "MONITOREXIT"); + put(MULTIANEWARRAY, "MULTIANEWARRAY"); + put(IFNULL, "IFNULL"); + put(IFNONNULL, "IFNONNULL"); + putFrame(F_NEW, "F_NEW"); + putFrame(F_FULL, "F_FULL"); + putFrame(F_APPEND, "F_APPEND"); + putFrame(F_CHOP, "F_CHOP"); + putFrame(F_SAME, "F_SAME"); + putFrame(F_APPEND, "F_APPEND"); + putFrame(F_SAME1, "F_SAME1"); + putTag(Opcodes.H_GETFIELD, "H_GETFIELD"); + putTag(Opcodes.H_GETSTATIC, "H_GETSTATIC"); + putTag(Opcodes.H_PUTFIELD, "H_PUTFIELD"); + putTag(Opcodes.H_PUTSTATIC, "H_PUTSTATIC"); + putTag(Opcodes.H_INVOKEINTERFACE, "H_INVOKEINTERFACE"); + putTag(Opcodes.H_INVOKESPECIAL, "H_INVOKESPECIAL"); + putTag(Opcodes.H_INVOKESTATIC, "H_INVOKESTATIC"); + putTag(Opcodes.H_INVOKEVIRTUAL, "H_INVOKEVIRTUAL"); + putTag(Opcodes.H_NEWINVOKESPECIAL, "H_NEWINVOKESPECIAL"); + insnTypeToCodes.put(AbstractInsnNode.FIELD_INSN, OpcodeUtil.OPS_FIELD); + insnTypeToCodes.put(AbstractInsnNode.FRAME, OpcodeUtil.OPS_FRAME); + insnTypeToCodes.put(AbstractInsnNode.IINC_INSN, OpcodeUtil.OPS_IINC); + insnTypeToCodes.put(AbstractInsnNode.INSN, OpcodeUtil.OPS_INSN); + insnTypeToCodes.put(AbstractInsnNode.INT_INSN, OpcodeUtil.OPS_INT); + insnTypeToCodes.put(AbstractInsnNode.INVOKE_DYNAMIC_INSN, OpcodeUtil.OPS_INDY_METHOD); + insnTypeToCodes.put(AbstractInsnNode.JUMP_INSN, OpcodeUtil.OPS_JUMP); + insnTypeToCodes.put(AbstractInsnNode.LABEL, OpcodeUtil.OPS_LABEL); + insnTypeToCodes.put(AbstractInsnNode.LDC_INSN, OpcodeUtil.OPS_LDC); + insnTypeToCodes.put(AbstractInsnNode.LINE, OpcodeUtil.OPS_LINE); + insnTypeToCodes.put(AbstractInsnNode.LOOKUPSWITCH_INSN, OpcodeUtil.OPS_LOOKUPSWITCH); + insnTypeToCodes.put(AbstractInsnNode.METHOD_INSN, OpcodeUtil.OPS_METHOD); + insnTypeToCodes.put(AbstractInsnNode.MULTIANEWARRAY_INSN, OpcodeUtil.OPS_MULTIANEWARRAY); + insnTypeToCodes.put(AbstractInsnNode.TABLESWITCH_INSN, OpcodeUtil.OPS_TABLESWITCH); + insnTypeToCodes.put(AbstractInsnNode.TYPE_INSN, OpcodeUtil.OPS_TYPE); + insnTypeToCodes.put(AbstractInsnNode.VAR_INSN, OpcodeUtil.OPS_VAR); + } } diff --git a/src/me/coley/recaf/asm/PluginClassReader.java b/src/me/coley/recaf/asm/PluginClassReader.java index e1f871192..7bce581e4 100644 --- a/src/me/coley/recaf/asm/PluginClassReader.java +++ b/src/me/coley/recaf/asm/PluginClassReader.java @@ -13,8 +13,8 @@ */ public class PluginClassReader extends ClassReader { - public PluginClassReader(InputStream is) throws IOException { - super(is); - } + public PluginClassReader(InputStream is) throws IOException { + super(is); + } } diff --git a/src/me/coley/recaf/cfr/CFRResourceLookup.java b/src/me/coley/recaf/cfr/CFRResourceLookup.java index 515d4fd4b..126499d8f 100644 --- a/src/me/coley/recaf/cfr/CFRResourceLookup.java +++ b/src/me/coley/recaf/cfr/CFRResourceLookup.java @@ -11,38 +11,38 @@ * inner classes and such. */ public class CFRResourceLookup { - private final Recaf program; - private final ClassNode override; - - public CFRResourceLookup(Recaf program) { - this(program, null); - } - - public CFRResourceLookup(Recaf program, ClassNode override) { - this.program = program; - this.override = override; - } - - public byte[] get(String path) { - byte[] bytes = null; - try { - if (override != null && path.equals(override.name)) { - bytes = program.asm.toBytes(override); - } else { - Map classes = program.jarData.classes; - if (classes.containsKey(path)) { - bytes = program.asm.toBytes(classes.get(path)); - } else { - ClassNode runtime = program.asm.getNode(Class.forName(path.replace("/", "."))); - if (runtime != null) { - bytes = program.asm.toBytes(runtime); - } - } - } - } catch (Exception e) { - program.window.displayError(e); - } - return bytes; - } + private final Recaf program; + private final ClassNode override; + + public CFRResourceLookup(Recaf program) { + this(program, null); + } + + public CFRResourceLookup(Recaf program, ClassNode override) { + this.program = program; + this.override = override; + } + + public byte[] get(String path) { + byte[] bytes = null; + try { + if (override != null && path.equals(override.name)) { + bytes = program.asm.toBytes(override); + } else { + Map classes = program.jarData.classes; + if (classes.containsKey(path)) { + bytes = program.asm.toBytes(classes.get(path)); + } else { + ClassNode runtime = program.asm.getNode(Class.forName(path.replace("/", "."))); + if (runtime != null) { + bytes = program.asm.toBytes(runtime); + } + } + } + } catch (Exception e) { + program.window.displayError(e); + } + return bytes; + } } diff --git a/src/me/coley/recaf/cfr/CFRSetting.java b/src/me/coley/recaf/cfr/CFRSetting.java index 0148ca18f..0c819e84c 100644 --- a/src/me/coley/recaf/cfr/CFRSetting.java +++ b/src/me/coley/recaf/cfr/CFRSetting.java @@ -10,94 +10,94 @@ * */ public enum CFRSetting { - //@formatter:off - DECODE_ENUM_SWITCH("decodeenumswitch", "Decode Enum Switch", true), - SUGAR_ENUMS("sugarenums", "SugarEnums", true), - DECODE_STRING_SWITCH("decodestringswitch", "Decode String Switch", true), - ARRAYITER("arrayiter", "Arrayiter", true), - COLLECTIONITER("collectioniter", "Collectioniter", true), - INNER_CLASSES("innerclasses", "Inner Classes", false), - REMOVE_BOILER_PLATE("removeboilerplate", "Remove Boiler Plate", true), - REMOVE_INNER_CLASS_SYNTHETICS("removeinnerclasssynthetics", "Remove Inner Class Synthetics", true), - DECODE_LAMBDAS("decodelambdas", "Decode Lambdas", true), - HIDE_BRIDGE_METHODS("hidebridgemethods", "Hide Bridge Methods", false), - LIFT_CONSTRUCTOR_INIT("liftconstructorinit", "Lift Constructor Init", true), - REMOVE_DEAD_METHODS("removedeadmethods", "Remove Dead Methods", false), - REMOVE_BAD_GENERICS("removebadgenerics", "Remove Bad Generics", true), - SUGAR_ASSERTS("sugarasserts", "Sugar Asserts", true), - SUGAR_BOXING("sugarboxing", "Sugar Boxing", true), - SHOW_VERSION("showversion", "Show Version"), - DECODE_FINALLY("decodefinally", "Decode Finally", true), - TIDY_MONITORS("tidymonitors", "Tidy Monitors", true), - LENIENT("lenient", "Lenient", true), - DUMP_CLASS_PATH("dumpclasspath", "Dump Classpath"), - COMMENTS("comments", "Comments"), - FORCE_TOP_SORT("forcetopsort", "Force Top Sort", true), - FORCE_TOP_SORT_AGGRESSIVE("forcetopsortaggress", "Force Top Sort Aggressive", true), - STRINGBUFFER("stringbuffer", "StringBuffer"), - STRINGBUILDER("stringbuilder", "StringBuilder", true), - SILENT("silent", "Silent", true), - RECOVER("recover", "Recover", true), - ECLIPSE("eclipse", "Eclipse", true), - OVERRIDE("override", "Override", true), - SHOW_INFERRABLE("showinferrable", "Show Inferrable", false), - FORCE_AGGRESSIVE_EXCEPTION_AGG("aexagg", "Force Aggressive Exception Aggregation", true), - FORCE_COND_PROPAGATE("forcecondpropagate", "Force Conditional Propogation", true), - HIDE_UTF("hideutf", "Hide UTF", true), - HIDE_LONG_STRINGS("hidelongstrings", "Hide Long Strings"), - COMMENT_MONITORS("commentmonitors", "Comment Monitors"), - ALLOW_CORRECTING("allowcorrecting", "Allow Correcting", true), - LABELLED_BLOCKS("labelledblocks", "Labelled Blocks", true), - J14_CLASS_OBJ("j14classobj", "Java 1.4 Class Objects"), - HIDE_LANG_IMPORTS("hidelangimports", "Hide Lang Imports", true), - RECOVER_TYPE_CLASH("recovertypeclash", "Recover Type Clash", true), - RECOVER_TYPE_HINTS("recovertypehints", "Recover Type Hints", true), - FORCE_RETURNING_IFS("forcereturningifs", "Force Returning Ifs", true), - FOR_LOOP_AGG_CAPTURE("forloopaggcapture", "For Loop Aggressive Capture", true), - RENAME_ILLEGAL_IDENTIFIERS("renameillegalidents", "Rename illegal identifiers", false), - RENAME_DUPE_MEMBERS("renamedupmembers", "Rename duplicated member names", false); - //@formatter:on + //@formatter:off + DECODE_ENUM_SWITCH("decodeenumswitch", "Decode Enum Switch", true), + SUGAR_ENUMS("sugarenums", "SugarEnums", true), + DECODE_STRING_SWITCH("decodestringswitch", "Decode String Switch", true), + ARRAYITER("arrayiter", "Arrayiter", true), + COLLECTIONITER("collectioniter", "Collectioniter", true), + INNER_CLASSES("innerclasses", "Inner Classes", false), + REMOVE_BOILER_PLATE("removeboilerplate", "Remove Boiler Plate", true), + REMOVE_INNER_CLASS_SYNTHETICS("removeinnerclasssynthetics", "Remove Inner Class Synthetics", true), + DECODE_LAMBDAS("decodelambdas", "Decode Lambdas", true), + HIDE_BRIDGE_METHODS("hidebridgemethods", "Hide Bridge Methods", false), + LIFT_CONSTRUCTOR_INIT("liftconstructorinit", "Lift Constructor Init", true), + REMOVE_DEAD_METHODS("removedeadmethods", "Remove Dead Methods", false), + REMOVE_BAD_GENERICS("removebadgenerics", "Remove Bad Generics", true), + SUGAR_ASSERTS("sugarasserts", "Sugar Asserts", true), + SUGAR_BOXING("sugarboxing", "Sugar Boxing", true), + SHOW_VERSION("showversion", "Show Version"), + DECODE_FINALLY("decodefinally", "Decode Finally", true), + TIDY_MONITORS("tidymonitors", "Tidy Monitors", true), + LENIENT("lenient", "Lenient", true), + DUMP_CLASS_PATH("dumpclasspath", "Dump Classpath"), + COMMENTS("comments", "Comments"), + FORCE_TOP_SORT("forcetopsort", "Force Top Sort", true), + FORCE_TOP_SORT_AGGRESSIVE("forcetopsortaggress", "Force Top Sort Aggressive", true), + STRINGBUFFER("stringbuffer", "StringBuffer"), + STRINGBUILDER("stringbuilder", "StringBuilder", true), + SILENT("silent", "Silent", true), + RECOVER("recover", "Recover", true), + ECLIPSE("eclipse", "Eclipse", true), + OVERRIDE("override", "Override", true), + SHOW_INFERRABLE("showinferrable", "Show Inferrable", false), + FORCE_AGGRESSIVE_EXCEPTION_AGG("aexagg", "Force Aggressive Exception Aggregation", true), + FORCE_COND_PROPAGATE("forcecondpropagate", "Force Conditional Propogation", true), + HIDE_UTF("hideutf", "Hide UTF", true), + HIDE_LONG_STRINGS("hidelongstrings", "Hide Long Strings"), + COMMENT_MONITORS("commentmonitors", "Comment Monitors"), + ALLOW_CORRECTING("allowcorrecting", "Allow Correcting", true), + LABELLED_BLOCKS("labelledblocks", "Labelled Blocks", true), + J14_CLASS_OBJ("j14classobj", "Java 1.4 Class Objects"), + HIDE_LANG_IMPORTS("hidelangimports", "Hide Lang Imports", true), + RECOVER_TYPE_CLASH("recovertypeclash", "Recover Type Clash", true), + RECOVER_TYPE_HINTS("recovertypehints", "Recover Type Hints", true), + FORCE_RETURNING_IFS("forcereturningifs", "Force Returning Ifs", true), + FOR_LOOP_AGG_CAPTURE("forloopaggcapture", "For Loop Aggressive Capture", true), + RENAME_ILLEGAL_IDENTIFIERS("renameillegalidents", "Rename illegal identifiers", false), + RENAME_DUPE_MEMBERS("renamedupmembers", "Rename duplicated member names", false); + //@formatter:on - private final String name; - private final String param; - private boolean on; + private final String name; + private final String param; + private boolean on; - CFRSetting(String param, String name) { - this(param, name, false); - } + CFRSetting(String param, String name) { + this(param, name, false); + } - CFRSetting(String param, String name, boolean on) { - this.name = name; - this.param = param; - this.on = on; - } + CFRSetting(String param, String name, boolean on) { + this.name = name; + this.param = param; + this.on = on; + } - public String getParam() { - return param; - } + public String getParam() { + return param; + } - public String getText() { - return name; - } + public String getText() { + return name; + } - public boolean isEnabled() { - return on; - } + public boolean isEnabled() { + return on; + } - public void setEnabled(boolean enabled) { - this.on = enabled; - } + public void setEnabled(boolean enabled) { + this.on = enabled; + } - /** Obtain repreesntation of the CFR settings as a string map. - * - * @return <String, String(of boolean)> map of the settings and their - * current status. - */ - public static Map toStringMap() { - Map options = new HashMap<>(); - for (CFRSetting setting : CFRSetting.values()) { - options.put(setting.getParam(), String.valueOf(setting.isEnabled())); - } - return options; - } + /** Obtain repreesntation of the CFR settings as a string map. + * + * @return <String, String(of boolean)> map of the settings and their + * current status. + */ + public static Map toStringMap() { + Map options = new HashMap<>(); + for (CFRSetting setting : CFRSetting.values()) { + options.put(setting.getParam(), String.valueOf(setting.isEnabled())); + } + return options; + } } diff --git a/src/me/coley/recaf/cfr/CFRSourceImpl.java b/src/me/coley/recaf/cfr/CFRSourceImpl.java index 8bd2f5a57..dc2a79c0b 100644 --- a/src/me/coley/recaf/cfr/CFRSourceImpl.java +++ b/src/me/coley/recaf/cfr/CFRSourceImpl.java @@ -6,31 +6,31 @@ import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; public class CFRSourceImpl implements ClassFileSource { - /** - * Lookup assistor for inner classes and other references. - */ - private final CFRResourceLookup resources; + /** + * Lookup assistor for inner classes and other references. + */ + private final CFRResourceLookup resources; - public CFRSourceImpl(CFRResourceLookup resources) { - this.resources = resources; - } + public CFRSourceImpl(CFRResourceLookup resources) { + this.resources = resources; + } - @Override - public void informAnalysisRelativePathDetail(String s, String s1) {} + @Override + public void informAnalysisRelativePathDetail(String s, String s1) {} - @Override - public Collection addJar(String s) { - throw new UnsupportedOperationException("Return paths of all classfiles in jar."); - } + @Override + public Collection addJar(String s) { + throw new UnsupportedOperationException("Return paths of all classfiles in jar."); + } - @Override - public String getPossiblyRenamedPath(String s) { - return s; - } + @Override + public String getPossiblyRenamedPath(String s) { + return s; + } - @Override - public Pair getClassFileContent(String pathOrName) throws IOException { - pathOrName = pathOrName.substring(0, pathOrName.length() - ".class".length()); - return Pair.make(resources.get(pathOrName), pathOrName); - } + @Override + public Pair getClassFileContent(String pathOrName) throws IOException { + pathOrName = pathOrName.substring(0, pathOrName.length() - ".class".length()); + return Pair.make(resources.get(pathOrName), pathOrName); + } } diff --git a/src/me/coley/recaf/ui/FileChoosers.java b/src/me/coley/recaf/ui/FileChoosers.java index 748914f45..54f82ea77 100644 --- a/src/me/coley/recaf/ui/FileChoosers.java +++ b/src/me/coley/recaf/ui/FileChoosers.java @@ -6,52 +6,52 @@ import javax.swing.filechooser.FileNameExtensionFilter; public class FileChoosers { - private JFileChooser fileChooser; + private JFileChooser fileChooser; - /** - * @return The file chooser. If it is null it is instantiated and set to the - * working directory with a filter for jar files. - */ - public JFileChooser getFileChooser() { - return getFileChooser("Java Archives", "jar"); - } + /** + * @return The file chooser. If it is null it is instantiated and set to the + * working directory with a filter for jar files. + */ + public JFileChooser getFileChooser() { + return getFileChooser("Java Archives", "jar"); + } - /** - * @return The file chooser. If it is null it is instantiated and set to the - * working directory with a filter for the given file type. To allow any - * type, have the parameters be null. - * - * @param fileType Name of the type of file - * @param extension Actual file extension. - */ - public JFileChooser getFileChooser(String fileType, String extension) { - if (fileChooser == null) { - fileChooser = new JFileChooser(); - String dir = System.getProperty("user.dir"); - File fileDir = new File(dir); - fileChooser.setDialogTitle("Open File"); - fileChooser.setCurrentDirectory(fileDir); - } - if (fileType == null || extension == null) { - fileChooser.setFileFilter(null); - } else { - FileNameExtensionFilter filter = new FileNameExtensionFilter(fileType, extension); - fileChooser.setFileFilter(filter); - } - return fileChooser; - } + /** + * @return The file chooser. If it is null it is instantiated and set to the + * working directory with a filter for the given file type. To allow any + * type, have the parameters be null. + * + * @param fileType Name of the type of file + * @param extension Actual file extension. + */ + public JFileChooser getFileChooser(String fileType, String extension) { + if (fileChooser == null) { + fileChooser = new JFileChooser(); + String dir = System.getProperty("user.dir"); + File fileDir = new File(dir); + fileChooser.setDialogTitle("Open File"); + fileChooser.setCurrentDirectory(fileDir); + } + if (fileType == null || extension == null) { + fileChooser.setFileFilter(null); + } else { + FileNameExtensionFilter filter = new FileNameExtensionFilter(fileType, extension); + fileChooser.setFileFilter(filter); + } + return fileChooser; + } - /** - * Creates and returns a file chooser set in the working directory. - * - * @return The file chooser. - */ - public JFileChooser createFileSaver() { - JFileChooser fileSaver = new JFileChooser(); - String dir = System.getProperty("user.dir"); - File fileDir = new File(dir); - fileSaver.setCurrentDirectory(fileDir); - fileSaver.setDialogTitle("Save to File"); - return fileSaver; - } + /** + * Creates and returns a file chooser set in the working directory. + * + * @return The file chooser. + */ + public JFileChooser createFileSaver() { + JFileChooser fileSaver = new JFileChooser(); + String dir = System.getProperty("user.dir"); + File fileDir = new File(dir); + fileSaver.setCurrentDirectory(fileDir); + fileSaver.setDialogTitle("Save to File"); + return fileSaver; + } } diff --git a/src/me/coley/recaf/ui/FontUtil.java b/src/me/coley/recaf/ui/FontUtil.java index e26def715..bcbc48cf1 100644 --- a/src/me/coley/recaf/ui/FontUtil.java +++ b/src/me/coley/recaf/ui/FontUtil.java @@ -12,32 +12,32 @@ * @author Matt */ public class FontUtil { - private static final AffineTransform affinetransform = new AffineTransform(); - private static final FontRenderContext frc = new FontRenderContext(affinetransform, true, true); - public static final Font monospace; - static { - String consolas = null; - String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); - for (String font : fonts) { - if (font.toLowerCase().contains("consolas")) { - consolas = font; - } - } - if (consolas == null) { - monospace = new Font(Font.MONOSPACED, Font.TRUETYPE_FONT, 12); - } else { - monospace = new Font(consolas, Font.TRUETYPE_FONT, 12); - } - } + private static final AffineTransform affinetransform = new AffineTransform(); + private static final FontRenderContext frc = new FontRenderContext(affinetransform, true, true); + public static final Font monospace; + static { + String consolas = null; + String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + for (String font : fonts) { + if (font.toLowerCase().contains("consolas")) { + consolas = font; + } + } + if (consolas == null) { + monospace = new Font(Font.MONOSPACED, Font.TRUETYPE_FONT, 12); + } else { + monospace = new Font(consolas, Font.TRUETYPE_FONT, 12); + } + } - /** - * Create a bounding box for the visual representation of the given text. - * - * @param text The text. - * @param font The font in which to render the text. - * @return The bounding box. - */ - public static Rectangle2D getStringBounds(String text, Font font) { - return font.getStringBounds(text, frc); - } + /** + * Create a bounding box for the visual representation of the given text. + * + * @param text The text. + * @param font The font in which to render the text. + * @return The bounding box. + */ + public static Rectangle2D getStringBounds(String text, Font font) { + return font.getStringBounds(text, frc); + } } diff --git a/src/me/coley/recaf/ui/Gui.java b/src/me/coley/recaf/ui/Gui.java index 0a3560d7f..749dbbe0b 100644 --- a/src/me/coley/recaf/ui/Gui.java +++ b/src/me/coley/recaf/ui/Gui.java @@ -34,216 +34,216 @@ import java.util.List; public class Gui { - private final Recaf recaf = Recaf.getInstance(); - private JFrame frame; - private JarFileTree treeFiles; - private TabbedPanel tabbedContent; - private JMenu mnSearch; - - public Gui() { - initialize(); - } - - /** - * Initialize the contents of the frame. - */ - @SuppressWarnings("serial") - private void initialize() { - frame = new JFrame("Recaf: Java Bytecode Editor"); - frame.setBounds(100, 100, 1200, 730); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - JMenuBar menuBar = new JMenuBar(); - frame.setJMenuBar(menuBar); - - JMenu mnFile = new JMenu("File"); - menuBar.add(mnFile); - - JMenuItem mntmOpenJar = new JMenuItem("Open Jar"); - mntmOpenJar.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JFileChooser chooser = recaf.fileChoosers.getFileChooser(); - int val = chooser.showOpenDialog(null); - if (val == JFileChooser.APPROVE_OPTION) { - try { - recaf.openFile(chooser.getSelectedFile()); - } catch (Exception e1) { - displayError(e1); - } - } - } - - }); - mnFile.add(mntmOpenJar); - - JMenuItem mntmSaveJar = new JMenuItem("Save Jar"); - mntmSaveJar.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JFileChooser chooser = recaf.fileChoosers.createFileSaver(); - int val = chooser.showOpenDialog(null); - if (val == JFileChooser.APPROVE_OPTION) { - try { - recaf.saveFile(chooser.getSelectedFile()); - } catch (Exception e1) { - displayError(e1); - } - } - } - - }); - mnFile.add(mntmSaveJar); - - /* - * JMenu mnEdit = new JMenu("Edit"); JMenuItem mntmUndo = new - * JMenuItem("Undo"); mntmUndo.addActionListener(new ActionListener() { - * - * @Override public void actionPerformed(ActionEvent e) { - * recaf.history.undoLast(); } }); mnEdit.add(mntmUndo); - * menuBar.add(mnEdit); - */ - - JMenu mnOptions = new JMenu("Options"); - mnOptions.add(new ActionCheckBox("Show jump hints", recaf.options.opcodeShowJumpHelp,b -> recaf.options.opcodeShowJumpHelp = b)); - mnOptions.add(new ActionCheckBox("Simplify type descriptors", recaf.options.opcodeSimplifyDescriptors,b -> recaf.options.opcodeSimplifyDescriptors = b)); - mnOptions.add(new ActionCheckBox("Advanced Variable Table", recaf.options.showVariableSignatureInTable,b -> recaf.options.showVariableSignatureInTable = b)); - mnOptions.add(new ActionCheckBox("Confirm deletions", recaf.options.confirmDeletions,b -> recaf.options.confirmDeletions = b)); - mnOptions.add(new ActionMenuItem("ASM flags", () -> { - openTab("ASM Flags", new AsmFlagsPanel()); - })); - menuBar.add(mnOptions); - - mnSearch = new JMenu("Search"); - mnSearch.setEnabled(false); - JMenuItem mntmSearch1 = new ActionMenuItem("Strings", () -> openTab("Search: Strings", new SearchPanel(SearchPanel.S_STRINGS))); - JMenuItem mntmSearch2 = new ActionMenuItem("Fields", () -> openTab("Search: Fields", new SearchPanel(SearchPanel.S_FIELD))); - JMenuItem mntmSearch3 = new ActionMenuItem("Methods", () -> openTab("Search: Methods", new SearchPanel(SearchPanel.S_METHOD))); - JMenuItem mntmSearch4 = new ActionMenuItem("Class Name", () -> openTab("Search: Class", new SearchPanel(SearchPanel.S_CLASS_NAME))); - JMenuItem mntmSearch5 = new ActionMenuItem("Class References", () -> openTab("Search: Class References", new SearchPanel(SearchPanel.S_CLASS_REF))); - mnSearch.add(mntmSearch1); - mnSearch.add(mntmSearch2); - mnSearch.add(mntmSearch3); - mnSearch.add(mntmSearch4); - mnSearch.add(mntmSearch5); - menuBar.add(mnSearch); - - frame.getContentPane().setLayout(new BorderLayout(0, 0)); - - JSplitPane splitPane = new JSplitPane(); - splitPane.setResizeWeight(0.1); - splitPane.setOneTouchExpandable(true); - frame.getContentPane().add(splitPane, BorderLayout.CENTER); - - treeFiles = new JarFileTree(); - splitPane.setLeftComponent(treeFiles); - treeFiles.setDropTarget(new DropTarget() { - @Override - public final void drop(final DropTargetDropEvent event) { - try { - event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); - Object transferData = event.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); - if (transferData == null) { - return; - } - @SuppressWarnings("unchecked") - List ls = (List) transferData; - File file = ls.get(0); - if (ls.size() > 1) { - JOptionPane.showMessageDialog(null, "Only one file can be accepted. Going with: " + file); - } - if (file.getName().toLowerCase().endsWith(".jar")) { - recaf.openFile(file); - } else { - JOptionPane.showMessageDialog(null, "Input was not a java archive (jar)."); - } - } catch (UnsupportedFlavorException ex) { - JOptionPane.showMessageDialog(null, "Input was not a java archive (jar)."); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - }); - - tabbedContent = new TabbedPanel(); - splitPane.setRightComponent(tabbedContent); - - } - - /** - * Creates a new tab with the text of the exception. - * - * @param e The exception. - */ - public void displayError(Throwable e) { - JTextArea text = new JTextArea(); - text.setEditable(false); - text.append(e.getClass().getSimpleName() + ":\n"); - text.append("Message: " + e.getMessage() + "\n"); - text.append("Trace: \n"); - for (StackTraceElement element : e.getStackTrace()) { - text.append(element.toString() + "\n"); - } - - // TODO: Logging of cause - // text.append("Cause: " + e.getCause() + "\n"); - - tabbedContent.addTab("Error: " + e.getClass().getSimpleName(), new JScrollPane(text)); - tabbedContent.setSelectedTab(tabbedContent.getTabCount() - 1); - } - - /** - * Opens up a class tab for the given class-node, or opens an existing page - * if one is found. - * - * @param node The node. - */ - public void addClassView(ClassNode node) { - if (tabbedContent.hasCached(node.name)) { - tabbedContent.setSelectedTab(tabbedContent.getCachedIndex(node.name)); - } else { - tabbedContent.addTab(node.name, new JScrollPane(new ClassDisplayPanel(node))); - tabbedContent.setSelectedTab(tabbedContent.getTabCount() - 1); - int i = tabbedContent.getCachedIndex(node.name); - if (i == -1) { - i = tabbedContent.getTabCount() - 1; - } - tabbedContent.setSelectedTab(i); - } - } - - /** - * Opens up a tab for the given component, or opens an existing page if one - * is found. - * - * @param title - * Title of tab. - * @param component - * Content of tab. - */ - public void openTab(String title, Component component) { - if (tabbedContent.hasCached(title)) { - tabbedContent.setSelectedTab(tabbedContent.getCachedIndex(title)); - } else { - tabbedContent.addTab(title, component); - int i = tabbedContent.getCachedIndex(title); - if (i == -1) { - i = tabbedContent.getTabCount() - 1; - } - tabbedContent.setSelectedTab(i); - } - } - - /** - * Refreshes the tree to display the current jar file. - */ - public void updateTree() { - mnSearch.setEnabled(true); - treeFiles.refresh(); - } - - public JFrame getFrame() { - return frame; - } + private final Recaf recaf = Recaf.getInstance(); + private JFrame frame; + private JarFileTree treeFiles; + private TabbedPanel tabbedContent; + private JMenu mnSearch; + + public Gui() { + initialize(); + } + + /** + * Initialize the contents of the frame. + */ + @SuppressWarnings("serial") + private void initialize() { + frame = new JFrame("Recaf: Java Bytecode Editor"); + frame.setBounds(100, 100, 1200, 730); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JMenuBar menuBar = new JMenuBar(); + frame.setJMenuBar(menuBar); + + JMenu mnFile = new JMenu("File"); + menuBar.add(mnFile); + + JMenuItem mntmOpenJar = new JMenuItem("Open Jar"); + mntmOpenJar.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser chooser = recaf.fileChoosers.getFileChooser(); + int val = chooser.showOpenDialog(null); + if (val == JFileChooser.APPROVE_OPTION) { + try { + recaf.openFile(chooser.getSelectedFile()); + } catch (Exception e1) { + displayError(e1); + } + } + } + + }); + mnFile.add(mntmOpenJar); + + JMenuItem mntmSaveJar = new JMenuItem("Save Jar"); + mntmSaveJar.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser chooser = recaf.fileChoosers.createFileSaver(); + int val = chooser.showOpenDialog(null); + if (val == JFileChooser.APPROVE_OPTION) { + try { + recaf.saveFile(chooser.getSelectedFile()); + } catch (Exception e1) { + displayError(e1); + } + } + } + + }); + mnFile.add(mntmSaveJar); + + /* + * JMenu mnEdit = new JMenu("Edit"); JMenuItem mntmUndo = new + * JMenuItem("Undo"); mntmUndo.addActionListener(new ActionListener() { + * + * @Override public void actionPerformed(ActionEvent e) { + * recaf.history.undoLast(); } }); mnEdit.add(mntmUndo); + * menuBar.add(mnEdit); + */ + + JMenu mnOptions = new JMenu("Options"); + mnOptions.add(new ActionCheckBox("Show jump hints", recaf.options.opcodeShowJumpHelp,b -> recaf.options.opcodeShowJumpHelp = b)); + mnOptions.add(new ActionCheckBox("Simplify type descriptors", recaf.options.opcodeSimplifyDescriptors,b -> recaf.options.opcodeSimplifyDescriptors = b)); + mnOptions.add(new ActionCheckBox("Advanced Variable Table", recaf.options.showVariableSignatureInTable,b -> recaf.options.showVariableSignatureInTable = b)); + mnOptions.add(new ActionCheckBox("Confirm deletions", recaf.options.confirmDeletions,b -> recaf.options.confirmDeletions = b)); + mnOptions.add(new ActionMenuItem("ASM flags", () -> { + openTab("ASM Flags", new AsmFlagsPanel()); + })); + menuBar.add(mnOptions); + + mnSearch = new JMenu("Search"); + mnSearch.setEnabled(false); + JMenuItem mntmSearch1 = new ActionMenuItem("Strings", () -> openTab("Search: Strings", new SearchPanel(SearchPanel.S_STRINGS))); + JMenuItem mntmSearch2 = new ActionMenuItem("Fields", () -> openTab("Search: Fields", new SearchPanel(SearchPanel.S_FIELD))); + JMenuItem mntmSearch3 = new ActionMenuItem("Methods", () -> openTab("Search: Methods", new SearchPanel(SearchPanel.S_METHOD))); + JMenuItem mntmSearch4 = new ActionMenuItem("Class Name", () -> openTab("Search: Class", new SearchPanel(SearchPanel.S_CLASS_NAME))); + JMenuItem mntmSearch5 = new ActionMenuItem("Class References", () -> openTab("Search: Class References", new SearchPanel(SearchPanel.S_CLASS_REF))); + mnSearch.add(mntmSearch1); + mnSearch.add(mntmSearch2); + mnSearch.add(mntmSearch3); + mnSearch.add(mntmSearch4); + mnSearch.add(mntmSearch5); + menuBar.add(mnSearch); + + frame.getContentPane().setLayout(new BorderLayout(0, 0)); + + JSplitPane splitPane = new JSplitPane(); + splitPane.setResizeWeight(0.1); + splitPane.setOneTouchExpandable(true); + frame.getContentPane().add(splitPane, BorderLayout.CENTER); + + treeFiles = new JarFileTree(); + splitPane.setLeftComponent(treeFiles); + treeFiles.setDropTarget(new DropTarget() { + @Override + public final void drop(final DropTargetDropEvent event) { + try { + event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); + Object transferData = event.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); + if (transferData == null) { + return; + } + @SuppressWarnings("unchecked") + List ls = (List) transferData; + File file = ls.get(0); + if (ls.size() > 1) { + JOptionPane.showMessageDialog(null, "Only one file can be accepted. Going with: " + file); + } + if (file.getName().toLowerCase().endsWith(".jar")) { + recaf.openFile(file); + } else { + JOptionPane.showMessageDialog(null, "Input was not a java archive (jar)."); + } + } catch (UnsupportedFlavorException ex) { + JOptionPane.showMessageDialog(null, "Input was not a java archive (jar)."); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }); + + tabbedContent = new TabbedPanel(); + splitPane.setRightComponent(tabbedContent); + + } + + /** + * Creates a new tab with the text of the exception. + * + * @param e The exception. + */ + public void displayError(Throwable e) { + JTextArea text = new JTextArea(); + text.setEditable(false); + text.append(e.getClass().getSimpleName() + ":\n"); + text.append("Message: " + e.getMessage() + "\n"); + text.append("Trace: \n"); + for (StackTraceElement element : e.getStackTrace()) { + text.append(element.toString() + "\n"); + } + + // TODO: Logging of cause + // text.append("Cause: " + e.getCause() + "\n"); + + tabbedContent.addTab("Error: " + e.getClass().getSimpleName(), new JScrollPane(text)); + tabbedContent.setSelectedTab(tabbedContent.getTabCount() - 1); + } + + /** + * Opens up a class tab for the given class-node, or opens an existing page + * if one is found. + * + * @param node The node. + */ + public void addClassView(ClassNode node) { + if (tabbedContent.hasCached(node.name)) { + tabbedContent.setSelectedTab(tabbedContent.getCachedIndex(node.name)); + } else { + tabbedContent.addTab(node.name, new JScrollPane(new ClassDisplayPanel(node))); + tabbedContent.setSelectedTab(tabbedContent.getTabCount() - 1); + int i = tabbedContent.getCachedIndex(node.name); + if (i == -1) { + i = tabbedContent.getTabCount() - 1; + } + tabbedContent.setSelectedTab(i); + } + } + + /** + * Opens up a tab for the given component, or opens an existing page if one + * is found. + * + * @param title + * Title of tab. + * @param component + * Content of tab. + */ + public void openTab(String title, Component component) { + if (tabbedContent.hasCached(title)) { + tabbedContent.setSelectedTab(tabbedContent.getCachedIndex(title)); + } else { + tabbedContent.addTab(title, component); + int i = tabbedContent.getCachedIndex(title); + if (i == -1) { + i = tabbedContent.getTabCount() - 1; + } + tabbedContent.setSelectedTab(i); + } + } + + /** + * Refreshes the tree to display the current jar file. + */ + public void updateTree() { + mnSearch.setEnabled(true); + treeFiles.refresh(); + } + + public JFrame getFrame() { + return frame; + } } diff --git a/src/me/coley/recaf/ui/HtmlRenderer.java b/src/me/coley/recaf/ui/HtmlRenderer.java index 172d170b5..9cdb2664e 100644 --- a/src/me/coley/recaf/ui/HtmlRenderer.java +++ b/src/me/coley/recaf/ui/HtmlRenderer.java @@ -5,110 +5,110 @@ import me.coley.recaf.Options; public interface HtmlRenderer { - final String colBlueDark = "#193049"; - final String colTealDark = "#154234"; - final String colGreenDark = "#184216"; - final String colRedDark = "#351717"; - final String colGray = "#555555"; + final String colBlueDark = "#193049"; + final String colTealDark = "#154234"; + final String colGreenDark = "#184216"; + final String colRedDark = "#351717"; + final String colGray = "#555555"; - /** - * HTML escape '&', '<' and '>'. - * - * @param s Text to escape - * @return Text with amp, lt, and gt escaped correctly. - */ + /** + * HTML escape '&', '<' and '>'. + * + * @param s Text to escape + * @return Text with amp, lt, and gt escaped correctly. + */ default String escape(String s) { - return s.replace("&", "&").replace("<", "<").replace(">", ">"); - } + return s.replace("&", "&").replace("<", "<").replace(">", ">"); + } - /** - * Converts a given type to a string. - * - * @param type The type object. - * @return String representation of the type object. - */ + /** + * Converts a given type to a string. + * + * @param type The type object. + * @return String representation of the type object. + */ default String getTypeStr(Type type) { - return getTypeStr(type, null); - } + return getTypeStr(type, null); + } - /** - * Converts a given type to a string. Output will be simplified if - * enabled in passed options. - * - * TODO: this javadoc should either link to documentation for the - * Options class, or document how to use it correctly in this context. - * - * - Charles - * - * @param type The type object. - * @param options Options object. - * @return String representation of the type object. - */ + /** + * Converts a given type to a string. Output will be simplified if + * enabled in passed options. + * + * TODO: this javadoc should either link to documentation for the + * Options class, or document how to use it correctly in this context. + * + * - Charles + * + * @param type The type object. + * @param options Options object. + * @return String representation of the type object. + */ default String getTypeStr(Type type, Options options) { - String s = ""; - if (type.getDescriptor().length() == 1) { - switch (type.getDescriptor().charAt(0)) { - case 'Z': - return "boolean"; - case 'I': - return "int"; - case 'J': - return "long"; - case 'D': - return "double"; - case 'F': - return "float"; - case 'B': - return "byte"; - case 'C': - return "char"; - case 'S': - return "short"; - case 'V': - return "void"; - default: - return type.getDescriptor(); - } - } else { - s += type.getInternalName(); - } - if (options != null && options.opcodeSimplifyDescriptors && s.contains("/")) { - s = s.substring(s.lastIndexOf("/") + 1); - if (s.endsWith(";")) { - s = s.substring(0, s.length() - 1); - } - } - return s; - } + String s = ""; + if (type.getDescriptor().length() == 1) { + switch (type.getDescriptor().charAt(0)) { + case 'Z': + return "boolean"; + case 'I': + return "int"; + case 'J': + return "long"; + case 'D': + return "double"; + case 'F': + return "float"; + case 'B': + return "byte"; + case 'C': + return "char"; + case 'S': + return "short"; + case 'V': + return "void"; + default: + return type.getDescriptor(); + } + } else { + s += type.getInternalName(); + } + if (options != null && options.opcodeSimplifyDescriptors && s.contains("/")) { + s = s.substring(s.lastIndexOf("/") + 1); + if (s.endsWith(";")) { + s = s.substring(0, s.length() - 1); + } + } + return s; + } - /** - * Italicize the given text. - * - * @param input Text to italicize. - * @return HTML markup to italicize the text. - */ + /** + * Italicize the given text. + * + * @param input Text to italicize. + * @return HTML markup to italicize the text. + */ default String italic(String input) { - return "" + input + ""; - } + return "" + input + ""; + } - /** - * Bold the given text. - * - * @param input Text to bold. - * @return HTML markup with the text bolded. - */ + /** + * Bold the given text. + * + * @param input Text to bold. + * @return HTML markup with the text bolded. + */ default String bold(String input) { - return "" + input + ""; - } + return "" + input + ""; + } - /** - * Color the given text. - * - * @param color The color to turn the text, must be a valid HTML color. - * @param input The text to color. - * @return HTML markup with the text colored appropriately. - */ + /** + * Color the given text. + * + * @param color The color to turn the text, must be a valid HTML color. + * @param input The text to color. + * @return HTML markup with the text colored appropriately. + */ default String color(String color, String input) { - return "" + input + ""; - } + return "" + input + ""; + } } diff --git a/src/me/coley/recaf/ui/Icons.java b/src/me/coley/recaf/ui/Icons.java index 76c47c52b..31624ba23 100644 --- a/src/me/coley/recaf/ui/Icons.java +++ b/src/me/coley/recaf/ui/Icons.java @@ -4,67 +4,67 @@ import javax.swing.ImageIcon; public class Icons { - // Class access - public static final Icon CL_CLASS; - public static final Icon CL_INTERFACE; - public static final Icon CL_ENUM; - public static final Icon CL_ANNOTATION; - // Field access - public static final Icon FL_PUBLIC; - public static final Icon FL_PROTECTED; - public static final Icon FL_PRIVATE; - public static final Icon FL_DEFAULT; - // Method access - public static final Icon ML_PUBLIC; - public static final Icon ML_PROTECTED; - public static final Icon ML_PRIVATE; - public static final Icon ML_DEFAULT; - // General modifiers - public static final Icon MOD_STATIC; - public static final Icon MOD_VOLATILE; - public static final Icon MOD_TRANSIENT; - public static final Icon MOD_SYNTHETIC; - public static final Icon MOD_NATIVE; - public static final Icon MOD_ABSTRACT; - public static final Icon MOD_FINAL; - // Misc - public static final Icon MISC_PACKAGE; - public static final Icon MISC_RESULT; + // Class access + public static final Icon CL_CLASS; + public static final Icon CL_INTERFACE; + public static final Icon CL_ENUM; + public static final Icon CL_ANNOTATION; + // Field access + public static final Icon FL_PUBLIC; + public static final Icon FL_PROTECTED; + public static final Icon FL_PRIVATE; + public static final Icon FL_DEFAULT; + // Method access + public static final Icon ML_PUBLIC; + public static final Icon ML_PROTECTED; + public static final Icon ML_PRIVATE; + public static final Icon ML_DEFAULT; + // General modifiers + public static final Icon MOD_STATIC; + public static final Icon MOD_VOLATILE; + public static final Icon MOD_TRANSIENT; + public static final Icon MOD_SYNTHETIC; + public static final Icon MOD_NATIVE; + public static final Icon MOD_ABSTRACT; + public static final Icon MOD_FINAL; + // Misc + public static final Icon MISC_PACKAGE; + public static final Icon MISC_RESULT; - static { - // - CL_CLASS = load("class.png"); - CL_INTERFACE = load("interface.png"); - CL_ENUM = load("enum.png"); - CL_ANNOTATION = load("annotation.png"); - // - FL_PUBLIC = load("field_public.png"); - FL_PROTECTED = load("field_protected.png"); - FL_PRIVATE = load("field_private.png"); - FL_DEFAULT = load("field_default.png"); - // - ML_PUBLIC = load("method_public.png"); - ML_PROTECTED = load("method_protected.png"); - ML_PRIVATE = load("method_private.png"); - ML_DEFAULT = load("method_default.png"); - // - MOD_STATIC = load("static.png"); - MOD_VOLATILE = load("volatile.png"); - MOD_TRANSIENT = load("transient.png"); - MOD_SYNTHETIC = load("synthetic.png"); - MOD_NATIVE = load("native.png"); - MOD_ABSTRACT = load("abstract.png"); - MOD_FINAL = load("final.png"); - // - MISC_PACKAGE = load("package.png"); - MISC_RESULT = load("result.png"); - } + static { + // + CL_CLASS = load("class.png"); + CL_INTERFACE = load("interface.png"); + CL_ENUM = load("enum.png"); + CL_ANNOTATION = load("annotation.png"); + // + FL_PUBLIC = load("field_public.png"); + FL_PROTECTED = load("field_protected.png"); + FL_PRIVATE = load("field_private.png"); + FL_DEFAULT = load("field_default.png"); + // + ML_PUBLIC = load("method_public.png"); + ML_PROTECTED = load("method_protected.png"); + ML_PRIVATE = load("method_private.png"); + ML_DEFAULT = load("method_default.png"); + // + MOD_STATIC = load("static.png"); + MOD_VOLATILE = load("volatile.png"); + MOD_TRANSIENT = load("transient.png"); + MOD_SYNTHETIC = load("synthetic.png"); + MOD_NATIVE = load("native.png"); + MOD_ABSTRACT = load("abstract.png"); + MOD_FINAL = load("final.png"); + // + MISC_PACKAGE = load("package.png"); + MISC_RESULT = load("result.png"); + } - private static Icon load(String url) { - // TODO: Why does File.separator force non-relative path names but this - // works fine? - String prefix = "/resources/"; - String file = prefix + url; - return new ImageIcon(Icons.class.getResource(file)); - } + private static Icon load(String url) { + // TODO: Why does File.separator force non-relative path names but this + // works fine? + String prefix = "/resources/"; + String file = prefix + url; + return new ImageIcon(Icons.class.getResource(file)); + } } diff --git a/src/me/coley/recaf/ui/component/LabeledComponent.java b/src/me/coley/recaf/ui/component/LabeledComponent.java index c6cc0a2f9..e2a1077e8 100644 --- a/src/me/coley/recaf/ui/component/LabeledComponent.java +++ b/src/me/coley/recaf/ui/component/LabeledComponent.java @@ -17,9 +17,9 @@ */ @SuppressWarnings("serial") public class LabeledComponent extends JPanel { - public LabeledComponent(String label, JComponent component) { - setLayout(new BorderLayout()); - add(new JLabel(label), BorderLayout.WEST); - add(component, BorderLayout.CENTER); - } + public LabeledComponent(String label, JComponent component) { + setLayout(new BorderLayout()); + add(new JLabel(label), BorderLayout.WEST); + add(component, BorderLayout.CENTER); + } } diff --git a/src/me/coley/recaf/ui/component/ReleaseListener.java b/src/me/coley/recaf/ui/component/ReleaseListener.java index 1df1f017a..e56f67772 100644 --- a/src/me/coley/recaf/ui/component/ReleaseListener.java +++ b/src/me/coley/recaf/ui/component/ReleaseListener.java @@ -11,15 +11,15 @@ * @author Matt */ public interface ReleaseListener extends MouseListener { - @Override + @Override default void mouseClicked(MouseEvent e) {} - @Override + @Override default void mousePressed(MouseEvent e) {} - @Override + @Override default void mouseEntered(MouseEvent e) {} - @Override + @Override default void mouseExited(MouseEvent e) {} } diff --git a/src/me/coley/recaf/ui/component/action/ActionButton.java b/src/me/coley/recaf/ui/component/action/ActionButton.java index a7c0f44ea..b3ec9501b 100644 --- a/src/me/coley/recaf/ui/component/action/ActionButton.java +++ b/src/me/coley/recaf/ui/component/action/ActionButton.java @@ -7,13 +7,13 @@ @SuppressWarnings("serial") public class ActionButton extends JButton { - public ActionButton(String text, Runnable r) { - super(text); - addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - r.run(); - } - }); - } + public ActionButton(String text, Runnable r) { + super(text); + addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + r.run(); + } + }); + } } diff --git a/src/me/coley/recaf/ui/component/action/ActionCheckBox.java b/src/me/coley/recaf/ui/component/action/ActionCheckBox.java index 998f39d38..7ea61f22f 100644 --- a/src/me/coley/recaf/ui/component/action/ActionCheckBox.java +++ b/src/me/coley/recaf/ui/component/action/ActionCheckBox.java @@ -8,13 +8,13 @@ @SuppressWarnings("serial") public class ActionCheckBox extends JCheckBox { - public ActionCheckBox(String text, boolean defaultValue, Consumer r) { - super(text, defaultValue); - addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - r.accept(isSelected()); - } - }); - } + public ActionCheckBox(String text, boolean defaultValue, Consumer r) { + super(text, defaultValue); + addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + r.accept(isSelected()); + } + }); + } } diff --git a/src/me/coley/recaf/ui/component/action/ActionMenuItem.java b/src/me/coley/recaf/ui/component/action/ActionMenuItem.java index 5901f9a78..b1802ddb2 100644 --- a/src/me/coley/recaf/ui/component/action/ActionMenuItem.java +++ b/src/me/coley/recaf/ui/component/action/ActionMenuItem.java @@ -8,18 +8,18 @@ @SuppressWarnings("serial") public class ActionMenuItem extends JMenuItem { - public ActionMenuItem(String text, Runnable action) { - this(text, new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - action.run(); - } - }); - } + public ActionMenuItem(String text, Runnable action) { + this(text, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + action.run(); + } + }); + } - public ActionMenuItem(String text, ActionListener action) { - super(text); - addActionListener(action); - } + public ActionMenuItem(String text, ActionListener action) { + super(text); + addActionListener(action); + } } diff --git a/src/me/coley/recaf/ui/component/action/ActionTextField.java b/src/me/coley/recaf/ui/component/action/ActionTextField.java index e1933c3e3..c0dbd306c 100644 --- a/src/me/coley/recaf/ui/component/action/ActionTextField.java +++ b/src/me/coley/recaf/ui/component/action/ActionTextField.java @@ -9,31 +9,31 @@ @SuppressWarnings("serial") public class ActionTextField extends JTextField { - public ActionTextField(Object content, Consumer textAction) { - this(content.toString(), textAction); - } + public ActionTextField(Object content, Consumer textAction) { + this(content.toString(), textAction); + } - public ActionTextField(String content, Consumer textAction) { - super(resolve(content)); - setFont(FontUtil.monospace); - addKeyListener(new KeyListener() { - @Override - public void keyTyped(KeyEvent e) {} + public ActionTextField(String content, Consumer textAction) { + super(resolve(content)); + setFont(FontUtil.monospace); + addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) {} - @Override - public void keyPressed(KeyEvent e) {} + @Override + public void keyPressed(KeyEvent e) {} - @Override - public void keyReleased(KeyEvent e) { - textAction.accept(getText()); - } - }); - } + @Override + public void keyReleased(KeyEvent e) { + textAction.accept(getText()); + } + }); + } - private static String resolve(String content) { - if (content == null) { - return ""; - } - return content; - } + private static String resolve(String content) { + if (content == null) { + return ""; + } + return content; + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/AccessBox.java b/src/me/coley/recaf/ui/component/internalframe/AccessBox.java index bff00334e..2295cdc42 100644 --- a/src/me/coley/recaf/ui/component/internalframe/AccessBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/AccessBox.java @@ -13,23 +13,23 @@ @SuppressWarnings("serial") public class AccessBox extends BasicFrame { - public AccessBox(Object value, JComponent owner) throws Exception { - AccessPanel panel = createPanel(value, owner); - setLayout(new BorderLayout()); - add(panel, BorderLayout.CENTER); - setTitle(panel.getTitle()); - setVisible(true); - } - - private static AccessPanel createPanel(Object value, JComponent owner) throws Exception { - if (value instanceof ClassNode) { - return new AccessPanel((ClassNode) value, owner); - } else if (value instanceof FieldNode) { - return new AccessPanel((FieldNode) value, owner); - } else if (value instanceof MethodNode) { - return new AccessPanel((MethodNode) value, owner); - } - return null; - } + public AccessBox(Object value, JComponent owner) throws Exception { + AccessPanel panel = createPanel(value, owner); + setLayout(new BorderLayout()); + add(panel, BorderLayout.CENTER); + setTitle(panel.getTitle()); + setVisible(true); + } + + private static AccessPanel createPanel(Object value, JComponent owner) throws Exception { + if (value instanceof ClassNode) { + return new AccessPanel((ClassNode) value, owner); + } else if (value instanceof FieldNode) { + return new AccessPanel((FieldNode) value, owner); + } else if (value instanceof MethodNode) { + return new AccessPanel((MethodNode) value, owner); + } + return null; + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/BasicFrame.java b/src/me/coley/recaf/ui/component/internalframe/BasicFrame.java index 847b8415e..2518514b1 100644 --- a/src/me/coley/recaf/ui/component/internalframe/BasicFrame.java +++ b/src/me/coley/recaf/ui/component/internalframe/BasicFrame.java @@ -6,24 +6,24 @@ @SuppressWarnings("serial") public class BasicFrame extends JInternalFrame { - protected int padding = 12; + protected int padding = 12; - public BasicFrame() { - this(""); - } + public BasicFrame() { + this(""); + } - public BasicFrame(String title) { - super(title); - setMaximumSize(new Dimension(400, 400)); - setResizable(true); - setIconifiable(true); - setClosable(true); - } + public BasicFrame(String title) { + super(title); + setMaximumSize(new Dimension(400, 400)); + setResizable(true); + setIconifiable(true); + setClosable(true); + } - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - pack(); - setSize(getWidth() + padding, getHeight() + padding); - } + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + pack(); + setSize(getWidth() + padding, getHeight() + padding); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/DecompileBox.java b/src/me/coley/recaf/ui/component/internalframe/DecompileBox.java index 208b9a849..74e099523 100644 --- a/src/me/coley/recaf/ui/component/internalframe/DecompileBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/DecompileBox.java @@ -5,11 +5,11 @@ @SuppressWarnings("serial") public class DecompileBox extends BasicFrame { - public DecompileBox(DecompilePanel value) throws Exception { - setLayout(new BorderLayout()); - add(value, BorderLayout.CENTER); - setMaximumSize(null); - setTitle(value.getTitle()); - setVisible(true); - } + public DecompileBox(DecompilePanel value) throws Exception { + setLayout(new BorderLayout()); + add(value, BorderLayout.CENTER); + setMaximumSize(null); + setTitle(value.getTitle()); + setVisible(true); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/DefaultValueBox.java b/src/me/coley/recaf/ui/component/internalframe/DefaultValueBox.java index 509ab7018..b5bf4a3d2 100644 --- a/src/me/coley/recaf/ui/component/internalframe/DefaultValueBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/DefaultValueBox.java @@ -8,11 +8,11 @@ @SuppressWarnings("serial") public class DefaultValueBox extends BasicFrame { - public DefaultValueBox(String fieldName, Object init, Consumer action) throws Exception { - super("Default Value: " + fieldName); - setLayout(new BorderLayout()); - String value = init == null ? "" : init.toString(); - add(new LabeledComponent("Default Value: ", new ActionTextField(value, action)), BorderLayout.CENTER); - setVisible(true); - } + public DefaultValueBox(String fieldName, Object init, Consumer action) throws Exception { + super("Default Value: " + fieldName); + setLayout(new BorderLayout()); + String value = init == null ? "" : init.toString(); + add(new LabeledComponent("Default Value: ", new ActionTextField(value, action)), BorderLayout.CENTER); + setVisible(true); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/EditBox.java b/src/me/coley/recaf/ui/component/internalframe/EditBox.java index e2c0e6146..e3e83fa39 100644 --- a/src/me/coley/recaf/ui/component/internalframe/EditBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/EditBox.java @@ -9,36 +9,36 @@ // Not extending BasicFrame is intentional. @SuppressWarnings("serial") public class EditBox extends JInternalFrame { - private boolean hasContent; - - public EditBox(String title) { - super(title); - setResizable(true); - setIconifiable(true); - setClosable(true); - setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); - } - - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - if (visible) { - pack(); - // setMinimumSize(getSize()); - } - } - - @Override - public Component add(Component comp) { - // Don't count internal swing components - if (!(comp instanceof BasicInternalFrameTitlePane)) { - hasContent = true; - } - return super.add(comp); - } - - public boolean hasContent() { - return hasContent; - } + private boolean hasContent; + + public EditBox(String title) { + super(title); + setResizable(true); + setIconifiable(true); + setClosable(true); + setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); + } + + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + if (visible) { + pack(); + // setMinimumSize(getSize()); + } + } + + @Override + public Component add(Component comp) { + // Don't count internal swing components + if (!(comp instanceof BasicInternalFrameTitlePane)) { + hasContent = true; + } + return super.add(comp); + } + + public boolean hasContent() { + return hasContent; + } } \ No newline at end of file diff --git a/src/me/coley/recaf/ui/component/internalframe/ExceptionsListBox.java b/src/me/coley/recaf/ui/component/internalframe/ExceptionsListBox.java index 82bf07bdc..f61dea093 100644 --- a/src/me/coley/recaf/ui/component/internalframe/ExceptionsListBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/ExceptionsListBox.java @@ -14,43 +14,43 @@ @SuppressWarnings("serial") public class ExceptionsListBox extends BasicFrame { - private static final Color bg = new Color(166, 166, 166); + private static final Color bg = new Color(166, 166, 166); - public ExceptionsListBox(MethodNode mn) { - super("Exceptions: " + mn.name); - setBackground(bg); - setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS)); - update(mn); - setVisible(true); - } + public ExceptionsListBox(MethodNode mn) { + super("Exceptions: " + mn.name); + setBackground(bg); + setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS)); + update(mn); + setVisible(true); + } - private void update(MethodNode mn) { - getContentPane().removeAll(); - for (int i = 0; i < mn.exceptions.size(); i++) { - final int j = i; - String ex = mn.exceptions.get(i); - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - panel.add(new ActionButton("Delete", () -> { - mn.exceptions.remove(j); - update(mn); - }), BorderLayout.WEST); - panel.add(new ActionTextField(ex, s -> mn.exceptions.set(j, s)), BorderLayout.CENTER); - add(panel); - } - JPanel panel = new JPanel(); - { - final JTextField text = new JTextField(); - panel.setLayout(new BorderLayout()); - panel.add(new ActionButton("Add", () -> { - mn.exceptions.add(text.getText()); - setSize(getWidth(), getHeight() + 30); - update(mn); - }), BorderLayout.WEST); - panel.add(text, BorderLayout.CENTER); - add(panel); - } - getContentPane().repaint(); - getContentPane().validate(); - } + private void update(MethodNode mn) { + getContentPane().removeAll(); + for (int i = 0; i < mn.exceptions.size(); i++) { + final int j = i; + String ex = mn.exceptions.get(i); + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.add(new ActionButton("Delete", () -> { + mn.exceptions.remove(j); + update(mn); + }), BorderLayout.WEST); + panel.add(new ActionTextField(ex, s -> mn.exceptions.set(j, s)), BorderLayout.CENTER); + add(panel); + } + JPanel panel = new JPanel(); + { + final JTextField text = new JTextField(); + panel.setLayout(new BorderLayout()); + panel.add(new ActionButton("Add", () -> { + mn.exceptions.add(text.getText()); + setSize(getWidth(), getHeight() + 30); + update(mn); + }), BorderLayout.WEST); + panel.add(text, BorderLayout.CENTER); + add(panel); + } + getContentPane().repaint(); + getContentPane().validate(); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/MemberDefinitionBox.java b/src/me/coley/recaf/ui/component/internalframe/MemberDefinitionBox.java index 439e26bc6..0b6b758d4 100644 --- a/src/me/coley/recaf/ui/component/internalframe/MemberDefinitionBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/MemberDefinitionBox.java @@ -13,47 +13,47 @@ @SuppressWarnings("serial") public class MemberDefinitionBox extends BasicFrame { - public MemberDefinitionBox(FieldNode fn, JList list) { - super("Definition: " + fn.name); - setup(fn.name, n -> { - fn.name = n; - list.repaint(); - }, fn.desc, d -> { - fn.desc = d; - list.repaint(); - }, fn.signature, s -> { - if (s.isEmpty()) { - fn.signature = null; - } else { - fn.signature = s; - } - }); - } - - public MemberDefinitionBox(MethodNode mn, JList list) { - super("Definition: " + mn.name); - setup(mn.name, n -> { - mn.name = n; - list.repaint(); - }, mn.desc, d -> { - mn.desc = d; - list.repaint(); - }, mn.signature, s -> { - if (s.isEmpty()) { - mn.signature = null; - } else { - mn.signature = s; - } - }); - } - - private void setup(String name, Consumer nameConsumer, String desc, Consumer descConsumer, String signature, - Consumer signatureConsumer) { - setLayout(new GridLayout(3, 1)); - add(new LabeledComponent("Name: ", new ActionTextField(name, nameConsumer))); - add(new LabeledComponent("Descriptor: ", new ActionTextField(desc, descConsumer))); - add(new LabeledComponent("Signature: ", new ActionTextField(signature == null ? "" : signature, signatureConsumer))); - setVisible(true); - } + public MemberDefinitionBox(FieldNode fn, JList list) { + super("Definition: " + fn.name); + setup(fn.name, n -> { + fn.name = n; + list.repaint(); + }, fn.desc, d -> { + fn.desc = d; + list.repaint(); + }, fn.signature, s -> { + if (s.isEmpty()) { + fn.signature = null; + } else { + fn.signature = s; + } + }); + } + + public MemberDefinitionBox(MethodNode mn, JList list) { + super("Definition: " + mn.name); + setup(mn.name, n -> { + mn.name = n; + list.repaint(); + }, mn.desc, d -> { + mn.desc = d; + list.repaint(); + }, mn.signature, s -> { + if (s.isEmpty()) { + mn.signature = null; + } else { + mn.signature = s; + } + }); + } + + private void setup(String name, Consumer nameConsumer, String desc, Consumer descConsumer, String signature, + Consumer signatureConsumer) { + setLayout(new GridLayout(3, 1)); + add(new LabeledComponent("Name: ", new ActionTextField(name, nameConsumer))); + add(new LabeledComponent("Descriptor: ", new ActionTextField(desc, descConsumer))); + add(new LabeledComponent("Signature: ", new ActionTextField(signature == null ? "" : signature, signatureConsumer))); + setVisible(true); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java b/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java index ddfb178e5..ac59a077f 100644 --- a/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/OpcodeCreationBox.java @@ -26,273 +26,273 @@ @SuppressWarnings("serial") public class OpcodeCreationBox extends BasicFrame { - private static final Map nameToType = new HashMap<>(); - private final Map> typeToOpcodeSelector = new HashMap<>(); - private final Map> typeToMapOfThings = new HashMap<>(); - private String currentType; + private static final Map nameToType = new HashMap<>(); + private final Map> typeToOpcodeSelector = new HashMap<>(); + private final Map> typeToMapOfThings = new HashMap<>(); + private String currentType; - public OpcodeCreationBox(boolean insertBefore, OpcodeList list, MethodNode method, AbstractInsnNode target) { - super("Create Opcode"); - setLayout(new BorderLayout()); - // Setting up center of the border panel to be a inner card-layout - // panel. - JPanel content = new JPanel(); - JComboBox comboCard = new JComboBox<>(from(nameToType.keySet())); - comboCard.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent evt) { - String item = (String) evt.getItem(); - currentType = item; - CardLayout cl = (CardLayout) (content.getLayout()); - cl.show(content, item); - } - }); - content.setLayout(new CardLayout()); - // Creating cards per opcode-type. - for (String key : nameToType.keySet()) { - Map map = new HashMap<>(); - typeToMapOfThings.put(key, map); - JPanel card = new JPanel(); - card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS)); - int type = nameToType.get(key); - content.add(card, key); - // Adding content to cards - String[] codes = OpcodeUtil.typeToCodes(type); - JComboBox comboCodes = new JComboBox<>(codes); - if (codes.length > 1) { - card.add(new LabeledComponent("Opcode: ", comboCodes)); - } - typeToOpcodeSelector.put(key, comboCodes); - // Type specific content - switch (type) { - case AbstractInsnNode.LDC_INSN: - case AbstractInsnNode.INT_INSN: { - JTextField text = new JTextField(); - card.add(new LabeledComponent("Value: ", text)); - map.put("value", text); - break; - } - case AbstractInsnNode.IINC_INSN: { - card.add(new JScrollPane(VariableTable.create(list, method))); - JTextField var = new JTextField(); - JTextField text = new JTextField(); - card.add(new LabeledComponent("Variable: ", var)); - card.add(new LabeledComponent("Increment: ", text)); - map.put("var", var); - map.put("inc", text); - break; - } - case AbstractInsnNode.VAR_INSN: { - card.add(new JScrollPane(VariableTable.create(list, method))); - JTextField var = new JTextField(); - card.add(new LabeledComponent("Variable: ", var)); - map.put("var", var); - break; - } - case AbstractInsnNode.TYPE_INSN: { - JTextField text = new JTextField(); - card.add(new LabeledComponent("Type: ", text)); - map.put("value", text); - break; - } - case AbstractInsnNode.FIELD_INSN: - case AbstractInsnNode.METHOD_INSN: { - JTextField owner = new JTextField(); - JTextField name = new JTextField(); - JTextField desc = new JTextField(); - card.add(new LabeledComponent("Owner: ", owner)); - card.add(new LabeledComponent("Name: ", name)); - card.add(new LabeledComponent("Desc: ", desc)); - map.put("owner", owner); - map.put("name", name); - map.put("desc", desc); - break; - } - case AbstractInsnNode.MULTIANEWARRAY_INSN: { - JTextField desc = new JTextField(); - JTextField dim = new JTextField(); - card.add(new LabeledComponent("Desc: ", desc)); - card.add(new LabeledComponent("Dimensions: ", dim)); - map.put("desc", desc); - map.put("dims", dim); - break; - } - case AbstractInsnNode.LINE: { - JTextField text = new JTextField(); - card.add(new LabeledComponent("Line: ", text)); - map.put("value", text); - break; - } - // TODO: The rest of these - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - break; - case AbstractInsnNode.JUMP_INSN: - break; - case AbstractInsnNode.LABEL: - break; - case AbstractInsnNode.TABLESWITCH_INSN: - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - break; - case AbstractInsnNode.FRAME: - break; - } - } - // Action for adding opcode. - ActionButton btn = new ActionButton("Add Opcode", () -> { - AbstractInsnNode ain = create(); - if (ain != null) { - // Insert - if (insertBefore) { - method.instructions.insertBefore(target, ain); - } else { - method.instructions.insert(target, ain); - } - list.repopulate(); - // Close window - try { - setClosed(true); - } catch (PropertyVetoException e) { - e.printStackTrace(); - } - } else { - // Couldn't make insn, show error. - setTitle("Error: Check inputs!"); - } - }); - add(content, BorderLayout.CENTER); - add(btn, BorderLayout.SOUTH); - add(comboCard, BorderLayout.NORTH); - setVisible(true); - pack(); - } + public OpcodeCreationBox(boolean insertBefore, OpcodeList list, MethodNode method, AbstractInsnNode target) { + super("Create Opcode"); + setLayout(new BorderLayout()); + // Setting up center of the border panel to be a inner card-layout + // panel. + JPanel content = new JPanel(); + JComboBox comboCard = new JComboBox<>(from(nameToType.keySet())); + comboCard.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent evt) { + String item = (String) evt.getItem(); + currentType = item; + CardLayout cl = (CardLayout) (content.getLayout()); + cl.show(content, item); + } + }); + content.setLayout(new CardLayout()); + // Creating cards per opcode-type. + for (String key : nameToType.keySet()) { + Map map = new HashMap<>(); + typeToMapOfThings.put(key, map); + JPanel card = new JPanel(); + card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS)); + int type = nameToType.get(key); + content.add(card, key); + // Adding content to cards + String[] codes = OpcodeUtil.typeToCodes(type); + JComboBox comboCodes = new JComboBox<>(codes); + if (codes.length > 1) { + card.add(new LabeledComponent("Opcode: ", comboCodes)); + } + typeToOpcodeSelector.put(key, comboCodes); + // Type specific content + switch (type) { + case AbstractInsnNode.LDC_INSN: + case AbstractInsnNode.INT_INSN: { + JTextField text = new JTextField(); + card.add(new LabeledComponent("Value: ", text)); + map.put("value", text); + break; + } + case AbstractInsnNode.IINC_INSN: { + card.add(new JScrollPane(VariableTable.create(list, method))); + JTextField var = new JTextField(); + JTextField text = new JTextField(); + card.add(new LabeledComponent("Variable: ", var)); + card.add(new LabeledComponent("Increment: ", text)); + map.put("var", var); + map.put("inc", text); + break; + } + case AbstractInsnNode.VAR_INSN: { + card.add(new JScrollPane(VariableTable.create(list, method))); + JTextField var = new JTextField(); + card.add(new LabeledComponent("Variable: ", var)); + map.put("var", var); + break; + } + case AbstractInsnNode.TYPE_INSN: { + JTextField text = new JTextField(); + card.add(new LabeledComponent("Type: ", text)); + map.put("value", text); + break; + } + case AbstractInsnNode.FIELD_INSN: + case AbstractInsnNode.METHOD_INSN: { + JTextField owner = new JTextField(); + JTextField name = new JTextField(); + JTextField desc = new JTextField(); + card.add(new LabeledComponent("Owner: ", owner)); + card.add(new LabeledComponent("Name: ", name)); + card.add(new LabeledComponent("Desc: ", desc)); + map.put("owner", owner); + map.put("name", name); + map.put("desc", desc); + break; + } + case AbstractInsnNode.MULTIANEWARRAY_INSN: { + JTextField desc = new JTextField(); + JTextField dim = new JTextField(); + card.add(new LabeledComponent("Desc: ", desc)); + card.add(new LabeledComponent("Dimensions: ", dim)); + map.put("desc", desc); + map.put("dims", dim); + break; + } + case AbstractInsnNode.LINE: { + JTextField text = new JTextField(); + card.add(new LabeledComponent("Line: ", text)); + map.put("value", text); + break; + } + // TODO: The rest of these + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + break; + case AbstractInsnNode.JUMP_INSN: + break; + case AbstractInsnNode.LABEL: + break; + case AbstractInsnNode.TABLESWITCH_INSN: + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + break; + case AbstractInsnNode.FRAME: + break; + } + } + // Action for adding opcode. + ActionButton btn = new ActionButton("Add Opcode", () -> { + AbstractInsnNode ain = create(); + if (ain != null) { + // Insert + if (insertBefore) { + method.instructions.insertBefore(target, ain); + } else { + method.instructions.insert(target, ain); + } + list.repopulate(); + // Close window + try { + setClosed(true); + } catch (PropertyVetoException e) { + e.printStackTrace(); + } + } else { + // Couldn't make insn, show error. + setTitle("Error: Check inputs!"); + } + }); + add(content, BorderLayout.CENTER); + add(btn, BorderLayout.SOUTH); + add(comboCard, BorderLayout.NORTH); + setVisible(true); + pack(); + } - /** - * Create an opcode from the current open card. If there's an input - * error no node is returned. - * - * @return The opcode created. - */ - public AbstractInsnNode create() { - try { - switch (nameToType.get(currentType)) { - case AbstractInsnNode.INSN: - return new InsnNode(getOpcode()); - case AbstractInsnNode.INT_INSN: - return new IntInsnNode(getOpcode(), getInt("value")); - case AbstractInsnNode.VAR_INSN: - return new VarInsnNode(getOpcode(), getInt("var")); - case AbstractInsnNode.TYPE_INSN: - return new TypeInsnNode(getOpcode(), getString("value")); - case AbstractInsnNode.FIELD_INSN: - return new FieldInsnNode(getOpcode(), getString("owner"), getString("name"), getString("desc")); - case AbstractInsnNode.METHOD_INSN: - return new MethodInsnNode(getOpcode(), getString("owner"), getString("name"), getString("desc"), - getOpcode() == Opcodes.INVOKEINTERFACE); - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - break; - case AbstractInsnNode.LABEL: - return new LabelNode(); - case AbstractInsnNode.LDC_INSN: - return new LdcInsnNode(get("value")); - case AbstractInsnNode.IINC_INSN: - return new IincInsnNode(getInt("var"), getInt("inc")); - case AbstractInsnNode.LINE: - return new LineNumberNode(getInt("value"), new LabelNode()); - case AbstractInsnNode.MULTIANEWARRAY_INSN: - return new MultiANewArrayInsnNode(getString("desc"), getInt("dims")); - case AbstractInsnNode.JUMP_INSN: - break; - case AbstractInsnNode.TABLESWITCH_INSN: - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - break; - case AbstractInsnNode.FRAME: - break; - } - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + /** + * Create an opcode from the current open card. If there's an input + * error no node is returned. + * + * @return The opcode created. + */ + public AbstractInsnNode create() { + try { + switch (nameToType.get(currentType)) { + case AbstractInsnNode.INSN: + return new InsnNode(getOpcode()); + case AbstractInsnNode.INT_INSN: + return new IntInsnNode(getOpcode(), getInt("value")); + case AbstractInsnNode.VAR_INSN: + return new VarInsnNode(getOpcode(), getInt("var")); + case AbstractInsnNode.TYPE_INSN: + return new TypeInsnNode(getOpcode(), getString("value")); + case AbstractInsnNode.FIELD_INSN: + return new FieldInsnNode(getOpcode(), getString("owner"), getString("name"), getString("desc")); + case AbstractInsnNode.METHOD_INSN: + return new MethodInsnNode(getOpcode(), getString("owner"), getString("name"), getString("desc"), + getOpcode() == Opcodes.INVOKEINTERFACE); + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + break; + case AbstractInsnNode.LABEL: + return new LabelNode(); + case AbstractInsnNode.LDC_INSN: + return new LdcInsnNode(get("value")); + case AbstractInsnNode.IINC_INSN: + return new IincInsnNode(getInt("var"), getInt("inc")); + case AbstractInsnNode.LINE: + return new LineNumberNode(getInt("value"), new LabelNode()); + case AbstractInsnNode.MULTIANEWARRAY_INSN: + return new MultiANewArrayInsnNode(getString("desc"), getInt("dims")); + case AbstractInsnNode.JUMP_INSN: + break; + case AbstractInsnNode.TABLESWITCH_INSN: + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + break; + case AbstractInsnNode.FRAME: + break; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } - /** - * Get selected opcode. - * - * @return - */ - private int getOpcode() { - return OpcodeUtil.nameToOpcode(typeToOpcodeSelector.get(currentType).getSelectedItem().toString()); - } + /** + * Get selected opcode. + * + * @return + */ + private int getOpcode() { + return OpcodeUtil.nameToOpcode(typeToOpcodeSelector.get(currentType).getSelectedItem().toString()); + } - /** - * Get value for the current card pertaining to the given key as a String. - * - * @param key - * Label associated with an input. - * @return - */ - private String getString(String key) { - return get(key).toString(); - } + /** + * Get value for the current card pertaining to the given key as a String. + * + * @param key + * Label associated with an input. + * @return + */ + private String getString(String key) { + return get(key).toString(); + } - /** - * Get value for the current card pertaining to the given key as an integer. - * - * @param key - * Label associated with an input. - * @return - */ - private int getInt(String key) { - return Integer.parseInt(get(key).toString()); - } + /** + * Get value for the current card pertaining to the given key as an integer. + * + * @param key + * Label associated with an input. + * @return + */ + private int getInt(String key) { + return Integer.parseInt(get(key).toString()); + } - /** - * Get value for the current card pertaining to the given key. - * - * @param key - * Label associated with an input. - * @return - */ - private Object get(String key) { - JTextField field = typeToMapOfThings.get(currentType).get(key); - if (field != null) { - return field.getText(); - } - return null; - } + /** + * Get value for the current card pertaining to the given key. + * + * @param key + * Label associated with an input. + * @return + */ + private Object get(String key) { + JTextField field = typeToMapOfThings.get(currentType).get(key); + if (field != null) { + return field.getText(); + } + return null; + } - /** - * Set to array. - * - * @param set - * @return - */ - private static String[] from(Set set) { - String[] s = new String[set.size()]; - int i = 0; - for (String ss : set) { - s[i++] = ss; - } - return s; - } + /** + * Set to array. + * + * @param set + * @return + */ + private static String[] from(Set set) { + String[] s = new String[set.size()]; + int i = 0; + for (String ss : set) { + s[i++] = ss; + } + return s; + } - static { - // Commenting out the lines that would add cards for unsupported insn - // types. When they're supported they'll be uncommented. - nameToType.put("Insn", AbstractInsnNode.INSN); - nameToType.put("Field", AbstractInsnNode.FIELD_INSN); - // nameToType.put("Frame", AbstractInsnNode.FRAME); - nameToType.put("Increment", AbstractInsnNode.IINC_INSN); - nameToType.put("Integer", AbstractInsnNode.INT_INSN); - // nameToType.put("Jump", AbstractInsnNode.JUMP_INSN); - nameToType.put("Ldc", AbstractInsnNode.LDC_INSN); - // nameToType.put("Line", AbstractInsnNode.LINE); - // nameToType.put("LookupSwitch", AbstractInsnNode.LOOKUPSWITCH_INSN); - nameToType.put("Method", AbstractInsnNode.METHOD_INSN); - // nameToType.put("MethodIndy", AbstractInsnNode.INVOKE_DYNAMIC_INSN); - nameToType.put("MultiANewArray", AbstractInsnNode.MULTIANEWARRAY_INSN); - // nameToType.put("TableSwitch", AbstractInsnNode.TABLESWITCH_INSN); - nameToType.put("Type", AbstractInsnNode.TYPE_INSN); - nameToType.put("Variable", AbstractInsnNode.VAR_INSN); - } + static { + // Commenting out the lines that would add cards for unsupported insn + // types. When they're supported they'll be uncommented. + nameToType.put("Insn", AbstractInsnNode.INSN); + nameToType.put("Field", AbstractInsnNode.FIELD_INSN); + // nameToType.put("Frame", AbstractInsnNode.FRAME); + nameToType.put("Increment", AbstractInsnNode.IINC_INSN); + nameToType.put("Integer", AbstractInsnNode.INT_INSN); + // nameToType.put("Jump", AbstractInsnNode.JUMP_INSN); + nameToType.put("Ldc", AbstractInsnNode.LDC_INSN); + // nameToType.put("Line", AbstractInsnNode.LINE); + // nameToType.put("LookupSwitch", AbstractInsnNode.LOOKUPSWITCH_INSN); + nameToType.put("Method", AbstractInsnNode.METHOD_INSN); + // nameToType.put("MethodIndy", AbstractInsnNode.INVOKE_DYNAMIC_INSN); + nameToType.put("MultiANewArray", AbstractInsnNode.MULTIANEWARRAY_INSN); + // nameToType.put("TableSwitch", AbstractInsnNode.TABLESWITCH_INSN); + nameToType.put("Type", AbstractInsnNode.TYPE_INSN); + nameToType.put("Variable", AbstractInsnNode.VAR_INSN); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/OpcodeListBox.java b/src/me/coley/recaf/ui/component/internalframe/OpcodeListBox.java index e740728f8..5e03d1cdc 100644 --- a/src/me/coley/recaf/ui/component/internalframe/OpcodeListBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/OpcodeListBox.java @@ -12,15 +12,15 @@ @SuppressWarnings("serial") public class OpcodeListBox extends BasicFrame { - private static final Color bg = new Color(166, 166, 166); + private static final Color bg = new Color(166, 166, 166); - public OpcodeListBox(ClassDisplayPanel display, MethodNode mn) throws Exception { - super("Opcodes: " + mn.name); - setBackground(bg); - setLayout(new BorderLayout()); - setMaximumSize(new Dimension(900, 900)); - // Opcodes list - add(new JScrollPane(new OpcodeList(display, mn)), BorderLayout.CENTER); - setVisible(true); - } + public OpcodeListBox(ClassDisplayPanel display, MethodNode mn) throws Exception { + super("Opcodes: " + mn.name); + setBackground(bg); + setLayout(new BorderLayout()); + setMaximumSize(new Dimension(900, 900)); + // Opcodes list + add(new JScrollPane(new OpcodeList(display, mn)), BorderLayout.CENTER); + setVisible(true); + } } diff --git a/src/me/coley/recaf/ui/component/internalframe/TryCatchBox.java b/src/me/coley/recaf/ui/component/internalframe/TryCatchBox.java index 6deebb9f6..57f9922eb 100644 --- a/src/me/coley/recaf/ui/component/internalframe/TryCatchBox.java +++ b/src/me/coley/recaf/ui/component/internalframe/TryCatchBox.java @@ -23,65 +23,65 @@ @SuppressWarnings("serial") public class TryCatchBox extends BasicFrame { - private static final Color bg = new Color(166, 166, 166); - private final JScrollPane scroll = new JScrollPane(); + private static final Color bg = new Color(166, 166, 166); + private final JScrollPane scroll = new JScrollPane(); - public TryCatchBox(MethodNode mn) { - super("Try-Catches: " + mn.name); - setBackground(bg); - setLayout(new BorderLayout()); - add(scroll, BorderLayout.CENTER); - update(mn); - int k = 162; - int s = Math.min(k * 2, k * mn.tryCatchBlocks.size()); - scroll.setPreferredSize(new Dimension(350, s)); - setVisible(true); - } + public TryCatchBox(MethodNode mn) { + super("Try-Catches: " + mn.name); + setBackground(bg); + setLayout(new BorderLayout()); + add(scroll, BorderLayout.CENTER); + update(mn); + int k = 162; + int s = Math.min(k * 2, k * mn.tryCatchBlocks.size()); + scroll.setPreferredSize(new Dimension(350, s)); + setVisible(true); + } - private void update(MethodNode mn) { - JPanel content = new JPanel(); - content.setLayout(new GridLayout(0, 1)); - for (int i = 0; i <= mn.tryCatchBlocks.size(); i++) { - content.add(make(i, mn)); - } - scroll.setViewportView(content); - } + private void update(MethodNode mn) { + JPanel content = new JPanel(); + content.setLayout(new GridLayout(0, 1)); + for (int i = 0; i <= mn.tryCatchBlocks.size(); i++) { + content.add(make(i, mn)); + } + scroll.setViewportView(content); + } - private JPanel make(final int i, MethodNode mn) { - boolean isNew = i >= mn.tryCatchBlocks.size(); - JPanel panel = new JPanel(); - panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); - panel.setBorder(BorderFactory.createEtchedBorder()); - TryCatchBlockNode block; - if (isNew) { - block = new TryCatchBlockNode(null, null, null, ""); - } else { - block = mn.tryCatchBlocks.get(i); - } - List comps = new ArrayList<>(); - comps.add(new LabeledComponent("Start: ", new LabelSwitcherPanel(mn, block.start, l -> block.start = l))); - comps.add(new LabeledComponent("End: ", new LabelSwitcherPanel(mn, block.end, l -> block.end = l))); - comps.add(new LabeledComponent("Handler: ", new LabelSwitcherPanel(mn, block.handler, - l -> block.handler = l))); - comps.add(new LabeledComponent("Type: ", new ActionTextField(block.type, s -> block.type = s))); - if (isNew) { - comps.add(new ActionButton("Insert", () -> { - if (block.start == null || block.end == null || block.handler == null) { - return; - } - mn.tryCatchBlocks.add(block); - update(mn); - })); - } else { - comps.add(new ActionButton("Remove", () -> { - mn.tryCatchBlocks.remove(i); - update(mn); - })); - } - for (JComponent c : comps) { - c.setAlignmentX(JComponent.LEFT_ALIGNMENT); - panel.add(c); - } - return panel; - } + private JPanel make(final int i, MethodNode mn) { + boolean isNew = i >= mn.tryCatchBlocks.size(); + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBorder(BorderFactory.createEtchedBorder()); + TryCatchBlockNode block; + if (isNew) { + block = new TryCatchBlockNode(null, null, null, ""); + } else { + block = mn.tryCatchBlocks.get(i); + } + List comps = new ArrayList<>(); + comps.add(new LabeledComponent("Start: ", new LabelSwitcherPanel(mn, block.start, l -> block.start = l))); + comps.add(new LabeledComponent("End: ", new LabelSwitcherPanel(mn, block.end, l -> block.end = l))); + comps.add(new LabeledComponent("Handler: ", new LabelSwitcherPanel(mn, block.handler, + l -> block.handler = l))); + comps.add(new LabeledComponent("Type: ", new ActionTextField(block.type, s -> block.type = s))); + if (isNew) { + comps.add(new ActionButton("Insert", () -> { + if (block.start == null || block.end == null || block.handler == null) { + return; + } + mn.tryCatchBlocks.add(block); + update(mn); + })); + } else { + comps.add(new ActionButton("Remove", () -> { + mn.tryCatchBlocks.remove(i); + update(mn); + })); + } + for (JComponent c : comps) { + c.setAlignmentX(JComponent.LEFT_ALIGNMENT); + panel.add(c); + } + return panel; + } } diff --git a/src/me/coley/recaf/ui/component/list/MemberNodeClickListener.java b/src/me/coley/recaf/ui/component/list/MemberNodeClickListener.java index 9c40a62d6..a2f683978 100644 --- a/src/me/coley/recaf/ui/component/list/MemberNodeClickListener.java +++ b/src/me/coley/recaf/ui/component/list/MemberNodeClickListener.java @@ -35,203 +35,203 @@ * @author Matt */ public class MemberNodeClickListener implements ReleaseListener { - private final Recaf recaf = Recaf.getInstance(); - private final ClassDisplayPanel display; - private final JList list; - private final ClassNode node; + private final Recaf recaf = Recaf.getInstance(); + private final ClassDisplayPanel display; + private final JList list; + private final ClassNode node; - public MemberNodeClickListener(ClassDisplayPanel display, ClassNode node, JList list) { - this.list = list; - this.node = node; - this.display = display; - } + public MemberNodeClickListener(ClassDisplayPanel display, ClassNode node, JList list) { + this.list = list; + this.node = node; + this.display = display; + } - @Override - public void mouseReleased(MouseEvent e) { - int button = e.getButton(); - // If not left-click, enforce selection at the given location - if (button != MouseEvent.BUTTON1) { - int index = list.locationToIndex(e.getPoint()); - list.setSelectedIndex(index); - } - Object value = list.getSelectedValue(); - if (value == null) { - return; - } - // Middle-click to open editor - // Right-click to open context menu - if (button == MouseEvent.BUTTON2) { - // TODO: Allow users to choose custom middle-click actions - if (value instanceof FieldNode) { - openDefaultValue((FieldNode) value); - } else if (value instanceof MethodNode) { - openOpcodes((MethodNode) value); - } - } else if (button == MouseEvent.BUTTON3) { - createContextMenu(value, e.getX(), e.getY()); - } - } + @Override + public void mouseReleased(MouseEvent e) { + int button = e.getButton(); + // If not left-click, enforce selection at the given location + if (button != MouseEvent.BUTTON1) { + int index = list.locationToIndex(e.getPoint()); + list.setSelectedIndex(index); + } + Object value = list.getSelectedValue(); + if (value == null) { + return; + } + // Middle-click to open editor + // Right-click to open context menu + if (button == MouseEvent.BUTTON2) { + // TODO: Allow users to choose custom middle-click actions + if (value instanceof FieldNode) { + openDefaultValue((FieldNode) value); + } else if (value instanceof MethodNode) { + openOpcodes((MethodNode) value); + } + } else if (button == MouseEvent.BUTTON3) { + createContextMenu(value, e.getX(), e.getY()); + } + } - private void createContextMenu(Object value, int x, int y) { - JPopupMenu popup = new JPopupMenu(); - // Field/Method only actions - if (value instanceof FieldNode) { - FieldNode fn = (FieldNode) value; - if (fn.desc.length() == 1 || fn.desc.equals("Ljava/lang/String;")) { - popup.add(new ActionMenuItem("Edit DefaultValue", () -> openDefaultValue((FieldNode) value))); - } - } else { - MethodNode mn = (MethodNode) value; - if (!Access.isAbstract(mn.access)) { - popup.add(new ActionMenuItem("Edit Opcodes", () -> openOpcodes(mn))); - } - if (mn.exceptions != null) { - popup.add(new ActionMenuItem("Edit Exceptions", () -> openExceptions(mn))); - } - if (mn.tryCatchBlocks != null && !mn.tryCatchBlocks.isEmpty()) { - popup.add(new ActionMenuItem("Edit Try-Catch Blocks", () -> openTryCatchBlocks(mn))); - } - if (mn.instructions.size() > 0) { - popup.add(new ActionMenuItem("Show Decompilation", () -> decompile(node, mn))); - } - } - // General actions - ActionMenuItem itemDefine = new ActionMenuItem("Edit Definition", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - try { - if (value instanceof FieldNode) { - FieldNode fn = (FieldNode) value; - display.addWindow(new MemberDefinitionBox(fn, list)); - } else if (value instanceof MethodNode) { - MethodNode mn = (MethodNode) value; - display.addWindow(new MemberDefinitionBox(mn, list)); - } - } catch (Exception e1) { - display.exception(e1); - } - } - })); - ActionMenuItem itemAccess = new ActionMenuItem("Edit Access", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - try { - if (value instanceof FieldNode) { - FieldNode fn = (FieldNode) value; - display.addWindow(new AccessBox(fn, list)); - } else if (value instanceof MethodNode) { - MethodNode mn = (MethodNode) value; - display.addWindow(new AccessBox(mn, list)); - } - } catch (Exception e1) { - display.exception(e1); - } - } - })); - ActionMenuItem itemDeletThis = new ActionMenuItem("Remove", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - // Show confirmation - if (recaf.options.confirmDeletions) { - int dialogResult = JOptionPane.showConfirmDialog(null, "You sure you want to delete that member?", "Warning", - JOptionPane.YES_NO_OPTION); - if (dialogResult != JOptionPane.YES_OPTION) { - return; - } - } - // remove from class node - if (value instanceof FieldNode) { - node.fields.remove(value); - } else { - node.methods.remove(value); - } - // remove from list - DefaultListModel model = (DefaultListModel) list.getModel(); - model.removeElement(value); + private void createContextMenu(Object value, int x, int y) { + JPopupMenu popup = new JPopupMenu(); + // Field/Method only actions + if (value instanceof FieldNode) { + FieldNode fn = (FieldNode) value; + if (fn.desc.length() == 1 || fn.desc.equals("Ljava/lang/String;")) { + popup.add(new ActionMenuItem("Edit DefaultValue", () -> openDefaultValue((FieldNode) value))); + } + } else { + MethodNode mn = (MethodNode) value; + if (!Access.isAbstract(mn.access)) { + popup.add(new ActionMenuItem("Edit Opcodes", () -> openOpcodes(mn))); + } + if (mn.exceptions != null) { + popup.add(new ActionMenuItem("Edit Exceptions", () -> openExceptions(mn))); + } + if (mn.tryCatchBlocks != null && !mn.tryCatchBlocks.isEmpty()) { + popup.add(new ActionMenuItem("Edit Try-Catch Blocks", () -> openTryCatchBlocks(mn))); + } + if (mn.instructions.size() > 0) { + popup.add(new ActionMenuItem("Show Decompilation", () -> decompile(node, mn))); + } + } + // General actions + ActionMenuItem itemDefine = new ActionMenuItem("Edit Definition", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + if (value instanceof FieldNode) { + FieldNode fn = (FieldNode) value; + display.addWindow(new MemberDefinitionBox(fn, list)); + } else if (value instanceof MethodNode) { + MethodNode mn = (MethodNode) value; + display.addWindow(new MemberDefinitionBox(mn, list)); + } + } catch (Exception e1) { + display.exception(e1); + } + } + })); + ActionMenuItem itemAccess = new ActionMenuItem("Edit Access", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + if (value instanceof FieldNode) { + FieldNode fn = (FieldNode) value; + display.addWindow(new AccessBox(fn, list)); + } else if (value instanceof MethodNode) { + MethodNode mn = (MethodNode) value; + display.addWindow(new AccessBox(mn, list)); + } + } catch (Exception e1) { + display.exception(e1); + } + } + })); + ActionMenuItem itemDeletThis = new ActionMenuItem("Remove", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Show confirmation + if (recaf.options.confirmDeletions) { + int dialogResult = JOptionPane.showConfirmDialog(null, "You sure you want to delete that member?", "Warning", + JOptionPane.YES_NO_OPTION); + if (dialogResult != JOptionPane.YES_OPTION) { + return; + } + } + // remove from class node + if (value instanceof FieldNode) { + node.fields.remove(value); + } else { + node.methods.remove(value); + } + // remove from list + DefaultListModel model = (DefaultListModel) list.getModel(); + model.removeElement(value); - } - })); - popup.add(itemDefine); - popup.add(itemAccess); - popup.add(itemDeletThis); - // Display popup - popup.show(list, x, y); - } + } + })); + popup.add(itemDefine); + popup.add(itemAccess); + popup.add(itemDeletThis); + // Display popup + popup.show(list, x, y); + } - /** - * Opens a window showing the decompiled method belonging to the given - * class. - * - * @param cn - * @param mn - */ - private void decompile(ClassNode cn, MethodNode mn) { - try { - display.addWindow(new DecompileBox(new DecompilePanel(cn, mn))); - } catch (Exception e) { - display.exception(e); - } - } + /** + * Opens a window showing the decompiled method belonging to the given + * class. + * + * @param cn + * @param mn + */ + private void decompile(ClassNode cn, MethodNode mn) { + try { + display.addWindow(new DecompileBox(new DecompilePanel(cn, mn))); + } catch (Exception e) { + display.exception(e); + } + } - /** - * Open window for modifying default value of a field. - * - * @param field - */ - private void openDefaultValue(FieldNode field) { - try { - display.addWindow(new DefaultValueBox(field.name, field.value, value -> { - if (field.desc.length() == 1) { - // Convert string value to int. - if (Misc.isInt(value)) { - field.value = Integer.parseInt(value); - } - } else { - // Just set value as string - field.value = value; - } - })); - } catch (Exception e) { - display.exception(e); - } - } + /** + * Open window for modifying default value of a field. + * + * @param field + */ + private void openDefaultValue(FieldNode field) { + try { + display.addWindow(new DefaultValueBox(field.name, field.value, value -> { + if (field.desc.length() == 1) { + // Convert string value to int. + if (Misc.isInt(value)) { + field.value = Integer.parseInt(value); + } + } else { + // Just set value as string + field.value = value; + } + })); + } catch (Exception e) { + display.exception(e); + } + } - /** - * Open window for modifying method opcodes. - * - * @param method - */ - private void openOpcodes(MethodNode method) { - try { - display.addWindow(new OpcodeListBox(display, method)); - } catch (Exception e) { - display.exception(e); - } - } + /** + * Open window for modifying method opcodes. + * + * @param method + */ + private void openOpcodes(MethodNode method) { + try { + display.addWindow(new OpcodeListBox(display, method)); + } catch (Exception e) { + display.exception(e); + } + } - /** - * Open window for modifying method exceptions. - * - * @param method - */ - private void openExceptions(MethodNode method) { - try { - display.addWindow(new ExceptionsListBox(method)); - } catch (Exception e) { - display.exception(e); - } - } + /** + * Open window for modifying method exceptions. + * + * @param method + */ + private void openExceptions(MethodNode method) { + try { + display.addWindow(new ExceptionsListBox(method)); + } catch (Exception e) { + display.exception(e); + } + } - /** - * Open window for modifying method try-catch blocks. - * - * @param method - */ - private void openTryCatchBlocks(MethodNode method) { - try { - display.addWindow(new TryCatchBox(method)); - } catch (Exception e) { - display.exception(e); - } - } + /** + * Open window for modifying method try-catch blocks. + * + * @param method + */ + private void openTryCatchBlocks(MethodNode method) { + try { + display.addWindow(new TryCatchBox(method)); + } catch (Exception e) { + display.exception(e); + } + } } diff --git a/src/me/coley/recaf/ui/component/list/MemberNodeRenderer.java b/src/me/coley/recaf/ui/component/list/MemberNodeRenderer.java index 82043da1a..deb04654b 100644 --- a/src/me/coley/recaf/ui/component/list/MemberNodeRenderer.java +++ b/src/me/coley/recaf/ui/component/list/MemberNodeRenderer.java @@ -31,112 +31,112 @@ * @author Matt */ public class MemberNodeRenderer implements HtmlRenderer, ListCellRenderer { - private static final Color bg = new Color(200, 200, 200); - private static final Color bg2 = new Color(166, 166, 166); - private final Options options; + private static final Color bg = new Color(200, 200, 200); + private static final Color bg2 = new Color(166, 166, 166); + private final Options options; - public MemberNodeRenderer(Options options) { - this.options = options; - } + public MemberNodeRenderer(Options options) { + this.options = options; + } - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, - boolean cellHasFocus) { - list.setBackground(bg2); - String display = value.toString(); - int access = -1; - boolean method = false; - if (value instanceof MethodNode) { - MethodNode node = (MethodNode) value; - display = formatMethod(node); - access = node.access; - method = true; - } else if (value instanceof FieldNode) { - FieldNode node = (FieldNode) value; - display = formatField(node); - access = node.access; - } - JPanel content = new JPanel(); - content.setBackground(bg2); - content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS)); - JLabel label = new JLabel("" + display + ""); - label.setFont(FontUtil.monospace); - formatComponent(label, isSelected); - content.add(label); - addAccess(content, access, method, isSelected); - return content; - } + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + list.setBackground(bg2); + String display = value.toString(); + int access = -1; + boolean method = false; + if (value instanceof MethodNode) { + MethodNode node = (MethodNode) value; + display = formatMethod(node); + access = node.access; + method = true; + } else if (value instanceof FieldNode) { + FieldNode node = (FieldNode) value; + display = formatField(node); + access = node.access; + } + JPanel content = new JPanel(); + content.setBackground(bg2); + content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS)); + JLabel label = new JLabel("" + display + ""); + label.setFont(FontUtil.monospace); + formatComponent(label, isSelected); + content.add(label); + addAccess(content, access, method, isSelected); + return content; + } - private void addAccess(JPanel content, int access, boolean method, boolean selected) { - if (Access.isPublic(access)) { - add(content, selected, method ? Icons.ML_PUBLIC : Icons.FL_PUBLIC); - } else if (Access.isProtected(access)) { - add(content, selected, method ? Icons.ML_PROTECTED : Icons.FL_PROTECTED); - } else if (Access.isPrivate(access)) { - add(content, selected, method ? Icons.ML_PRIVATE : Icons.FL_PRIVATE); - } else if (Access.isPrivate(access)) { - add(content, selected, method ? Icons.ML_PRIVATE : Icons.FL_PRIVATE); - } else { - add(content, selected, method ? Icons.ML_DEFAULT : Icons.FL_DEFAULT); - } - if (Access.isAbstract(access)) { - add(content, selected, MOD_ABSTRACT); - } - if (Access.isFinal(access)) { - add(content, selected, MOD_FINAL); - } - if (Access.isNative(access)) { - add(content, selected, MOD_NATIVE); - } - if (Access.isStatic(access)) { - add(content, selected, MOD_STATIC); - } - if (Access.isTransient(access)) { - add(content, selected, MOD_TRANSIENT); - } - if (Access.isVolatile(access)) { - add(content, selected, MOD_VOLATILE); - } - if (Access.isSynthetic(access) || Access.isBridge(access)) { - add(content, selected, MOD_SYNTHETIC); - } - } + private void addAccess(JPanel content, int access, boolean method, boolean selected) { + if (Access.isPublic(access)) { + add(content, selected, method ? Icons.ML_PUBLIC : Icons.FL_PUBLIC); + } else if (Access.isProtected(access)) { + add(content, selected, method ? Icons.ML_PROTECTED : Icons.FL_PROTECTED); + } else if (Access.isPrivate(access)) { + add(content, selected, method ? Icons.ML_PRIVATE : Icons.FL_PRIVATE); + } else if (Access.isPrivate(access)) { + add(content, selected, method ? Icons.ML_PRIVATE : Icons.FL_PRIVATE); + } else { + add(content, selected, method ? Icons.ML_DEFAULT : Icons.FL_DEFAULT); + } + if (Access.isAbstract(access)) { + add(content, selected, MOD_ABSTRACT); + } + if (Access.isFinal(access)) { + add(content, selected, MOD_FINAL); + } + if (Access.isNative(access)) { + add(content, selected, MOD_NATIVE); + } + if (Access.isStatic(access)) { + add(content, selected, MOD_STATIC); + } + if (Access.isTransient(access)) { + add(content, selected, MOD_TRANSIENT); + } + if (Access.isVolatile(access)) { + add(content, selected, MOD_VOLATILE); + } + if (Access.isSynthetic(access) || Access.isBridge(access)) { + add(content, selected, MOD_SYNTHETIC); + } + } - private void add(JPanel content, boolean selected, Icon icon) { - JLabel lbl = new JLabel(icon); - lbl.setPreferredSize(new Dimension(18,16)); - formatComponent(lbl, selected); - content.add(lbl); - } + private void add(JPanel content, boolean selected, Icon icon) { + JLabel lbl = new JLabel(icon); + lbl.setPreferredSize(new Dimension(18,16)); + formatComponent(lbl, selected); + content.add(lbl); + } - private void formatComponent(JComponent component, boolean selected) { - component.setOpaque(true); - component.setBorder(BorderFactory.createEtchedBorder()); - if (selected) { - component.setBackground(Color.white); - } else { - component.setBackground(bg); - } - } + private void formatComponent(JComponent component, boolean selected) { + component.setOpaque(true); + component.setBorder(BorderFactory.createEtchedBorder()); + if (selected) { + component.setBackground(Color.white); + } else { + component.setBackground(bg); + } + } - private String formatField(FieldNode node) { - return italic(color(colBlueDark, getTypeStr(Type.getType(node.desc), options))) + " " + escape(node.name); - } + private String formatField(FieldNode node) { + return italic(color(colBlueDark, getTypeStr(Type.getType(node.desc), options))) + " " + escape(node.name); + } - private String formatMethod(MethodNode node) { - Type typeMethod = Type.getMethodType(node.desc); - // Args string - String args = ""; - for (Type t : typeMethod.getArgumentTypes()) { - args += getTypeStr(t, options) + ", "; - } - if (args.endsWith(", ")) { - args = args.substring(0, args.length() - 2); - } - String s = italic(color(colBlueDark, getTypeStr(typeMethod.getReturnType(), options))) + " "; - s += color(colRedDark, escape(node.name)) + "("; - s += color(colTealDark, args); - s += ")"; - return s; - } + private String formatMethod(MethodNode node) { + Type typeMethod = Type.getMethodType(node.desc); + // Args string + String args = ""; + for (Type t : typeMethod.getArgumentTypes()) { + args += getTypeStr(t, options) + ", "; + } + if (args.endsWith(", ")) { + args = args.substring(0, args.length() - 2); + } + String s = italic(color(colBlueDark, getTypeStr(typeMethod.getReturnType(), options))) + " "; + s += color(colRedDark, escape(node.name)) + "("; + s += color(colTealDark, args); + s += ")"; + return s; + } } diff --git a/src/me/coley/recaf/ui/component/list/OpcodeCellRenderer.java b/src/me/coley/recaf/ui/component/list/OpcodeCellRenderer.java index 70a976eaa..bfde6c58c 100644 --- a/src/me/coley/recaf/ui/component/list/OpcodeCellRenderer.java +++ b/src/me/coley/recaf/ui/component/list/OpcodeCellRenderer.java @@ -19,271 +19,271 @@ import me.coley.recaf.ui.HtmlRenderer; public class OpcodeCellRenderer implements HtmlRenderer, ListCellRenderer, Opcodes { - private final MethodNode method; - private final Options options; + private final MethodNode method; + private final Options options; - public OpcodeCellRenderer(MethodNode method, Options options) { - this.method = method; - this.options = options; - } + public OpcodeCellRenderer(MethodNode method, Options options) { + this.method = method; + this.options = options; + } - @Override - public Component getListCellRendererComponent(JList list, AbstractInsnNode value, int index, - boolean isSelected, boolean cellHasFocus) { - OpcodeList opcodeCastedList = (OpcodeList) list; - JLabel label = new JLabel(getOpcodeText(opcodeCastedList, value)); - label.setFont(FontUtil.monospace); - label.setOpaque(true); - label.setBorder(BorderFactory.createEtchedBorder()); - if (isSelected) { - label.setBackground(Color.white); - } else { - label.setBackground(opcodeCastedList.getColorFor(index, value)); - } - return label; - } + @Override + public Component getListCellRendererComponent(JList list, AbstractInsnNode value, int index, + boolean isSelected, boolean cellHasFocus) { + OpcodeList opcodeCastedList = (OpcodeList) list; + JLabel label = new JLabel(getOpcodeText(opcodeCastedList, value)); + label.setFont(FontUtil.monospace); + label.setOpaque(true); + label.setBorder(BorderFactory.createEtchedBorder()); + if (isSelected) { + label.setBackground(Color.white); + } else { + label.setBackground(opcodeCastedList.getColorFor(index, value)); + } + return label; + } - public String getOpcodeText(OpcodeList list, AbstractInsnNode ain) { - int ainIndex = method.instructions.indexOf(ain); - int zeros = String.valueOf(method.instructions.size()).length() - String.valueOf(ainIndex).length() + 1; - String ss = ""; - for (int i = 0; i < zeros; i++) { - ss += " "; - } - String s = "" + color(colGray, ainIndex + ".") + ss + "" + OpcodeUtil.opcodeToName(ain.getOpcode()) + ""; - switch (ain.getType()) { - case AbstractInsnNode.INT_INSN: - // Add int value to string - IntInsnNode insnInt = (IntInsnNode) ain; - s += " " + insnInt.operand; - break; - case AbstractInsnNode.VAR_INSN: - // Add local variable index to string - VarInsnNode insnVar = (VarInsnNode) ain; - s += " " + insnVar.var; - // Add local variable name if possible - if (insnVar.var < method.localVariables.size()) { - LocalVariableNode var = method.localVariables.get(insnVar.var); - String varStr = var.name; - s += color(colBlueDark, italic(" (" + varStr + ") - " + getTypeStr(Type.getType(var.desc), options))); - } else if (insnVar.var == 0 && !Access.isStatic(method.access)) { - // If the local variable doesn't have a name, we can assume at - // index = 0 that it is 'this'. - s += color(colBlueDark, italic(" (this)")); - } - break; - case AbstractInsnNode.TYPE_INSN: - // Add type name to string - TypeInsnNode insnType = (TypeInsnNode) ain; - String typeDeclaredStr = getTypeStr(Type.getType(insnType.desc), options); - s += color(colBlueDark, italic(" " + typeDeclaredStr)); - break; - case AbstractInsnNode.FIELD_INSN: - FieldInsnNode insnField = (FieldInsnNode) ain; - s += " " + italic(color(colBlueDark, getTypeStr(Type.getType(insnField.desc), options))) + " "; - s += color(colRedDark, getTypeStr(Type.getObjectType(insnField.owner), options)) + "." + escape(insnField.name); - break; - case AbstractInsnNode.METHOD_INSN: - MethodInsnNode insnMethod = (MethodInsnNode) ain; - Type typeMethod = Type.getMethodType(insnMethod.desc); - // Args string - String args = ""; - for (Type t : typeMethod.getArgumentTypes()) { - args += getTypeStr(t, options) + ", "; - } - if (args.endsWith(", ")) { - args = args.substring(0, args.length() - 2); - } - s += " " + italic(color(colBlueDark, getTypeStr(typeMethod.getReturnType(), options))) + " "; - s += color(colRedDark, getTypeStr(Type.getObjectType(insnMethod.owner), options)) + "." + escape(insnMethod.name) - + "("; - s += color(colTealDark, args); - s += ")"; - break; - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - InvokeDynamicInsnNode insnIndy = (InvokeDynamicInsnNode) ain; - if (insnIndy.bsmArgs.length >= 2 && insnIndy.bsmArgs[1] instanceof Handle) { - Handle handle = (Handle) insnIndy.bsmArgs[1]; - Type typeIndyOwner = Type.getObjectType(handle.getOwner()); - Type typeIndyDesc = Type.getMethodType(handle.getDesc()); - // args string - String argsIndy = ""; - for (Type t : typeIndyDesc.getArgumentTypes()) { - argsIndy += getTypeStr(t, options) + ", "; - } - if (argsIndy.endsWith(", ")) { - argsIndy = argsIndy.substring(0, argsIndy.length() - 2); - } - s += " " + italic(color(colBlueDark, getTypeStr(typeIndyDesc.getReturnType(), options))) + " "; - s += color(colRedDark, getTypeStr(typeIndyOwner, options)) + "." + escape(handle.getName()) + "("; - s += color(colTealDark, argsIndy); - s += ")"; - } else { - s += " " + italic(color(colGray, "(unknown indy format)")); - } - break; - case AbstractInsnNode.JUMP_INSN: - JumpInsnNode insnJump = (JumpInsnNode) ain; - if (insnJump.label != null) { - s += " " + method.instructions.indexOf(insnJump.label); - } - if (options.opcodeShowJumpHelp) { - //@formatter:off - String z = ""; - switch (ain.getOpcode()) { - case IFEQ : - z = "($0 == 0 -> offset)"; - break; - case IFNE : - z = "($0 != 0 -> offset)"; - break; - case IFLE : - z = "($0 <= 0 -> offset)"; - break; - case IFLT : - z = "($0 < 0 -> offset)"; - break; - case IFGE : - z = "($0 >= 0 -> offset)"; - break; - case IFGT : - z = "($0 > 0 -> offset)"; - break; - case IF_ACMPNE: - z = "($1 != $0 -> offset)"; - break; - case IF_ACMPEQ: - z = "($1 == $0 -> offset)"; - break; - case IF_ICMPEQ: - z = "($1 == $0 -> offset)"; - break; - case IF_ICMPNE: - z = "($1 != $0 -> offset)"; - break; - case IF_ICMPLE: - z = "($1 <= $0 -> offset)"; - break; - case IF_ICMPLT: - z = "($1 < $0 -> offset)"; - break; - case IF_ICMPGE: - z = "($1 >= $0 -> offset)"; - break; - case IF_ICMPGT: - z = "($1 > $0 -> offset)"; - break; - case GOTO : - z = "(-> offset)"; - break; - case JSR : - z = "(-> offset, +address)"; - break; - case IFNULL : - z = "($0 == null -> offset)"; - break; - case IFNONNULL: - z = "($0 != null -> offset)"; - break; - } - //@formatter:on - s += " " + italic(color(colGray, escape(z))); - } - break; - case AbstractInsnNode.LDC_INSN: - LdcInsnNode insnLdc = (LdcInsnNode) ain; - String v = escape(insnLdc.cst.toString()); - boolean extended = false; - if (v.length() > options.ldcMaxLength) { - v = v.substring(0, options.ldcMaxLength); - extended = true; - } - String x = italic(color(colGreenDark, v)); - if (insnLdc.cst instanceof String) { - x = "\"" + x; - if (extended) { - x += italic(color(colGray, " (too long)")); - } - x += "\""; - } - s += " " + x; - break; - case AbstractInsnNode.IINC_INSN: - // Add local variable index to string - IincInsnNode insnIinc = (IincInsnNode) ain; - s += " " + insnIinc.var; - // Add local variable name if possible - if (insnIinc.var < method.localVariables.size()) { - LocalVariableNode var = method.localVariables.get(insnIinc.var); - String varStr = var.name; - s += color(colBlueDark, italic(" (" + varStr + ") ")); - } else if (insnIinc.var == 0 && !Access.isStatic(method.access)) { - // If the local variable doesn't have a name, we can assume at - // index = 0 that it is 'this'. - s += color(colBlueDark, italic(" (this) ")); - } - if (insnIinc.incr > 0) { - s += color(colRedDark, "+" + insnIinc.incr); - } else { - s += color(colRedDark, "-" + insnIinc.incr); - } - break; - case AbstractInsnNode.TABLESWITCH_INSN: - TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; - String o = ""; - for (LabelNode label : insnTableSwitch.labels) { - o += method.instructions.indexOf(label) + ", "; - } - if (o.endsWith(", ")) { - o = o.substring(0, o.length() - 2); - } - int tableDefaultOffset = method.instructions.indexOf(insnTableSwitch.dflt); - s += color(colGray, " range[" + insnTableSwitch.min + "-" + insnTableSwitch.max + "] offsets:[" + o + "] default:" - + tableDefaultOffset); - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; - String u = ""; - for (int i = 0; i < insnLookupSwitch.keys.size(); i++) { - int offset = method.instructions.indexOf(insnLookupSwitch.labels.get(i)); - u += insnLookupSwitch.keys.get(i) + "->" + offset + ", "; - } - if (insnLookupSwitch.dflt != null) { - int offset = method.instructions.indexOf(insnLookupSwitch.dflt); - u += "default:" + offset; - } - if (u.endsWith(", ")) { - u = u.substring(0, u.length() - 2); - } - s += color(colGray, italic(" (" + u + ")")); - break; - case AbstractInsnNode.MULTIANEWARRAY_INSN: - // MultiANewArrayInsnNode insnArray = (MultiANewArrayInsnNode) ain; - // TODO - break; - case AbstractInsnNode.FRAME: - FrameNode fn = (FrameNode) ain; - s = s.replaceAll("F_NEW", OpcodeUtil.opcodeToName(fn.type)); - break; - case AbstractInsnNode.LABEL: - if (options.opcodeSimplifyDescriptors) { - s = s.replace("F_NEW", ""); - } else { - s += " "; - } - s += color(colGray, italic("Label " + bold(list.getLabelName(ain)))); - break; - case AbstractInsnNode.LINE: - LineNumberNode line = (LineNumberNode) ain; - if (options.opcodeSimplifyDescriptors) { - s = s.replace("F_NEW", ""); - } else { - s += " "; - } - s += color(colGray, italic("line #" + line.line)); - break; + public String getOpcodeText(OpcodeList list, AbstractInsnNode ain) { + int ainIndex = method.instructions.indexOf(ain); + int zeros = String.valueOf(method.instructions.size()).length() - String.valueOf(ainIndex).length() + 1; + String ss = ""; + for (int i = 0; i < zeros; i++) { + ss += " "; + } + String s = "" + color(colGray, ainIndex + ".") + ss + "" + OpcodeUtil.opcodeToName(ain.getOpcode()) + ""; + switch (ain.getType()) { + case AbstractInsnNode.INT_INSN: + // Add int value to string + IntInsnNode insnInt = (IntInsnNode) ain; + s += " " + insnInt.operand; + break; + case AbstractInsnNode.VAR_INSN: + // Add local variable index to string + VarInsnNode insnVar = (VarInsnNode) ain; + s += " " + insnVar.var; + // Add local variable name if possible + if (insnVar.var < method.localVariables.size()) { + LocalVariableNode var = method.localVariables.get(insnVar.var); + String varStr = var.name; + s += color(colBlueDark, italic(" (" + varStr + ") - " + getTypeStr(Type.getType(var.desc), options))); + } else if (insnVar.var == 0 && !Access.isStatic(method.access)) { + // If the local variable doesn't have a name, we can assume at + // index = 0 that it is 'this'. + s += color(colBlueDark, italic(" (this)")); + } + break; + case AbstractInsnNode.TYPE_INSN: + // Add type name to string + TypeInsnNode insnType = (TypeInsnNode) ain; + String typeDeclaredStr = getTypeStr(Type.getType(insnType.desc), options); + s += color(colBlueDark, italic(" " + typeDeclaredStr)); + break; + case AbstractInsnNode.FIELD_INSN: + FieldInsnNode insnField = (FieldInsnNode) ain; + s += " " + italic(color(colBlueDark, getTypeStr(Type.getType(insnField.desc), options))) + " "; + s += color(colRedDark, getTypeStr(Type.getObjectType(insnField.owner), options)) + "." + escape(insnField.name); + break; + case AbstractInsnNode.METHOD_INSN: + MethodInsnNode insnMethod = (MethodInsnNode) ain; + Type typeMethod = Type.getMethodType(insnMethod.desc); + // Args string + String args = ""; + for (Type t : typeMethod.getArgumentTypes()) { + args += getTypeStr(t, options) + ", "; + } + if (args.endsWith(", ")) { + args = args.substring(0, args.length() - 2); + } + s += " " + italic(color(colBlueDark, getTypeStr(typeMethod.getReturnType(), options))) + " "; + s += color(colRedDark, getTypeStr(Type.getObjectType(insnMethod.owner), options)) + "." + escape(insnMethod.name) + + "("; + s += color(colTealDark, args); + s += ")"; + break; + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + InvokeDynamicInsnNode insnIndy = (InvokeDynamicInsnNode) ain; + if (insnIndy.bsmArgs.length >= 2 && insnIndy.bsmArgs[1] instanceof Handle) { + Handle handle = (Handle) insnIndy.bsmArgs[1]; + Type typeIndyOwner = Type.getObjectType(handle.getOwner()); + Type typeIndyDesc = Type.getMethodType(handle.getDesc()); + // args string + String argsIndy = ""; + for (Type t : typeIndyDesc.getArgumentTypes()) { + argsIndy += getTypeStr(t, options) + ", "; + } + if (argsIndy.endsWith(", ")) { + argsIndy = argsIndy.substring(0, argsIndy.length() - 2); + } + s += " " + italic(color(colBlueDark, getTypeStr(typeIndyDesc.getReturnType(), options))) + " "; + s += color(colRedDark, getTypeStr(typeIndyOwner, options)) + "." + escape(handle.getName()) + "("; + s += color(colTealDark, argsIndy); + s += ")"; + } else { + s += " " + italic(color(colGray, "(unknown indy format)")); + } + break; + case AbstractInsnNode.JUMP_INSN: + JumpInsnNode insnJump = (JumpInsnNode) ain; + if (insnJump.label != null) { + s += " " + method.instructions.indexOf(insnJump.label); + } + if (options.opcodeShowJumpHelp) { + //@formatter:off + String z = ""; + switch (ain.getOpcode()) { + case IFEQ : + z = "($0 == 0 -> offset)"; + break; + case IFNE : + z = "($0 != 0 -> offset)"; + break; + case IFLE : + z = "($0 <= 0 -> offset)"; + break; + case IFLT : + z = "($0 < 0 -> offset)"; + break; + case IFGE : + z = "($0 >= 0 -> offset)"; + break; + case IFGT : + z = "($0 > 0 -> offset)"; + break; + case IF_ACMPNE: + z = "($1 != $0 -> offset)"; + break; + case IF_ACMPEQ: + z = "($1 == $0 -> offset)"; + break; + case IF_ICMPEQ: + z = "($1 == $0 -> offset)"; + break; + case IF_ICMPNE: + z = "($1 != $0 -> offset)"; + break; + case IF_ICMPLE: + z = "($1 <= $0 -> offset)"; + break; + case IF_ICMPLT: + z = "($1 < $0 -> offset)"; + break; + case IF_ICMPGE: + z = "($1 >= $0 -> offset)"; + break; + case IF_ICMPGT: + z = "($1 > $0 -> offset)"; + break; + case GOTO : + z = "(-> offset)"; + break; + case JSR : + z = "(-> offset, +address)"; + break; + case IFNULL : + z = "($0 == null -> offset)"; + break; + case IFNONNULL: + z = "($0 != null -> offset)"; + break; + } + //@formatter:on + s += " " + italic(color(colGray, escape(z))); + } + break; + case AbstractInsnNode.LDC_INSN: + LdcInsnNode insnLdc = (LdcInsnNode) ain; + String v = escape(insnLdc.cst.toString()); + boolean extended = false; + if (v.length() > options.ldcMaxLength) { + v = v.substring(0, options.ldcMaxLength); + extended = true; + } + String x = italic(color(colGreenDark, v)); + if (insnLdc.cst instanceof String) { + x = "\"" + x; + if (extended) { + x += italic(color(colGray, " (too long)")); + } + x += "\""; + } + s += " " + x; + break; + case AbstractInsnNode.IINC_INSN: + // Add local variable index to string + IincInsnNode insnIinc = (IincInsnNode) ain; + s += " " + insnIinc.var; + // Add local variable name if possible + if (insnIinc.var < method.localVariables.size()) { + LocalVariableNode var = method.localVariables.get(insnIinc.var); + String varStr = var.name; + s += color(colBlueDark, italic(" (" + varStr + ") ")); + } else if (insnIinc.var == 0 && !Access.isStatic(method.access)) { + // If the local variable doesn't have a name, we can assume at + // index = 0 that it is 'this'. + s += color(colBlueDark, italic(" (this) ")); + } + if (insnIinc.incr > 0) { + s += color(colRedDark, "+" + insnIinc.incr); + } else { + s += color(colRedDark, "-" + insnIinc.incr); + } + break; + case AbstractInsnNode.TABLESWITCH_INSN: + TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; + String o = ""; + for (LabelNode label : insnTableSwitch.labels) { + o += method.instructions.indexOf(label) + ", "; + } + if (o.endsWith(", ")) { + o = o.substring(0, o.length() - 2); + } + int tableDefaultOffset = method.instructions.indexOf(insnTableSwitch.dflt); + s += color(colGray, " range[" + insnTableSwitch.min + "-" + insnTableSwitch.max + "] offsets:[" + o + "] default:" + + tableDefaultOffset); + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; + String u = ""; + for (int i = 0; i < insnLookupSwitch.keys.size(); i++) { + int offset = method.instructions.indexOf(insnLookupSwitch.labels.get(i)); + u += insnLookupSwitch.keys.get(i) + "->" + offset + ", "; + } + if (insnLookupSwitch.dflt != null) { + int offset = method.instructions.indexOf(insnLookupSwitch.dflt); + u += "default:" + offset; + } + if (u.endsWith(", ")) { + u = u.substring(0, u.length() - 2); + } + s += color(colGray, italic(" (" + u + ")")); + break; + case AbstractInsnNode.MULTIANEWARRAY_INSN: + // MultiANewArrayInsnNode insnArray = (MultiANewArrayInsnNode) ain; + // TODO + break; + case AbstractInsnNode.FRAME: + FrameNode fn = (FrameNode) ain; + s = s.replaceAll("F_NEW", OpcodeUtil.opcodeToName(fn.type)); + break; + case AbstractInsnNode.LABEL: + if (options.opcodeSimplifyDescriptors) { + s = s.replace("F_NEW", ""); + } else { + s += " "; + } + s += color(colGray, italic("Label " + bold(list.getLabelName(ain)))); + break; + case AbstractInsnNode.LINE: + LineNumberNode line = (LineNumberNode) ain; + if (options.opcodeSimplifyDescriptors) { + s = s.replace("F_NEW", ""); + } else { + s += " "; + } + s += color(colGray, italic("line #" + line.line)); + break; - } - return s + color(colGray, italic(list.getAppendFor(ainIndex, ain))) + ""; - } + } + return s + color(colGray, italic(list.getAppendFor(ainIndex, ain))) + ""; + } } diff --git a/src/me/coley/recaf/ui/component/list/OpcodeKeyListener.java b/src/me/coley/recaf/ui/component/list/OpcodeKeyListener.java index 60a77864c..bfd82a7a6 100644 --- a/src/me/coley/recaf/ui/component/list/OpcodeKeyListener.java +++ b/src/me/coley/recaf/ui/component/list/OpcodeKeyListener.java @@ -4,38 +4,38 @@ import java.awt.event.KeyListener; public class OpcodeKeyListener implements KeyListener { - private final OpcodeList list; - private boolean control, shift; - - public OpcodeKeyListener(OpcodeList list) { - this.list = list; - } - - @Override - public void keyTyped(KeyEvent e) {} - - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_CONTROL) { - control = true; - } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) { - shift = true; - } - update(); - } - - @Override - public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_CONTROL) { - control = false; - } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) { - shift = false; - } - update(); - } - - private void update() { - list.setModifiers(control, shift); - } + private final OpcodeList list; + private boolean control, shift; + + public OpcodeKeyListener(OpcodeList list) { + this.list = list; + } + + @Override + public void keyTyped(KeyEvent e) {} + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_CONTROL) { + control = true; + } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) { + shift = true; + } + update(); + } + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_CONTROL) { + control = false; + } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) { + shift = false; + } + update(); + } + + private void update() { + list.setModifiers(control, shift); + } } diff --git a/src/me/coley/recaf/ui/component/list/OpcodeList.java b/src/me/coley/recaf/ui/component/list/OpcodeList.java index c64273b85..522c34b5b 100644 --- a/src/me/coley/recaf/ui/component/list/OpcodeList.java +++ b/src/me/coley/recaf/ui/component/list/OpcodeList.java @@ -17,143 +17,143 @@ @SuppressWarnings("serial") public class OpcodeList extends JList { - private final Recaf recaf = Recaf.getInstance(); - private static final Color colEntryBG = new Color(200, 200, 200); - private static final Color colListBG = new Color(166, 166, 166); - /** - * The method being viewed. - */ - private final MethodNode method; - /** - * Map of background-color overrides to be drawn by the cell renderer. - */ - private Map colorMap = new HashMap<>(); - /** - * Map of label opcodes to some label name. - */ - private final Map labels = new HashMap<>(); - /** - * Map of appended text to be added to the cell renderer. - */ - private Map appendMap = new HashMap<>(); - /** - * Key modifiers - */ - public boolean controlDown, shiftDown; + private final Recaf recaf = Recaf.getInstance(); + private static final Color colEntryBG = new Color(200, 200, 200); + private static final Color colListBG = new Color(166, 166, 166); + /** + * The method being viewed. + */ + private final MethodNode method; + /** + * Map of background-color overrides to be drawn by the cell renderer. + */ + private Map colorMap = new HashMap<>(); + /** + * Map of label opcodes to some label name. + */ + private final Map labels = new HashMap<>(); + /** + * Map of appended text to be added to the cell renderer. + */ + private Map appendMap = new HashMap<>(); + /** + * Key modifiers + */ + public boolean controlDown, shiftDown; - public OpcodeList(ClassDisplayPanel display, MethodNode method) { - this.method = method; - setBackground(colListBG); - setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - DefaultListModel model = new DefaultListModel<>(); - for (AbstractInsnNode ain : method.instructions.toArray()) { - model.addElement(ain); - } - setModel(model); - setCellRenderer(new OpcodeCellRenderer(method, recaf.options)); - addListSelectionListener(new OpcodeSelectionListener()); - addMouseListener(new OpcodeMouseListener(method, display, this)); - addKeyListener(new OpcodeKeyListener(this)); - int i = 1; - for (AbstractInsnNode ain : method.instructions.toArray()) { - if (ain.getType() == AbstractInsnNode.LABEL) { - labels.put(ain, Integer.toHexString(i++)); - } - } - } + public OpcodeList(ClassDisplayPanel display, MethodNode method) { + this.method = method; + setBackground(colListBG); + setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + DefaultListModel model = new DefaultListModel<>(); + for (AbstractInsnNode ain : method.instructions.toArray()) { + model.addElement(ain); + } + setModel(model); + setCellRenderer(new OpcodeCellRenderer(method, recaf.options)); + addListSelectionListener(new OpcodeSelectionListener()); + addMouseListener(new OpcodeMouseListener(method, display, this)); + addKeyListener(new OpcodeKeyListener(this)); + int i = 1; + for (AbstractInsnNode ain : method.instructions.toArray()) { + if (ain.getType() == AbstractInsnNode.LABEL) { + labels.put(ain, Integer.toHexString(i++)); + } + } + } - /** - * Re-populate the model. - */ - public void repopulate() { - DefaultListModel model = (DefaultListModel) getModel(); - model.clear(); - for (AbstractInsnNode ain : method.instructions.toArray()) { - model.addElement(ain); - } - setModel(model); - } + /** + * Re-populate the model. + */ + public void repopulate() { + DefaultListModel model = (DefaultListModel) getModel(); + model.clear(); + for (AbstractInsnNode ain : method.instructions.toArray()) { + model.addElement(ain); + } + setModel(model); + } - /** - * Get the background color for the given opcode. - * - * @param index Opcode index. - * @param value Opcode value. - * @return Background color. - */ - public Color getColorFor(int index, AbstractInsnNode value) { - if (colorMap.containsKey(value)) { - return colorMap.get(value); - } - return colEntryBG; - } + /** + * Get the background color for the given opcode. + * + * @param index Opcode index. + * @param value Opcode value. + * @return Background color. + */ + public Color getColorFor(int index, AbstractInsnNode value) { + if (colorMap.containsKey(value)) { + return colorMap.get(value); + } + return colEntryBG; + } - /** - * Get the appended text for the given opcode. - * - * @param index Opcode index. - * @param value Opcode value. - * @return appended text. - */ - public String getAppendFor(int index, AbstractInsnNode value) { - if (appendMap.containsKey(value)) { - return appendMap.get(value); - } - return ""; - } + /** + * Get the appended text for the given opcode. + * + * @param index Opcode index. + * @param value Opcode value. + * @return appended text. + */ + public String getAppendFor(int index, AbstractInsnNode value) { + if (appendMap.containsKey(value)) { + return appendMap.get(value); + } + return ""; + } - /** - * Get the arbitrary label identifier for the given label opcode. - * - * @param ain Label opcode. - * @return label identifier. - */ - public String getLabelName(AbstractInsnNode ain) { - return labels.getOrDefault(ain, "(New Label)"); - } + /** + * Get the arbitrary label identifier for the given label opcode. + * + * @param ain Label opcode. + * @return label identifier. + */ + public String getLabelName(AbstractInsnNode ain) { + return labels.getOrDefault(ain, "(New Label)"); + } - /** - * Get the method node associated with the list. - * - * @return the method node. - */ - public MethodNode getMethod() { - return method; - } + /** + * Get the method node associated with the list. + * + * @return the method node. + */ + public MethodNode getMethod() { + return method; + } - /** - * Getter for {@link #colorMap}. - * - * @return Map associating AbstractInsnNode instances with their - * colors. - */ - public Map getColorMap() { - return colorMap; - } + /** + * Getter for {@link #colorMap}. + * + * @return Map associating AbstractInsnNode instances with their + * colors. + */ + public Map getColorMap() { + return colorMap; + } - /** - * Getter for {@link #appendMap}. - * - * @return Map associated AbstractInsnNode instances with their - * appended text. - */ - public Map getAppendMap() { - return appendMap; - } + /** + * Getter for {@link #appendMap}. + * + * @return Map associated AbstractInsnNode instances with their + * appended text. + */ + public Map getAppendMap() { + return appendMap; + } - /** - * Set key-modifiers. - * - * @param control TODO - * @param shift TODO - * - * TODO: What do control and shift correspond to? What is this method - * for? - * - * - Charles - */ - public void setModifiers(boolean control, boolean shift) { - this.controlDown = control; - this.shiftDown = shift; - } + /** + * Set key-modifiers. + * + * @param control TODO + * @param shift TODO + * + * TODO: What do control and shift correspond to? What is this method + * for? + * + * - Charles + */ + public void setModifiers(boolean control, boolean shift) { + this.controlDown = control; + this.shiftDown = shift; + } } diff --git a/src/me/coley/recaf/ui/component/list/OpcodeMouseListener.java b/src/me/coley/recaf/ui/component/list/OpcodeMouseListener.java index 82a8d78e8..68c7649e8 100644 --- a/src/me/coley/recaf/ui/component/list/OpcodeMouseListener.java +++ b/src/me/coley/recaf/ui/component/list/OpcodeMouseListener.java @@ -31,233 +31,233 @@ import me.coley.recaf.util.Misc; public class OpcodeMouseListener implements ReleaseListener { - private final Recaf recaf = Recaf.getInstance(); - private final MethodNode method; - private final OpcodeList list; - private final ClassDisplayPanel display; + private final Recaf recaf = Recaf.getInstance(); + private final MethodNode method; + private final OpcodeList list; + private final ClassDisplayPanel display; - public OpcodeMouseListener(MethodNode method, ClassDisplayPanel display, OpcodeList list) { - this.method = method; - this.display = display; - this.list = list; - } + public OpcodeMouseListener(MethodNode method, ClassDisplayPanel display, OpcodeList list) { + this.method = method; + this.display = display; + this.list = list; + } - @Override - public void mouseReleased(MouseEvent e) { - int button = e.getButton(); + @Override + public void mouseReleased(MouseEvent e) { + int button = e.getButton(); - if (list.getSelectedIndices().length == 1) { - // If not left-click, enforce selection at the given location - if (button != MouseEvent.BUTTON1) { - int index = list.locationToIndex(e.getPoint()); - list.setSelectedIndex(index); - } - } + if (list.getSelectedIndices().length == 1) { + // If not left-click, enforce selection at the given location + if (button != MouseEvent.BUTTON1) { + int index = list.locationToIndex(e.getPoint()); + list.setSelectedIndex(index); + } + } - Object value = list.getSelectedValue(); - if (value == null) { - return; - } - if (button == MouseEvent.BUTTON3) { - createContextMenu((AbstractInsnNode) value, e.getX(), e.getY()); - } else if (button == MouseEvent.BUTTON2) { - createEdit((AbstractInsnNode) value, e.getX(), e.getY()); - } - } + Object value = list.getSelectedValue(); + if (value == null) { + return; + } + if (button == MouseEvent.BUTTON3) { + createContextMenu((AbstractInsnNode) value, e.getX(), e.getY()); + } else if (button == MouseEvent.BUTTON2) { + createEdit((AbstractInsnNode) value, e.getX(), e.getY()); + } + } - private void createContextMenu(AbstractInsnNode ain, int x, int y) { - JPopupMenu popup = new JPopupMenu(); - ActionMenuItem itemEdit = new ActionMenuItem("Edit", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - createEdit(ain, x, y); - } - })); - popup.add(itemEdit); - ActionMenuItem itemNewBefore = new ActionMenuItem("New Opcode Before...", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - display.addWindow(new OpcodeCreationBox(true, list, method, ain)); - } - })); - popup.add(itemNewBefore); - ActionMenuItem itemNewAfter = new ActionMenuItem("New Opcode After...", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - display.addWindow(new OpcodeCreationBox(false, list, method, ain)); - } - })); - popup.add(itemNewAfter); - ActionMenuItem itemRemove = new ActionMenuItem("Remove", (new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (recaf.options.confirmDeletions) { - int dialogResult = JOptionPane.showConfirmDialog(null, "You sure you want to delete that opcode?", "Warning", - JOptionPane.YES_NO_OPTION); - if (dialogResult != JOptionPane.YES_OPTION) { - return; - } - } - DefaultListModel model = (DefaultListModel) list.getModel(); - int[] descending = new int[list.getSelectedIndices().length]; - if (descending.length > 1) { - // sort the list and remove highest index objects first - for (int i = 0; i < descending.length; i++) { - descending[i] = list.getSelectedIndices()[i]; - } - Arrays.sort(descending); - for (int i = 0; i < descending.length; i++) { - int j = descending[descending.length - 1 - i]; - model.remove(j); - method.instructions.remove(method.instructions.get(j)); - } - } else { - model.remove(list.getSelectedIndex()); - method.instructions.remove(ain); - } + private void createContextMenu(AbstractInsnNode ain, int x, int y) { + JPopupMenu popup = new JPopupMenu(); + ActionMenuItem itemEdit = new ActionMenuItem("Edit", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + createEdit(ain, x, y); + } + })); + popup.add(itemEdit); + ActionMenuItem itemNewBefore = new ActionMenuItem("New Opcode Before...", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + display.addWindow(new OpcodeCreationBox(true, list, method, ain)); + } + })); + popup.add(itemNewBefore); + ActionMenuItem itemNewAfter = new ActionMenuItem("New Opcode After...", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + display.addWindow(new OpcodeCreationBox(false, list, method, ain)); + } + })); + popup.add(itemNewAfter); + ActionMenuItem itemRemove = new ActionMenuItem("Remove", (new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (recaf.options.confirmDeletions) { + int dialogResult = JOptionPane.showConfirmDialog(null, "You sure you want to delete that opcode?", "Warning", + JOptionPane.YES_NO_OPTION); + if (dialogResult != JOptionPane.YES_OPTION) { + return; + } + } + DefaultListModel model = (DefaultListModel) list.getModel(); + int[] descending = new int[list.getSelectedIndices().length]; + if (descending.length > 1) { + // sort the list and remove highest index objects first + for (int i = 0; i < descending.length; i++) { + descending[i] = list.getSelectedIndices()[i]; + } + Arrays.sort(descending); + for (int i = 0; i < descending.length; i++) { + int j = descending[descending.length - 1 - i]; + model.remove(j); + method.instructions.remove(method.instructions.get(j)); + } + } else { + model.remove(list.getSelectedIndex()); + method.instructions.remove(ain); + } - } - })); - popup.add(itemRemove); - popup.show(list, x, y); - } + } + })); + popup.add(itemRemove); + popup.show(list, x, y); + } - private void createEdit(AbstractInsnNode ain, int x, int y) { - EditBox frame = new EditBox("Opcode: " + OpcodeUtil.opcodeToName(ain.getOpcode())); - switch (ain.getType()) { - case AbstractInsnNode.INT_INSN: - IntInsnNode insnInt = (IntInsnNode) ain; - frame.add(new LabeledComponent("Value: ", new ActionTextField(insnInt.operand, s -> { - if (Misc.isInt(s)) { - insnInt.operand = Integer.parseInt(s); - } - }))); - break; - case AbstractInsnNode.VAR_INSN: - VarInsnNode insnVar = (VarInsnNode) ain; - frame.add(new JScrollPane(VariableTable.create(list, method))); - frame.add(new LabeledComponent("Variable Index: ", new ActionTextField(insnVar.var, s -> { - if (Misc.isInt(s)) { - insnVar.var = Integer.parseInt(s); - } - }))); - break; - case AbstractInsnNode.TYPE_INSN: - TypeInsnNode insnType = (TypeInsnNode) ain; - frame.add(new LabeledComponent("Type: ", new ActionTextField(insnType.desc, s -> insnType.desc = s))); - break; - case AbstractInsnNode.FIELD_INSN: - FieldInsnNode insnField = (FieldInsnNode) ain; - frame.add(new LabeledComponent("Owner: ", new ActionTextField(insnField.owner, s -> insnField.owner = s))); - frame.add(new LabeledComponent("Name: ", new ActionTextField(insnField.name, s -> insnField.name = s))); - frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnField.desc, s -> insnField.desc = s))); - break; - case AbstractInsnNode.METHOD_INSN: - MethodInsnNode insnMethod = (MethodInsnNode) ain; - frame.add(new LabeledComponent("Owner: ", new ActionTextField(insnMethod.owner, s -> insnMethod.owner = s))); - frame.add(new LabeledComponent("Name: ", new ActionTextField(insnMethod.name, s -> insnMethod.name = s))); - frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnMethod.desc, s -> insnMethod.desc = s))); - // ITF is labeled so it's not a centered checkbox. - frame.add(new LabeledComponent("", new ActionCheckBox("Owner is Interface (ITF)", insnMethod.itf, - b -> insnMethod.itf = b))); - break; - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - InvokeDynamicInsnNode insnIndy = (InvokeDynamicInsnNode) ain; - if (insnIndy.bsmArgs.length > 2 && insnIndy.bsmArgs[1] instanceof Handle) { - Handle h = (Handle) insnIndy.bsmArgs[1]; - frame.add(new LabeledComponent("Name: ", new ActionTextField(h.getName(), s -> Misc.set(h, "name", s)))); - frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(h.getDesc(), s -> Misc.set(h, "desc", s)))); - frame.add(new LabeledComponent("Owner: ", new ActionTextField(h.getOwner(), s -> Misc.set(h, "owner", s)))); - frame.add(new LabeledComponent("IsInterface: ", new ActionTextField(h.isInterface(), s -> Misc.setBoolean( - insnIndy.bsm, "itf", s)))); - frame.add(new TagTypeSwitchPanel(list, h)); - } - break; - case AbstractInsnNode.JUMP_INSN: - JumpInsnNode insnJump = (JumpInsnNode) ain; - frame.add(new LabelSwitcherPanel(list, method, insnJump.label, l -> insnJump.label = l)); - break; - case AbstractInsnNode.LDC_INSN: - LdcInsnNode insnLdc = (LdcInsnNode) ain; - frame.add(new LabeledComponent("Value: ", new ActionTextField(insnLdc.cst, s -> { - if (insnLdc.cst instanceof String) { - insnLdc.cst = s; - } else if (Misc.isInt(s)) { - insnLdc.cst = Integer.parseInt(s); - } - }))); - break; - case AbstractInsnNode.IINC_INSN: - IincInsnNode insnIinc = (IincInsnNode) ain; - frame.add(new JScrollPane(VariableTable.create(list, method))); - frame.add(new LabeledComponent("Variable Index: ", new ActionTextField(insnIinc.var, s -> { - if (Misc.isInt(s)) { - insnIinc.var = Integer.parseInt(s); - } - }))); - break; - case AbstractInsnNode.TABLESWITCH_INSN: - TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; - frame.add(new LabeledComponent("Default: ", new LabelSwitcherPanel(list, method, insnTableSwitch.dflt, - l -> insnTableSwitch.dflt = l))); - for (int i = 0; i < insnTableSwitch.labels.size(); i++) { - final int fi = i; - LabelNode label = insnTableSwitch.labels.get(i); - int j = insnTableSwitch.min + i; - frame.add(new LabeledComponent(j + ": ", new LabelSwitcherPanel(list, method, label, l -> insnTableSwitch.labels - .set(fi, l)))); - } - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; - frame.add(new LabeledComponent("Default: ", new LabelSwitcherPanel(list, method, insnLookupSwitch.dflt, - l -> insnLookupSwitch.dflt = l))); - for (int i = 0; i < insnLookupSwitch.labels.size(); i++) { - final int fi = i; - LabelNode label = insnLookupSwitch.labels.get(i); - int j = insnLookupSwitch.keys.get(i); - frame.add(new LabeledComponent(j + ": ", new LabelSwitcherPanel(list, method, label, l -> insnLookupSwitch.labels - .set(fi, l)))); - } - break; - case AbstractInsnNode.MULTIANEWARRAY_INSN: - MultiANewArrayInsnNode insnArray = (MultiANewArrayInsnNode) ain; - frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnArray.desc, s -> insnArray.desc = s))); - frame.add(new LabeledComponent("Dimensions: ", new ActionTextField(insnArray.dims, s -> { - if (Misc.isInt(s)) { - insnArray.dims = Integer.parseInt(s); - } - }))); - break; - case AbstractInsnNode.FRAME: - // TODO - FrameNode insnFrame = (FrameNode) ain; - break; - case AbstractInsnNode.LINE: - LineNumberNode insnLine = (LineNumberNode) ain; - frame.add(new LabeledComponent("Line: ", new ActionTextField(insnLine.line, s -> { - if (Misc.isInt(s)) { - insnLine.line = Integer.parseInt(s); - } - }))); - frame.add(new LabeledComponent("Start: ", new LabelSwitcherPanel(list, method, insnLine.start, - l -> insnLine.start = l))); - break; - } - OpcodeTypeSwitchPanel opSelector = new OpcodeTypeSwitchPanel(list, ain); - if (opSelector.getOptionCount() > 0) { - frame.add(opSelector); - } - // Tell the user the empty box is intentional. - if (!frame.hasContent()) { - JLabel nothing = new JLabel("Nothing to edit"); - nothing.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - frame.add(nothing); - } - display.addWindow(frame); - // TODO: Reliable way of positioning frame in a reasonable place (near - // the mouse) - // frame.setLocation(x, y); - frame.setVisible(true); - } + private void createEdit(AbstractInsnNode ain, int x, int y) { + EditBox frame = new EditBox("Opcode: " + OpcodeUtil.opcodeToName(ain.getOpcode())); + switch (ain.getType()) { + case AbstractInsnNode.INT_INSN: + IntInsnNode insnInt = (IntInsnNode) ain; + frame.add(new LabeledComponent("Value: ", new ActionTextField(insnInt.operand, s -> { + if (Misc.isInt(s)) { + insnInt.operand = Integer.parseInt(s); + } + }))); + break; + case AbstractInsnNode.VAR_INSN: + VarInsnNode insnVar = (VarInsnNode) ain; + frame.add(new JScrollPane(VariableTable.create(list, method))); + frame.add(new LabeledComponent("Variable Index: ", new ActionTextField(insnVar.var, s -> { + if (Misc.isInt(s)) { + insnVar.var = Integer.parseInt(s); + } + }))); + break; + case AbstractInsnNode.TYPE_INSN: + TypeInsnNode insnType = (TypeInsnNode) ain; + frame.add(new LabeledComponent("Type: ", new ActionTextField(insnType.desc, s -> insnType.desc = s))); + break; + case AbstractInsnNode.FIELD_INSN: + FieldInsnNode insnField = (FieldInsnNode) ain; + frame.add(new LabeledComponent("Owner: ", new ActionTextField(insnField.owner, s -> insnField.owner = s))); + frame.add(new LabeledComponent("Name: ", new ActionTextField(insnField.name, s -> insnField.name = s))); + frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnField.desc, s -> insnField.desc = s))); + break; + case AbstractInsnNode.METHOD_INSN: + MethodInsnNode insnMethod = (MethodInsnNode) ain; + frame.add(new LabeledComponent("Owner: ", new ActionTextField(insnMethod.owner, s -> insnMethod.owner = s))); + frame.add(new LabeledComponent("Name: ", new ActionTextField(insnMethod.name, s -> insnMethod.name = s))); + frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnMethod.desc, s -> insnMethod.desc = s))); + // ITF is labeled so it's not a centered checkbox. + frame.add(new LabeledComponent("", new ActionCheckBox("Owner is Interface (ITF)", insnMethod.itf, + b -> insnMethod.itf = b))); + break; + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + InvokeDynamicInsnNode insnIndy = (InvokeDynamicInsnNode) ain; + if (insnIndy.bsmArgs.length > 2 && insnIndy.bsmArgs[1] instanceof Handle) { + Handle h = (Handle) insnIndy.bsmArgs[1]; + frame.add(new LabeledComponent("Name: ", new ActionTextField(h.getName(), s -> Misc.set(h, "name", s)))); + frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(h.getDesc(), s -> Misc.set(h, "desc", s)))); + frame.add(new LabeledComponent("Owner: ", new ActionTextField(h.getOwner(), s -> Misc.set(h, "owner", s)))); + frame.add(new LabeledComponent("IsInterface: ", new ActionTextField(h.isInterface(), s -> Misc.setBoolean( + insnIndy.bsm, "itf", s)))); + frame.add(new TagTypeSwitchPanel(list, h)); + } + break; + case AbstractInsnNode.JUMP_INSN: + JumpInsnNode insnJump = (JumpInsnNode) ain; + frame.add(new LabelSwitcherPanel(list, method, insnJump.label, l -> insnJump.label = l)); + break; + case AbstractInsnNode.LDC_INSN: + LdcInsnNode insnLdc = (LdcInsnNode) ain; + frame.add(new LabeledComponent("Value: ", new ActionTextField(insnLdc.cst, s -> { + if (insnLdc.cst instanceof String) { + insnLdc.cst = s; + } else if (Misc.isInt(s)) { + insnLdc.cst = Integer.parseInt(s); + } + }))); + break; + case AbstractInsnNode.IINC_INSN: + IincInsnNode insnIinc = (IincInsnNode) ain; + frame.add(new JScrollPane(VariableTable.create(list, method))); + frame.add(new LabeledComponent("Variable Index: ", new ActionTextField(insnIinc.var, s -> { + if (Misc.isInt(s)) { + insnIinc.var = Integer.parseInt(s); + } + }))); + break; + case AbstractInsnNode.TABLESWITCH_INSN: + TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; + frame.add(new LabeledComponent("Default: ", new LabelSwitcherPanel(list, method, insnTableSwitch.dflt, + l -> insnTableSwitch.dflt = l))); + for (int i = 0; i < insnTableSwitch.labels.size(); i++) { + final int fi = i; + LabelNode label = insnTableSwitch.labels.get(i); + int j = insnTableSwitch.min + i; + frame.add(new LabeledComponent(j + ": ", new LabelSwitcherPanel(list, method, label, l -> insnTableSwitch.labels + .set(fi, l)))); + } + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; + frame.add(new LabeledComponent("Default: ", new LabelSwitcherPanel(list, method, insnLookupSwitch.dflt, + l -> insnLookupSwitch.dflt = l))); + for (int i = 0; i < insnLookupSwitch.labels.size(); i++) { + final int fi = i; + LabelNode label = insnLookupSwitch.labels.get(i); + int j = insnLookupSwitch.keys.get(i); + frame.add(new LabeledComponent(j + ": ", new LabelSwitcherPanel(list, method, label, l -> insnLookupSwitch.labels + .set(fi, l)))); + } + break; + case AbstractInsnNode.MULTIANEWARRAY_INSN: + MultiANewArrayInsnNode insnArray = (MultiANewArrayInsnNode) ain; + frame.add(new LabeledComponent("Descriptor: ", new ActionTextField(insnArray.desc, s -> insnArray.desc = s))); + frame.add(new LabeledComponent("Dimensions: ", new ActionTextField(insnArray.dims, s -> { + if (Misc.isInt(s)) { + insnArray.dims = Integer.parseInt(s); + } + }))); + break; + case AbstractInsnNode.FRAME: + // TODO + FrameNode insnFrame = (FrameNode) ain; + break; + case AbstractInsnNode.LINE: + LineNumberNode insnLine = (LineNumberNode) ain; + frame.add(new LabeledComponent("Line: ", new ActionTextField(insnLine.line, s -> { + if (Misc.isInt(s)) { + insnLine.line = Integer.parseInt(s); + } + }))); + frame.add(new LabeledComponent("Start: ", new LabelSwitcherPanel(list, method, insnLine.start, + l -> insnLine.start = l))); + break; + } + OpcodeTypeSwitchPanel opSelector = new OpcodeTypeSwitchPanel(list, ain); + if (opSelector.getOptionCount() > 0) { + frame.add(opSelector); + } + // Tell the user the empty box is intentional. + if (!frame.hasContent()) { + JLabel nothing = new JLabel("Nothing to edit"); + nothing.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + frame.add(nothing); + } + display.addWindow(frame); + // TODO: Reliable way of positioning frame in a reasonable place (near + // the mouse) + // frame.setLocation(x, y); + frame.setVisible(true); + } } diff --git a/src/me/coley/recaf/ui/component/list/OpcodeSelectionListener.java b/src/me/coley/recaf/ui/component/list/OpcodeSelectionListener.java index d48414b38..9feabbcfe 100644 --- a/src/me/coley/recaf/ui/component/list/OpcodeSelectionListener.java +++ b/src/me/coley/recaf/ui/component/list/OpcodeSelectionListener.java @@ -8,96 +8,96 @@ import org.objectweb.asm.tree.*; public class OpcodeSelectionListener implements ListSelectionListener, Opcodes { - // Jumps - private static final Color colJumpFail = new Color(250, 200, 200); - private static final Color colJumpSuccess = new Color(200, 250, 200); - private static final Color colJumpRange = new Color(220, 220, 170); - // Labels - private static final Color colDestinationReference = new Color(247, 255, 191); + // Jumps + private static final Color colJumpFail = new Color(250, 200, 200); + private static final Color colJumpSuccess = new Color(200, 250, 200); + private static final Color colJumpRange = new Color(220, 220, 170); + // Labels + private static final Color colDestinationReference = new Color(247, 255, 191); - @Override - public void valueChanged(ListSelectionEvent e) { - // TODO: getValueIsAdjusting = true for keyboard up/down - // getValueIsAdjusting = false for mouse press (true release) - // - // Should find a way so this isn't called twice but is instant for both. - /* - * if (e.getValueIsAdjusting()) { return; } - */ - OpcodeList list = (OpcodeList) e.getSource(); - boolean multiple = list.getMaxSelectionIndex() != list.getMinSelectionIndex(); - AbstractInsnNode selected = list.getSelectedValue(); - list.getColorMap().clear(); - list.getAppendMap().clear(); - list.repaint(); - if (!multiple && selected != null) { - int op = selected.getOpcode(); - switch (selected.getType()) { - case AbstractInsnNode.LABEL: - MethodNode method = list.getMethod(); - for (AbstractInsnNode ain : method.instructions.toArray()) { - if (ain.getType() == AbstractInsnNode.JUMP_INSN) { - JumpInsnNode insnJump = (JumpInsnNode) ain; - if (insnJump.label.equals(selected)) { - list.getColorMap().put(insnJump, colDestinationReference); - } - } else if (ain.getType() == AbstractInsnNode.TABLESWITCH_INSN) { - TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; - if (selected.equals(insnTableSwitch.dflt)) { - list.getColorMap().put(insnTableSwitch, colDestinationReference); - } - for (LabelNode ln : insnTableSwitch.labels) { - if (selected.equals(ln)) { - list.getColorMap().put(insnTableSwitch, colDestinationReference); - } - } - } else if (ain.getType() == AbstractInsnNode.LOOKUPSWITCH_INSN) { - LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; - if (selected.equals(insnLookupSwitch.dflt)) { - list.getColorMap().put(insnLookupSwitch, colDestinationReference); - } - for (LabelNode ln : insnLookupSwitch.labels) { - if (selected.equals(ln)) { - list.getColorMap().put(insnLookupSwitch, colDestinationReference); - } - } - } - } - break; - case AbstractInsnNode.JUMP_INSN: - JumpInsnNode insnJump = (JumpInsnNode) selected; - if (op != GOTO && op != JSR) { - list.getColorMap().put(insnJump.getNext(), colJumpFail); - } - list.getColorMap().put(insnJump.label, colJumpSuccess); - break; - case AbstractInsnNode.TABLESWITCH_INSN: - TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) selected; - int diff = insnTableSwitch.max - insnTableSwitch.min; - for (int i = 0; i <= diff; i++) { - int key = i + insnTableSwitch.min; - LabelNode label = insnTableSwitch.labels.get(i); - list.getAppendMap().put(label, " [switch key: " + key + "]"); - list.getColorMap().put(label, colJumpRange); - } - for (LabelNode label : insnTableSwitch.labels) { - list.getColorMap().put(label, colJumpRange); - } - list.getColorMap().put(insnTableSwitch.dflt, colJumpFail); - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) selected; - for (int i = 0; i < insnLookupSwitch.keys.size(); i++) { - int key = insnLookupSwitch.keys.get(i); - LabelNode label = insnLookupSwitch.labels.get(i); - list.getAppendMap().put(label, " [switch key: " + key + "]"); - list.getColorMap().put(label, colJumpRange); - } - list.getColorMap().put(insnLookupSwitch.dflt, colJumpFail); - break; - } - } - } + @Override + public void valueChanged(ListSelectionEvent e) { + // TODO: getValueIsAdjusting = true for keyboard up/down + // getValueIsAdjusting = false for mouse press (true release) + // + // Should find a way so this isn't called twice but is instant for both. + /* + * if (e.getValueIsAdjusting()) { return; } + */ + OpcodeList list = (OpcodeList) e.getSource(); + boolean multiple = list.getMaxSelectionIndex() != list.getMinSelectionIndex(); + AbstractInsnNode selected = list.getSelectedValue(); + list.getColorMap().clear(); + list.getAppendMap().clear(); + list.repaint(); + if (!multiple && selected != null) { + int op = selected.getOpcode(); + switch (selected.getType()) { + case AbstractInsnNode.LABEL: + MethodNode method = list.getMethod(); + for (AbstractInsnNode ain : method.instructions.toArray()) { + if (ain.getType() == AbstractInsnNode.JUMP_INSN) { + JumpInsnNode insnJump = (JumpInsnNode) ain; + if (insnJump.label.equals(selected)) { + list.getColorMap().put(insnJump, colDestinationReference); + } + } else if (ain.getType() == AbstractInsnNode.TABLESWITCH_INSN) { + TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) ain; + if (selected.equals(insnTableSwitch.dflt)) { + list.getColorMap().put(insnTableSwitch, colDestinationReference); + } + for (LabelNode ln : insnTableSwitch.labels) { + if (selected.equals(ln)) { + list.getColorMap().put(insnTableSwitch, colDestinationReference); + } + } + } else if (ain.getType() == AbstractInsnNode.LOOKUPSWITCH_INSN) { + LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) ain; + if (selected.equals(insnLookupSwitch.dflt)) { + list.getColorMap().put(insnLookupSwitch, colDestinationReference); + } + for (LabelNode ln : insnLookupSwitch.labels) { + if (selected.equals(ln)) { + list.getColorMap().put(insnLookupSwitch, colDestinationReference); + } + } + } + } + break; + case AbstractInsnNode.JUMP_INSN: + JumpInsnNode insnJump = (JumpInsnNode) selected; + if (op != GOTO && op != JSR) { + list.getColorMap().put(insnJump.getNext(), colJumpFail); + } + list.getColorMap().put(insnJump.label, colJumpSuccess); + break; + case AbstractInsnNode.TABLESWITCH_INSN: + TableSwitchInsnNode insnTableSwitch = (TableSwitchInsnNode) selected; + int diff = insnTableSwitch.max - insnTableSwitch.min; + for (int i = 0; i <= diff; i++) { + int key = i + insnTableSwitch.min; + LabelNode label = insnTableSwitch.labels.get(i); + list.getAppendMap().put(label, " [switch key: " + key + "]"); + list.getColorMap().put(label, colJumpRange); + } + for (LabelNode label : insnTableSwitch.labels) { + list.getColorMap().put(label, colJumpRange); + } + list.getColorMap().put(insnTableSwitch.dflt, colJumpFail); + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + LookupSwitchInsnNode insnLookupSwitch = (LookupSwitchInsnNode) selected; + for (int i = 0; i < insnLookupSwitch.keys.size(); i++) { + int key = insnLookupSwitch.keys.get(i); + LabelNode label = insnLookupSwitch.labels.get(i); + list.getAppendMap().put(label, " [switch key: " + key + "]"); + list.getColorMap().put(label, colJumpRange); + } + list.getColorMap().put(insnLookupSwitch.dflt, colJumpFail); + break; + } + } + } } diff --git a/src/me/coley/recaf/ui/component/panel/AccessPanel.java b/src/me/coley/recaf/ui/component/panel/AccessPanel.java index 434fb9779..3fb17e87d 100644 --- a/src/me/coley/recaf/ui/component/panel/AccessPanel.java +++ b/src/me/coley/recaf/ui/component/panel/AccessPanel.java @@ -21,101 +21,101 @@ @SuppressWarnings("serial") public class AccessPanel extends JPanel { - public final static String TITLE_CLASS = "Class Access"; - public final static String TITLE_FIELD = "Field Access"; - public final static String TITLE_METHOD = "Method Access"; - public final static String TITLE_PARAMETER = "Parameter Access"; - private final Map compToAccess = new HashMap<>(); - private final Consumer action; - private final String title; + public final static String TITLE_CLASS = "Class Access"; + public final static String TITLE_FIELD = "Field Access"; + public final static String TITLE_METHOD = "Method Access"; + public final static String TITLE_PARAMETER = "Parameter Access"; + private final Map compToAccess = new HashMap<>(); + private final Consumer action; + private final String title; - public AccessPanel(ClassNode clazz, JComponent owner) throws Exception { - this(AccessPanel.TITLE_CLASS + ": " + clazz.name, clazz.access, acc -> clazz.access = acc, owner); - } + public AccessPanel(ClassNode clazz, JComponent owner) throws Exception { + this(AccessPanel.TITLE_CLASS + ": " + clazz.name, clazz.access, acc -> clazz.access = acc, owner); + } - public AccessPanel(FieldNode field, JComponent owner) throws Exception { - this(AccessPanel.TITLE_FIELD + ": " + field.name, field.access, acc -> field.access = acc, owner); - } + public AccessPanel(FieldNode field, JComponent owner) throws Exception { + this(AccessPanel.TITLE_FIELD + ": " + field.name, field.access, acc -> field.access = acc, owner); + } - public AccessPanel(MethodNode method, JComponent owner) throws Exception { - this(AccessPanel.TITLE_METHOD + ": " + method.name, method.access, acc -> method.access = acc, owner); - } + public AccessPanel(MethodNode method, JComponent owner) throws Exception { + this(AccessPanel.TITLE_METHOD + ": " + method.name, method.access, acc -> method.access = acc, owner); + } - private AccessPanel(String title, int init, Consumer action, JComponent owner) throws Exception { - this.title = title; - this.action = action; - this.setLayout(new GridLayout(0, 3)); - // this.add(comp) - for (Field acc : Access.class.getDeclaredFields()) { - acc.setAccessible(true); - String name = acc.getName(); - // Skip non-modifier value fields - if (name.contains("_")) { - continue; - } - int accValue = acc.getInt(null); - // Skip modifiers that don't apply to the given access - if (title.contains(TITLE_CLASS)) { - // Classes - if (!Access.hasAccess(Access.CLASS_MODIFIERS, accValue)) { - continue; - } - } else if (title.contains(TITLE_FIELD)) { - // fields - if (!Access.hasAccess(Access.FIELD_MODIFIERS, accValue)) { - continue; - } - } else if (title.contains(TITLE_METHOD)) { - if (title.contains(" action, JComponent owner) throws Exception { + this.title = title; + this.action = action; + this.setLayout(new GridLayout(0, 3)); + // this.add(comp) + for (Field acc : Access.class.getDeclaredFields()) { + acc.setAccessible(true); + String name = acc.getName(); + // Skip non-modifier value fields + if (name.contains("_")) { + continue; + } + int accValue = acc.getInt(null); + // Skip modifiers that don't apply to the given access + if (title.contains(TITLE_CLASS)) { + // Classes + if (!Access.hasAccess(Access.CLASS_MODIFIERS, accValue)) { + continue; + } + } else if (title.contains(TITLE_FIELD)) { + // fields + if (!Access.hasAccess(Access.FIELD_MODIFIERS, accValue)) { + continue; + } + } else if (title.contains(TITLE_METHOD)) { + if (title.contains(" entry : compToAccess.entrySet()) { - if (entry.getKey().isSelected()) { - access |= entry.getValue().intValue(); - } - } - this.action.accept(access); - } + public void onUpdate() { + // Create new access + int access = 0; + for (Entry entry : compToAccess.entrySet()) { + if (entry.getKey().isSelected()) { + access |= entry.getValue().intValue(); + } + } + this.action.accept(access); + } - public String getTitle() { - return title; - } + public String getTitle() { + return title; + } } diff --git a/src/me/coley/recaf/ui/component/panel/AsmFlagsPanel.java b/src/me/coley/recaf/ui/component/panel/AsmFlagsPanel.java index 935b03458..6d6b8c342 100644 --- a/src/me/coley/recaf/ui/component/panel/AsmFlagsPanel.java +++ b/src/me/coley/recaf/ui/component/panel/AsmFlagsPanel.java @@ -21,51 +21,51 @@ */ @SuppressWarnings("serial") public class AsmFlagsPanel extends JPanel { - private final Options options = Recaf.getInstance().options; - private ActionCheckBox inE, inD, inF, inC, outF, outM; + private final Options options = Recaf.getInstance().options; + private ActionCheckBox inE, inD, inF, inC, outF, outM; - public AsmFlagsPanel() { - //@formatter:off - setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - JPanel p1 = new JPanel(); - p1.setBorder(BorderFactory.createTitledBorder("Input Flags")); - p1.setLayout(new GridLayout(0, 2)); - p1.add(inE = new ActionCheckBox("Expand Frames", Access.hasAccess(options.classFlagsInput, ClassReader.EXPAND_FRAMES), (b) -> update())); - p1.add(inD = new ActionCheckBox("Skip Debug", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_DEBUG), (b) -> update())); - p1.add(inF = new ActionCheckBox("Skip Frames", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_FRAMES), (b) -> update())); - p1.add(inC = new ActionCheckBox("Skip Code", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_CODE), (b) -> update())); - JPanel p2 = new JPanel(); - p2.setBorder(BorderFactory.createTitledBorder("Output Flags")); - p2.setLayout(new GridLayout(0, 2)); - p2.add(outF = new ActionCheckBox("Compute Frames", Access.hasAccess(options.classFlagsOutput, ClassWriter.COMPUTE_FRAMES), (b) -> update())); - p2.add(outM = new ActionCheckBox("Compute Maxs", Access.hasAccess(options.classFlagsOutput, ClassWriter.COMPUTE_MAXS), (b) -> update())); - add(p1); - add(p2); - //@formatter:on - } + public AsmFlagsPanel() { + //@formatter:off + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + JPanel p1 = new JPanel(); + p1.setBorder(BorderFactory.createTitledBorder("Input Flags")); + p1.setLayout(new GridLayout(0, 2)); + p1.add(inE = new ActionCheckBox("Expand Frames", Access.hasAccess(options.classFlagsInput, ClassReader.EXPAND_FRAMES), (b) -> update())); + p1.add(inD = new ActionCheckBox("Skip Debug", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_DEBUG), (b) -> update())); + p1.add(inF = new ActionCheckBox("Skip Frames", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_FRAMES), (b) -> update())); + p1.add(inC = new ActionCheckBox("Skip Code", Access.hasAccess(options.classFlagsInput, ClassReader.SKIP_CODE), (b) -> update())); + JPanel p2 = new JPanel(); + p2.setBorder(BorderFactory.createTitledBorder("Output Flags")); + p2.setLayout(new GridLayout(0, 2)); + p2.add(outF = new ActionCheckBox("Compute Frames", Access.hasAccess(options.classFlagsOutput, ClassWriter.COMPUTE_FRAMES), (b) -> update())); + p2.add(outM = new ActionCheckBox("Compute Maxs", Access.hasAccess(options.classFlagsOutput, ClassWriter.COMPUTE_MAXS), (b) -> update())); + add(p1); + add(p2); + //@formatter:on + } - private void update() { - int in = 0; - int out = 0; - if (inE.isSelected()) { - in |= ClassReader.EXPAND_FRAMES; - } - if (inD.isSelected()) { - in |= ClassReader.SKIP_DEBUG; - } - if (inF.isSelected()) { - in |= ClassReader.SKIP_FRAMES; - } - if (inC.isSelected()) { - in |= ClassReader.SKIP_CODE; - } - if (outF.isSelected()) { - out |= ClassWriter.COMPUTE_FRAMES; - } - if (outM.isSelected()) { - out |= ClassWriter.COMPUTE_MAXS; - } - options.classFlagsInput = in; - options.classFlagsOutput = out; - } + private void update() { + int in = 0; + int out = 0; + if (inE.isSelected()) { + in |= ClassReader.EXPAND_FRAMES; + } + if (inD.isSelected()) { + in |= ClassReader.SKIP_DEBUG; + } + if (inF.isSelected()) { + in |= ClassReader.SKIP_FRAMES; + } + if (inC.isSelected()) { + in |= ClassReader.SKIP_CODE; + } + if (outF.isSelected()) { + out |= ClassWriter.COMPUTE_FRAMES; + } + if (outM.isSelected()) { + out |= ClassWriter.COMPUTE_MAXS; + } + options.classFlagsInput = in; + options.classFlagsOutput = out; + } } diff --git a/src/me/coley/recaf/ui/component/panel/ClassDisplayPanel.java b/src/me/coley/recaf/ui/component/panel/ClassDisplayPanel.java index 4ffd9f0a8..8402d3549 100644 --- a/src/me/coley/recaf/ui/component/panel/ClassDisplayPanel.java +++ b/src/me/coley/recaf/ui/component/panel/ClassDisplayPanel.java @@ -27,155 +27,155 @@ @SuppressWarnings("serial") public class ClassDisplayPanel extends JPanel { - private final Recaf recaf = Recaf.getInstance(); - private final Gui gui = recaf.window; - private final JDesktopPane desktopPane = new JDesktopPane(); - private final ClassNode node; + private final Recaf recaf = Recaf.getInstance(); + private final Gui gui = recaf.window; + private final JDesktopPane desktopPane = new JDesktopPane(); + private final ClassNode node; - public ClassDisplayPanel(ClassNode node) { - this.node = node; - setLayout(new BorderLayout(0, 0)); - // Class - JInternalFrame frameClass = setupClassFrame(); - addWindow(frameClass); - // Fields - if (node.fields.size() > 0) { - JInternalFrame frameFields = setupFieldsFrame(); - addWindow(frameFields); - } - // Methods - if (node.methods.size() > 0) { - JInternalFrame frameMethods = setupMethodsFrame(); - addWindow(frameMethods); - } - add(desktopPane); - } + public ClassDisplayPanel(ClassNode node) { + this.node = node; + setLayout(new BorderLayout(0, 0)); + // Class + JInternalFrame frameClass = setupClassFrame(); + addWindow(frameClass); + // Fields + if (node.fields.size() > 0) { + JInternalFrame frameFields = setupFieldsFrame(); + addWindow(frameFields); + } + // Methods + if (node.methods.size() > 0) { + JInternalFrame frameMethods = setupMethodsFrame(); + addWindow(frameMethods); + } + add(desktopPane); + } - private JInternalFrame setupClassFrame() { - JInternalFrame frameClass = new JInternalFrame("Class Data"); - frameClass.setResizable(true); - frameClass.setIconifiable(true); - frameClass.setBounds(10, 11, 240, 276); - frameClass.setVisible(true); - frameClass.setLayout(new BoxLayout(frameClass.getContentPane(), BoxLayout.Y_AXIS)); - //@formatter:off - Misc.addAll(frameClass, - new LabeledComponent("Version: ", new ActionTextField(node.version, s -> { - if (Misc.isInt(s)) { - node.version = Integer.parseInt(s); - } - })), - new LabeledComponent("Source File: ", new ActionTextField(node.sourceFile, s -> { - if (s.isEmpty()) { - node.sourceFile = null; - } else { - node.sourceFile = s; - } - })), - new LabeledComponent("Source Debug: ", new ActionTextField(node.sourceDebug, s -> { - if (s.isEmpty()) { - node.sourceDebug = null; - } else { - node.sourceDebug = s; - } - })), - new LabeledComponent("Signature: ", new ActionTextField(node.signature == null ? "" : node.signature, s -> { - if (s.isEmpty()) { - node.signature = null; - } else { - node.signature = s; - } - })), - new LabeledComponent("Outer Class: ", new ActionTextField(node.outerClass == null ? "" : node.outerClass, s -> { - if (s.isEmpty()) { - node.outerClass = null; - } else { - node.outerClass = s; - } - })), - new LabeledComponent("Outer Method Name: ", new ActionTextField(node.outerMethod == null ? "" : node.outerMethod, s -> { - if (s.isEmpty()) { - node.outerMethod = null; - } else { - node.outerMethod = s; - } - })), - new LabeledComponent("Outer Method Desc: ", new ActionTextField(node.outerMethodDesc == null ? "" : node.outerMethodDesc, s -> { - if (s.isEmpty()) { - node.outerMethodDesc = null; - } else { - node.outerMethodDesc = s; - } - })), - new LabeledComponent("", new ActionButton("Edit Access",() -> { - try { - addWindow(new AccessBox(node, null)); - } catch (Exception e) { - exception(e); - } - })), - new LabeledComponent("", new ActionButton("Decompile", () -> { - try { - addWindow(new DecompileBox(new DecompilePanel(node))); - } catch (Exception e) { - exception(e); - } - })) - ); - //@formatter:on - return frameClass; - } + private JInternalFrame setupClassFrame() { + JInternalFrame frameClass = new JInternalFrame("Class Data"); + frameClass.setResizable(true); + frameClass.setIconifiable(true); + frameClass.setBounds(10, 11, 240, 276); + frameClass.setVisible(true); + frameClass.setLayout(new BoxLayout(frameClass.getContentPane(), BoxLayout.Y_AXIS)); + //@formatter:off + Misc.addAll(frameClass, + new LabeledComponent("Version: ", new ActionTextField(node.version, s -> { + if (Misc.isInt(s)) { + node.version = Integer.parseInt(s); + } + })), + new LabeledComponent("Source File: ", new ActionTextField(node.sourceFile, s -> { + if (s.isEmpty()) { + node.sourceFile = null; + } else { + node.sourceFile = s; + } + })), + new LabeledComponent("Source Debug: ", new ActionTextField(node.sourceDebug, s -> { + if (s.isEmpty()) { + node.sourceDebug = null; + } else { + node.sourceDebug = s; + } + })), + new LabeledComponent("Signature: ", new ActionTextField(node.signature == null ? "" : node.signature, s -> { + if (s.isEmpty()) { + node.signature = null; + } else { + node.signature = s; + } + })), + new LabeledComponent("Outer Class: ", new ActionTextField(node.outerClass == null ? "" : node.outerClass, s -> { + if (s.isEmpty()) { + node.outerClass = null; + } else { + node.outerClass = s; + } + })), + new LabeledComponent("Outer Method Name: ", new ActionTextField(node.outerMethod == null ? "" : node.outerMethod, s -> { + if (s.isEmpty()) { + node.outerMethod = null; + } else { + node.outerMethod = s; + } + })), + new LabeledComponent("Outer Method Desc: ", new ActionTextField(node.outerMethodDesc == null ? "" : node.outerMethodDesc, s -> { + if (s.isEmpty()) { + node.outerMethodDesc = null; + } else { + node.outerMethodDesc = s; + } + })), + new LabeledComponent("", new ActionButton("Edit Access",() -> { + try { + addWindow(new AccessBox(node, null)); + } catch (Exception e) { + exception(e); + } + })), + new LabeledComponent("", new ActionButton("Decompile", () -> { + try { + addWindow(new DecompileBox(new DecompilePanel(node))); + } catch (Exception e) { + exception(e); + } + })) + ); + //@formatter:on + return frameClass; + } - private JInternalFrame setupFieldsFrame() { - JInternalFrame frameFields = new JInternalFrame("Fields"); - frameFields.setResizable(true); - frameFields.setIconifiable(true); - frameFields.setBounds(260, 11, 180, 140); - frameFields.setVisible(true); - frameFields.setLayout(new BorderLayout()); - JList fields = new JList<>(); - fields.setCellRenderer(new MemberNodeRenderer(recaf.options)); - fields.addMouseListener(new MemberNodeClickListener(this, node, fields)); - DefaultListModel model = new DefaultListModel<>(); - for (FieldNode fn : node.fields) { - model.addElement(fn); - } - fields.setModel(model); - frameFields.add(new JScrollPane(fields), BorderLayout.CENTER); - frameFields.pack(); - return frameFields; - } + private JInternalFrame setupFieldsFrame() { + JInternalFrame frameFields = new JInternalFrame("Fields"); + frameFields.setResizable(true); + frameFields.setIconifiable(true); + frameFields.setBounds(260, 11, 180, 140); + frameFields.setVisible(true); + frameFields.setLayout(new BorderLayout()); + JList fields = new JList<>(); + fields.setCellRenderer(new MemberNodeRenderer(recaf.options)); + fields.addMouseListener(new MemberNodeClickListener(this, node, fields)); + DefaultListModel model = new DefaultListModel<>(); + for (FieldNode fn : node.fields) { + model.addElement(fn); + } + fields.setModel(model); + frameFields.add(new JScrollPane(fields), BorderLayout.CENTER); + frameFields.pack(); + return frameFields; + } - private JInternalFrame setupMethodsFrame() { - JInternalFrame frameMethods = new JInternalFrame("Methods"); - frameMethods.setResizable(true); - frameMethods.setIconifiable(true); - frameMethods.setBounds(445, 11, 180, 120); - frameMethods.setVisible(true); - frameMethods.setLayout(new BorderLayout()); + private JInternalFrame setupMethodsFrame() { + JInternalFrame frameMethods = new JInternalFrame("Methods"); + frameMethods.setResizable(true); + frameMethods.setIconifiable(true); + frameMethods.setBounds(445, 11, 180, 120); + frameMethods.setVisible(true); + frameMethods.setLayout(new BorderLayout()); - JList methods = new JList<>(); - methods.setCellRenderer(new MemberNodeRenderer(recaf.options)); - methods.addMouseListener(new MemberNodeClickListener(this, node, methods)); - DefaultListModel model = new DefaultListModel<>(); - for (MethodNode mn : node.methods) { - model.addElement(mn); - } - methods.setModel(model); - frameMethods.add(new JScrollPane(methods), BorderLayout.CENTER); - // TODO: Switch to table - // frameMethods.add(new JScrollPane(MemberTable.create(node.methods)), - // BorderLayout.CENTER); - frameMethods.pack(); - return frameMethods; - } + JList methods = new JList<>(); + methods.setCellRenderer(new MemberNodeRenderer(recaf.options)); + methods.addMouseListener(new MemberNodeClickListener(this, node, methods)); + DefaultListModel model = new DefaultListModel<>(); + for (MethodNode mn : node.methods) { + model.addElement(mn); + } + methods.setModel(model); + frameMethods.add(new JScrollPane(methods), BorderLayout.CENTER); + // TODO: Switch to table + // frameMethods.add(new JScrollPane(MemberTable.create(node.methods)), + // BorderLayout.CENTER); + frameMethods.pack(); + return frameMethods; + } - public void addWindow(JInternalFrame frame) { - desktopPane.add(frame); - desktopPane.moveToFront(frame); - } + public void addWindow(JInternalFrame frame) { + desktopPane.add(frame); + desktopPane.moveToFront(frame); + } - public void exception(Exception e) { - gui.displayError(e); - } + public void exception(Exception e) { + gui.displayError(e); + } } diff --git a/src/me/coley/recaf/ui/component/panel/DecompilePanel.java b/src/me/coley/recaf/ui/component/panel/DecompilePanel.java index cebc103b0..50dd7c47c 100644 --- a/src/me/coley/recaf/ui/component/panel/DecompilePanel.java +++ b/src/me/coley/recaf/ui/component/panel/DecompilePanel.java @@ -18,79 +18,79 @@ @SuppressWarnings("serial") public class DecompilePanel extends JPanel { - private final RSyntaxTextArea textArea = new RSyntaxTextArea(25, 70); - private final RTextScrollPane scrollText = new RTextScrollPane(textArea); - private final ClassNode classNode; - private final MethodNode methodNode; - private final CFRResourceLookup lookupHelper; + private final RSyntaxTextArea textArea = new RSyntaxTextArea(25, 70); + private final RTextScrollPane scrollText = new RTextScrollPane(textArea); + private final ClassNode classNode; + private final MethodNode methodNode; + private final CFRResourceLookup lookupHelper; - public DecompilePanel(ClassNode cn) { - this(cn, null); - } + public DecompilePanel(ClassNode cn) { + this(cn, null); + } - public DecompilePanel(ClassNode cn, MethodNode mn) { - this.classNode = cn; - this.methodNode = mn; - if (mn != null) { - this.lookupHelper = new CFRResourceLookup(Recaf.getInstance(), getIsolatedMethodClass()); - } else { - this.lookupHelper = new CFRResourceLookup(Recaf.getInstance()); - } - // - textArea.setCaretPosition(0); - textArea.requestFocusInWindow(); - textArea.setMarkOccurrences(true); - textArea.setClearWhitespaceLinesEnabled(false); - textArea.setEditable(false); - textArea.setAntiAliasingEnabled(true); - textArea.setCodeFoldingEnabled(true); - textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); - textArea.setComponentPopupMenu(null); - textArea.setPopupMenu(null); - // - setLayout(new BorderLayout()); - add(scrollText, BorderLayout.CENTER); - // - decompile(); - } + public DecompilePanel(ClassNode cn, MethodNode mn) { + this.classNode = cn; + this.methodNode = mn; + if (mn != null) { + this.lookupHelper = new CFRResourceLookup(Recaf.getInstance(), getIsolatedMethodClass()); + } else { + this.lookupHelper = new CFRResourceLookup(Recaf.getInstance()); + } + // + textArea.setCaretPosition(0); + textArea.requestFocusInWindow(); + textArea.setMarkOccurrences(true); + textArea.setClearWhitespaceLinesEnabled(false); + textArea.setEditable(false); + textArea.setAntiAliasingEnabled(true); + textArea.setCodeFoldingEnabled(true); + textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + textArea.setComponentPopupMenu(null); + textArea.setPopupMenu(null); + // + setLayout(new BorderLayout()); + add(scrollText, BorderLayout.CENTER); + // + decompile(); + } - /** - * Returns a title for the containing parent to access (Groupbox / - * InternalWindow). - * - * @return The title. - */ - public String getTitle() { - String s = "CFR: " + classNode.name; - if (methodNode != null) { - s += "#" + methodNode.name + methodNode.desc; - } - return s; - } + /** + * Returns a title for the containing parent to access (Groupbox / + * InternalWindow). + * + * @return The title. + */ + public String getTitle() { + String s = "CFR: " + classNode.name; + if (methodNode != null) { + s += "#" + methodNode.name + methodNode.desc; + } + return s; + } - private ClassNode getIsolatedMethodClass() { - ClassNode copy = new ClassNode(); - copy.visit(classNode.version, classNode.access, classNode.name, classNode.signature, classNode.superName, - classNode.interfaces.stream().toArray(String[]::new)); - // I initially though sharing method nodes would be bad, - // but copying it is even more of a pain. - copy.methods.add(methodNode); - return copy; - } + private ClassNode getIsolatedMethodClass() { + ClassNode copy = new ClassNode(); + copy.visit(classNode.version, classNode.access, classNode.name, classNode.signature, classNode.superName, + classNode.interfaces.stream().toArray(String[]::new)); + // I initially though sharing method nodes would be bad, + // but copying it is even more of a pain. + copy.methods.add(methodNode); + return copy; + } - /** - * Decompiled the class. - */ - private void decompile() { - String name = classNode.name; - String text = new PluginRunner(CFRSetting.toStringMap(), new CFRSourceImpl(lookupHelper)).getDecompilationFor(name); - // Hack to substring the first indent (Where the isolated method begins) - // to the end of the class, minus one (so it substrings to the method's - // closing brace) - if (methodNode != null) { - text = text.substring(text.indexOf(" "), text.lastIndexOf("}") - 1); - } - textArea.setText(text); - textArea.moveCaretPosition(0); - } + /** + * Decompiled the class. + */ + private void decompile() { + String name = classNode.name; + String text = new PluginRunner(CFRSetting.toStringMap(), new CFRSourceImpl(lookupHelper)).getDecompilationFor(name); + // Hack to substring the first indent (Where the isolated method begins) + // to the end of the class, minus one (so it substrings to the method's + // closing brace) + if (methodNode != null) { + text = text.substring(text.indexOf(" "), text.lastIndexOf("}") - 1); + } + textArea.setText(text); + textArea.moveCaretPosition(0); + } } diff --git a/src/me/coley/recaf/ui/component/panel/LabelSwitcherPanel.java b/src/me/coley/recaf/ui/component/panel/LabelSwitcherPanel.java index c9509045f..9ffc13a38 100644 --- a/src/me/coley/recaf/ui/component/panel/LabelSwitcherPanel.java +++ b/src/me/coley/recaf/ui/component/panel/LabelSwitcherPanel.java @@ -24,69 +24,69 @@ */ @SuppressWarnings("serial") public class LabelSwitcherPanel extends JPanel implements Opcodes { - /** - * Map of strings to labels. - */ - private final Map labels = new LinkedHashMap<>(); - /** - * Initial label value. - */ - private final LabelNode initial; - /** - * Callback to the label setter. - */ - private final Consumer updater; - /** - * Reference so list can be re-painted. - */ - private final OpcodeList list; - /** - * Combobox containing label node indices. - */ - private final JComboBox combo = new JComboBox<>(); + /** + * Map of strings to labels. + */ + private final Map labels = new LinkedHashMap<>(); + /** + * Initial label value. + */ + private final LabelNode initial; + /** + * Callback to the label setter. + */ + private final Consumer updater; + /** + * Reference so list can be re-painted. + */ + private final OpcodeList list; + /** + * Combobox containing label node indices. + */ + private final JComboBox combo = new JComboBox<>(); - public LabelSwitcherPanel(MethodNode method, LabelNode initial, Consumer updater) { - this(null, method, initial, updater); - } + public LabelSwitcherPanel(MethodNode method, LabelNode initial, Consumer updater) { + this(null, method, initial, updater); + } - public LabelSwitcherPanel(OpcodeList list, MethodNode method, LabelNode initial, Consumer updater) { - this.initial = initial; - this.updater = updater; - this.list = list; - setLayout(new BorderLayout()); - populate(method.instructions); - add(combo, BorderLayout.CENTER); - } + public LabelSwitcherPanel(OpcodeList list, MethodNode method, LabelNode initial, Consumer updater) { + this.initial = initial; + this.updater = updater; + this.list = list; + setLayout(new BorderLayout()); + populate(method.instructions); + add(combo, BorderLayout.CENTER); + } - private void populate(InsnList opcodes) { - int selected = -1, labelCount = 0;; - DefaultComboBoxModel model = new DefaultComboBoxModel<>(); - for (int i = 0; i < opcodes.size(); i++) { - AbstractInsnNode ain = opcodes.get(i); - if (ain.getType() == AbstractInsnNode.LABEL) { - LabelNode label = (LabelNode) ain; - String s = i + "."; - if (list != null) { - s += " : " + list.getLabelName(ain); - } - labels.put(s, label); - model.addElement(s); - if (label.equals(initial)) { - selected = labelCount; - } - labelCount++; - } - } - combo.setModel(model); - combo.setSelectedIndex(selected); - combo.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - updater.accept(labels.get(e.getItem())); - if (list != null) { - list.repaint(); - } - } - }); - } + private void populate(InsnList opcodes) { + int selected = -1, labelCount = 0;; + DefaultComboBoxModel model = new DefaultComboBoxModel<>(); + for (int i = 0; i < opcodes.size(); i++) { + AbstractInsnNode ain = opcodes.get(i); + if (ain.getType() == AbstractInsnNode.LABEL) { + LabelNode label = (LabelNode) ain; + String s = i + "."; + if (list != null) { + s += " : " + list.getLabelName(ain); + } + labels.put(s, label); + model.addElement(s); + if (label.equals(initial)) { + selected = labelCount; + } + labelCount++; + } + } + combo.setModel(model); + combo.setSelectedIndex(selected); + combo.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + updater.accept(labels.get(e.getItem())); + if (list != null) { + list.repaint(); + } + } + }); + } } diff --git a/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java b/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java index 7f1854b98..8de8b44db 100644 --- a/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java +++ b/src/me/coley/recaf/ui/component/panel/OpcodeTypeSwitchPanel.java @@ -25,175 +25,175 @@ */ @SuppressWarnings("serial") public class OpcodeTypeSwitchPanel extends JPanel implements Opcodes { - /** - * Map of radio buttons to possible opcodes. - */ - private final Map compToOpcode = new HashMap<>(); - /** - * Opcode node being modified. - */ - private final AbstractInsnNode opcode; - /** - * Reference so list can be re-painted. - */ - private final JList list; - /** - * Content wrapper. - */ - private final JPanel content = new JPanel(); - - public OpcodeTypeSwitchPanel(JList list, AbstractInsnNode opcode) { - this.list = list; - this.opcode = opcode; - // setMaximumSize(new Dimension(900, 200)); - // content.setMaximumSize(new Dimension(900, 300)); - // scroll.setMaximumSize(new Dimension(900, 300)); - populate(); - setLayout(new BorderLayout()); - JScrollPane scroll = new JScrollPane(content); - add(scroll, BorderLayout.CENTER); - } - - private void populate() { - switch (opcode.getType()) { - case AbstractInsnNode.INSN: - populate(OpcodeUtil.getInsnSubset(OpcodeUtil.opcodeToName(opcode.getOpcode()))); - break; - case AbstractInsnNode.INT_INSN: - populate(OpcodeUtil.OPS_INT); - break; - case AbstractInsnNode.VAR_INSN: - populate(OpcodeUtil.OPS_VAR); - break; - case AbstractInsnNode.TYPE_INSN: - populate(OpcodeUtil.OPS_TYPE); - break; - case AbstractInsnNode.FIELD_INSN: - populate(OpcodeUtil.OPS_FIELD); - break; - case AbstractInsnNode.METHOD_INSN: - populate(OpcodeUtil.OPS_METHOD); - break; - case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - populate(OpcodeUtil.OPS_INDY_METHOD); - break; - case AbstractInsnNode.JUMP_INSN: - populate(OpcodeUtil.OPS_JUMP); - break; - case AbstractInsnNode.LDC_INSN: - populate(OpcodeUtil.OPS_LDC); - break; - case AbstractInsnNode.IINC_INSN: - populate(OpcodeUtil.OPS_IINC); - break; - case AbstractInsnNode.TABLESWITCH_INSN: - populate(OpcodeUtil.OPS_TABLESWITCH); - break; - case AbstractInsnNode.LOOKUPSWITCH_INSN: - populate(OpcodeUtil.OPS_LOOKUPSWITCH); - break; - case AbstractInsnNode.MULTIANEWARRAY_INSN: - populate(OpcodeUtil.OPS_MULTIANEWARRAY); - break; - case AbstractInsnNode.LABEL: - case AbstractInsnNode.LINE: - break; - case AbstractInsnNode.FRAME: - populateFrames(OpcodeUtil.OPS_FRAME); - break; - } - } - - private void populate(String[] opcodes) { - populate(opcodes, s -> OpcodeUtil.nameToOpcode(s)); - - } - - private void populateFrames(String[] opcodes) { - populate(opcodes, s -> OpcodeUtil.nameToFrame(s)); - } - - private void populate(String[] opcodes, Function getter) { - // don't bother showing the option to change if there are no other - // options - if (opcodes.length == 1) { - return; - } - // Set layout based on number of options - setLayout(opcodes.length); - // Add options - for (String op : opcodes) { - int value = getter.apply(op);; - JRadioButton btn = new JRadioButton(op); - if (value == opcode.getOpcode()) { - btn.setSelected(true); - } - btn.addActionListener(new RadioListener(btn)); - compToOpcode.put(btn, value); - content.add(btn); - } - } - - /** - * Update {@link #opcode} value. - * - * @param value - */ - private void setValue(int value) { - try { - Field op = AbstractInsnNode.class.getDeclaredField("opcode"); - op.setAccessible(true); - op.set(opcode, value); - list.repaint(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Sets layout depending on the content size. - * - * @param size - */ - private void setLayout(int size) { - if (size % 6 == 0 || size % 3 == 0) { - content.setLayout(new GridLayout(0, 3)); - } else if (size % 2 == 0) { - content.setLayout(new GridLayout(0, 2)); - } else { - content.setLayout(new GridLayout(0, 3)); - } - } - - /** - * @return the number of radio buttons. - - */ - public int getOptionCount() { - return compToOpcode.keySet().size(); - } - - /** - * Listener for disabling other radio buttons. - * - * @author Matt - */ - private class RadioListener implements ActionListener { - private final JRadioButton btn; - - public RadioListener(JRadioButton btn) { - this.btn = btn; - } - - @Override - public void actionPerformed(ActionEvent e) { - for (JRadioButton comp : compToOpcode.keySet()) { - if (comp != btn && comp.isSelected()) { - comp.setSelected(false); - } else if (comp == btn) { - setValue(compToOpcode.get(comp)); - } - } - } - } + /** + * Map of radio buttons to possible opcodes. + */ + private final Map compToOpcode = new HashMap<>(); + /** + * Opcode node being modified. + */ + private final AbstractInsnNode opcode; + /** + * Reference so list can be re-painted. + */ + private final JList list; + /** + * Content wrapper. + */ + private final JPanel content = new JPanel(); + + public OpcodeTypeSwitchPanel(JList list, AbstractInsnNode opcode) { + this.list = list; + this.opcode = opcode; + // setMaximumSize(new Dimension(900, 200)); + // content.setMaximumSize(new Dimension(900, 300)); + // scroll.setMaximumSize(new Dimension(900, 300)); + populate(); + setLayout(new BorderLayout()); + JScrollPane scroll = new JScrollPane(content); + add(scroll, BorderLayout.CENTER); + } + + private void populate() { + switch (opcode.getType()) { + case AbstractInsnNode.INSN: + populate(OpcodeUtil.getInsnSubset(OpcodeUtil.opcodeToName(opcode.getOpcode()))); + break; + case AbstractInsnNode.INT_INSN: + populate(OpcodeUtil.OPS_INT); + break; + case AbstractInsnNode.VAR_INSN: + populate(OpcodeUtil.OPS_VAR); + break; + case AbstractInsnNode.TYPE_INSN: + populate(OpcodeUtil.OPS_TYPE); + break; + case AbstractInsnNode.FIELD_INSN: + populate(OpcodeUtil.OPS_FIELD); + break; + case AbstractInsnNode.METHOD_INSN: + populate(OpcodeUtil.OPS_METHOD); + break; + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + populate(OpcodeUtil.OPS_INDY_METHOD); + break; + case AbstractInsnNode.JUMP_INSN: + populate(OpcodeUtil.OPS_JUMP); + break; + case AbstractInsnNode.LDC_INSN: + populate(OpcodeUtil.OPS_LDC); + break; + case AbstractInsnNode.IINC_INSN: + populate(OpcodeUtil.OPS_IINC); + break; + case AbstractInsnNode.TABLESWITCH_INSN: + populate(OpcodeUtil.OPS_TABLESWITCH); + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + populate(OpcodeUtil.OPS_LOOKUPSWITCH); + break; + case AbstractInsnNode.MULTIANEWARRAY_INSN: + populate(OpcodeUtil.OPS_MULTIANEWARRAY); + break; + case AbstractInsnNode.LABEL: + case AbstractInsnNode.LINE: + break; + case AbstractInsnNode.FRAME: + populateFrames(OpcodeUtil.OPS_FRAME); + break; + } + } + + private void populate(String[] opcodes) { + populate(opcodes, s -> OpcodeUtil.nameToOpcode(s)); + + } + + private void populateFrames(String[] opcodes) { + populate(opcodes, s -> OpcodeUtil.nameToFrame(s)); + } + + private void populate(String[] opcodes, Function getter) { + // don't bother showing the option to change if there are no other + // options + if (opcodes.length == 1) { + return; + } + // Set layout based on number of options + setLayout(opcodes.length); + // Add options + for (String op : opcodes) { + int value = getter.apply(op);; + JRadioButton btn = new JRadioButton(op); + if (value == opcode.getOpcode()) { + btn.setSelected(true); + } + btn.addActionListener(new RadioListener(btn)); + compToOpcode.put(btn, value); + content.add(btn); + } + } + + /** + * Update {@link #opcode} value. + * + * @param value + */ + private void setValue(int value) { + try { + Field op = AbstractInsnNode.class.getDeclaredField("opcode"); + op.setAccessible(true); + op.set(opcode, value); + list.repaint(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Sets layout depending on the content size. + * + * @param size + */ + private void setLayout(int size) { + if (size % 6 == 0 || size % 3 == 0) { + content.setLayout(new GridLayout(0, 3)); + } else if (size % 2 == 0) { + content.setLayout(new GridLayout(0, 2)); + } else { + content.setLayout(new GridLayout(0, 3)); + } + } + + /** + * @return the number of radio buttons. + + */ + public int getOptionCount() { + return compToOpcode.keySet().size(); + } + + /** + * Listener for disabling other radio buttons. + * + * @author Matt + */ + private class RadioListener implements ActionListener { + private final JRadioButton btn; + + public RadioListener(JRadioButton btn) { + this.btn = btn; + } + + @Override + public void actionPerformed(ActionEvent e) { + for (JRadioButton comp : compToOpcode.keySet()) { + if (comp != btn && comp.isSelected()) { + comp.setSelected(false); + } else if (comp == btn) { + setValue(compToOpcode.get(comp)); + } + } + } + } } diff --git a/src/me/coley/recaf/ui/component/panel/SearchPanel.java b/src/me/coley/recaf/ui/component/panel/SearchPanel.java index 52f320ad0..df46c1cbc 100644 --- a/src/me/coley/recaf/ui/component/panel/SearchPanel.java +++ b/src/me/coley/recaf/ui/component/panel/SearchPanel.java @@ -34,211 +34,211 @@ @SuppressWarnings("serial") public class SearchPanel extends JPanel { - public static final int S_STRINGS = 0; - public static final int S_FIELD = 10; - public static final int S_METHOD = 20; - public static final int S_CLASS_NAME = 30, S_CLASS_REF = 31; - private final Recaf recaf = Recaf.getInstance(); - private final JTree tree = new JTree(new String[] {}); + public static final int S_STRINGS = 0; + public static final int S_FIELD = 10; + public static final int S_METHOD = 20; + public static final int S_CLASS_NAME = 30, S_CLASS_REF = 31; + private final Recaf recaf = Recaf.getInstance(); + private final JTree tree = new JTree(new String[] {}); - public SearchPanel(int type) { - setLayout(new BorderLayout()); - JPanel pnlInput = new JPanel(), pnlOutput = new JPanel(); - pnlInput.setLayout(new BoxLayout(pnlInput, BoxLayout.Y_AXIS)); - pnlOutput.setLayout(new BorderLayout()); - JScrollPane scrollTree = new JScrollPane(tree); - pnlOutput.add(scrollTree, BorderLayout.CENTER); - tree.setCellRenderer(new JavaTreeRenderer()); - JavaTreeListener sel = new JavaTreeListener(); - tree.addTreeSelectionListener(sel); - tree.addMouseListener(sel); - tree.addTreeExpansionListener(sel); - JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pnlInput, pnlOutput); - split.setResizeWeight(0.67); - switch (type) { - case S_STRINGS: { - JTextField text; - JCheckBox caseSense; - pnlInput.add(new LabeledComponent("String", text = new JTextField(""))); - pnlInput.add(caseSense = new JCheckBox("Case sensitive")); - pnlInput.add(new ActionButton("Search", () -> searchString(text.getText(), caseSense.isSelected()))); - break; - } - case S_FIELD: { - JTextField name, desc; - pnlInput.add(new LabeledComponent("Field name", name = new JTextField(""))); - pnlInput.add(new LabeledComponent("Field desc", desc = new JTextField(""))); - pnlInput.add(new ActionButton("Search", () -> searchField(name.getText(), desc.getText()))); - break; - } - case S_METHOD: { - JTextField name, desc; - pnlInput.add(new LabeledComponent("Method name", name = new JTextField(""))); - pnlInput.add(new LabeledComponent("Method desc", desc = new JTextField(""))); - pnlInput.add(new ActionButton("Search", () -> searchMethod(name.getText(), desc.getText()))); - break; - } - case S_CLASS_NAME: { - JTextField clazz; - JCheckBox ex; - pnlInput.add(new LabeledComponent("Class name", clazz = new JTextField(""))); - pnlInput.add(ex = new JCheckBox("Exact match")); - pnlInput.add(new ActionButton("Search", () -> searchClass(clazz.getText(), ex.isSelected()))); - break; - } - case S_CLASS_REF: { - JTextField clazz, name, desc; - JCheckBox ex; - pnlInput.add(new LabeledComponent("Class owner", clazz = new JTextField(""))); - pnlInput.add(new LabeledComponent("Member name", name = new JTextField(""))); - pnlInput.add(new LabeledComponent("Member desc", desc = new JTextField(""))); - pnlInput.add(ex = new JCheckBox("Exact match")); - pnlInput.add(new ActionButton("Search", () -> searchClassRef(clazz.getText(), name.getText(), desc.getText(), ex.isSelected()))); - break; - } - } - add(split, BorderLayout.CENTER); - } + public SearchPanel(int type) { + setLayout(new BorderLayout()); + JPanel pnlInput = new JPanel(), pnlOutput = new JPanel(); + pnlInput.setLayout(new BoxLayout(pnlInput, BoxLayout.Y_AXIS)); + pnlOutput.setLayout(new BorderLayout()); + JScrollPane scrollTree = new JScrollPane(tree); + pnlOutput.add(scrollTree, BorderLayout.CENTER); + tree.setCellRenderer(new JavaTreeRenderer()); + JavaTreeListener sel = new JavaTreeListener(); + tree.addTreeSelectionListener(sel); + tree.addMouseListener(sel); + tree.addTreeExpansionListener(sel); + JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pnlInput, pnlOutput); + split.setResizeWeight(0.67); + switch (type) { + case S_STRINGS: { + JTextField text; + JCheckBox caseSense; + pnlInput.add(new LabeledComponent("String", text = new JTextField(""))); + pnlInput.add(caseSense = new JCheckBox("Case sensitive")); + pnlInput.add(new ActionButton("Search", () -> searchString(text.getText(), caseSense.isSelected()))); + break; + } + case S_FIELD: { + JTextField name, desc; + pnlInput.add(new LabeledComponent("Field name", name = new JTextField(""))); + pnlInput.add(new LabeledComponent("Field desc", desc = new JTextField(""))); + pnlInput.add(new ActionButton("Search", () -> searchField(name.getText(), desc.getText()))); + break; + } + case S_METHOD: { + JTextField name, desc; + pnlInput.add(new LabeledComponent("Method name", name = new JTextField(""))); + pnlInput.add(new LabeledComponent("Method desc", desc = new JTextField(""))); + pnlInput.add(new ActionButton("Search", () -> searchMethod(name.getText(), desc.getText()))); + break; + } + case S_CLASS_NAME: { + JTextField clazz; + JCheckBox ex; + pnlInput.add(new LabeledComponent("Class name", clazz = new JTextField(""))); + pnlInput.add(ex = new JCheckBox("Exact match")); + pnlInput.add(new ActionButton("Search", () -> searchClass(clazz.getText(), ex.isSelected()))); + break; + } + case S_CLASS_REF: { + JTextField clazz, name, desc; + JCheckBox ex; + pnlInput.add(new LabeledComponent("Class owner", clazz = new JTextField(""))); + pnlInput.add(new LabeledComponent("Member name", name = new JTextField(""))); + pnlInput.add(new LabeledComponent("Member desc", desc = new JTextField(""))); + pnlInput.add(ex = new JCheckBox("Exact match")); + pnlInput.add(new ActionButton("Search", () -> searchClassRef(clazz.getText(), name.getText(), desc.getText(), ex.isSelected()))); + break; + } + } + add(split, BorderLayout.CENTER); + } - private void searchString(String text, boolean caseSensitive) { - DefaultTreeModel model = setup(); + private void searchString(String text, boolean caseSensitive) { + DefaultTreeModel model = setup(); - search((n) -> { - for (MethodNode m : n.methods) { - for (AbstractInsnNode ain : m.instructions.toArray()) { - if (ain.getType() == AbstractInsnNode.LDC_INSN) { - LdcInsnNode ldc = (LdcInsnNode) ain; - String s = ldc.cst.toString(); - if ((caseSensitive && s.contains(text)) || (!caseSensitive && (s.toLowerCase().contains(text.toLowerCase())))) { - // Get tree node for class - ASMTreeNode genClass = Misc.getOrCreateNode(model, n); + search((n) -> { + for (MethodNode m : n.methods) { + for (AbstractInsnNode ain : m.instructions.toArray()) { + if (ain.getType() == AbstractInsnNode.LDC_INSN) { + LdcInsnNode ldc = (LdcInsnNode) ain; + String s = ldc.cst.toString(); + if ((caseSensitive && s.contains(text)) || (!caseSensitive && (s.toLowerCase().contains(text.toLowerCase())))) { + // Get tree node for class + ASMTreeNode genClass = Misc.getOrCreateNode(model, n); - // Get or create tree node for method - ASMTreeNode genMethod = genClass.getChild(m.name); - if (genMethod == null) { - genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); - genClass.add(genMethod); - } - // Add opcode node to method tree node - genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": '" + s + "'", n, m, ain)); - } - } - } - } - }); - tree.setModel(model); - } + // Get or create tree node for method + ASMTreeNode genMethod = genClass.getChild(m.name); + if (genMethod == null) { + genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); + genClass.add(genMethod); + } + // Add opcode node to method tree node + genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": '" + s + "'", n, m, ain)); + } + } + } + } + }); + tree.setModel(model); + } - private void searchField(String name, String desc) { - DefaultTreeModel model = setup(); - search((n) -> { - for (FieldNode f : n.fields) { - if (f.name.contains(name) && f.desc.contains(desc)) { - ASMTreeNode genClass = Misc.getOrCreateNode(model, n); - ASMTreeNode genMethod = genClass.getChild(f.name); - if (genMethod == null) { - genMethod = new ASMFieldTreeNode(f.desc + " " + f.name, n, f); - } - genClass.add(genMethod); - } - } - }); - tree.setModel(model); - } + private void searchField(String name, String desc) { + DefaultTreeModel model = setup(); + search((n) -> { + for (FieldNode f : n.fields) { + if (f.name.contains(name) && f.desc.contains(desc)) { + ASMTreeNode genClass = Misc.getOrCreateNode(model, n); + ASMTreeNode genMethod = genClass.getChild(f.name); + if (genMethod == null) { + genMethod = new ASMFieldTreeNode(f.desc + " " + f.name, n, f); + } + genClass.add(genMethod); + } + } + }); + tree.setModel(model); + } - private void searchMethod(String name, String desc) { - DefaultTreeModel model = setup(); - search((n) -> { - for (MethodNode m : n.methods) { - if (m.name.contains(name) && m.desc.contains(desc)) { - ASMTreeNode genClass = Misc.getOrCreateNode(model, n); - ASMTreeNode genMethod = genClass.getChild(m.name); - if (genMethod == null) { - genMethod = new ASMMethodTreeNode(m.name + m.desc, n,m); - } - genClass.add(genMethod); - } - } - }); - tree.setModel(model); - } + private void searchMethod(String name, String desc) { + DefaultTreeModel model = setup(); + search((n) -> { + for (MethodNode m : n.methods) { + if (m.name.contains(name) && m.desc.contains(desc)) { + ASMTreeNode genClass = Misc.getOrCreateNode(model, n); + ASMTreeNode genMethod = genClass.getChild(m.name); + if (genMethod == null) { + genMethod = new ASMMethodTreeNode(m.name + m.desc, n,m); + } + genClass.add(genMethod); + } + } + }); + tree.setModel(model); + } - private void searchClass(String text, boolean exact) { - DefaultTreeModel model = setup(); - search((n) -> { - if (exact ? n.name.equals(text) : n.name.contains(text)) { - Misc.getOrCreateNode(model, n); - } - }); - tree.setModel(model); - } + private void searchClass(String text, boolean exact) { + DefaultTreeModel model = setup(); + search((n) -> { + if (exact ? n.name.equals(text) : n.name.contains(text)) { + Misc.getOrCreateNode(model, n); + } + }); + tree.setModel(model); + } - private void searchClassRef(String owner, String name, String desc, boolean exact) { - DefaultTreeModel model = setup(); - search((n) -> { - for (MethodNode m : n.methods) { - for (AbstractInsnNode ain : m.instructions.toArray()) { - if (ain.getType() == AbstractInsnNode.FIELD_INSN) { - FieldInsnNode fin = (FieldInsnNode) ain; - if ((exact && (fin.owner.equals(owner) && fin.name.equals(name) && fin.desc.equals(desc))) || - (!exact && (fin.owner.contains(owner) && fin.name.contains(name) && fin.desc.contains(desc)))) { - System.out.println("A"); - ASMTreeNode genClass = Misc.getOrCreateNode(model, n); - // Get or create tree node for method - ASMTreeNode genMethod = genClass.getChild(m.name); - if (genMethod == null) { - genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); - genClass.add(genMethod); - } - // Add opcode node to method tree node - genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": " + fin.name, n, m, ain)); - } - } else if (ain.getType() == AbstractInsnNode.METHOD_INSN) { - MethodInsnNode min = (MethodInsnNode) ain; - if ((exact && (min.owner.equals(owner) && min.name.equals(name) && min.desc.equals(desc))) || - (!exact && (min.owner.contains(owner) && min.name.contains(name) && min.desc.contains(desc)))) { - // Get tree node for class - ASMTreeNode genClass = Misc.getOrCreateNode(model, n); - // Get or create tree node for method - ASMTreeNode genMethod = genClass.getChild(m.name); - if (genMethod == null) { - genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); - genClass.add(genMethod); - } - // Add opcode node to method tree node - genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": " + min.name, n, m, ain)); - } - } - } - } - }); - tree.setModel(model); - } + private void searchClassRef(String owner, String name, String desc, boolean exact) { + DefaultTreeModel model = setup(); + search((n) -> { + for (MethodNode m : n.methods) { + for (AbstractInsnNode ain : m.instructions.toArray()) { + if (ain.getType() == AbstractInsnNode.FIELD_INSN) { + FieldInsnNode fin = (FieldInsnNode) ain; + if ((exact && (fin.owner.equals(owner) && fin.name.equals(name) && fin.desc.equals(desc))) || + (!exact && (fin.owner.contains(owner) && fin.name.contains(name) && fin.desc.contains(desc)))) { + System.out.println("A"); + ASMTreeNode genClass = Misc.getOrCreateNode(model, n); + // Get or create tree node for method + ASMTreeNode genMethod = genClass.getChild(m.name); + if (genMethod == null) { + genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); + genClass.add(genMethod); + } + // Add opcode node to method tree node + genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": " + fin.name, n, m, ain)); + } + } else if (ain.getType() == AbstractInsnNode.METHOD_INSN) { + MethodInsnNode min = (MethodInsnNode) ain; + if ((exact && (min.owner.equals(owner) && min.name.equals(name) && min.desc.equals(desc))) || + (!exact && (min.owner.contains(owner) && min.name.contains(name) && min.desc.contains(desc)))) { + // Get tree node for class + ASMTreeNode genClass = Misc.getOrCreateNode(model, n); + // Get or create tree node for method + ASMTreeNode genMethod = genClass.getChild(m.name); + if (genMethod == null) { + genClass.addChild(m.name, genMethod = new ASMMethodTreeNode(m.name + m.desc, n, m)); + genClass.add(genMethod); + } + // Add opcode node to method tree node + genMethod.add(new ASMInsnTreeNode(m.instructions.indexOf(ain) + ": " + min.name, n, m, ain)); + } + } + } + } + }); + tree.setModel(model); + } - /** - * Setup and return the tree model for a search. - * - * @return - */ - private DefaultTreeModel setup() { - String jarName = recaf.currentJar.getName(); - ASMTreeNode root = new ASMTreeNode(jarName, null); - DefaultTreeModel model = new DefaultTreeModel(root); - model.setRoot(root); - return model; - } + /** + * Setup and return the tree model for a search. + * + * @return + */ + private DefaultTreeModel setup() { + String jarName = recaf.currentJar.getName(); + ASMTreeNode root = new ASMTreeNode(jarName, null); + DefaultTreeModel model = new DefaultTreeModel(root); + model.setRoot(root); + return model; + } - /** - * Search and pass classnodes through the given function. - * - * @param model - * @param func - */ - private void search(Consumer func) { - List names = StreamUtil.listOfSortedJavaNames(recaf.jarData.classes.keySet()); - for (String className : names) { - ClassNode node = recaf.jarData.classes.get(className); - func.accept(node); - } - } + /** + * Search and pass classnodes through the given function. + * + * @param model + * @param func + */ + private void search(Consumer func) { + List names = StreamUtil.listOfSortedJavaNames(recaf.jarData.classes.keySet()); + for (String className : names) { + ClassNode node = recaf.jarData.classes.get(className); + func.accept(node); + } + } } diff --git a/src/me/coley/recaf/ui/component/panel/TabbedPanel.java b/src/me/coley/recaf/ui/component/panel/TabbedPanel.java index 4f750afb7..b2dd8168f 100644 --- a/src/me/coley/recaf/ui/component/panel/TabbedPanel.java +++ b/src/me/coley/recaf/ui/component/panel/TabbedPanel.java @@ -19,115 +19,115 @@ */ @SuppressWarnings("serial") public class TabbedPanel extends JPanel { - /** - * Wrapped tabbed pane. - */ - private final JTabbedPane pane; - private final Map children = new HashMap<>(); - private final Map childrenReverse = new HashMap<>(); + /** + * Wrapped tabbed pane. + */ + private final JTabbedPane pane; + private final Map children = new HashMap<>(); + private final Map childrenReverse = new HashMap<>(); - public TabbedPanel() { - setLayout(new BorderLayout()); - pane = new JTabbedPane(JTabbedPane.TOP); - pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); - pane.addMouseListener(new ReleaseListener() { - @Override - public void mouseReleased(MouseEvent e) { - // Only close tabs when middle-clicked - if (e.getButton() != MouseEvent.BUTTON2) { - return; - } - int index = pane.getSelectedIndex(); - if (index >= 0) { - String key = childrenReverse.remove(pane.getSelectedComponent()); - children.remove(key); - pane.remove(index); - } - } - }); - add(pane, BorderLayout.CENTER); - } + public TabbedPanel() { + setLayout(new BorderLayout()); + pane = new JTabbedPane(JTabbedPane.TOP); + pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + pane.addMouseListener(new ReleaseListener() { + @Override + public void mouseReleased(MouseEvent e) { + // Only close tabs when middle-clicked + if (e.getButton() != MouseEvent.BUTTON2) { + return; + } + int index = pane.getSelectedIndex(); + if (index >= 0) { + String key = childrenReverse.remove(pane.getSelectedComponent()); + children.remove(key); + pane.remove(index); + } + } + }); + add(pane, BorderLayout.CENTER); + } - /** - * Adds a tab to the panel. - * - * @param title The tab's title. - * @param component The component. - * - * TODO: What is the component for? - * - * - Charles - */ - public void addTab(String title, Component component) { - pane.add(title, component); - if (!shouldCache(title, component)) { - children.put(title, component); - childrenReverse.put(component, title); - } - } + /** + * Adds a tab to the panel. + * + * @param title The tab's title. + * @param component The component. + * + * TODO: What is the component for? + * + * - Charles + */ + public void addTab(String title, Component component) { + pane.add(title, component); + if (!shouldCache(title, component)) { + children.put(title, component); + childrenReverse.put(component, title); + } + } - /** - * Determines if the tab with the given title and component should - * cached for redirection, instead of duplicating tabs. - * - * @param title The tab's title. - * @param component The component. - * - * TODO: What is the component for? - * - * - Charles - * - * @return true if the tab should be cached. - */ - private boolean shouldCache(String title, Component component) { - return title.contains("Error: "); - } + /** + * Determines if the tab with the given title and component should + * cached for redirection, instead of duplicating tabs. + * + * @param title The tab's title. + * @param component The component. + * + * TODO: What is the component for? + * + * - Charles + * + * @return true if the tab should be cached. + */ + private boolean shouldCache(String title, Component component) { + return title.contains("Error: "); + } - /** - * @return The number of open tabs. + /** + * @return The number of open tabs. - */ - public int getTabCount() { - return pane.getTabCount(); - } + */ + public int getTabCount() { + return pane.getTabCount(); + } - /** - * Set the selected tab. - * - * @param index Index of the tab. - */ - public void setSelectedTab(int index) { - pane.setSelectedIndex(index); - } + /** + * Set the selected tab. + * + * @param index Index of the tab. + */ + public void setSelectedTab(int index) { + pane.setSelectedIndex(index); + } - /** - * Check if a tab by the given title exists and is available for - * redirection. - * - * @param title Title of the tab to check. - * @return true if the tab is available for redirection. - * - * TODO: Is the return accurate? I'm not entirely sure what this does. - * - * - Charles - */ - public boolean hasCached(String title) { - return children.containsKey(title); - } + /** + * Check if a tab by the given title exists and is available for + * redirection. + * + * @param title Title of the tab to check. + * @return true if the tab is available for redirection. + * + * TODO: Is the return accurate? I'm not entirely sure what this does. + * + * - Charles + */ + public boolean hasCached(String title) { + return children.containsKey(title); + } - /** - * Retrieve the index of the cached tab by its title. - * - * @param title The title of the tab. - * @return The tab's index. - */ - public int getCachedIndex(String title) { - for (int i = 0; i < getTabCount(); i++) { - Component component = pane.getComponentAt(i); - if (childrenReverse.get(component).equals(title)) { - return i; - } - } - return -1; - } + /** + * Retrieve the index of the cached tab by its title. + * + * @param title The title of the tab. + * @return The tab's index. + */ + public int getCachedIndex(String title) { + for (int i = 0; i < getTabCount(); i++) { + Component component = pane.getComponentAt(i); + if (childrenReverse.get(component).equals(title)) { + return i; + } + } + return -1; + } } diff --git a/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java b/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java index 1295d9f08..4b79e9f7b 100644 --- a/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java +++ b/src/me/coley/recaf/ui/component/panel/TagTypeSwitchPanel.java @@ -27,90 +27,90 @@ */ @SuppressWarnings("serial") public class TagTypeSwitchPanel extends JPanel implements Opcodes { - /** - * Map of radio buttons to possible tags. - */ - private final Map compToTag = new HashMap<>(); - /** - * InvokeDynamic handle being modified. - */ - private final Handle handle; - /** - * Only stored so the list can be re-painted when the tag is re-chosen. - */ - private final JList list; - /** - * Content wrapper. - */ - private final JPanel content = new JPanel(); + /** + * Map of radio buttons to possible tags. + */ + private final Map compToTag = new HashMap<>(); + /** + * InvokeDynamic handle being modified. + */ + private final Handle handle; + /** + * Only stored so the list can be re-painted when the tag is re-chosen. + */ + private final JList list; + /** + * Content wrapper. + */ + private final JPanel content = new JPanel(); - public TagTypeSwitchPanel(JList list, Handle handle) { - this.list = list; - this.handle = handle; - //setMaximumSize(new Dimension(300, 300)); - // content.setMaximumSize(new Dimension(300, 300)); - // scroll.setMaximumSize(new Dimension(300, 300)); - content.setLayout(new GridLayout(0, 2)); - populate(OpcodeUtil.OPS_TAG, s -> OpcodeUtil.nameToTag(s)); - setLayout(new BorderLayout()); - JScrollPane scroll = new JScrollPane(content); - add(scroll, BorderLayout.CENTER); - } + public TagTypeSwitchPanel(JList list, Handle handle) { + this.list = list; + this.handle = handle; + //setMaximumSize(new Dimension(300, 300)); + // content.setMaximumSize(new Dimension(300, 300)); + // scroll.setMaximumSize(new Dimension(300, 300)); + content.setLayout(new GridLayout(0, 2)); + populate(OpcodeUtil.OPS_TAG, s -> OpcodeUtil.nameToTag(s)); + setLayout(new BorderLayout()); + JScrollPane scroll = new JScrollPane(content); + add(scroll, BorderLayout.CENTER); + } - private void populate(String[] tags, Function getter) { - // Set layout based on number of options - // Add options - for (String op : tags) { - int value = getter.apply(op);; - JRadioButton btn = new JRadioButton(op); - if (value == handle.getTag()) { - btn.setSelected(true); - } - btn.addActionListener(new RadioListener(btn)); - compToTag.put(btn, value); - content.add(btn); - } - } + private void populate(String[] tags, Function getter) { + // Set layout based on number of options + // Add options + for (String op : tags) { + int value = getter.apply(op);; + JRadioButton btn = new JRadioButton(op); + if (value == handle.getTag()) { + btn.setSelected(true); + } + btn.addActionListener(new RadioListener(btn)); + compToTag.put(btn, value); + content.add(btn); + } + } - /** - * Update {@link #handle} value. - * - * @param value - */ - private void setValue(int value) { - Misc.set(handle, "tag", value); - list.repaint(); - } + /** + * Update {@link #handle} value. + * + * @param value + */ + private void setValue(int value) { + Misc.set(handle, "tag", value); + list.repaint(); + } - /** - * @return The number of radio buttons. + /** + * @return The number of radio buttons. - */ - public int getOptionCount() { - return compToTag.keySet().size(); - } + */ + public int getOptionCount() { + return compToTag.keySet().size(); + } - /** - * Listener for disabling other radio buttons. - * - * @author Matt - */ - private class RadioListener implements ActionListener { - private final JRadioButton btn; + /** + * Listener for disabling other radio buttons. + * + * @author Matt + */ + private class RadioListener implements ActionListener { + private final JRadioButton btn; - public RadioListener(JRadioButton btn) { - this.btn = btn; - } + public RadioListener(JRadioButton btn) { + this.btn = btn; + } - @Override - public void actionPerformed(ActionEvent e) { - for (JRadioButton comp : compToTag.keySet()) { - if (comp != btn && comp.isSelected()) { - comp.setSelected(false); - } else if (comp == btn) { - setValue(compToTag.get(comp)); - } - } - } - } + @Override + public void actionPerformed(ActionEvent e) { + for (JRadioButton comp : compToTag.keySet()) { + if (comp != btn && comp.isSelected()) { + comp.setSelected(false); + } else if (comp == btn) { + setValue(compToTag.get(comp)); + } + } + } + } } diff --git a/src/me/coley/recaf/ui/component/table/MemberTable.java b/src/me/coley/recaf/ui/component/table/MemberTable.java index 157171dc4..5475abfe5 100644 --- a/src/me/coley/recaf/ui/component/table/MemberTable.java +++ b/src/me/coley/recaf/ui/component/table/MemberTable.java @@ -17,69 +17,69 @@ @SuppressWarnings("serial") public class MemberTable extends JTable { - // TODO: Clean this up and make it a viable alternative to the list display. - // TODO: Male alternative for List - // - // Pros: - // * Sortable - // - // Cons: - // * Usually 2x wider than list display - public static MemberTable create(List methods) { - String column[] = { "Index", "Name", "Descriptor", "Flags" }; - Object data[][] = new Object[methods.size()][4]; - // Determine widths of table - int maxIndexSize = 45; - int maxNameSize = 10; - int maxTypeSize = 10; - int maxAccessSize = 45; - int padding = 1; - for (int i = 0; i < methods.size(); i++) { - MethodNode method = methods.get(i); - data[i][0] = i; - data[i][1] = method.name; - data[i][2] = method.desc; - data[i][3] = method.access; - // Widths detection - int sIndex = (int) (FontUtil.getStringBounds(data[i][0].toString(), FontUtil.monospace).getWidth()); - if (maxIndexSize < sIndex) { - maxIndexSize = sIndex; - } - int sName = (int) (FontUtil.getStringBounds(data[i][1].toString(), FontUtil.monospace).getWidth()); - if (maxNameSize < sName) { - maxNameSize = sName; - } - int sDesc = (int) (FontUtil.getStringBounds(data[i][2].toString(), FontUtil.monospace).getWidth()); - if (maxTypeSize < sDesc) { - maxTypeSize = sDesc; - } - int sAccess = (int) (FontUtil.getStringBounds(data[i][3].toString(), FontUtil.monospace).getWidth()); - if (maxAccessSize < sAccess) { - maxAccessSize = sAccess; - } - } - MemberTable table = new MemberTable(column, data); - table.setFont(FontUtil.monospace); - table.getColumn("Index").setPreferredWidth(maxIndexSize + (padding * 2)); - table.getColumn("Name").setPreferredWidth(maxNameSize + (padding * 3)); - table.getColumn("Descriptor").setPreferredWidth(maxTypeSize + (padding * 4)); - table.getColumn("Flags").setPreferredWidth(maxAccessSize + (padding * 4)); - return table; - } + // TODO: Clean this up and make it a viable alternative to the list display. + // TODO: Male alternative for List + // + // Pros: + // * Sortable + // + // Cons: + // * Usually 2x wider than list display + public static MemberTable create(List methods) { + String column[] = { "Index", "Name", "Descriptor", "Flags" }; + Object data[][] = new Object[methods.size()][4]; + // Determine widths of table + int maxIndexSize = 45; + int maxNameSize = 10; + int maxTypeSize = 10; + int maxAccessSize = 45; + int padding = 1; + for (int i = 0; i < methods.size(); i++) { + MethodNode method = methods.get(i); + data[i][0] = i; + data[i][1] = method.name; + data[i][2] = method.desc; + data[i][3] = method.access; + // Widths detection + int sIndex = (int) (FontUtil.getStringBounds(data[i][0].toString(), FontUtil.monospace).getWidth()); + if (maxIndexSize < sIndex) { + maxIndexSize = sIndex; + } + int sName = (int) (FontUtil.getStringBounds(data[i][1].toString(), FontUtil.monospace).getWidth()); + if (maxNameSize < sName) { + maxNameSize = sName; + } + int sDesc = (int) (FontUtil.getStringBounds(data[i][2].toString(), FontUtil.monospace).getWidth()); + if (maxTypeSize < sDesc) { + maxTypeSize = sDesc; + } + int sAccess = (int) (FontUtil.getStringBounds(data[i][3].toString(), FontUtil.monospace).getWidth()); + if (maxAccessSize < sAccess) { + maxAccessSize = sAccess; + } + } + MemberTable table = new MemberTable(column, data); + table.setFont(FontUtil.monospace); + table.getColumn("Index").setPreferredWidth(maxIndexSize + (padding * 2)); + table.getColumn("Name").setPreferredWidth(maxNameSize + (padding * 3)); + table.getColumn("Descriptor").setPreferredWidth(maxTypeSize + (padding * 4)); + table.getColumn("Flags").setPreferredWidth(maxAccessSize + (padding * 4)); + return table; + } - private MemberTable(String[] column, Object[][] data) { - super(data, column); - } + private MemberTable(String[] column, Object[][] data) { + super(data, column); + } - /** - * Override the getPrefferedScrollableViewportSize to prevent the wrapping - * scroll pane from adding lots of pointless empty space near the bottom of - * the container. - * - * Credits: https://stackoverflow.com/a/42436205/8071915 - */ - @Override - public Dimension getPreferredScrollableViewportSize() { - return new Dimension(super.getPreferredSize().width, getRowHeight() * getRowCount()); - } + /** + * Override the getPrefferedScrollableViewportSize to prevent the wrapping + * scroll pane from adding lots of pointless empty space near the bottom of + * the container. + * + * Credits: https://stackoverflow.com/a/42436205/8071915 + */ + @Override + public Dimension getPreferredScrollableViewportSize() { + return new Dimension(super.getPreferredSize().width, getRowHeight() * getRowCount()); + } } diff --git a/src/me/coley/recaf/ui/component/table/VariableTable.java b/src/me/coley/recaf/ui/component/table/VariableTable.java index f39449447..f64ef3103 100644 --- a/src/me/coley/recaf/ui/component/table/VariableTable.java +++ b/src/me/coley/recaf/ui/component/table/VariableTable.java @@ -22,116 +22,116 @@ */ @SuppressWarnings("serial") public class VariableTable extends JTable { - private static final int INDEX = 0, NAME = 1, DESC = 2, SIGNATURE = 3; - private static final Options options = Recaf.getInstance().options; + private static final int INDEX = 0, NAME = 1, DESC = 2, SIGNATURE = 3; + private static final Options options = Recaf.getInstance().options; - /** - * Construct a local variable table from the given method. - * - * @param list List of opcodes. - * - * @param method The method. - * @return VariableTable containing the local variables for the method. - */ - public static VariableTable create(OpcodeList list, MethodNode method) { - boolean showSignatures = options.showVariableSignatureInTable; - int max = showSignatures ? 4 : 3; - String column[] = { "Index", "Name", "Descriptor", "Signature" }; - if (!showSignatures) { - // If not showing signatures, remove last column. - column = Arrays.copyOf(column, max); - } - int locals = method.localVariables != null ? method.localVariables.size() : method.maxLocals; - String data[][] = new String[locals][max]; - // Determine widths of table - int maxIndexSize = 45; - int maxNameSize = 10; - int maxTypeSize = 10; - int maxSigSize = 10; - int padding = 10; - for (int i = 0; i < locals; i++) { - // Raw indices - data[i][INDEX] = String.valueOf(i); - int sIndex = (int) (FontUtil.getStringBounds(data[i][0], FontUtil.monospace).getWidth()); - if (maxIndexSize < sIndex) { - maxIndexSize = sIndex; - } - // If possible, add data from local variable table. - if (method.localVariables != null && i < method.localVariables.size()) { - LocalVariableNode variable = method.localVariables.get(i); - data[i][NAME] = variable.name; - data[i][DESC] = variable.desc; - int sName = (int) (FontUtil.getStringBounds(data[i][1], FontUtil.monospace).getWidth()); - int sDesc = (int) (FontUtil.getStringBounds(data[i][2], FontUtil.monospace).getWidth()); - if (maxNameSize < sName) { - maxNameSize = sName; - } - if (maxTypeSize < sDesc) { - maxTypeSize = sDesc; - } - // Signature - if (showSignatures) { - data[i][SIGNATURE] = variable.signature == null ? "" : variable.signature; - int sSign = (int) (FontUtil.getStringBounds(data[i][3], FontUtil.monospace).getWidth()); - if (maxSigSize < sSign) { - maxSigSize = sSign; - } - } - } - } - VariableTable table = new VariableTable(column, data); - table.setFont(FontUtil.monospace); - table.getColumn(column[INDEX]).setPreferredWidth(maxIndexSize + (padding * 2)); - table.getColumn(column[NAME]).setPreferredWidth(maxNameSize + (padding * 3)); - table.getColumn(column[DESC]).setPreferredWidth(maxTypeSize + (padding * 4)); - if (showSignatures) { - table.getColumn(column[SIGNATURE]).setPreferredWidth(maxSigSize + (padding * 4)); - } - table.setCellSelectionEnabled(true); - if (method.localVariables != null) { - table.addKeyListener(new KeyAdapter() { - @Override - public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - int row = table.getSelectedRow(); - int col = table.getSelectedColumn(); - String value = table.getValueAt(row, col).toString(); - switch (col) { - case INDEX: - break; - case NAME: - method.localVariables.get(row).name = value; - list.repaint(); - break; - case DESC: - method.localVariables.get(row).desc = value; - list.repaint(); - break; - case SIGNATURE: - method.localVariables.get(row).signature = value; - list.repaint(); - break; - } - } - } - }); - } - return table; - } + /** + * Construct a local variable table from the given method. + * + * @param list List of opcodes. + * + * @param method The method. + * @return VariableTable containing the local variables for the method. + */ + public static VariableTable create(OpcodeList list, MethodNode method) { + boolean showSignatures = options.showVariableSignatureInTable; + int max = showSignatures ? 4 : 3; + String column[] = { "Index", "Name", "Descriptor", "Signature" }; + if (!showSignatures) { + // If not showing signatures, remove last column. + column = Arrays.copyOf(column, max); + } + int locals = method.localVariables != null ? method.localVariables.size() : method.maxLocals; + String data[][] = new String[locals][max]; + // Determine widths of table + int maxIndexSize = 45; + int maxNameSize = 10; + int maxTypeSize = 10; + int maxSigSize = 10; + int padding = 10; + for (int i = 0; i < locals; i++) { + // Raw indices + data[i][INDEX] = String.valueOf(i); + int sIndex = (int) (FontUtil.getStringBounds(data[i][0], FontUtil.monospace).getWidth()); + if (maxIndexSize < sIndex) { + maxIndexSize = sIndex; + } + // If possible, add data from local variable table. + if (method.localVariables != null && i < method.localVariables.size()) { + LocalVariableNode variable = method.localVariables.get(i); + data[i][NAME] = variable.name; + data[i][DESC] = variable.desc; + int sName = (int) (FontUtil.getStringBounds(data[i][1], FontUtil.monospace).getWidth()); + int sDesc = (int) (FontUtil.getStringBounds(data[i][2], FontUtil.monospace).getWidth()); + if (maxNameSize < sName) { + maxNameSize = sName; + } + if (maxTypeSize < sDesc) { + maxTypeSize = sDesc; + } + // Signature + if (showSignatures) { + data[i][SIGNATURE] = variable.signature == null ? "" : variable.signature; + int sSign = (int) (FontUtil.getStringBounds(data[i][3], FontUtil.monospace).getWidth()); + if (maxSigSize < sSign) { + maxSigSize = sSign; + } + } + } + } + VariableTable table = new VariableTable(column, data); + table.setFont(FontUtil.monospace); + table.getColumn(column[INDEX]).setPreferredWidth(maxIndexSize + (padding * 2)); + table.getColumn(column[NAME]).setPreferredWidth(maxNameSize + (padding * 3)); + table.getColumn(column[DESC]).setPreferredWidth(maxTypeSize + (padding * 4)); + if (showSignatures) { + table.getColumn(column[SIGNATURE]).setPreferredWidth(maxSigSize + (padding * 4)); + } + table.setCellSelectionEnabled(true); + if (method.localVariables != null) { + table.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + int row = table.getSelectedRow(); + int col = table.getSelectedColumn(); + String value = table.getValueAt(row, col).toString(); + switch (col) { + case INDEX: + break; + case NAME: + method.localVariables.get(row).name = value; + list.repaint(); + break; + case DESC: + method.localVariables.get(row).desc = value; + list.repaint(); + break; + case SIGNATURE: + method.localVariables.get(row).signature = value; + list.repaint(); + break; + } + } + } + }); + } + return table; + } - private VariableTable(String[] column, String[][] data) { - super(data, column); - } + private VariableTable(String[] column, String[][] data) { + super(data, column); + } - /** - * Override the getPrefferedScrollableViewportSize to prevent the wrapping - * scroll pane from adding lots of pointless empty space near the bottom of - * the container. - * - * Credits: https://stackoverflow.com/a/42436205/8071915 - */ - @Override - public Dimension getPreferredScrollableViewportSize() { - return new Dimension(super.getPreferredSize().width, getRowHeight() * getRowCount()); - } + /** + * Override the getPrefferedScrollableViewportSize to prevent the wrapping + * scroll pane from adding lots of pointless empty space near the bottom of + * the container. + * + * Credits: https://stackoverflow.com/a/42436205/8071915 + */ + @Override + public Dimension getPreferredScrollableViewportSize() { + return new Dimension(super.getPreferredSize().width, getRowHeight() * getRowCount()); + } } diff --git a/src/me/coley/recaf/ui/component/tree/ASMFieldTreeNode.java b/src/me/coley/recaf/ui/component/tree/ASMFieldTreeNode.java index e24c2eb44..a99a0e261 100644 --- a/src/me/coley/recaf/ui/component/tree/ASMFieldTreeNode.java +++ b/src/me/coley/recaf/ui/component/tree/ASMFieldTreeNode.java @@ -10,14 +10,14 @@ */ @SuppressWarnings("serial") public class ASMFieldTreeNode extends ASMTreeNode { - private final FieldNode field; + private final FieldNode field; - public ASMFieldTreeNode(String title, ClassNode node, FieldNode field) { - super(title, node); - this.field = field; - } + public ASMFieldTreeNode(String title, ClassNode node, FieldNode field) { + super(title, node); + this.field = field; + } - public FieldNode getField() { - return field; - } + public FieldNode getField() { + return field; + } } diff --git a/src/me/coley/recaf/ui/component/tree/ASMInsnTreeNode.java b/src/me/coley/recaf/ui/component/tree/ASMInsnTreeNode.java index 4c3f256f0..71e5b24b5 100644 --- a/src/me/coley/recaf/ui/component/tree/ASMInsnTreeNode.java +++ b/src/me/coley/recaf/ui/component/tree/ASMInsnTreeNode.java @@ -11,14 +11,14 @@ */ @SuppressWarnings("serial") public class ASMInsnTreeNode extends ASMMethodTreeNode { - private final AbstractInsnNode ain; + private final AbstractInsnNode ain; - public ASMInsnTreeNode(String title, ClassNode node, MethodNode method, AbstractInsnNode ain) { - super(title, node, method); - this.ain = ain; - } + public ASMInsnTreeNode(String title, ClassNode node, MethodNode method, AbstractInsnNode ain) { + super(title, node, method); + this.ain = ain; + } - public AbstractInsnNode getInsn() { - return ain; - } + public AbstractInsnNode getInsn() { + return ain; + } } diff --git a/src/me/coley/recaf/ui/component/tree/ASMMethodTreeNode.java b/src/me/coley/recaf/ui/component/tree/ASMMethodTreeNode.java index 6bb0f1e76..29c7dda8b 100644 --- a/src/me/coley/recaf/ui/component/tree/ASMMethodTreeNode.java +++ b/src/me/coley/recaf/ui/component/tree/ASMMethodTreeNode.java @@ -10,14 +10,14 @@ */ @SuppressWarnings("serial") public class ASMMethodTreeNode extends ASMTreeNode { - private final MethodNode method; + private final MethodNode method; - public ASMMethodTreeNode(String title, ClassNode node, MethodNode method) { - super(title, node); - this.method = method; - } + public ASMMethodTreeNode(String title, ClassNode node, MethodNode method) { + super(title, node); + this.method = method; + } - public MethodNode getMethod() { - return method; - } + public MethodNode getMethod() { + return method; + } } diff --git a/src/me/coley/recaf/ui/component/tree/ASMTreeNode.java b/src/me/coley/recaf/ui/component/tree/ASMTreeNode.java index a1cef5241..932307fcc 100644 --- a/src/me/coley/recaf/ui/component/tree/ASMTreeNode.java +++ b/src/me/coley/recaf/ui/component/tree/ASMTreeNode.java @@ -14,23 +14,23 @@ */ @SuppressWarnings("serial") public class ASMTreeNode extends DefaultMutableTreeNode { - private final Map children = new HashMap<>(); - private final ClassNode node; + private final Map children = new HashMap<>(); + private final ClassNode node; - public ASMTreeNode(String title, ClassNode node) { - super(title); - this.node = node; - } + public ASMTreeNode(String title, ClassNode node) { + super(title); + this.node = node; + } - public ASMTreeNode getChild(String name) { - return children.get(name); - } + public ASMTreeNode getChild(String name) { + return children.get(name); + } - public void addChild(String name, ASMTreeNode node) { - children.put(name, node); - } + public void addChild(String name, ASMTreeNode node) { + children.put(name, node); + } - public final ClassNode getNode() { - return node; - } + public final ClassNode getNode() { + return node; + } } diff --git a/src/me/coley/recaf/ui/component/tree/JarFileTree.java b/src/me/coley/recaf/ui/component/tree/JarFileTree.java index 79d87493f..07e4c34fc 100644 --- a/src/me/coley/recaf/ui/component/tree/JarFileTree.java +++ b/src/me/coley/recaf/ui/component/tree/JarFileTree.java @@ -24,47 +24,47 @@ */ @SuppressWarnings("serial") public class JarFileTree extends JPanel { - private final Recaf recaf = Recaf.getInstance(); - private final JTree tree = new JTree(new String[] { "Open a jar" }); - private final JScrollPane scrollTree = new JScrollPane(tree); + private final Recaf recaf = Recaf.getInstance(); + private final JTree tree = new JTree(new String[] { "Open a jar" }); + private final JScrollPane scrollTree = new JScrollPane(tree); - public JarFileTree() { - try { - tree.setCellRenderer(new JavaTreeRenderer()); - JavaTreeListener listener = new JavaTreeListener(); - tree.addTreeExpansionListener(listener); - tree.addTreeSelectionListener(listener); - tree.addMouseListener(listener); - } catch (Exception e) { - e.printStackTrace(); - } - setLayout(new BorderLayout()); - add(scrollTree, BorderLayout.CENTER); - } + public JarFileTree() { + try { + tree.setCellRenderer(new JavaTreeRenderer()); + JavaTreeListener listener = new JavaTreeListener(); + tree.addTreeExpansionListener(listener); + tree.addTreeSelectionListener(listener); + tree.addMouseListener(listener); + } catch (Exception e) { + e.printStackTrace(); + } + setLayout(new BorderLayout()); + add(scrollTree, BorderLayout.CENTER); + } - /** - * Updates the JTree with class files loaded from the current jar. - */ - public void refresh() { - JarData read = recaf.jarData; - // Root node - String jarName = recaf.currentJar.getName(); - ASMTreeNode root = new ASMTreeNode(jarName, null); - DefaultTreeModel model = new DefaultTreeModel(root); - tree.setModel(model); - // Iterate classes - List names = StreamUtil.listOfSortedJavaNames(read.classes.keySet()); - for (String className : names) { - if (!read.classes.containsKey(className)) { - continue; - } - ClassNode node = read.classes.get(className); - // Create directory path based on current node name. - ArrayList dirPath = new ArrayList(Arrays.asList(node.name.split("/"))); - // Create directory of nodes - Misc.generateTreePath(root, dirPath, node, model); - } - model.setRoot(root); + /** + * Updates the JTree with class files loaded from the current jar. + */ + public void refresh() { + JarData read = recaf.jarData; + // Root node + String jarName = recaf.currentJar.getName(); + ASMTreeNode root = new ASMTreeNode(jarName, null); + DefaultTreeModel model = new DefaultTreeModel(root); + tree.setModel(model); + // Iterate classes + List names = StreamUtil.listOfSortedJavaNames(read.classes.keySet()); + for (String className : names) { + if (!read.classes.containsKey(className)) { + continue; + } + ClassNode node = read.classes.get(className); + // Create directory path based on current node name. + ArrayList dirPath = new ArrayList(Arrays.asList(node.name.split("/"))); + // Create directory of nodes + Misc.generateTreePath(root, dirPath, node, model); + } + model.setRoot(root); - } + } } diff --git a/src/me/coley/recaf/ui/component/tree/JavaTreeListener.java b/src/me/coley/recaf/ui/component/tree/JavaTreeListener.java index 8fedfddb1..889048c46 100644 --- a/src/me/coley/recaf/ui/component/tree/JavaTreeListener.java +++ b/src/me/coley/recaf/ui/component/tree/JavaTreeListener.java @@ -18,58 +18,58 @@ * @author Matt */ public class JavaTreeListener implements TreeSelectionListener, MouseListener, TreeExpansionListener { - private final Recaf recaf = Recaf.getInstance(); - private ASMTreeNode lastSelected; - private JTree tree; + private final Recaf recaf = Recaf.getInstance(); + private ASMTreeNode lastSelected; + private JTree tree; - @Override - public void valueChanged(TreeSelectionEvent e) { - tree = (JTree) e.getSource(); - } + @Override + public void valueChanged(TreeSelectionEvent e) { + tree = (JTree) e.getSource(); + } - @Override - public void treeExpanded(TreeExpansionEvent e) { - // Reset selection, prevents expansion from opening the contained value. - lastSelected = null; - } + @Override + public void treeExpanded(TreeExpansionEvent e) { + // Reset selection, prevents expansion from opening the contained value. + lastSelected = null; + } - @Override - public void treeCollapsed(TreeExpansionEvent e) { - // Reset selection, prevents collapsing from opening the contained - // value. - lastSelected = null; - } + @Override + public void treeCollapsed(TreeExpansionEvent e) { + // Reset selection, prevents collapsing from opening the contained + // value. + lastSelected = null; + } - @Override - public void mousePressed(MouseEvent e) { - // Skip if nothing selected (tree null) or not a left click - if (tree == null || e.getButton() != MouseEvent.BUTTON1) { - return; - } - // Skip if the press did not occur in the selection's bounds - if (tree.getSelectionPath() == null || !tree.getPathBounds(tree.getSelectionPath()).contains(e.getX(), e.getY())) { - return; - } - // Update selection, open if double clicked. - Object selection = tree.getLastSelectedPathComponent(); - if (selection instanceof ASMTreeNode) { - ASMTreeNode node = (ASMTreeNode) selection; - if (node != null && node == lastSelected && node.getNode() != null) { - recaf.selectClass(node.getNode()); - } - lastSelected = node; - } - } + @Override + public void mousePressed(MouseEvent e) { + // Skip if nothing selected (tree null) or not a left click + if (tree == null || e.getButton() != MouseEvent.BUTTON1) { + return; + } + // Skip if the press did not occur in the selection's bounds + if (tree.getSelectionPath() == null || !tree.getPathBounds(tree.getSelectionPath()).contains(e.getX(), e.getY())) { + return; + } + // Update selection, open if double clicked. + Object selection = tree.getLastSelectedPathComponent(); + if (selection instanceof ASMTreeNode) { + ASMTreeNode node = (ASMTreeNode) selection; + if (node != null && node == lastSelected && node.getNode() != null) { + recaf.selectClass(node.getNode()); + } + lastSelected = node; + } + } - @Override - public void mouseClicked(MouseEvent e) {} + @Override + public void mouseClicked(MouseEvent e) {} - @Override - public void mouseReleased(MouseEvent e) {} + @Override + public void mouseReleased(MouseEvent e) {} - @Override - public void mouseEntered(MouseEvent e) {} + @Override + public void mouseEntered(MouseEvent e) {} - @Override - public void mouseExited(MouseEvent e) {} + @Override + public void mouseExited(MouseEvent e) {} } diff --git a/src/me/coley/recaf/ui/component/tree/JavaTreeRenderer.java b/src/me/coley/recaf/ui/component/tree/JavaTreeRenderer.java index c7e02d26d..4c4069b43 100644 --- a/src/me/coley/recaf/ui/component/tree/JavaTreeRenderer.java +++ b/src/me/coley/recaf/ui/component/tree/JavaTreeRenderer.java @@ -18,70 +18,70 @@ */ @SuppressWarnings("serial") public class JavaTreeRenderer extends DefaultTreeCellRenderer { - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, - boolean hasFocus) { - super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; - if (node instanceof ASMInsnTreeNode) { - setIcon(MISC_RESULT); - } else if (node instanceof ASMMethodTreeNode) { - int acc = ((ASMMethodTreeNode) node).getMethod().access; - if (Access.isPublic(acc)) { - setIcon(ML_PUBLIC); - } else if (Access.isProtected(acc)) { - setIcon(ML_PROTECTED); - } else if (Access.isPrivate(acc)) { - setIcon(ML_PRIVATE); - } else { - setIcon(ML_DEFAULT); - } - } else if (node instanceof ASMFieldTreeNode) { - int acc = ((ASMFieldTreeNode) node).getField().access; - if (Access.isPublic(acc)) { - setIcon(FL_PUBLIC); - } else if (Access.isProtected(acc)) { - setIcon(FL_PROTECTED); - } else if (Access.isPrivate(acc)) { - setIcon(FL_PRIVATE); - } else { - setIcon(FL_DEFAULT); - } - } else if (node instanceof ASMTreeNode) { - ASMTreeNode mtNode = (ASMTreeNode) node; - if (mtNode.getNode() == null) { - // The root node of the tree has no node. - // The root isn't DefaultMutableTreeNode because otherwise - // it makes the code for generating the tree a uglier. This - // if statement is the exchange. - if (node.getChildCount() > 0) { - // Tis a package. - setIcon(MISC_PACKAGE); - } else { - setIcon(MISC_RESULT); - } - } else { - // Get the classnode, determine icon by access - ClassNode cn = mtNode.getNode(); - int acc = cn.access; - if (Access.isInterface(acc)) { - setIcon(CL_INTERFACE); - } else if (Access.isEnum(acc)) { - setIcon(CL_ENUM); - } else if (Access.isAnnotation(acc)) { - setIcon(CL_ANNOTATION); - } else { - setIcon(CL_CLASS); - } - } - } else if (node.getChildCount() > 0) { - // Tis a package. - setIcon(MISC_PACKAGE); - } else { - setIcon(MISC_RESULT); - } + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, + boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; + if (node instanceof ASMInsnTreeNode) { + setIcon(MISC_RESULT); + } else if (node instanceof ASMMethodTreeNode) { + int acc = ((ASMMethodTreeNode) node).getMethod().access; + if (Access.isPublic(acc)) { + setIcon(ML_PUBLIC); + } else if (Access.isProtected(acc)) { + setIcon(ML_PROTECTED); + } else if (Access.isPrivate(acc)) { + setIcon(ML_PRIVATE); + } else { + setIcon(ML_DEFAULT); + } + } else if (node instanceof ASMFieldTreeNode) { + int acc = ((ASMFieldTreeNode) node).getField().access; + if (Access.isPublic(acc)) { + setIcon(FL_PUBLIC); + } else if (Access.isProtected(acc)) { + setIcon(FL_PROTECTED); + } else if (Access.isPrivate(acc)) { + setIcon(FL_PRIVATE); + } else { + setIcon(FL_DEFAULT); + } + } else if (node instanceof ASMTreeNode) { + ASMTreeNode mtNode = (ASMTreeNode) node; + if (mtNode.getNode() == null) { + // The root node of the tree has no node. + // The root isn't DefaultMutableTreeNode because otherwise + // it makes the code for generating the tree a uglier. This + // if statement is the exchange. + if (node.getChildCount() > 0) { + // Tis a package. + setIcon(MISC_PACKAGE); + } else { + setIcon(MISC_RESULT); + } + } else { + // Get the classnode, determine icon by access + ClassNode cn = mtNode.getNode(); + int acc = cn.access; + if (Access.isInterface(acc)) { + setIcon(CL_INTERFACE); + } else if (Access.isEnum(acc)) { + setIcon(CL_ENUM); + } else if (Access.isAnnotation(acc)) { + setIcon(CL_ANNOTATION); + } else { + setIcon(CL_CLASS); + } + } + } else if (node.getChildCount() > 0) { + // Tis a package. + setIcon(MISC_PACKAGE); + } else { + setIcon(MISC_RESULT); + } - return this; - } + return this; + } } \ No newline at end of file diff --git a/src/me/coley/recaf/util/IndexableDataStream.java b/src/me/coley/recaf/util/IndexableDataStream.java index a532d82e1..5b67ec83d 100644 --- a/src/me/coley/recaf/util/IndexableDataStream.java +++ b/src/me/coley/recaf/util/IndexableDataStream.java @@ -8,32 +8,32 @@ * index. */ public class IndexableDataStream extends DataInputStream { - private PositionExposer exposer; - - public IndexableDataStream(byte[] data) { - super(new PositionExposer(data)); - this.exposer = ((PositionExposer) in); - } - - public int getIndex() { - return exposer.getIndex(); - } - - public void reset(int len) { - exposer.reset(len); - } - - private static final class PositionExposer extends ByteArrayInputStream { - public PositionExposer(byte[] data) { - super(data); - } - - public void reset(int len) { - pos -= len; - } - - public int getIndex() { - return pos; - } - } + private PositionExposer exposer; + + public IndexableDataStream(byte[] data) { + super(new PositionExposer(data)); + this.exposer = ((PositionExposer) in); + } + + public int getIndex() { + return exposer.getIndex(); + } + + public void reset(int len) { + exposer.reset(len); + } + + private static final class PositionExposer extends ByteArrayInputStream { + public PositionExposer(byte[] data) { + super(data); + } + + public void reset(int len) { + pos -= len; + } + + public int getIndex() { + return pos; + } + } } diff --git a/src/me/coley/recaf/util/JavaNameSorter.java b/src/me/coley/recaf/util/JavaNameSorter.java index 5d08c38e6..de02f20aa 100644 --- a/src/me/coley/recaf/util/JavaNameSorter.java +++ b/src/me/coley/recaf/util/JavaNameSorter.java @@ -9,24 +9,24 @@ */ public class JavaNameSorter implements Comparator { - @Override - public int compare(String s1, String s2) { - String[] split1 = s1.split("/"); - String[] split2 = s2.split("/"); - int l1 = split1.length; - int l2 = split2.length; - int len = Math.min(l1, l2); - for (int i = 0; i < len; i++) { - String p1 = split1[i]; - String p2 = split2[i]; - if (i == len - 1 && l1 != l2) { - return (l1 > l2) ? -1 : 1; - } - int cmp = p1.compareTo(p2); - if (cmp != 0) { - return cmp; - } - } - return 0; - } + @Override + public int compare(String s1, String s2) { + String[] split1 = s1.split("/"); + String[] split2 = s2.split("/"); + int l1 = split1.length; + int l2 = split2.length; + int len = Math.min(l1, l2); + for (int i = 0; i < len; i++) { + String p1 = split1[i]; + String p2 = split2[i]; + if (i == len - 1 && l1 != l2) { + return (l1 > l2) ? -1 : 1; + } + int cmp = p1.compareTo(p2); + if (cmp != 0) { + return cmp; + } + } + return 0; + } } \ No newline at end of file diff --git a/src/me/coley/recaf/util/Misc.java b/src/me/coley/recaf/util/Misc.java index 70e2520c3..415c80464 100644 --- a/src/me/coley/recaf/util/Misc.java +++ b/src/me/coley/recaf/util/Misc.java @@ -22,139 +22,139 @@ */ public class Misc { - public static boolean isInt(String s) { - if (s.length() == 0) { - return false; - } - try { - Integer.parseInt(s); - return true; - } catch (Exception e) { - return false; - } - } - - public static boolean isBoolean(String s) { - if (s.length() == 0) { - return false; - } - try { - Boolean.parseBoolean(s); - return true; - } catch (Exception e) { - return false; - } - } - - public static void addAll(JInternalFrame owner, JComponent... components) { - for (JComponent component : components) { - owner.add(component); - } - } - - public static void setBoolean(Object owner, String fieldName, Object value) { - String vts = value.toString(); - if (Misc.isBoolean(vts)) { - set(owner, fieldName, Boolean.parseBoolean(vts)); - } - } - - public static void setInt(Object owner, String fieldName, Object value) { - String vts = value.toString(); - if (Misc.isInt(vts)) { - set(owner, fieldName, Integer.parseInt(vts)); - } - } - - public static void set(Object owner, String fieldName, Object value) { - // Ok, so this is mostly used in lambdas, which can't handle - // exceptions.... - // so just try-catch it. Ugly, but hey it'll have to do. - try { - Field field = owner.getClass().getDeclaredField(fieldName); - if (!field.isAccessible()) { - field.setAccessible(true); - } - field.set(owner, value); - } catch (Exception e) {} - } - - public static String readFile(String path) throws IOException { - return new String(Files.readAllBytes(Paths.get(path)), Charset.forName("utf-8")); - } - - public static void writeFile(String path, String content) throws IOException { - Files.write(Paths.get(path), content.getBytes("utf-8")); - } - - /** - * Adds a path to a given parent node. Also updates the given model. - * - * @param parent The parent node. - * @param dirPath TODO - * @param cn Class - * @param model Model to add node to - * - * TODO: document dirPath param; I'm not sure what it's for. - * - * - Charles - */ - public static ASMTreeNode generateTreePath(ASMTreeNode parent, List dirPath, ClassNode cn, DefaultTreeModel model) { - ASMTreeNode ret = null; - while (dirPath.size() > 0) { - String section = dirPath.get(0); - ASMTreeNode node; - // Create child if it doesn't exist. - if ((node = parent.getChild(section)) == null) { - ASMTreeNode newDir = ret = new ASMTreeNode(section, dirPath.size() == 1 ? cn : null); - parent.addChild(section, newDir); - parent.add(newDir); - // update model - model.nodesWereInserted(parent, new int[] { parent.getIndex(newDir) }); - node = newDir; - } - parent = node; - dirPath.remove(0); - } - return ret; - } - - /** - * Adds a path to a given parent node. Also updates the given model. - * - * @param parent The parent node - * @param dirPath TODO - * - * TODO: document dirPath param; I'm not sure what it's for. - * - * - Charles - */ - public static ASMTreeNode getTreePath(ASMTreeNode parent, List dirPath) { - ASMTreeNode node = parent; - while (dirPath.size() > 0) { - node = node.getChild(dirPath.get(0)); - dirPath.remove(0); - } - return node; - } - - /** - * Get or create the tree node for the given class node from the given - * model. - * - * @param model The default tree model to use. - * @param classNode The class node. - * @return The tree node. - */ - public static ASMTreeNode getOrCreateNode(DefaultTreeModel model, ClassNode classNode) { - ASMTreeNode root = (ASMTreeNode) model.getRoot(); - ArrayList dirPath = new ArrayList(Arrays.asList(classNode.name.split("/"))); - ASMTreeNode genClass = generateTreePath(root, dirPath, classNode, model); - if (genClass == null) { - dirPath = new ArrayList(Arrays.asList(classNode.name.split("/"))); - genClass = getTreePath(root, dirPath); - } - return genClass; - } + public static boolean isInt(String s) { + if (s.length() == 0) { + return false; + } + try { + Integer.parseInt(s); + return true; + } catch (Exception e) { + return false; + } + } + + public static boolean isBoolean(String s) { + if (s.length() == 0) { + return false; + } + try { + Boolean.parseBoolean(s); + return true; + } catch (Exception e) { + return false; + } + } + + public static void addAll(JInternalFrame owner, JComponent... components) { + for (JComponent component : components) { + owner.add(component); + } + } + + public static void setBoolean(Object owner, String fieldName, Object value) { + String vts = value.toString(); + if (Misc.isBoolean(vts)) { + set(owner, fieldName, Boolean.parseBoolean(vts)); + } + } + + public static void setInt(Object owner, String fieldName, Object value) { + String vts = value.toString(); + if (Misc.isInt(vts)) { + set(owner, fieldName, Integer.parseInt(vts)); + } + } + + public static void set(Object owner, String fieldName, Object value) { + // Ok, so this is mostly used in lambdas, which can't handle + // exceptions.... + // so just try-catch it. Ugly, but hey it'll have to do. + try { + Field field = owner.getClass().getDeclaredField(fieldName); + if (!field.isAccessible()) { + field.setAccessible(true); + } + field.set(owner, value); + } catch (Exception e) {} + } + + public static String readFile(String path) throws IOException { + return new String(Files.readAllBytes(Paths.get(path)), Charset.forName("utf-8")); + } + + public static void writeFile(String path, String content) throws IOException { + Files.write(Paths.get(path), content.getBytes("utf-8")); + } + + /** + * Adds a path to a given parent node. Also updates the given model. + * + * @param parent The parent node. + * @param dirPath TODO + * @param cn Class + * @param model Model to add node to + * + * TODO: document dirPath param; I'm not sure what it's for. + * + * - Charles + */ + public static ASMTreeNode generateTreePath(ASMTreeNode parent, List dirPath, ClassNode cn, DefaultTreeModel model) { + ASMTreeNode ret = null; + while (dirPath.size() > 0) { + String section = dirPath.get(0); + ASMTreeNode node; + // Create child if it doesn't exist. + if ((node = parent.getChild(section)) == null) { + ASMTreeNode newDir = ret = new ASMTreeNode(section, dirPath.size() == 1 ? cn : null); + parent.addChild(section, newDir); + parent.add(newDir); + // update model + model.nodesWereInserted(parent, new int[] { parent.getIndex(newDir) }); + node = newDir; + } + parent = node; + dirPath.remove(0); + } + return ret; + } + + /** + * Adds a path to a given parent node. Also updates the given model. + * + * @param parent The parent node + * @param dirPath TODO + * + * TODO: document dirPath param; I'm not sure what it's for. + * + * - Charles + */ + public static ASMTreeNode getTreePath(ASMTreeNode parent, List dirPath) { + ASMTreeNode node = parent; + while (dirPath.size() > 0) { + node = node.getChild(dirPath.get(0)); + dirPath.remove(0); + } + return node; + } + + /** + * Get or create the tree node for the given class node from the given + * model. + * + * @param model The default tree model to use. + * @param classNode The class node. + * @return The tree node. + */ + public static ASMTreeNode getOrCreateNode(DefaultTreeModel model, ClassNode classNode) { + ASMTreeNode root = (ASMTreeNode) model.getRoot(); + ArrayList dirPath = new ArrayList(Arrays.asList(classNode.name.split("/"))); + ASMTreeNode genClass = generateTreePath(root, dirPath, classNode, model); + if (genClass == null) { + dirPath = new ArrayList(Arrays.asList(classNode.name.split("/"))); + genClass = getTreePath(root, dirPath); + } + return genClass; + } } diff --git a/src/me/coley/recaf/util/StreamUtil.java b/src/me/coley/recaf/util/StreamUtil.java index 6bb25abcd..2b4a1defb 100644 --- a/src/me/coley/recaf/util/StreamUtil.java +++ b/src/me/coley/recaf/util/StreamUtil.java @@ -9,55 +9,55 @@ import java.util.stream.Stream; public class StreamUtil { - private final static int BUFF_SIZE = (int) Math.pow(128, 2); + private final static int BUFF_SIZE = (int) Math.pow(128, 2); - /** - * Creates a DataInputStream from byte[]. - * - * @param data byte[] to convert to DataInputStream. - * @return The data input stream. - */ - public static IndexableDataStream fromBytes(byte[] data) { - return new IndexableDataStream(data); - } + /** + * Creates a DataInputStream from byte[]. + * + * @param data byte[] to convert to DataInputStream. + * @return The data input stream. + */ + public static IndexableDataStream fromBytes(byte[] data) { + return new IndexableDataStream(data); + } - /** - * Reads the bytes from the inputstream into a byte array. - * - * @param is InputStream to read from. - * @return byt earray representation of the input stream. - * @throws IOException Thrown if the given input stream cannot be read - * from. - */ - public static byte[] fromStream(InputStream is) throws IOException { - try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { - int r; - byte[] data = new byte[BUFF_SIZE]; - while ((r = is.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, r); - } - buffer.flush(); - return buffer.toByteArray(); - } - } + /** + * Reads the bytes from the inputstream into a byte array. + * + * @param is InputStream to read from. + * @return byt earray representation of the input stream. + * @throws IOException Thrown if the given input stream cannot be read + * from. + */ + public static byte[] fromStream(InputStream is) throws IOException { + try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { + int r; + byte[] data = new byte[BUFF_SIZE]; + while ((r = is.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, r); + } + buffer.flush(); + return buffer.toByteArray(); + } + } - /** - * Sorts the stream of java names. - * - * @param stream Stream of names. - * @return The stream, sorted. - */ - public static Stream sortJavaNames(Stream stream) { - return stream.sorted(new JavaNameSorter()); - } + /** + * Sorts the stream of java names. + * + * @param stream Stream of names. + * @return The stream, sorted. + */ + public static Stream sortJavaNames(Stream stream) { + return stream.sorted(new JavaNameSorter()); + } - /** - * Creates a list of sorted java names from a given collection. - * - * @param names Collection of names. - * @return The collection, sorted and converted to a list. - */ - public static List listOfSortedJavaNames(Collection names) { - return sortJavaNames(names.stream()).collect(Collectors.toList()); - } + /** + * Creates a list of sorted java names from a given collection. + * + * @param names Collection of names. + * @return The collection, sorted and converted to a list. + */ + public static List listOfSortedJavaNames(Collection names) { + return sortJavaNames(names.stream()).collect(Collectors.toList()); + } } From b3c7d56179ac586200bfe79feb2fcf7a40910f37 Mon Sep 17 00:00:00 2001 From: Charles Daniels Date: Sat, 14 Oct 2017 13:35:05 -0400 Subject: [PATCH 5/6] Added code-quality assurance tools to pom.xml * Added CheckStyle to perform static analysis on the Recaf codebase. * View output on the console with "mvn checkstyle:check". * Added FindBugs to check for common anti-patterns that tend to cause bugs. * View the output on the console with "mvn clean compile; mvn findbugs:check". * View the output in the GUI with "mvn clean compile; mvn findbugs:gui". * "mvn site" should now include HTML versions of the CheckStyle and FindBugs reports. Note that for the FindBugs one to show up, you might need to run "mvn clean compile" before "mvn site". * In the future, the project should be configured to refuse to compile if any CheckStyle or FindBugs issues are present (i.e. after the standing issues are fixed). * For CheckStyle: http://maven.apache.org/plugins/maven-checkstyle-plugin/usage.html * For FindBugs: http://memorynotfound.com/findbugs-maven-plugin-fail-build/ --- pom.xml | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 8a145d275..189acc8f4 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ 4.0.0 Recaf - Recaf + Recaf https://github.com/Col-E/Recaf/ 0.7 Recaf @@ -62,7 +62,42 @@ jar-with-dependencies - + - \ No newline at end of file + + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.5 + + + Max + + Low + + true + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + + checkstyle + + + + + + + + From 31478cd398575a2a181e96950736e7a512c0497e Mon Sep 17 00:00:00 2001 From: Col-E Date: Sat, 14 Oct 2017 19:27:44 -0400 Subject: [PATCH 6/6] Update .gitingore --- .gitignore | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 1ae203eb9..acb71d81c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,4 @@ .project bin/** temp/** -target/** -src/org/** -src/com/** \ No newline at end of file +target/** \ No newline at end of file