summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/gui/stats
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/gui/stats')
-rw-r--r--src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java197
-rw-r--r--src/main/java/cuchaz/enigma/gui/stats/StatsMember.java8
2 files changed, 0 insertions, 205 deletions
diff --git a/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java b/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java
deleted file mode 100644
index e783530..0000000
--- a/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java
+++ /dev/null
@@ -1,197 +0,0 @@
1package cuchaz.enigma.gui.stats;
2
3import com.google.gson.GsonBuilder;
4import cuchaz.enigma.EnigmaProject;
5import cuchaz.enigma.ProgressListener;
6import cuchaz.enigma.analysis.index.EntryIndex;
7import cuchaz.enigma.api.service.NameProposalService;
8import cuchaz.enigma.api.service.ObfuscationTestService;
9import cuchaz.enigma.translation.mapping.EntryRemapper;
10import cuchaz.enigma.translation.mapping.EntryResolver;
11import cuchaz.enigma.translation.mapping.ResolutionStrategy;
12import cuchaz.enigma.translation.representation.TypeDescriptor;
13import cuchaz.enigma.translation.representation.entry.*;
14import cuchaz.enigma.utils.I18n;
15
16import java.util.*;
17
18public class StatsGenerator {
19 private final EntryIndex entryIndex;
20 private final EntryRemapper mapper;
21 private final EntryResolver entryResolver;
22 private final List<ObfuscationTestService> obfuscationTestServices;
23 private final List<NameProposalService> nameProposalServices;
24
25 public StatsGenerator(EnigmaProject project) {
26 entryIndex = project.getJarIndex().getEntryIndex();
27 mapper = project.getMapper();
28 entryResolver = project.getJarIndex().getEntryResolver();
29 obfuscationTestServices = project.getEnigma().getServices().get(ObfuscationTestService.TYPE);
30 nameProposalServices = project.getEnigma().getServices().get(NameProposalService.TYPE);
31 }
32
33 public String generate(ProgressListener progress, Set<StatsMember> includedMembers) {
34 includedMembers = EnumSet.copyOf(includedMembers);
35 int totalWork = 0;
36
37 if (includedMembers.contains(StatsMember.METHODS) || includedMembers.contains(StatsMember.PARAMETERS)) {
38 totalWork += entryIndex.getMethods().size();
39 }
40
41 if (includedMembers.contains(StatsMember.FIELDS)) {
42 totalWork += entryIndex.getFields().size();
43 }
44
45 if (includedMembers.contains(StatsMember.CLASSES)) {
46 totalWork += entryIndex.getClasses().size();
47 }
48
49 progress.init(totalWork, I18n.translate("progress.stats"));
50
51 Map<String, Integer> counts = new HashMap<>();
52
53 int numDone = 0;
54 if (includedMembers.contains(StatsMember.METHODS) || includedMembers.contains(StatsMember.PARAMETERS)) {
55 for (MethodEntry method : entryIndex.getMethods()) {
56 progress.step(numDone++, I18n.translate("type.methods"));
57 MethodEntry root = entryResolver
58 .resolveEntry(method, ResolutionStrategy.RESOLVE_ROOT)
59 .stream()
60 .findFirst()
61 .orElseThrow(AssertionError::new);
62
63 if (root == method && !((MethodDefEntry) method).getAccess().isSynthetic()) {
64 if (includedMembers.contains(StatsMember.METHODS)) {
65 update(counts, method);
66 }
67
68 if (includedMembers.contains(StatsMember.PARAMETERS)) {
69 int index = ((MethodDefEntry) method).getAccess().isStatic() ? 0 : 1;
70 for (TypeDescriptor argument : method.getDesc().getArgumentDescs()) {
71 update(counts, new LocalVariableEntry(method, index, "", true,null));
72 index += argument.getSize();
73 }
74 }
75 }
76 }
77 }
78
79 if (includedMembers.contains(StatsMember.FIELDS)) {
80 for (FieldEntry field : entryIndex.getFields()) {
81 progress.step(numDone++, I18n.translate("type.fields"));
82 update(counts, field);
83 }
84 }
85
86 if (includedMembers.contains(StatsMember.CLASSES)) {
87 for (ClassEntry clazz : entryIndex.getClasses()) {
88 progress.step(numDone++, I18n.translate("type.classes"));
89 update(counts, clazz);
90 }
91 }
92
93 progress.step(-1, I18n.translate("progress.stats.data"));
94
95 Tree<Integer> tree = new Tree<>();
96
97 for (Map.Entry<String, Integer> entry : counts.entrySet()) {
98 if (entry.getKey().startsWith("com.mojang")) continue; // just a few unmapped names, no point in having a subsection
99 tree.getNode(entry.getKey()).value = entry.getValue();
100 }
101
102 tree.collapse(tree.root);
103 return new GsonBuilder().setPrettyPrinting().create().toJson(tree.root);
104 }
105
106 private void update(Map<String, Integer> counts, Entry<?> entry) {
107 if (isObfuscated(entry)) {
108 String parent = mapper.deobfuscate(entry.getAncestry().get(0)).getName().replace('/', '.');
109 counts.put(parent, counts.getOrDefault(parent, 0) + 1);
110 }
111 }
112
113 private boolean isObfuscated(Entry<?> entry) {
114 String name = entry.getName();
115
116 if (!obfuscationTestServices.isEmpty()) {
117 for (ObfuscationTestService service : obfuscationTestServices) {
118 if (service.testDeobfuscated(entry)) {
119 return false;
120 }
121 }
122 }
123
124 if (!nameProposalServices.isEmpty()) {
125 for (NameProposalService service : nameProposalServices) {
126 if (service.proposeName(entry, mapper).isPresent()) {
127 return false;
128 }
129 }
130 }
131
132 String mappedName = mapper.deobfuscate(entry).getName();
133 if (mappedName != null && !mappedName.isEmpty() && !mappedName.equals(name)) {
134 return false;
135 }
136
137 return true;
138 }
139
140 private static class Tree<T> {
141 public final Node<T> root;
142 private final Map<String, Node<T>> nodes = new HashMap<>();
143
144 public static class Node<T> {
145 public String name;
146 public T value;
147 public List<Node<T>> children = new ArrayList<>();
148 private final transient Map<String, Node<T>> namedChildren = new HashMap<>();
149
150 public Node(String name, T value) {
151 this.name = name;
152 this.value = value;
153 }
154 }
155
156 public Tree() {
157 root = new Node<>("", null);
158 }
159
160 public Node<T> getNode(String name) {
161 Node<T> node = nodes.get(name);
162
163 if (node == null) {
164 node = root;
165
166 for (String part : name.split("\\.")) {
167 Node<T> child = node.namedChildren.get(part);
168
169 if (child == null) {
170 child = new Node<>(part, null);
171 node.namedChildren.put(part, child);
172 node.children.add(child);
173 }
174
175 node = child;
176 }
177
178 nodes.put(name, node);
179 }
180
181 return node;
182 }
183
184 public void collapse(Node<T> node) {
185 while (node.children.size() == 1) {
186 Node<T> child = node.children.get(0);
187 node.name = node.name.isEmpty() ? child.name : node.name + "." + child.name;
188 node.children = child.children;
189 node.value = child.value;
190 }
191
192 for (Node<T> child : node.children) {
193 collapse(child);
194 }
195 }
196 }
197}
diff --git a/src/main/java/cuchaz/enigma/gui/stats/StatsMember.java b/src/main/java/cuchaz/enigma/gui/stats/StatsMember.java
deleted file mode 100644
index 70b4f40..0000000
--- a/src/main/java/cuchaz/enigma/gui/stats/StatsMember.java
+++ /dev/null
@@ -1,8 +0,0 @@
1package cuchaz.enigma.gui.stats;
2
3public enum StatsMember {
4 METHODS,
5 FIELDS,
6 PARAMETERS,
7 CLASSES
8}