From e16f81dba9edadb3fc02492bfeff06266890e754 Mon Sep 17 00:00:00 2001 From: Yanis48 Date: Mon, 14 Dec 2020 21:15:53 +0100 Subject: Structure panel! --- .../src/main/java/cuchaz/enigma/gui/Gui.java | 56 +++++++++-- .../main/java/cuchaz/enigma/gui/GuiController.java | 12 ++- .../cuchaz/enigma/gui/panels/StructurePanel.java | 102 +++++++++++++++++++ .../main/java/cuchaz/enigma/gui/util/GuiUtil.java | 31 ++++-- enigma-swing/src/main/resources/icons/class.png | Bin 0 -> 408 bytes enigma-swing/src/main/resources/icons/field.png | Bin 0 -> 392 bytes enigma-swing/src/main/resources/icons/method.png | Bin 0 -> 618 bytes .../cuchaz/enigma/analysis/StructureTreeNode.java | 109 +++++++++++++++++++++ .../cuchaz/enigma/analysis/index/JarIndex.java | 24 ++++- .../translation/representation/TypeDescriptor.java | 27 +++-- .../representation/entry/ClassEntry.java | 3 + .../translation/representation/entry/Entry.java | 7 ++ enigma/src/main/resources/lang/en_us.json | 2 + enigma/src/main/resources/lang/fr_fr.json | 2 + 14 files changed, 338 insertions(+), 37 deletions(-) create mode 100644 enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java create mode 100644 enigma-swing/src/main/resources/icons/class.png create mode 100644 enigma-swing/src/main/resources/icons/field.png create mode 100644 enigma-swing/src/main/resources/icons/method.png create mode 100644 enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java index c56731d..a3a438e 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java @@ -51,10 +51,7 @@ import cuchaz.enigma.network.packet.RemoveMappingC2SPacket; import cuchaz.enigma.network.packet.RenameC2SPacket; import cuchaz.enigma.source.Token; import cuchaz.enigma.translation.mapping.EntryRemapper; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; +import cuchaz.enigma.translation.representation.entry.*; import cuchaz.enigma.utils.I18n; import cuchaz.enigma.utils.validation.ParameterizedMessage; import cuchaz.enigma.utils.validation.ValidationContext; @@ -82,6 +79,7 @@ public class Gui implements LanguageChangeListener { private JPanel classesPanel; private JSplitPane splitClasses; private IdentifierPanel infoPanel; + private StructurePanel structurePanel; private JTree inheritanceTree; private JTree implementationsTree; private JTree callsTree; @@ -163,6 +161,9 @@ public class Gui implements LanguageChangeListener { // init info panel infoPanel = new IdentifierPanel(this); + // init structure panel + this.structurePanel = new StructurePanel(this); + // init inheritance panel inheritanceTree = new JTree(); inheritanceTree.setModel(null); @@ -287,6 +288,8 @@ public class Gui implements LanguageChangeListener { editorTabPopupMenu.show(openFiles, e.getX(), e.getY(), EditorPanel.byUi(openFiles.getComponentAt(i))); } } + + showStructure(getActiveEditor()); } }); @@ -311,6 +314,7 @@ public class Gui implements LanguageChangeListener { centerPanel.add(openFiles, BorderLayout.CENTER); tabs = new JTabbedPane(); tabs.setPreferredSize(ScaleUtil.getDimension(250, 0)); + tabs.addTab(I18n.translate("info_panel.tree.structure"), structurePanel); tabs.addTab(I18n.translate("info_panel.tree.inheritance"), inheritancePanel); tabs.addTab(I18n.translate("info_panel.tree.implementations"), implementationsPanel); tabs.addTab(I18n.translate("info_panel.tree.calls"), callPanel); @@ -482,11 +486,14 @@ public class Gui implements LanguageChangeListener { } }); + showStructure(ed); + return ed; }); if (editorPanel != null) { openFiles.setSelectedComponent(editors.get(entry).getUi()); } + return editorPanel; } @@ -506,6 +513,7 @@ public class Gui implements LanguageChangeListener { public void closeEditor(EditorPanel ed) { openFiles.remove(ed.getUi()); editors.inverse().remove(ed); + showStructure(getActiveEditor()); ed.destroy(); } @@ -595,6 +603,32 @@ public class Gui implements LanguageChangeListener { infoPanel.startRenaming(); } + public void showStructure(EditorPanel editor) { + JTree structureTree = this.structurePanel.getStructureTree(); + structureTree.setModel(null); + + if (editor == null) { + this.structurePanel.getSortingPanel().setVisible(false); + return; + } + + ClassEntry classEntry = editor.getClassHandle().getRef(); + if (classEntry == null) return; + + this.structurePanel.getSortingPanel().setVisible(true); + + // get the class structure + StructureTreeNode node = this.controller.getClassStructure(classEntry, this.structurePanel.shouldHideDeobfuscated()); + + // show the tree at the root + TreePath path = getPathToRoot(node); + structureTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0))); + structureTree.expandPath(path); + structureTree.setSelectionRow(structureTree.getRowForPath(path)); + + redraw(); + } + public void showInheritance(EditorPanel editor) { EntryReference, Entry> cursorReference = editor.getCursorReference(); if (cursorReference == null) return; @@ -621,7 +655,7 @@ public class Gui implements LanguageChangeListener { inheritanceTree.setSelectionRow(inheritanceTree.getRowForPath(path)); } - tabs.setSelectedIndex(0); + tabs.setSelectedIndex(1); redraw(); } @@ -649,7 +683,7 @@ public class Gui implements LanguageChangeListener { implementationsTree.setSelectionRow(implementationsTree.getRowForPath(path)); } - tabs.setSelectedIndex(1); + tabs.setSelectedIndex(2); redraw(); } @@ -669,7 +703,7 @@ public class Gui implements LanguageChangeListener { callsTree.setModel(new DefaultTreeModel(node)); } - tabs.setSelectedIndex(2); + tabs.setSelectedIndex(3); redraw(); } @@ -893,9 +927,10 @@ public class Gui implements LanguageChangeListener { public void retranslateUi() { this.jarFileChooser.setTitle(I18n.translate("menu.file.jar.open")); this.exportJarFileChooser.setTitle(I18n.translate("menu.file.export.jar")); - this.tabs.setTitleAt(0, I18n.translate("info_panel.tree.inheritance")); - this.tabs.setTitleAt(1, I18n.translate("info_panel.tree.implementations")); - this.tabs.setTitleAt(2, I18n.translate("info_panel.tree.calls")); + this.tabs.setTitleAt(0, I18n.translate("info_panel.tree.structure")); + this.tabs.setTitleAt(1, I18n.translate("info_panel.tree.inheritance")); + this.tabs.setTitleAt(2, I18n.translate("info_panel.tree.implementations")); + this.tabs.setTitleAt(3, I18n.translate("info_panel.tree.calls")); this.logTabs.setTitleAt(0, I18n.translate("log_panel.users")); this.logTabs.setTitleAt(1, I18n.translate("log_panel.messages")); this.connectionStatusLabel.setText(I18n.translate(connectionState == ConnectionState.NOT_CONNECTED ? "status.disconnected" : "status.connected")); @@ -907,6 +942,7 @@ public class Gui implements LanguageChangeListener { this.deobfPanel.retranslateUi(); this.deobfPanelPopupMenu.retranslateUi(); this.infoPanel.retranslateUi(); + this.structurePanel.retranslateUi(); this.editors.values().forEach(EditorPanel::retranslateUi); } diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java index 4f7819e..4e964da 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java @@ -57,10 +57,7 @@ import cuchaz.enigma.translation.mapping.serde.MappingParseException; import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; import cuchaz.enigma.translation.mapping.tree.EntryTree; import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; +import cuchaz.enigma.translation.representation.entry.*; import cuchaz.enigma.utils.I18n; import cuchaz.enigma.utils.Utils; import cuchaz.enigma.utils.validation.ValidationContext; @@ -395,6 +392,13 @@ public class GuiController implements ClientPacketHandler { chp.invalidateMapped(); } + public StructureTreeNode getClassStructure(ClassEntry entry, boolean hideDeobfuscated) { + Translator translator = this.project.getMapper().getDeobfuscator(); + StructureTreeNode rootNode = new StructureTreeNode(translator, entry, entry); + rootNode.load(this.project.getJarIndex(), hideDeobfuscated); + return rootNode; + } + public ClassInheritanceTreeNode getClassInheritance(ClassEntry entry) { Translator translator = project.getMapper().getDeobfuscator(); ClassInheritanceTreeNode rootNode = indexTreeBuilder.buildClassInheritance(translator, entry); diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java new file mode 100644 index 0000000..32f803f --- /dev/null +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java @@ -0,0 +1,102 @@ +package cuchaz.enigma.gui.panels; + +import cuchaz.enigma.analysis.StructureTreeNode; +import cuchaz.enigma.gui.Gui; +import cuchaz.enigma.gui.util.GuiUtil; +import cuchaz.enigma.translation.representation.entry.ClassEntry; +import cuchaz.enigma.translation.representation.entry.FieldEntry; +import cuchaz.enigma.translation.representation.entry.MethodEntry; +import cuchaz.enigma.translation.representation.entry.ParentedEntry; +import cuchaz.enigma.utils.I18n; + +import javax.swing.*; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class StructurePanel extends JPanel { + private final Gui gui; + + private JPanel sortingPanel; + private JCheckBox hideDeobfuscated; + + private JTree structureTree; + + public StructurePanel(Gui gui) { + this.gui = gui; + + this.sortingPanel = new JPanel(); + this.hideDeobfuscated = new JCheckBox(I18n.translate("info_panel.tree.structure.hide_deobfuscated")); + this.hideDeobfuscated.addActionListener(event -> gui.showStructure(gui.getActiveEditor())); + this.sortingPanel.add(this.hideDeobfuscated); + this.sortingPanel.setVisible(false); + + this.structureTree = new JTree(); + this.structureTree.setModel(null); + this.structureTree.setCellRenderer(new StructureTreeCellRenderer()); + this.structureTree.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent event) { + if (event.getClickCount() >= 2) { + // get the selected node + TreePath path = structureTree.getSelectionPath(); + if (path == null) { + return; + } + + Object node = path.getLastPathComponent(); + if (node instanceof StructureTreeNode) { + gui.getController().navigateTo(((StructureTreeNode) node).getEntry()); + } + } + } + }); + + this.setLayout(new BorderLayout()); + this.add(this.sortingPanel, BorderLayout.NORTH); + this.add(new JScrollPane(this.structureTree)); + } + + public JPanel getSortingPanel() { + return this.sortingPanel; + } + + public boolean shouldHideDeobfuscated() { + return this.hideDeobfuscated.isSelected(); + } + + public JTree getStructureTree() { + return this.structureTree; + } + + public void retranslateUi() { + this.hideDeobfuscated.setText(I18n.translate("info_panel.tree.structure.hide_deobfuscated")); + } + + class StructureTreeCellRenderer implements TreeCellRenderer { + private JLabel label; + + public StructureTreeCellRenderer() { + this.label = new JLabel(); + } + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + ParentedEntry entry = ((StructureTreeNode) value).getEntry(); + + if (entry instanceof ClassEntry) { + this.label.setIcon(GuiUtil.CLASS_ICON); + } else if (entry instanceof MethodEntry) { + this.label.setIcon(GuiUtil.METHOD_ICON); + } else if (entry instanceof FieldEntry) { + this.label.setIcon(GuiUtil.FIELD_ICON); + } + + this.label.setText(value.toString()); + + return this.label; + } + } +} diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java index 7fe942d..666fc0a 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java @@ -1,24 +1,24 @@ package cuchaz.enigma.gui.util; -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Desktop; -import java.awt.Font; +import cuchaz.enigma.utils.Os; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.font.TextAttribute; import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.Map; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.ToolTipManager; - -import cuchaz.enigma.utils.Os; - public class GuiUtil { + public static final Icon CLASS_ICON = loadIcon("class"); + public static final Icon METHOD_ICON = loadIcon("method"); + public static final Icon FIELD_ICON = loadIcon("field"); + public static void openUrl(String url) { try { switch (Os.getOs()) { @@ -70,4 +70,15 @@ public class GuiUtil { return link; } + public static Icon loadIcon(String name) { + try { + InputStream inputStream = GuiUtil.class.getResourceAsStream("/icons/" + name + ".png"); + Image image = ImageIO.read(inputStream).getScaledInstance(ScaleUtil.scale(16), ScaleUtil.scale(16), Image.SCALE_DEFAULT); + return new ImageIcon(image); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } } diff --git a/enigma-swing/src/main/resources/icons/class.png b/enigma-swing/src/main/resources/icons/class.png new file mode 100644 index 0000000..4f7d0f4 Binary files /dev/null and b/enigma-swing/src/main/resources/icons/class.png differ diff --git a/enigma-swing/src/main/resources/icons/field.png b/enigma-swing/src/main/resources/icons/field.png new file mode 100644 index 0000000..b124dcf Binary files /dev/null and b/enigma-swing/src/main/resources/icons/field.png differ diff --git a/enigma-swing/src/main/resources/icons/method.png b/enigma-swing/src/main/resources/icons/method.png new file mode 100644 index 0000000..4ed0ccc Binary files /dev/null and b/enigma-swing/src/main/resources/icons/method.png differ diff --git a/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java new file mode 100644 index 0000000..13f277c --- /dev/null +++ b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java @@ -0,0 +1,109 @@ +package cuchaz.enigma.analysis; + +import cuchaz.enigma.analysis.index.JarIndex; +import cuchaz.enigma.translation.Translator; +import cuchaz.enigma.translation.representation.TypeDescriptor; +import cuchaz.enigma.translation.representation.entry.*; + +import javax.swing.tree.DefaultMutableTreeNode; +import java.util.List; + +public class StructureTreeNode extends DefaultMutableTreeNode { + private final Translator translator; + private final ClassEntry parentEntry; + private final ParentedEntry entry; + + public StructureTreeNode(Translator translator, ClassEntry parentEntry, ParentedEntry entry) { + this.translator = translator; + this.parentEntry = parentEntry; + this.entry = entry; + } + + /** + * Returns the parented entry corresponding to this tree node. + */ + public ParentedEntry getEntry() { + return this.entry; + } + + public void load(JarIndex jarIndex, boolean hideDeobfuscated) { + List children = jarIndex.getChildrenByClass().get(this.parentEntry); + + for (ParentedEntry child : children) { + StructureTreeNode childNode = new StructureTreeNode(this.translator, this.parentEntry, child); + + if (child instanceof ClassEntry) { + childNode = new StructureTreeNode(this.translator, (ClassEntry) child, child); + childNode.load(jarIndex, hideDeobfuscated); + } + + // don't add deobfuscated members if hideDeobfuscated is true, unless it's an inner class + if (hideDeobfuscated && this.translator.extendedTranslate(child).isDeobfuscated() && !(child instanceof ClassEntry)) { + continue; + } + + // don't add constructor methods if hideDeobfuscated is true + if (hideDeobfuscated && (child instanceof MethodEntry) && ((MethodEntry) child).isConstructor()) { + continue; + } + + this.add(childNode); + } + } + + @Override + public String toString() { + ParentedEntry translatedEntry = this.translator.extendedTranslate(this.entry).getValue(); + String result = translatedEntry.getName(); + + if (this.entry instanceof FieldDefEntry) { + FieldDefEntry field = (FieldDefEntry) translatedEntry; + String returnType = this.parseDesc(field.getDesc()); + + result = result + ": " + returnType; + } else if (this.entry instanceof MethodDefEntry) { + MethodDefEntry method = (MethodDefEntry) translatedEntry; + String args = this.parseArgs(method.getDesc().getArgumentDescs()); + String returnType = this.parseDesc(method.getDesc().getReturnDesc()); + + if (method.isConstructor()) { + result = method.getParent().getSimpleName() + args; + } else { + result = result + args + ": " + returnType; + } + } + + return result; + } + + private String parseArgs(List args) { + if (args.size() > 0) { + String result = "("; + + for (int i = 0; i < args.size(); i++) { + if (i > 0) { + result += ", "; + } + + result += this.parseDesc(args.get(i)); + } + + return result + ")"; + } + + return "()"; + } + + private String parseDesc(TypeDescriptor desc) { + if (desc.isVoid()) return "void"; + if (desc.isPrimitive()) return desc.getPrimitive().getKeyword(); + if (desc.isType()) return desc.getTypeEntry().getSimpleName(); + + if (desc.isArray()) { + if (desc.getArrayType().isPrimitive()) return desc.getArrayType().getPrimitive().getKeyword() + "[]"; + if (desc.getArrayType().isType()) return desc.getArrayType().getTypeEntry().getSimpleName() + "[]"; + } + + return null; + } +} diff --git a/enigma/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java b/enigma/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java index b5ad91a..d41731f 100644 --- a/enigma/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java +++ b/enigma/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java @@ -23,10 +23,7 @@ import cuchaz.enigma.translation.representation.Lambda; import cuchaz.enigma.translation.representation.entry.*; import cuchaz.enigma.utils.I18n; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; +import java.util.*; public class JarIndex implements JarIndexer { private final Set indexedClasses = new HashSet<>(); @@ -40,6 +37,7 @@ public class JarIndex implements JarIndexer { private final Collection indexers; private final Multimap methodImplementations = HashMultimap.create(); + private final Map> childrenByClass; public JarIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex, BridgeMethodIndex bridgeMethodIndex, PackageVisibilityIndex packageVisibilityIndex) { this.entryIndex = entryIndex; @@ -49,6 +47,7 @@ public class JarIndex implements JarIndexer { this.packageVisibilityIndex = packageVisibilityIndex; this.indexers = Arrays.asList(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex, packageVisibilityIndex); this.entryResolver = new IndexEntryResolver(this); + this.childrenByClass = new HashMap<>(); } public static JarIndex empty() { @@ -101,6 +100,11 @@ public class JarIndex implements JarIndexer { } indexers.forEach(indexer -> indexer.indexClass(classEntry)); + childrenByClass.putIfAbsent(classEntry, new ArrayList<>()); + if (classEntry.isInnerClass() && !classEntry.getAccess().isSynthetic()) { + childrenByClass.putIfAbsent(classEntry.getParent(), new ArrayList<>()); + childrenByClass.get(classEntry.getParent()).add(classEntry); + } } @Override @@ -110,6 +114,10 @@ public class JarIndex implements JarIndexer { } indexers.forEach(indexer -> indexer.indexField(fieldEntry)); + if (!fieldEntry.getAccess().isSynthetic()) { + childrenByClass.putIfAbsent(fieldEntry.getParent(), new ArrayList<>()); + childrenByClass.get(fieldEntry.getParent()).add(fieldEntry); + } } @Override @@ -119,6 +127,10 @@ public class JarIndex implements JarIndexer { } indexers.forEach(indexer -> indexer.indexMethod(methodEntry)); + if (!methodEntry.getAccess().isSynthetic() && !methodEntry.getName().equals("")) { + childrenByClass.putIfAbsent(methodEntry.getParent(), new ArrayList<>()); + childrenByClass.get(methodEntry.getParent()).add(methodEntry); + } if (!methodEntry.isConstructor()) { methodImplementations.put(methodEntry.getParent().getFullName(), methodEntry); @@ -176,6 +188,10 @@ public class JarIndex implements JarIndexer { return entryResolver; } + public Map> getChildrenByClass() { + return this.childrenByClass; + } + public boolean isIndexed(String internalName) { return indexedClasses.contains(internalName); } diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java index a7dccfc..6a1b82f 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java @@ -235,14 +235,14 @@ public class TypeDescriptor implements Translatable { } public enum Primitive { - BYTE('B'), - CHARACTER('C'), - SHORT('S'), - INTEGER('I'), - LONG('J'), - FLOAT('F'), - DOUBLE('D'), - BOOLEAN('Z'); + BYTE('B', "byte"), + CHARACTER('C', "char"), + SHORT('S', "short"), + INTEGER('I', "int"), + LONG('J', "long"), + FLOAT('F', "float"), + DOUBLE('D', "double"), + BOOLEAN('Z', "boolean"); private static final Map lookup; @@ -254,9 +254,11 @@ public class TypeDescriptor implements Translatable { } private char code; + private String keyword; - Primitive(char code) { + Primitive(char code, String keyword) { this.code = code; + this.keyword = keyword; } public static Primitive get(char code) { @@ -266,5 +268,12 @@ public class TypeDescriptor implements Translatable { public char getCode() { return this.code; } + + /** + * Returns the Java keyword corresponding to this primitive. + */ + public String getKeyword() { + return this.keyword; + } } } diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java index 4a50021..b4a22f1 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java @@ -134,6 +134,9 @@ public class ClassEntry extends ParentedEntry implements Comparable< return name; } + /** + * Returns whether this class entry has a parent, and therefore is an inner class. + */ public boolean isInnerClass() { return parent != null; } diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java index ff392fe..6fd412a 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java @@ -29,6 +29,13 @@ public interface Entry

> extends Translatable { return getName(); } + /** + * Returns the parent entry of this entry. + * + *

The parent entry should be a {@linkplain MethodEntry method} for local variables, + * a {@linkplain ClassEntry class} for methods, fields and inner classes, and {@code null} + * for other classes.

+ */ @Nullable P getParent(); diff --git a/enigma/src/main/resources/lang/en_us.json b/enigma/src/main/resources/lang/en_us.json index 9db4e1f..8195bb1 100644 --- a/enigma/src/main/resources/lang/en_us.json +++ b/enigma/src/main/resources/lang/en_us.json @@ -101,6 +101,8 @@ "info_panel.identifier.index": "Index", "info_panel.editor.class.decompiling": "(decompiling...)", "info_panel.editor.class.not_found": "Unable to find class:", + "info_panel.tree.structure": "Structure", + "info_panel.tree.structure.hide_deobfuscated": "Hide deobfuscated members", "info_panel.tree.inheritance": "Inheritance", "info_panel.tree.implementations": "Implementations", "info_panel.tree.calls": "Call Graph", diff --git a/enigma/src/main/resources/lang/fr_fr.json b/enigma/src/main/resources/lang/fr_fr.json index 127b9c8..43bea4d 100644 --- a/enigma/src/main/resources/lang/fr_fr.json +++ b/enigma/src/main/resources/lang/fr_fr.json @@ -101,6 +101,8 @@ "info_panel.identifier.index": "Index", "info_panel.editor.class.decompiling": "(décompilation...)", "info_panel.editor.class.not_found": "Impossible de trouver la classe :", + "info_panel.tree.structure": "Structure", + "info_panel.tree.structure.hide_deobfuscated": "Masquer les membres déobfusqués", "info_panel.tree.inheritance": "Héritage", "info_panel.tree.implementations": "Implémentations", "info_panel.tree.calls": "Graphique des appels", -- cgit v1.2.3 From 7a13c0583ab8fa6372617cd073c53fd7dd66de41 Mon Sep 17 00:00:00 2001 From: Juuxel Date: Mon, 14 Dec 2020 23:13:11 +0200 Subject: Create alternate set of icons for the structure panel (#1) --- enigma-swing/src/main/resources/icons/class.png | Bin 408 -> 768 bytes enigma-swing/src/main/resources/icons/field.png | Bin 392 -> 534 bytes enigma-swing/src/main/resources/icons/method.png | Bin 618 -> 633 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/enigma-swing/src/main/resources/icons/class.png b/enigma-swing/src/main/resources/icons/class.png index 4f7d0f4..17d82ec 100644 Binary files a/enigma-swing/src/main/resources/icons/class.png and b/enigma-swing/src/main/resources/icons/class.png differ diff --git a/enigma-swing/src/main/resources/icons/field.png b/enigma-swing/src/main/resources/icons/field.png index b124dcf..4ac1aab 100644 Binary files a/enigma-swing/src/main/resources/icons/field.png and b/enigma-swing/src/main/resources/icons/field.png differ diff --git a/enigma-swing/src/main/resources/icons/method.png b/enigma-swing/src/main/resources/icons/method.png index 4ed0ccc..e4e9679 100644 Binary files a/enigma-swing/src/main/resources/icons/method.png and b/enigma-swing/src/main/resources/icons/method.png differ -- cgit v1.2.3 From 37b0fb65413f13ff70d9f9747799d11cbf62a0d9 Mon Sep 17 00:00:00 2001 From: Juuxel Date: Mon, 14 Dec 2020 23:13:57 +0200 Subject: Use class icon in class tree (ClassSelector) (#2) --- enigma-swing/src/main/java/cuchaz/enigma/gui/ClassSelector.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/ClassSelector.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/ClassSelector.java index 488d04e..b27832b 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/ClassSelector.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/ClassSelector.java @@ -27,6 +27,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import cuchaz.enigma.gui.node.ClassSelectorClassNode; import cuchaz.enigma.gui.node.ClassSelectorPackageNode; +import cuchaz.enigma.gui.util.GuiUtil; import cuchaz.enigma.translation.Translator; import cuchaz.enigma.translation.representation.entry.ClassEntry; import cuchaz.enigma.utils.validation.ValidationContext; @@ -69,10 +70,13 @@ public class ClassSelector extends JTree { } }); + final DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); + renderer.setLeafIcon(GuiUtil.CLASS_ICON); + setCellRenderer(renderer); + final JTree tree = this; - final DefaultTreeCellEditor editor = new DefaultTreeCellEditor(tree, - (DefaultTreeCellRenderer) tree.getCellRenderer()) { + final DefaultTreeCellEditor editor = new DefaultTreeCellEditor(tree, renderer) { @Override public boolean isCellEditable(EventObject event) { return isRenamable && !(event instanceof MouseEvent) && super.isCellEditable(event); -- cgit v1.2.3 From 68dd12b0efd2632e292e32827f1870310a003634 Mon Sep 17 00:00:00 2001 From: Yanis48 Date: Tue, 15 Dec 2020 09:17:08 +0100 Subject: Fix automapped entries Automatically deobfuscated names (like in enums) were displayed with their obfuscated name, and were not considered as deobf when selecting "hide deobf members" --- .../main/java/cuchaz/enigma/gui/GuiController.java | 5 +- .../cuchaz/enigma/analysis/StructureTreeNode.java | 63 +++++++++++++++++----- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java index 4e964da..656f5a4 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java @@ -393,9 +393,8 @@ public class GuiController implements ClientPacketHandler { } public StructureTreeNode getClassStructure(ClassEntry entry, boolean hideDeobfuscated) { - Translator translator = this.project.getMapper().getDeobfuscator(); - StructureTreeNode rootNode = new StructureTreeNode(translator, entry, entry); - rootNode.load(this.project.getJarIndex(), hideDeobfuscated); + StructureTreeNode rootNode = new StructureTreeNode(this.project, entry, entry); + rootNode.load(this.project, hideDeobfuscated); return rootNode; } diff --git a/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java index 13f277c..312c2fe 100644 --- a/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java +++ b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java @@ -1,7 +1,9 @@ package cuchaz.enigma.analysis; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.translation.Translator; +import cuchaz.enigma.EnigmaProject; +import cuchaz.enigma.api.service.NameProposalService; +import cuchaz.enigma.api.service.ObfuscationTestService; +import cuchaz.enigma.translation.mapping.EntryRemapper; import cuchaz.enigma.translation.representation.TypeDescriptor; import cuchaz.enigma.translation.representation.entry.*; @@ -9,12 +11,14 @@ import javax.swing.tree.DefaultMutableTreeNode; import java.util.List; public class StructureTreeNode extends DefaultMutableTreeNode { - private final Translator translator; + private final List nameProposalServices; + private final EntryRemapper mapper; private final ClassEntry parentEntry; private final ParentedEntry entry; - public StructureTreeNode(Translator translator, ClassEntry parentEntry, ParentedEntry entry) { - this.translator = translator; + public StructureTreeNode(EnigmaProject project, ClassEntry parentEntry, ParentedEntry entry) { + this.nameProposalServices = project.getEnigma().getServices().get(NameProposalService.TYPE); + this.mapper = project.getMapper(); this.parentEntry = parentEntry; this.entry = entry; } @@ -26,19 +30,19 @@ public class StructureTreeNode extends DefaultMutableTreeNode { return this.entry; } - public void load(JarIndex jarIndex, boolean hideDeobfuscated) { - List children = jarIndex.getChildrenByClass().get(this.parentEntry); + public void load(EnigmaProject project, boolean hideDeobfuscated) { + List children = project.getJarIndex().getChildrenByClass().get(this.parentEntry); for (ParentedEntry child : children) { - StructureTreeNode childNode = new StructureTreeNode(this.translator, this.parentEntry, child); + StructureTreeNode childNode = new StructureTreeNode(project, this.parentEntry, child); if (child instanceof ClassEntry) { - childNode = new StructureTreeNode(this.translator, (ClassEntry) child, child); - childNode.load(jarIndex, hideDeobfuscated); + childNode = new StructureTreeNode(project, (ClassEntry) child, child); + childNode.load(project, hideDeobfuscated); } // don't add deobfuscated members if hideDeobfuscated is true, unless it's an inner class - if (hideDeobfuscated && this.translator.extendedTranslate(child).isDeobfuscated() && !(child instanceof ClassEntry)) { + if (hideDeobfuscated && this.isDeobfuscated(project, child) && !(child instanceof ClassEntry)) { continue; } @@ -51,11 +55,46 @@ public class StructureTreeNode extends DefaultMutableTreeNode { } } + private boolean isDeobfuscated(EnigmaProject project, ParentedEntry child) { + List obfuscationTestServices = project.getEnigma().getServices().get(ObfuscationTestService.TYPE); + + if (!obfuscationTestServices.isEmpty()) { + for (ObfuscationTestService service : obfuscationTestServices) { + if (service.testDeobfuscated(child)) { + return true; + } + } + } + + if (!this.nameProposalServices.isEmpty()) { + for (NameProposalService service : this.nameProposalServices) { + if (service.proposeName(child, this.mapper).isPresent()) { + return true; + } + } + } + + String mappedName = project.getMapper().deobfuscate(child).getName(); + if (mappedName != null && !mappedName.isEmpty() && !mappedName.equals(child.getName())) { + return true; + } + + return false; + } + @Override public String toString() { - ParentedEntry translatedEntry = this.translator.extendedTranslate(this.entry).getValue(); + ParentedEntry translatedEntry = this.mapper.deobfuscate(this.entry); String result = translatedEntry.getName(); + if (!this.nameProposalServices.isEmpty()) { + for (NameProposalService service : this.nameProposalServices) { + if (service.proposeName(this.entry, this.mapper).isPresent()) { + result = service.proposeName(this.entry, this.mapper).get(); + } + } + } + if (this.entry instanceof FieldDefEntry) { FieldDefEntry field = (FieldDefEntry) translatedEntry; String returnType = this.parseDesc(field.getDesc()); -- cgit v1.2.3 From 559bac70027bd5161697a3c8dd0907cf89111d31 Mon Sep 17 00:00:00 2001 From: Yanis48 Date: Tue, 15 Dec 2020 19:37:13 +0100 Subject: Fix automapped again --- .../cuchaz/enigma/analysis/StructureTreeNode.java | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java index 312c2fe..876b5ca 100644 --- a/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java +++ b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java @@ -3,6 +3,7 @@ package cuchaz.enigma.analysis; import cuchaz.enigma.EnigmaProject; import cuchaz.enigma.api.service.NameProposalService; import cuchaz.enigma.api.service.ObfuscationTestService; +import cuchaz.enigma.translation.TranslateResult; import cuchaz.enigma.translation.mapping.EntryRemapper; import cuchaz.enigma.translation.representation.TypeDescriptor; import cuchaz.enigma.translation.representation.entry.*; @@ -84,24 +85,26 @@ public class StructureTreeNode extends DefaultMutableTreeNode { @Override public String toString() { - ParentedEntry translatedEntry = this.mapper.deobfuscate(this.entry); - String result = translatedEntry.getName(); - - if (!this.nameProposalServices.isEmpty()) { - for (NameProposalService service : this.nameProposalServices) { - if (service.proposeName(this.entry, this.mapper).isPresent()) { - result = service.proposeName(this.entry, this.mapper).get(); + TranslateResult translateResult = this.mapper.extendedDeobfuscate(this.entry); + String result = translateResult.getValue().getName(); + + if (translateResult.isObfuscated()) { + if (!this.nameProposalServices.isEmpty()) { + for (NameProposalService service : this.nameProposalServices) { + if (service.proposeName(this.entry, this.mapper).isPresent()) { + result = service.proposeName(this.entry, this.mapper).get(); + } } } } if (this.entry instanceof FieldDefEntry) { - FieldDefEntry field = (FieldDefEntry) translatedEntry; + FieldDefEntry field = (FieldDefEntry) translateResult.getValue(); String returnType = this.parseDesc(field.getDesc()); result = result + ": " + returnType; } else if (this.entry instanceof MethodDefEntry) { - MethodDefEntry method = (MethodDefEntry) translatedEntry; + MethodDefEntry method = (MethodDefEntry) translateResult.getValue(); String args = this.parseArgs(method.getDesc().getArgumentDescs()); String returnType = this.parseDesc(method.getDesc().getReturnDesc()); -- cgit v1.2.3 From 68117693dab53007b023ab6c237ee71a4bcf4df5 Mon Sep 17 00:00:00 2001 From: Yanis48 Date: Tue, 15 Dec 2020 19:38:28 +0100 Subject: Refresh structure panel on rename/mark as deobf/reset to obf --- enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java index 656f5a4..5217b25 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java @@ -457,6 +457,7 @@ public class GuiController implements ClientPacketHandler { Entry entry = reference.getNameableEntry(); EntryMapping previous = project.getMapper().getDeobfMapping(entry); project.getMapper().mapFromObf(vc, entry, previous != null ? previous.withName(newName) : new EntryMapping(newName), true, validateOnly); + gui.showStructure(gui.getActiveEditor()); if (validateOnly || !vc.canProceed()) return; @@ -469,6 +470,7 @@ public class GuiController implements ClientPacketHandler { @Override public void removeMapping(ValidationContext vc, EntryReference, Entry> reference) { project.getMapper().removeByObf(vc, reference.getNameableEntry()); + gui.showStructure(gui.getActiveEditor()); if (!vc.canProceed()) return; @@ -507,6 +509,7 @@ public class GuiController implements ClientPacketHandler { EntryRemapper mapper = project.getMapper(); Entry entry = reference.getNameableEntry(); mapper.mapFromObf(vc, entry, new EntryMapping(mapper.deobfuscate(entry).getName())); + gui.showStructure(gui.getActiveEditor()); if (!vc.canProceed()) return; -- cgit v1.2.3 From 348fb6f35c03534229f56c318b2b149abead8b90 Mon Sep 17 00:00:00 2001 From: Yanis48 Date: Tue, 15 Dec 2020 20:05:27 +0100 Subject: minor bump --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3dfbae4..8b0a2c5 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ subprojects { } group = 'cuchaz' - version = '0.21.8' + version = '0.22.0' version = version + (System.getenv("GITHUB_ACTIONS") ? "" : "+local") -- cgit v1.2.3 From ee84d4187df3f399975c06238a385304c2c9cf21 Mon Sep 17 00:00:00 2001 From: Juuxel Date: Tue, 15 Dec 2020 22:21:17 +0200 Subject: Add separate constructor icon (#3) --- .../java/cuchaz/enigma/gui/panels/StructurePanel.java | 6 +++++- .../src/main/java/cuchaz/enigma/gui/util/GuiUtil.java | 1 + enigma-swing/src/main/resources/icons/constructor.png | Bin 0 -> 751 bytes 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 enigma-swing/src/main/resources/icons/constructor.png diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java index 32f803f..d6044dc 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java @@ -89,7 +89,7 @@ public class StructurePanel extends JPanel { if (entry instanceof ClassEntry) { this.label.setIcon(GuiUtil.CLASS_ICON); } else if (entry instanceof MethodEntry) { - this.label.setIcon(GuiUtil.METHOD_ICON); + this.label.setIcon(isConstructor(entry) ? GuiUtil.CONSTRUCTOR_ICON : GuiUtil.METHOD_ICON); } else if (entry instanceof FieldEntry) { this.label.setIcon(GuiUtil.FIELD_ICON); } @@ -98,5 +98,9 @@ public class StructurePanel extends JPanel { return this.label; } + + private boolean isConstructor(ParentedEntry entry) { + return "".equals(entry.getName()); + } } } diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java index 666fc0a..6393913 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java @@ -18,6 +18,7 @@ public class GuiUtil { public static final Icon CLASS_ICON = loadIcon("class"); public static final Icon METHOD_ICON = loadIcon("method"); public static final Icon FIELD_ICON = loadIcon("field"); + public static final Icon CONSTRUCTOR_ICON = loadIcon("constructor"); public static void openUrl(String url) { try { diff --git a/enigma-swing/src/main/resources/icons/constructor.png b/enigma-swing/src/main/resources/icons/constructor.png new file mode 100644 index 0000000..3728b55 Binary files /dev/null and b/enigma-swing/src/main/resources/icons/constructor.png differ -- cgit v1.2.3 From 12f270c80570b136add40dc259c25383ac36bf81 Mon Sep 17 00:00:00 2001 From: Yanis48 Date: Tue, 15 Dec 2020 21:22:55 +0100 Subject: avoid duplicate logic --- .../cuchaz/enigma/gui/stats/StatsGenerator.java | 43 +++------------------- .../src/main/java/cuchaz/enigma/EnigmaProject.java | 30 +++++++++++++++ .../cuchaz/enigma/analysis/StructureTreeNode.java | 30 +-------------- 3 files changed, 37 insertions(+), 66 deletions(-) diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java index b898eac..20d6a0e 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java @@ -3,8 +3,6 @@ package cuchaz.enigma.gui.stats; import cuchaz.enigma.EnigmaProject; import cuchaz.enigma.ProgressListener; import cuchaz.enigma.analysis.index.EntryIndex; -import cuchaz.enigma.api.service.NameProposalService; -import cuchaz.enigma.api.service.ObfuscationTestService; import cuchaz.enigma.translation.mapping.EntryRemapper; import cuchaz.enigma.translation.mapping.EntryResolver; import cuchaz.enigma.translation.mapping.ResolutionStrategy; @@ -15,18 +13,16 @@ import cuchaz.enigma.utils.I18n; import java.util.*; public class StatsGenerator { + private final EnigmaProject project; private final EntryIndex entryIndex; private final EntryRemapper mapper; private final EntryResolver entryResolver; - private final List obfuscationTestServices; - private final List nameProposalServices; public StatsGenerator(EnigmaProject project) { - entryIndex = project.getJarIndex().getEntryIndex(); - mapper = project.getMapper(); - entryResolver = project.getJarIndex().getEntryResolver(); - obfuscationTestServices = project.getEnigma().getServices().get(ObfuscationTestService.TYPE); - nameProposalServices = project.getEnigma().getServices().get(NameProposalService.TYPE); + this.project = project; + this.entryIndex = project.getJarIndex().getEntryIndex(); + this.mapper = project.getMapper(); + this.entryResolver = project.getJarIndex().getEntryResolver(); } public StatsResult generate(ProgressListener progress, Set includedMembers, String topLevelPackage, boolean includeSynthetic) { @@ -111,36 +107,9 @@ public class StatsGenerator { } private void update(Map counts, Entry entry) { - if (isObfuscated(entry)) { + if (project.isObfuscated(entry)) { String parent = mapper.deobfuscate(entry.getAncestry().get(0)).getName().replace('/', '.'); counts.put(parent, counts.getOrDefault(parent, 0) + 1); } } - - private boolean isObfuscated(Entry entry) { - String name = entry.getName(); - - if (!obfuscationTestServices.isEmpty()) { - for (ObfuscationTestService service : obfuscationTestServices) { - if (service.testDeobfuscated(entry)) { - return false; - } - } - } - - if (!nameProposalServices.isEmpty()) { - for (NameProposalService service : nameProposalServices) { - if (service.proposeName(entry, mapper).isPresent()) { - return false; - } - } - } - - String mappedName = mapper.deobfuscate(entry).getName(); - if (mappedName != null && !mappedName.isEmpty() && !mappedName.equals(name)) { - return false; - } - - return true; - } } diff --git a/enigma/src/main/java/cuchaz/enigma/EnigmaProject.java b/enigma/src/main/java/cuchaz/enigma/EnigmaProject.java index fcd2c96..a01eca1 100644 --- a/enigma/src/main/java/cuchaz/enigma/EnigmaProject.java +++ b/enigma/src/main/java/cuchaz/enigma/EnigmaProject.java @@ -18,6 +18,7 @@ import java.util.stream.Stream; import com.google.common.base.Functions; import com.google.common.base.Preconditions; +import cuchaz.enigma.api.service.ObfuscationTestService; import cuchaz.enigma.classprovider.ObfuscationFixClassProvider; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.tree.ClassNode; @@ -158,6 +159,35 @@ public class EnigmaProject { return obfReference.isNamed() && isRenamable(obfReference.getNameableEntry()); } + public boolean isObfuscated(Entry entry) { + String name = entry.getName(); + + List obfuscationTestServices = this.getEnigma().getServices().get(ObfuscationTestService.TYPE); + if (!obfuscationTestServices.isEmpty()) { + for (ObfuscationTestService service : obfuscationTestServices) { + if (service.testDeobfuscated(entry)) { + return false; + } + } + } + + List nameProposalServices = this.getEnigma().getServices().get(NameProposalService.TYPE); + if (!nameProposalServices.isEmpty()) { + for (NameProposalService service : nameProposalServices) { + if (service.proposeName(entry, mapper).isPresent()) { + return false; + } + } + } + + String mappedName = mapper.deobfuscate(entry).getName(); + if (mappedName != null && !mappedName.isEmpty() && !mappedName.equals(name)) { + return false; + } + + return true; + } + public JarExport exportRemappedJar(ProgressListener progress) { Collection classEntries = jarIndex.getEntryIndex().getClasses(); ClassProvider fixingClassProvider = new ObfuscationFixClassProvider(classProvider, jarIndex); diff --git a/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java index 876b5ca..f310aa7 100644 --- a/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java +++ b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java @@ -2,7 +2,6 @@ package cuchaz.enigma.analysis; import cuchaz.enigma.EnigmaProject; import cuchaz.enigma.api.service.NameProposalService; -import cuchaz.enigma.api.service.ObfuscationTestService; import cuchaz.enigma.translation.TranslateResult; import cuchaz.enigma.translation.mapping.EntryRemapper; import cuchaz.enigma.translation.representation.TypeDescriptor; @@ -43,7 +42,7 @@ public class StructureTreeNode extends DefaultMutableTreeNode { } // don't add deobfuscated members if hideDeobfuscated is true, unless it's an inner class - if (hideDeobfuscated && this.isDeobfuscated(project, child) && !(child instanceof ClassEntry)) { + if (hideDeobfuscated && !project.isObfuscated(child) && !(child instanceof ClassEntry)) { continue; } @@ -56,33 +55,6 @@ public class StructureTreeNode extends DefaultMutableTreeNode { } } - private boolean isDeobfuscated(EnigmaProject project, ParentedEntry child) { - List obfuscationTestServices = project.getEnigma().getServices().get(ObfuscationTestService.TYPE); - - if (!obfuscationTestServices.isEmpty()) { - for (ObfuscationTestService service : obfuscationTestServices) { - if (service.testDeobfuscated(child)) { - return true; - } - } - } - - if (!this.nameProposalServices.isEmpty()) { - for (NameProposalService service : this.nameProposalServices) { - if (service.proposeName(child, this.mapper).isPresent()) { - return true; - } - } - } - - String mappedName = project.getMapper().deobfuscate(child).getName(); - if (mappedName != null && !mappedName.isEmpty() && !mappedName.equals(child.getName())) { - return true; - } - - return false; - } - @Override public String toString() { TranslateResult translateResult = this.mapper.extendedDeobfuscate(this.entry); -- cgit v1.2.3 From 0cff54eb9a3db72464034e70f0d9e934728176e1 Mon Sep 17 00:00:00 2001 From: Yanis48 Date: Wed, 16 Dec 2020 15:53:49 +0100 Subject: isConstructor() from method entry --- .../src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java index d6044dc..a9ccffd 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java @@ -89,7 +89,7 @@ public class StructurePanel extends JPanel { if (entry instanceof ClassEntry) { this.label.setIcon(GuiUtil.CLASS_ICON); } else if (entry instanceof MethodEntry) { - this.label.setIcon(isConstructor(entry) ? GuiUtil.CONSTRUCTOR_ICON : GuiUtil.METHOD_ICON); + this.label.setIcon(((MethodEntry) entry).isConstructor() ? GuiUtil.CONSTRUCTOR_ICON : GuiUtil.METHOD_ICON); } else if (entry instanceof FieldEntry) { this.label.setIcon(GuiUtil.FIELD_ICON); } @@ -98,9 +98,5 @@ public class StructurePanel extends JPanel { return this.label; } - - private boolean isConstructor(ParentedEntry entry) { - return "".equals(entry.getName()); - } } } -- cgit v1.2.3 From c1226ecace03e2bf1b148b55cba44d61ace2189f Mon Sep 17 00:00:00 2001 From: Yanis48 Date: Sat, 19 Dec 2020 12:42:12 +0100 Subject: ensure it's left mouse button being used --- enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java | 6 +++--- .../src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java index a3a438e..06f67bc 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java @@ -170,7 +170,7 @@ public class Gui implements LanguageChangeListener { inheritanceTree.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent event) { - if (event.getClickCount() >= 2) { + if (event.getClickCount() >= 2 && event.getButton() == MouseEvent.BUTTON1) { // get the selected node TreePath path = inheritanceTree.getSelectionPath(); if (path == null) { @@ -203,7 +203,7 @@ public class Gui implements LanguageChangeListener { implementationsTree.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent event) { - if (event.getClickCount() >= 2) { + if (event.getClickCount() >= 2 && event.getButton() == MouseEvent.BUTTON1) { // get the selected node TreePath path = implementationsTree.getSelectionPath(); if (path == null) { @@ -232,7 +232,7 @@ public class Gui implements LanguageChangeListener { @SuppressWarnings("unchecked") @Override public void mouseClicked(MouseEvent event) { - if (event.getClickCount() >= 2) { + if (event.getClickCount() >= 2 && event.getButton() == MouseEvent.BUTTON1) { // get the selected node TreePath path = callsTree.getSelectionPath(); if (path == null) { diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java index a9ccffd..0ca2714 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java @@ -39,7 +39,7 @@ public class StructurePanel extends JPanel { this.structureTree.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent event) { - if (event.getClickCount() >= 2) { + if (event.getClickCount() >= 2 && event.getButton() == MouseEvent.BUTTON1) { // get the selected node TreePath path = structureTree.getSelectionPath(); if (path == null) { -- cgit v1.2.3 From c610379efaed44d29e195e92226bebf5e61eda1c Mon Sep 17 00:00:00 2001 From: Yanis48 Date: Sat, 19 Dec 2020 14:34:33 +0100 Subject: fix nodes not displayed as selected --- .../cuchaz/enigma/gui/panels/StructurePanel.java | 27 +++++++++------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java index 0ca2714..868edcf 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java @@ -10,23 +10,19 @@ import cuchaz.enigma.translation.representation.entry.ParentedEntry; import cuchaz.enigma.utils.I18n; import javax.swing.*; -import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class StructurePanel extends JPanel { - private final Gui gui; - private JPanel sortingPanel; private JCheckBox hideDeobfuscated; private JTree structureTree; public StructurePanel(Gui gui) { - this.gui = gui; - this.sortingPanel = new JPanel(); this.hideDeobfuscated = new JCheckBox(I18n.translate("info_panel.tree.structure.hide_deobfuscated")); this.hideDeobfuscated.addActionListener(event -> gui.showStructure(gui.getActiveEditor())); @@ -63,6 +59,9 @@ public class StructurePanel extends JPanel { return this.sortingPanel; } + /** + * Returns whether the "Hide Deobfuscated" option of this structure panel is selected. + */ public boolean shouldHideDeobfuscated() { return this.hideDeobfuscated.isSelected(); } @@ -75,28 +74,24 @@ public class StructurePanel extends JPanel { this.hideDeobfuscated.setText(I18n.translate("info_panel.tree.structure.hide_deobfuscated")); } - class StructureTreeCellRenderer implements TreeCellRenderer { - private JLabel label; - - public StructureTreeCellRenderer() { - this.label = new JLabel(); - } + class StructureTreeCellRenderer extends DefaultTreeCellRenderer { @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + JComponent c = (JComponent) super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); ParentedEntry entry = ((StructureTreeNode) value).getEntry(); if (entry instanceof ClassEntry) { - this.label.setIcon(GuiUtil.CLASS_ICON); + this.setIcon(GuiUtil.CLASS_ICON); } else if (entry instanceof MethodEntry) { - this.label.setIcon(((MethodEntry) entry).isConstructor() ? GuiUtil.CONSTRUCTOR_ICON : GuiUtil.METHOD_ICON); + this.setIcon(((MethodEntry) entry).isConstructor() ? GuiUtil.CONSTRUCTOR_ICON : GuiUtil.METHOD_ICON); } else if (entry instanceof FieldEntry) { - this.label.setIcon(GuiUtil.FIELD_ICON); + this.setIcon(GuiUtil.FIELD_ICON); } - this.label.setText(value.toString()); + this.setText(value.toString()); - return this.label; + return c; } } } -- cgit v1.2.3 From a30735c3069fdfa66bc24b1f9186272f9a9b1a0d Mon Sep 17 00:00:00 2001 From: Yanis48 Date: Sat, 19 Dec 2020 14:47:22 +0100 Subject: use ListMultimap when indexing jar --- .../java/cuchaz/enigma/analysis/index/JarIndex.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/enigma/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java b/enigma/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java index d41731f..aa360cf 100644 --- a/enigma/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java +++ b/enigma/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java @@ -11,8 +11,7 @@ package cuchaz.enigma.analysis.index; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; +import com.google.common.collect.*; import cuchaz.enigma.Enigma; import cuchaz.enigma.ProgressListener; import cuchaz.enigma.analysis.ReferenceTargetType; @@ -37,7 +36,7 @@ public class JarIndex implements JarIndexer { private final Collection indexers; private final Multimap methodImplementations = HashMultimap.create(); - private final Map> childrenByClass; + private final ListMultimap childrenByClass; public JarIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex, BridgeMethodIndex bridgeMethodIndex, PackageVisibilityIndex packageVisibilityIndex) { this.entryIndex = entryIndex; @@ -47,7 +46,7 @@ public class JarIndex implements JarIndexer { this.packageVisibilityIndex = packageVisibilityIndex; this.indexers = Arrays.asList(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex, packageVisibilityIndex); this.entryResolver = new IndexEntryResolver(this); - this.childrenByClass = new HashMap<>(); + this.childrenByClass = ArrayListMultimap.create(); } public static JarIndex empty() { @@ -100,10 +99,8 @@ public class JarIndex implements JarIndexer { } indexers.forEach(indexer -> indexer.indexClass(classEntry)); - childrenByClass.putIfAbsent(classEntry, new ArrayList<>()); if (classEntry.isInnerClass() && !classEntry.getAccess().isSynthetic()) { - childrenByClass.putIfAbsent(classEntry.getParent(), new ArrayList<>()); - childrenByClass.get(classEntry.getParent()).add(classEntry); + childrenByClass.put(classEntry.getParent(), classEntry); } } @@ -115,8 +112,7 @@ public class JarIndex implements JarIndexer { indexers.forEach(indexer -> indexer.indexField(fieldEntry)); if (!fieldEntry.getAccess().isSynthetic()) { - childrenByClass.putIfAbsent(fieldEntry.getParent(), new ArrayList<>()); - childrenByClass.get(fieldEntry.getParent()).add(fieldEntry); + childrenByClass.put(fieldEntry.getParent(), fieldEntry); } } @@ -128,8 +124,7 @@ public class JarIndex implements JarIndexer { indexers.forEach(indexer -> indexer.indexMethod(methodEntry)); if (!methodEntry.getAccess().isSynthetic() && !methodEntry.getName().equals("")) { - childrenByClass.putIfAbsent(methodEntry.getParent(), new ArrayList<>()); - childrenByClass.get(methodEntry.getParent()).add(methodEntry); + childrenByClass.put(methodEntry.getParent(), methodEntry); } if (!methodEntry.isConstructor()) { @@ -188,7 +183,7 @@ public class JarIndex implements JarIndexer { return entryResolver; } - public Map> getChildrenByClass() { + public ListMultimap getChildrenByClass() { return this.childrenByClass; } -- cgit v1.2.3 From 63d4cfc0845b48b71e971b73aa55ebbe1a96ff86 Mon Sep 17 00:00:00 2001 From: Yanis48 Date: Sat, 19 Dec 2020 23:55:19 +0100 Subject: fix invisible root toggle --- enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java | 3 +++ .../src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java | 1 + 2 files changed, 4 insertions(+) diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java index 06f67bc..d74fefd 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java @@ -167,6 +167,7 @@ public class Gui implements LanguageChangeListener { // init inheritance panel inheritanceTree = new JTree(); inheritanceTree.setModel(null); + inheritanceTree.setShowsRootHandles(true); inheritanceTree.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent event) { @@ -200,6 +201,7 @@ public class Gui implements LanguageChangeListener { // init implementations panel implementationsTree = new JTree(); implementationsTree.setModel(null); + implementationsTree.setShowsRootHandles(true); implementationsTree.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent event) { @@ -228,6 +230,7 @@ public class Gui implements LanguageChangeListener { // init call panel callsTree = new JTree(); callsTree.setModel(null); + callsTree.setShowsRootHandles(true); callsTree.addMouseListener(new MouseAdapter() { @SuppressWarnings("unchecked") @Override diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java index 868edcf..139923c 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java @@ -32,6 +32,7 @@ public class StructurePanel extends JPanel { this.structureTree = new JTree(); this.structureTree.setModel(null); this.structureTree.setCellRenderer(new StructureTreeCellRenderer()); + this.structureTree.setShowsRootHandles(true); this.structureTree.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent event) { -- cgit v1.2.3