summaryrefslogtreecommitdiff
path: root/enigma
diff options
context:
space:
mode:
authorGravatar 2xsaiko2020-12-20 12:25:56 +0100
committerGravatar GitHub2020-12-20 12:25:56 +0100
commit31ad56b7fe24a7958d3c0eae41b3c75a3f022f81 (patch)
tree98a30d7face25356c48ad859a66011d78d5e1617 /enigma
parentAdd true, false and null to invalid identifiers (diff)
parentfix invisible root toggle (diff)
downloadenigma-fork-31ad56b7fe24a7958d3c0eae41b3c75a3f022f81.tar.gz
enigma-fork-31ad56b7fe24a7958d3c0eae41b3c75a3f022f81.tar.xz
enigma-fork-31ad56b7fe24a7958d3c0eae41b3c75a3f022f81.zip
Merge pull request #331 from YanisBft/structure-panel
Structure panel
Diffstat (limited to 'enigma')
-rw-r--r--enigma/src/main/java/cuchaz/enigma/EnigmaProject.java30
-rw-r--r--enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java123
-rw-r--r--enigma/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java23
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java27
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java3
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java7
-rw-r--r--enigma/src/main/resources/lang/en_us.json2
-rw-r--r--enigma/src/main/resources/lang/fr_fr.json2
8 files changed, 202 insertions, 15 deletions
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;
18 18
19import com.google.common.base.Functions; 19import com.google.common.base.Functions;
20import com.google.common.base.Preconditions; 20import com.google.common.base.Preconditions;
21import cuchaz.enigma.api.service.ObfuscationTestService;
21import cuchaz.enigma.classprovider.ObfuscationFixClassProvider; 22import cuchaz.enigma.classprovider.ObfuscationFixClassProvider;
22import org.objectweb.asm.ClassWriter; 23import org.objectweb.asm.ClassWriter;
23import org.objectweb.asm.tree.ClassNode; 24import org.objectweb.asm.tree.ClassNode;
@@ -158,6 +159,35 @@ public class EnigmaProject {
158 return obfReference.isNamed() && isRenamable(obfReference.getNameableEntry()); 159 return obfReference.isNamed() && isRenamable(obfReference.getNameableEntry());
159 } 160 }
160 161
162 public boolean isObfuscated(Entry<?> entry) {
163 String name = entry.getName();
164
165 List<ObfuscationTestService> obfuscationTestServices = this.getEnigma().getServices().get(ObfuscationTestService.TYPE);
166 if (!obfuscationTestServices.isEmpty()) {
167 for (ObfuscationTestService service : obfuscationTestServices) {
168 if (service.testDeobfuscated(entry)) {
169 return false;
170 }
171 }
172 }
173
174 List<NameProposalService> nameProposalServices = this.getEnigma().getServices().get(NameProposalService.TYPE);
175 if (!nameProposalServices.isEmpty()) {
176 for (NameProposalService service : nameProposalServices) {
177 if (service.proposeName(entry, mapper).isPresent()) {
178 return false;
179 }
180 }
181 }
182
183 String mappedName = mapper.deobfuscate(entry).getName();
184 if (mappedName != null && !mappedName.isEmpty() && !mappedName.equals(name)) {
185 return false;
186 }
187
188 return true;
189 }
190
161 public JarExport exportRemappedJar(ProgressListener progress) { 191 public JarExport exportRemappedJar(ProgressListener progress) {
162 Collection<ClassEntry> classEntries = jarIndex.getEntryIndex().getClasses(); 192 Collection<ClassEntry> classEntries = jarIndex.getEntryIndex().getClasses();
163 ClassProvider fixingClassProvider = new ObfuscationFixClassProvider(classProvider, jarIndex); 193 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
new file mode 100644
index 0000000..f310aa7
--- /dev/null
+++ b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java
@@ -0,0 +1,123 @@
1package cuchaz.enigma.analysis;
2
3import cuchaz.enigma.EnigmaProject;
4import cuchaz.enigma.api.service.NameProposalService;
5import cuchaz.enigma.translation.TranslateResult;
6import cuchaz.enigma.translation.mapping.EntryRemapper;
7import cuchaz.enigma.translation.representation.TypeDescriptor;
8import cuchaz.enigma.translation.representation.entry.*;
9
10import javax.swing.tree.DefaultMutableTreeNode;
11import java.util.List;
12
13public class StructureTreeNode extends DefaultMutableTreeNode {
14 private final List<NameProposalService> nameProposalServices;
15 private final EntryRemapper mapper;
16 private final ClassEntry parentEntry;
17 private final ParentedEntry entry;
18
19 public StructureTreeNode(EnigmaProject project, ClassEntry parentEntry, ParentedEntry entry) {
20 this.nameProposalServices = project.getEnigma().getServices().get(NameProposalService.TYPE);
21 this.mapper = project.getMapper();
22 this.parentEntry = parentEntry;
23 this.entry = entry;
24 }
25
26 /**
27 * Returns the parented entry corresponding to this tree node.
28 */
29 public ParentedEntry getEntry() {
30 return this.entry;
31 }
32
33 public void load(EnigmaProject project, boolean hideDeobfuscated) {
34 List<ParentedEntry> children = project.getJarIndex().getChildrenByClass().get(this.parentEntry);
35
36 for (ParentedEntry child : children) {
37 StructureTreeNode childNode = new StructureTreeNode(project, this.parentEntry, child);
38
39 if (child instanceof ClassEntry) {
40 childNode = new StructureTreeNode(project, (ClassEntry) child, child);
41 childNode.load(project, hideDeobfuscated);
42 }
43
44 // don't add deobfuscated members if hideDeobfuscated is true, unless it's an inner class
45 if (hideDeobfuscated && !project.isObfuscated(child) && !(child instanceof ClassEntry)) {
46 continue;
47 }
48
49 // don't add constructor methods if hideDeobfuscated is true
50 if (hideDeobfuscated && (child instanceof MethodEntry) && ((MethodEntry) child).isConstructor()) {
51 continue;
52 }
53
54 this.add(childNode);
55 }
56 }
57
58 @Override
59 public String toString() {
60 TranslateResult<ParentedEntry> translateResult = this.mapper.extendedDeobfuscate(this.entry);
61 String result = translateResult.getValue().getName();
62
63 if (translateResult.isObfuscated()) {
64 if (!this.nameProposalServices.isEmpty()) {
65 for (NameProposalService service : this.nameProposalServices) {
66 if (service.proposeName(this.entry, this.mapper).isPresent()) {
67 result = service.proposeName(this.entry, this.mapper).get();
68 }
69 }
70 }
71 }
72
73 if (this.entry instanceof FieldDefEntry) {
74 FieldDefEntry field = (FieldDefEntry) translateResult.getValue();
75 String returnType = this.parseDesc(field.getDesc());
76
77 result = result + ": " + returnType;
78 } else if (this.entry instanceof MethodDefEntry) {
79 MethodDefEntry method = (MethodDefEntry) translateResult.getValue();
80 String args = this.parseArgs(method.getDesc().getArgumentDescs());
81 String returnType = this.parseDesc(method.getDesc().getReturnDesc());
82
83 if (method.isConstructor()) {
84 result = method.getParent().getSimpleName() + args;
85 } else {
86 result = result + args + ": " + returnType;
87 }
88 }
89
90 return result;
91 }
92
93 private String parseArgs(List<TypeDescriptor> args) {
94 if (args.size() > 0) {
95 String result = "(";
96
97 for (int i = 0; i < args.size(); i++) {
98 if (i > 0) {
99 result += ", ";
100 }
101
102 result += this.parseDesc(args.get(i));
103 }
104
105 return result + ")";
106 }
107
108 return "()";
109 }
110
111 private String parseDesc(TypeDescriptor desc) {
112 if (desc.isVoid()) return "void";
113 if (desc.isPrimitive()) return desc.getPrimitive().getKeyword();
114 if (desc.isType()) return desc.getTypeEntry().getSimpleName();
115
116 if (desc.isArray()) {
117 if (desc.getArrayType().isPrimitive()) return desc.getArrayType().getPrimitive().getKeyword() + "[]";
118 if (desc.getArrayType().isType()) return desc.getArrayType().getTypeEntry().getSimpleName() + "[]";
119 }
120
121 return null;
122 }
123}
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..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 @@
11 11
12package cuchaz.enigma.analysis.index; 12package cuchaz.enigma.analysis.index;
13 13
14import com.google.common.collect.HashMultimap; 14import com.google.common.collect.*;
15import com.google.common.collect.Multimap;
16import cuchaz.enigma.Enigma; 15import cuchaz.enigma.Enigma;
17import cuchaz.enigma.ProgressListener; 16import cuchaz.enigma.ProgressListener;
18import cuchaz.enigma.analysis.ReferenceTargetType; 17import cuchaz.enigma.analysis.ReferenceTargetType;
@@ -23,10 +22,7 @@ import cuchaz.enigma.translation.representation.Lambda;
23import cuchaz.enigma.translation.representation.entry.*; 22import cuchaz.enigma.translation.representation.entry.*;
24import cuchaz.enigma.utils.I18n; 23import cuchaz.enigma.utils.I18n;
25 24
26import java.util.Arrays; 25import java.util.*;
27import java.util.Collection;
28import java.util.HashSet;
29import java.util.Set;
30 26
31public class JarIndex implements JarIndexer { 27public class JarIndex implements JarIndexer {
32 private final Set<String> indexedClasses = new HashSet<>(); 28 private final Set<String> indexedClasses = new HashSet<>();
@@ -40,6 +36,7 @@ public class JarIndex implements JarIndexer {
40 private final Collection<JarIndexer> indexers; 36 private final Collection<JarIndexer> indexers;
41 37
42 private final Multimap<String, MethodDefEntry> methodImplementations = HashMultimap.create(); 38 private final Multimap<String, MethodDefEntry> methodImplementations = HashMultimap.create();
39 private final ListMultimap<ClassEntry, ParentedEntry> childrenByClass;
43 40
44 public JarIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex, BridgeMethodIndex bridgeMethodIndex, PackageVisibilityIndex packageVisibilityIndex) { 41 public JarIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex, BridgeMethodIndex bridgeMethodIndex, PackageVisibilityIndex packageVisibilityIndex) {
45 this.entryIndex = entryIndex; 42 this.entryIndex = entryIndex;
@@ -49,6 +46,7 @@ public class JarIndex implements JarIndexer {
49 this.packageVisibilityIndex = packageVisibilityIndex; 46 this.packageVisibilityIndex = packageVisibilityIndex;
50 this.indexers = Arrays.asList(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex, packageVisibilityIndex); 47 this.indexers = Arrays.asList(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex, packageVisibilityIndex);
51 this.entryResolver = new IndexEntryResolver(this); 48 this.entryResolver = new IndexEntryResolver(this);
49 this.childrenByClass = ArrayListMultimap.create();
52 } 50 }
53 51
54 public static JarIndex empty() { 52 public static JarIndex empty() {
@@ -101,6 +99,9 @@ public class JarIndex implements JarIndexer {
101 } 99 }
102 100
103 indexers.forEach(indexer -> indexer.indexClass(classEntry)); 101 indexers.forEach(indexer -> indexer.indexClass(classEntry));
102 if (classEntry.isInnerClass() && !classEntry.getAccess().isSynthetic()) {
103 childrenByClass.put(classEntry.getParent(), classEntry);
104 }
104 } 105 }
105 106
106 @Override 107 @Override
@@ -110,6 +111,9 @@ public class JarIndex implements JarIndexer {
110 } 111 }
111 112
112 indexers.forEach(indexer -> indexer.indexField(fieldEntry)); 113 indexers.forEach(indexer -> indexer.indexField(fieldEntry));
114 if (!fieldEntry.getAccess().isSynthetic()) {
115 childrenByClass.put(fieldEntry.getParent(), fieldEntry);
116 }
113 } 117 }
114 118
115 @Override 119 @Override
@@ -119,6 +123,9 @@ public class JarIndex implements JarIndexer {
119 } 123 }
120 124
121 indexers.forEach(indexer -> indexer.indexMethod(methodEntry)); 125 indexers.forEach(indexer -> indexer.indexMethod(methodEntry));
126 if (!methodEntry.getAccess().isSynthetic() && !methodEntry.getName().equals("<clinit>")) {
127 childrenByClass.put(methodEntry.getParent(), methodEntry);
128 }
122 129
123 if (!methodEntry.isConstructor()) { 130 if (!methodEntry.isConstructor()) {
124 methodImplementations.put(methodEntry.getParent().getFullName(), methodEntry); 131 methodImplementations.put(methodEntry.getParent().getFullName(), methodEntry);
@@ -176,6 +183,10 @@ public class JarIndex implements JarIndexer {
176 return entryResolver; 183 return entryResolver;
177 } 184 }
178 185
186 public ListMultimap<ClassEntry, ParentedEntry> getChildrenByClass() {
187 return this.childrenByClass;
188 }
189
179 public boolean isIndexed(String internalName) { 190 public boolean isIndexed(String internalName) {
180 return indexedClasses.contains(internalName); 191 return indexedClasses.contains(internalName);
181 } 192 }
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 {
235 } 235 }
236 236
237 public enum Primitive { 237 public enum Primitive {
238 BYTE('B'), 238 BYTE('B', "byte"),
239 CHARACTER('C'), 239 CHARACTER('C', "char"),
240 SHORT('S'), 240 SHORT('S', "short"),
241 INTEGER('I'), 241 INTEGER('I', "int"),
242 LONG('J'), 242 LONG('J', "long"),
243 FLOAT('F'), 243 FLOAT('F', "float"),
244 DOUBLE('D'), 244 DOUBLE('D', "double"),
245 BOOLEAN('Z'); 245 BOOLEAN('Z', "boolean");
246 246
247 private static final Map<Character, Primitive> lookup; 247 private static final Map<Character, Primitive> lookup;
248 248
@@ -254,9 +254,11 @@ public class TypeDescriptor implements Translatable {
254 } 254 }
255 255
256 private char code; 256 private char code;
257 private String keyword;
257 258
258 Primitive(char code) { 259 Primitive(char code, String keyword) {
259 this.code = code; 260 this.code = code;
261 this.keyword = keyword;
260 } 262 }
261 263
262 public static Primitive get(char code) { 264 public static Primitive get(char code) {
@@ -266,5 +268,12 @@ public class TypeDescriptor implements Translatable {
266 public char getCode() { 268 public char getCode() {
267 return this.code; 269 return this.code;
268 } 270 }
271
272 /**
273 * Returns the Java keyword corresponding to this primitive.
274 */
275 public String getKeyword() {
276 return this.keyword;
277 }
269 } 278 }
270} 279}
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<ClassEntry> implements Comparable<
134 return name; 134 return name;
135 } 135 }
136 136
137 /**
138 * Returns whether this class entry has a parent, and therefore is an inner class.
139 */
137 public boolean isInnerClass() { 140 public boolean isInnerClass() {
138 return parent != null; 141 return parent != null;
139 } 142 }
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<P extends Entry<?>> extends Translatable {
29 return getName(); 29 return getName();
30 } 30 }
31 31
32 /**
33 * Returns the parent entry of this entry.
34 *
35 * <p>The parent entry should be a {@linkplain MethodEntry method} for local variables,
36 * a {@linkplain ClassEntry class} for methods, fields and inner classes, and {@code null}
37 * for other classes.</p>
38 */
32 @Nullable 39 @Nullable
33 P getParent(); 40 P getParent();
34 41
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 @@
101 "info_panel.identifier.index": "Index", 101 "info_panel.identifier.index": "Index",
102 "info_panel.editor.class.decompiling": "(decompiling...)", 102 "info_panel.editor.class.decompiling": "(decompiling...)",
103 "info_panel.editor.class.not_found": "Unable to find class:", 103 "info_panel.editor.class.not_found": "Unable to find class:",
104 "info_panel.tree.structure": "Structure",
105 "info_panel.tree.structure.hide_deobfuscated": "Hide deobfuscated members",
104 "info_panel.tree.inheritance": "Inheritance", 106 "info_panel.tree.inheritance": "Inheritance",
105 "info_panel.tree.implementations": "Implementations", 107 "info_panel.tree.implementations": "Implementations",
106 "info_panel.tree.calls": "Call Graph", 108 "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 @@
101 "info_panel.identifier.index": "Index", 101 "info_panel.identifier.index": "Index",
102 "info_panel.editor.class.decompiling": "(décompilation...)", 102 "info_panel.editor.class.decompiling": "(décompilation...)",
103 "info_panel.editor.class.not_found": "Impossible de trouver la classe :", 103 "info_panel.editor.class.not_found": "Impossible de trouver la classe :",
104 "info_panel.tree.structure": "Structure",
105 "info_panel.tree.structure.hide_deobfuscated": "Masquer les membres déobfusqués",
104 "info_panel.tree.inheritance": "Héritage", 106 "info_panel.tree.inheritance": "Héritage",
105 "info_panel.tree.implementations": "Implémentations", 107 "info_panel.tree.implementations": "Implémentations",
106 "info_panel.tree.calls": "Graphique des appels", 108 "info_panel.tree.calls": "Graphique des appels",