summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/cuchaz/enigma/Deobfuscator.java78
-rw-r--r--src/main/java/cuchaz/enigma/TranslatingTypeLoader.java26
-rw-r--r--src/main/java/cuchaz/enigma/analysis/JavadocIndexVisitor.java375
-rw-r--r--src/main/java/cuchaz/enigma/analysis/SourceIndex.java37
-rw-r--r--src/main/java/cuchaz/enigma/analysis/Token.java34
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/ClassTranslator.java24
-rw-r--r--src/main/java/cuchaz/enigma/convert/ClassIdentifier.java2
-rw-r--r--src/main/java/cuchaz/enigma/mapping/javadoc/BaseJavaDocEntry.java50
-rw-r--r--src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocClass.java29
-rw-r--r--src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocField.java32
-rw-r--r--src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocMapping.java263
-rw-r--r--src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocMethod.java49
12 files changed, 954 insertions, 45 deletions
diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java
index e9a998da..82d0775b 100644
--- a/src/main/java/cuchaz/enigma/Deobfuscator.java
+++ b/src/main/java/cuchaz/enigma/Deobfuscator.java
@@ -21,13 +21,12 @@ import com.strobel.decompiler.DecompilerContext;
21import com.strobel.decompiler.DecompilerSettings; 21import com.strobel.decompiler.DecompilerSettings;
22import com.strobel.decompiler.PlainTextOutput; 22import com.strobel.decompiler.PlainTextOutput;
23import com.strobel.decompiler.languages.java.JavaOutputVisitor; 23import com.strobel.decompiler.languages.java.JavaOutputVisitor;
24import com.strobel.decompiler.languages.java.ast.AstBuilder; 24import com.strobel.decompiler.languages.java.ast.*;
25import com.strobel.decompiler.languages.java.ast.CompilationUnit;
26import com.strobel.decompiler.languages.java.ast.InsertParenthesesVisitor;
27import cuchaz.enigma.analysis.*; 25import cuchaz.enigma.analysis.*;
28import cuchaz.enigma.bytecode.ClassProtectifier; 26import cuchaz.enigma.bytecode.ClassProtectifier;
29import cuchaz.enigma.bytecode.ClassPublifier; 27import cuchaz.enigma.bytecode.ClassPublifier;
30import cuchaz.enigma.mapping.*; 28import cuchaz.enigma.mapping.*;
29import cuchaz.enigma.mapping.javadoc.JavaDocMapping;
31import cuchaz.enigma.utils.Utils; 30import cuchaz.enigma.utils.Utils;
32import javassist.CtClass; 31import javassist.CtClass;
33import javassist.bytecode.Descriptor; 32import javassist.bytecode.Descriptor;
@@ -40,6 +39,8 @@ import java.util.jar.JarOutputStream;
40 39
41public class Deobfuscator { 40public class Deobfuscator {
42 41
42 private final JavaDocMapping docMapping;
43
43 public interface ProgressListener { 44 public interface ProgressListener {
44 void init(int totalWork, String title); 45 void init(int totalWork, String title);
45 46
@@ -75,6 +76,8 @@ public class Deobfuscator {
75 this.renamer = new MappingsRenamer(this.jarIndex, null); 76 this.renamer = new MappingsRenamer(this.jarIndex, null);
76 // init mappings 77 // init mappings
77 setMappings(new Mappings()); 78 setMappings(new Mappings());
79
80 this.docMapping = new JavaDocMapping();
78 } 81 }
79 82
80 public JarFile getJar() { 83 public JarFile getJar() {
@@ -93,6 +96,11 @@ public class Deobfuscator {
93 return this.mappings; 96 return this.mappings;
94 } 97 }
95 98
99 public JavaDocMapping getDocMapping()
100 {
101 return docMapping;
102 }
103
96 public void setMappings(Mappings val) { 104 public void setMappings(Mappings val) {
97 setMappings(val, true); 105 setMappings(val, true);
98 } 106 }
@@ -176,7 +184,8 @@ public class Deobfuscator {
176 this.jar, 184 this.jar,
177 this.jarIndex, 185 this.jarIndex,
178 getTranslator(TranslationDirection.Obfuscating), 186 getTranslator(TranslationDirection.Obfuscating),
179 getTranslator(TranslationDirection.Deobfuscating) 187 getTranslator(TranslationDirection.Deobfuscating),
188 this.docMapping
180 ); 189 );
181 this.settings.setTypeLoader(loader); 190 this.settings.setTypeLoader(loader);
182 191
@@ -204,6 +213,14 @@ public class Deobfuscator {
204 } 213 }
205 214
206 public SourceIndex getSourceIndex(CompilationUnit sourceTree, String source, Boolean ignoreBadTokens) { 215 public SourceIndex getSourceIndex(CompilationUnit sourceTree, String source, Boolean ignoreBadTokens) {
216 List<Annotation> annotations = new ArrayList<>();
217
218 sourceTree.acceptVisitor(new JavadocIndexVisitor(), annotations);
219
220 // DEBUG
221 // sourceTree.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null );
222
223 annotations.forEach(AstNode::remove);
207 224
208 // build the source index 225 // build the source index
209 SourceIndex index; 226 SourceIndex index;
@@ -214,9 +231,6 @@ public class Deobfuscator {
214 } 231 }
215 sourceTree.acceptVisitor(new SourceIndexVisitor(), index); 232 sourceTree.acceptVisitor(new SourceIndexVisitor(), index);
216 233
217 // DEBUG
218 // sourceTree.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null );
219
220 // resolve all the classes in the source references 234 // resolve all the classes in the source references
221 for (Token token : index.referenceTokens()) { 235 for (Token token : index.referenceTokens()) {
222 EntryReference<Entry, Entry> deobfReference = index.getDeobfReference(token); 236 EntryReference<Entry, Entry> deobfReference = index.getDeobfReference(token);
@@ -234,11 +248,52 @@ public class Deobfuscator {
234 deobfReference.entry = deobfuscateEntry(obfEntry); 248 deobfReference.entry = deobfuscateEntry(obfEntry);
235 index.replaceDeobfReference(token, deobfReference); 249 index.replaceDeobfReference(token, deobfReference);
236 } 250 }
237
238 // DEBUG 251 // DEBUG
239 // System.out.println( token + " -> " + reference + " -> " + index.getReferenceToken( reference ) ); 252 // System.out.println( token + " -> " + reference + " -> " + index.getReferenceToken( reference ) );
240 } 253 }
241 254
255 source = index.getSource();
256
257 for (Annotation annotation : annotations)
258 {
259 // Get the decompiler before calling getText (after that we can get it...)
260 int pos = annotation.getRegion().getBeginLine();
261
262 // Get the exact annotation
263 String original = annotation.getText();
264
265 int originalAnnotationPosInSource = source.indexOf(original) - 1;
266 int prevLineBreak;
267 for (prevLineBreak = originalAnnotationPosInSource; prevLineBreak < source.length(); prevLineBreak--)
268 {
269 if (source.charAt(prevLineBreak) != ' ')
270 break;
271 }
272
273 // Format
274 String theComment = docMapping.convertAnnotationToJavaDoc(annotation, originalAnnotationPosInSource - prevLineBreak);
275
276 // Replace the annotation by the JavaDoc
277 source = source.replace(original, theComment);
278
279 // Calculate the offset of the changes for tokens
280 int offset = theComment.length() - original.length();
281
282 // Propagate positions changes
283 for (Token token : index.referenceTokens())
284 if (pos <= token.getRegion().getBeginLine())
285 token.offsetColum += offset;
286 }
287
288 // Set the source because of JavaDoc changes
289 index.setSource(source);
290
291 // Reccompute the start and end using the offset
292 for (Token token : index.referenceTokens())
293 token.computePos();
294
295 annotations.clear();
296
242 return index; 297 return index;
243 } 298 }
244 299
@@ -387,8 +442,7 @@ public class Deobfuscator {
387 this.jar, 442 this.jar,
388 this.jarIndex, 443 this.jarIndex,
389 getTranslator(TranslationDirection.Obfuscating), 444 getTranslator(TranslationDirection.Obfuscating),
390 getTranslator(TranslationDirection.Deobfuscating) 445 getTranslator(TranslationDirection.Deobfuscating), this.docMapping);
391 );
392 transformJar(out, progress, loader::transformClass); 446 transformJar(out, progress, loader::transformClass);
393 } 447 }
394 448
@@ -422,7 +476,7 @@ public class Deobfuscator {
422 outJar.write(c.toBytecode()); 476 outJar.write(c.toBytecode());
423 outJar.closeEntry(); 477 outJar.closeEntry();
424 } catch (Throwable t) { 478 } catch (Throwable t) {
425 throw new Error("Unable to transform class " + c.getName(), t); 479 throw new Error("Unable to tryToAddJavaDoc class " + c.getName(), t);
426 } 480 }
427 } 481 }
428 if (progress != null) { 482 if (progress != null) {
@@ -508,7 +562,7 @@ public class Deobfuscator {
508 } 562 }
509 563
510 public boolean isRenameable(EntryReference<Entry, Entry> obfReference, boolean activeHack) { 564 public boolean isRenameable(EntryReference<Entry, Entry> obfReference, boolean activeHack) {
511 return obfReference.isNamed() && isObfuscatedIdentifier(obfReference.getNameableEntry(), activeHack); 565 return obfReference != null && obfReference.isNamed() && isObfuscatedIdentifier(obfReference.getNameableEntry(), activeHack);
512 } 566 }
513 567
514 public boolean isRenameable(EntryReference<Entry, Entry> obfReference) { 568 public boolean isRenameable(EntryReference<Entry, Entry> obfReference) {
diff --git a/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java b/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java
index e4c162da..6ddfa634 100644
--- a/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java
+++ b/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java
@@ -12,10 +12,17 @@ package cuchaz.enigma;
12 12
13import com.google.common.collect.Lists; 13import com.google.common.collect.Lists;
14import com.google.common.collect.Maps; 14import com.google.common.collect.Maps;
15
16import com.strobel.assembler.metadata.Buffer; 15import com.strobel.assembler.metadata.Buffer;
17import com.strobel.assembler.metadata.ClasspathTypeLoader; 16import com.strobel.assembler.metadata.ClasspathTypeLoader;
18import com.strobel.assembler.metadata.ITypeLoader; 17import com.strobel.assembler.metadata.ITypeLoader;
18import cuchaz.enigma.analysis.BridgeMarker;
19import cuchaz.enigma.analysis.JarIndex;
20import cuchaz.enigma.bytecode.*;
21import cuchaz.enigma.mapping.ClassEntry;
22import cuchaz.enigma.mapping.Translator;
23import cuchaz.enigma.mapping.javadoc.JavaDocMapping;
24import javassist.*;
25import javassist.bytecode.Descriptor;
19 26
20import java.io.ByteArrayOutputStream; 27import java.io.ByteArrayOutputStream;
21import java.io.IOException; 28import java.io.IOException;
@@ -25,14 +32,6 @@ import java.util.Map;
25import java.util.jar.JarEntry; 32import java.util.jar.JarEntry;
26import java.util.jar.JarFile; 33import java.util.jar.JarFile;
27 34
28import cuchaz.enigma.analysis.BridgeMarker;
29import cuchaz.enigma.analysis.JarIndex;
30import cuchaz.enigma.bytecode.*;
31import cuchaz.enigma.mapping.ClassEntry;
32import cuchaz.enigma.mapping.Translator;
33import javassist.*;
34import javassist.bytecode.Descriptor;
35
36public class TranslatingTypeLoader implements ITypeLoader { 35public class TranslatingTypeLoader implements ITypeLoader {
37 36
38 private JarFile jar; 37 private JarFile jar;
@@ -41,14 +40,18 @@ public class TranslatingTypeLoader implements ITypeLoader {
41 private Translator deobfuscatingTranslator; 40 private Translator deobfuscatingTranslator;
42 private Map<String, byte[]> cache; 41 private Map<String, byte[]> cache;
43 private ClasspathTypeLoader defaultTypeLoader; 42 private ClasspathTypeLoader defaultTypeLoader;
43 private JavaDocMapping docMapping;
44 44
45 public TranslatingTypeLoader(JarFile jar, JarIndex jarIndex, Translator obfuscatingTranslator, Translator deobfuscatingTranslator) { 45 public TranslatingTypeLoader(JarFile jar, JarIndex jarIndex, Translator obfuscatingTranslator,
46 Translator deobfuscatingTranslator, JavaDocMapping docMapping) {
46 this.jar = jar; 47 this.jar = jar;
47 this.jarIndex = jarIndex; 48 this.jarIndex = jarIndex;
48 this.obfuscatingTranslator = obfuscatingTranslator; 49 this.obfuscatingTranslator = obfuscatingTranslator;
49 this.deobfuscatingTranslator = deobfuscatingTranslator; 50 this.deobfuscatingTranslator = deobfuscatingTranslator;
50 this.cache = Maps.newHashMap(); 51 this.cache = Maps.newHashMap();
51 this.defaultTypeLoader = new ClasspathTypeLoader(); 52 this.defaultTypeLoader = new ClasspathTypeLoader();
53 this.docMapping = docMapping;
54 this.docMapping.cleanBehaviors();
52 } 55 }
53 56
54 public void clearCache() { 57 public void clearCache() {
@@ -214,8 +217,7 @@ public class TranslatingTypeLoader implements ITypeLoader {
214 new BridgeMarker(this.jarIndex).markBridges(c); 217 new BridgeMarker(this.jarIndex).markBridges(c);
215 new MethodParameterWriter(this.deobfuscatingTranslator).writeMethodArguments(c); 218 new MethodParameterWriter(this.deobfuscatingTranslator).writeMethodArguments(c);
216 new LocalVariableRenamer(this.deobfuscatingTranslator).rename(c); 219 new LocalVariableRenamer(this.deobfuscatingTranslator).rename(c);
217 new ClassTranslator(this.deobfuscatingTranslator).translate(c); 220 new ClassTranslator(this.deobfuscatingTranslator, this.docMapping).translate(c);
218
219 return c; 221 return c;
220 } 222 }
221 223
diff --git a/src/main/java/cuchaz/enigma/analysis/JavadocIndexVisitor.java b/src/main/java/cuchaz/enigma/analysis/JavadocIndexVisitor.java
new file mode 100644
index 00000000..2845b497
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/analysis/JavadocIndexVisitor.java
@@ -0,0 +1,375 @@
1package cuchaz.enigma.analysis;
2
3import com.strobel.decompiler.languages.java.ast.*;
4import com.strobel.decompiler.patterns.Pattern;
5
6import java.util.List;
7
8/**
9 * Permit to data all javadoc markers
10 * Created by Thog
11 * 19/08/2016
12 */
13public class JavadocIndexVisitor implements IAstVisitor<List<Annotation>, Void>
14{
15
16 protected Void recurse(AstNode node, List<Annotation> data) {
17 for (final AstNode child : node.getChildren()) {
18 child.acceptVisitor(this, data);
19 }
20 return null;
21 }
22
23 @Override
24 public Void visitMethodDeclaration(MethodDeclaration node, List<Annotation> data) {
25 return recurse(node, data);
26 }
27
28 @Override
29 public Void visitConstructorDeclaration(ConstructorDeclaration node, List<Annotation> data) {
30 return recurse(node, data);
31 }
32
33 @Override
34 public Void visitFieldDeclaration(FieldDeclaration node, List<Annotation> data) {
35 return recurse(node, data);
36 }
37
38 @Override public Void visitTypeDeclaration(TypeDeclaration node, List<Annotation> data)
39 {
40 return recurse(node, data);
41 }
42
43 @Override
44 public Void visitEnumValueDeclaration(EnumValueDeclaration node, List<Annotation> data) {
45 return recurse(node, data);
46 }
47
48 @Override
49 public Void visitParameterDeclaration(ParameterDeclaration node, List<Annotation> data) {
50 return recurse(node, data);
51 }
52
53 @Override
54 public Void visitInvocationExpression(InvocationExpression node, List<Annotation> data) {
55 return recurse(node, data);
56 }
57
58 @Override
59 public Void visitMemberReferenceExpression(MemberReferenceExpression node, List<Annotation> data) {
60 return recurse(node, data);
61 }
62
63 @Override
64 public Void visitSimpleType(SimpleType node, List<Annotation> data) {
65 return recurse(node, data);
66 }
67
68 @Override
69 public Void visitIdentifierExpression(IdentifierExpression node, List<Annotation> data) {
70 return recurse(node, data);
71 }
72
73 @Override
74 public Void visitComment(Comment node, List<Annotation> data) {
75 return recurse(node, data);
76 }
77
78 @Override
79 public Void visitPatternPlaceholder(AstNode node, Pattern pattern, List<Annotation> data) {
80 return recurse(node, data);
81 }
82
83 @Override
84 public Void visitTypeReference(TypeReferenceExpression node, List<Annotation> data) {
85 return recurse(node, data);
86 }
87
88 @Override
89 public Void visitJavaTokenNode(JavaTokenNode node, List<Annotation> data) {
90 return recurse(node, data);
91 }
92
93 @Override
94 public Void visitIdentifier(Identifier node, List<Annotation> data) {
95 return recurse(node, data);
96 }
97
98 @Override
99 public Void visitNullReferenceExpression(NullReferenceExpression node, List<Annotation> data) {
100 return recurse(node, data);
101 }
102
103 @Override
104 public Void visitThisReferenceExpression(ThisReferenceExpression node, List<Annotation> data) {
105 return recurse(node, data);
106 }
107
108 @Override
109 public Void visitSuperReferenceExpression(SuperReferenceExpression node, List<Annotation> data) {
110 return recurse(node, data);
111 }
112
113 @Override
114 public Void visitClassOfExpression(ClassOfExpression node, List<Annotation> data) {
115 return recurse(node, data);
116 }
117
118 @Override
119 public Void visitBlockStatement(BlockStatement node, List<Annotation> data) {
120 return recurse(node, data);
121 }
122
123 @Override
124 public Void visitExpressionStatement(ExpressionStatement node, List<Annotation> data) {
125 return recurse(node, data);
126 }
127
128 @Override
129 public Void visitBreakStatement(BreakStatement node, List<Annotation> data) {
130 return recurse(node, data);
131 }
132
133 @Override
134 public Void visitContinueStatement(ContinueStatement node, List<Annotation> data) {
135 return recurse(node, data);
136 }
137
138 @Override
139 public Void visitDoWhileStatement(DoWhileStatement node, List<Annotation> data) {
140 return recurse(node, data);
141 }
142
143 @Override
144 public Void visitEmptyStatement(EmptyStatement node, List<Annotation> data) {
145 return recurse(node, data);
146 }
147
148 @Override
149 public Void visitIfElseStatement(IfElseStatement node, List<Annotation> data) {
150 return recurse(node, data);
151 }
152
153 @Override
154 public Void visitLabelStatement(LabelStatement node, List<Annotation> data) {
155 return recurse(node, data);
156 }
157
158 @Override
159 public Void visitLabeledStatement(LabeledStatement node, List<Annotation> data) {
160 return recurse(node, data);
161 }
162
163 @Override
164 public Void visitReturnStatement(ReturnStatement node, List<Annotation> data) {
165 return recurse(node, data);
166 }
167
168 @Override
169 public Void visitSwitchStatement(SwitchStatement node, List<Annotation> data) {
170 return recurse(node, data);
171 }
172
173 @Override
174 public Void visitSwitchSection(SwitchSection node, List<Annotation> data) {
175 return recurse(node, data);
176 }
177
178 @Override
179 public Void visitCaseLabel(CaseLabel node, List<Annotation> data) {
180 return recurse(node, data);
181 }
182
183 @Override
184 public Void visitThrowStatement(ThrowStatement node, List<Annotation> data) {
185 return recurse(node, data);
186 }
187
188 @Override
189 public Void visitCatchClause(CatchClause node, List<Annotation> data) {
190 return recurse(node, data);
191 }
192
193 @Override
194 public Void visitAnnotation(Annotation node, List<Annotation> data) {
195 String annotationType = node.getFirstChild().toString();
196 if (annotationType.startsWith("FieldDoc") || annotationType.startsWith("MethodDoc") || annotationType.startsWith("ClassDoc"))
197 data.add(node);
198 return recurse(node, data);
199 }
200
201 @Override
202 public Void visitNewLine(NewLineNode node, List<Annotation> data) {
203 return recurse(node, data);
204 }
205
206 @Override
207 public Void visitVariableDeclaration(VariableDeclarationStatement node, List<Annotation> data) {
208 return recurse(node, data);
209 }
210
211 @Override
212 public Void visitVariableInitializer(VariableInitializer node, List<Annotation> data) {
213 return recurse(node, data);
214 }
215
216 @Override
217 public Void visitText(TextNode node, List<Annotation> data) {
218 return recurse(node, data);
219 }
220
221 @Override
222 public Void visitImportDeclaration(ImportDeclaration node, List<Annotation> data) {
223 return recurse(node, data);
224 }
225
226 @Override
227 public Void visitInitializerBlock(InstanceInitializer node, List<Annotation> data) {
228 return recurse(node, data);
229 }
230
231 @Override
232 public Void visitTypeParameterDeclaration(TypeParameterDeclaration node, List<Annotation> data) {
233 return recurse(node, data);
234 }
235
236 @Override
237 public Void visitCompilationUnit(CompilationUnit node, List<Annotation> data) {
238 return recurse(node, data);
239 }
240
241 @Override
242 public Void visitPackageDeclaration(PackageDeclaration node, List<Annotation> data) {
243 return recurse(node, data);
244 }
245
246 @Override
247 public Void visitArraySpecifier(ArraySpecifier node, List<Annotation> data) {
248 return recurse(node, data);
249 }
250
251 @Override
252 public Void visitComposedType(ComposedType node, List<Annotation> data) {
253 return recurse(node, data);
254 }
255
256 @Override
257 public Void visitWhileStatement(WhileStatement node, List<Annotation> data) {
258 return recurse(node, data);
259 }
260
261 @Override
262 public Void visitPrimitiveExpression(PrimitiveExpression node, List<Annotation> data) {
263 return recurse(node, data);
264 }
265
266 @Override
267 public Void visitCastExpression(CastExpression node, List<Annotation> data) {
268 return recurse(node, data);
269 }
270
271 @Override
272 public Void visitBinaryOperatorExpression(BinaryOperatorExpression node, List<Annotation> data) {
273 return recurse(node, data);
274 }
275
276 @Override
277 public Void visitInstanceOfExpression(InstanceOfExpression node, List<Annotation> data) {
278 return recurse(node, data);
279 }
280
281 @Override
282 public Void visitIndexerExpression(IndexerExpression node, List<Annotation> data) {
283 return recurse(node, data);
284 }
285
286 @Override
287 public Void visitUnaryOperatorExpression(UnaryOperatorExpression node, List<Annotation> data) {
288 return recurse(node, data);
289 }
290
291 @Override
292 public Void visitConditionalExpression(ConditionalExpression node, List<Annotation> data) {
293 return recurse(node, data);
294 }
295
296 @Override
297 public Void visitArrayInitializerExpression(ArrayInitializerExpression node, List<Annotation> data) {
298 return recurse(node, data);
299 }
300
301 @Override
302 public Void visitObjectCreationExpression(ObjectCreationExpression node, List<Annotation> data) {
303 return recurse(node, data);
304 }
305
306 @Override
307 public Void visitArrayCreationExpression(ArrayCreationExpression node, List<Annotation> data) {
308 return recurse(node, data);
309 }
310
311 @Override
312 public Void visitAssignmentExpression(AssignmentExpression node, List<Annotation> data) {
313 return recurse(node, data);
314 }
315
316 @Override
317 public Void visitForStatement(ForStatement node, List<Annotation> data) {
318 return recurse(node, data);
319 }
320
321 @Override
322 public Void visitForEachStatement(ForEachStatement node, List<Annotation> data) {
323 return recurse(node, data);
324 }
325
326 @Override
327 public Void visitTryCatchStatement(TryCatchStatement node, List<Annotation> data) {
328 return recurse(node, data);
329 }
330
331 @Override
332 public Void visitGotoStatement(GotoStatement node, List<Annotation> data) {
333 return recurse(node, data);
334 }
335
336 @Override
337 public Void visitParenthesizedExpression(ParenthesizedExpression node, List<Annotation> data) {
338 return recurse(node, data);
339 }
340
341 @Override
342 public Void visitSynchronizedStatement(SynchronizedStatement node, List<Annotation> data) {
343 return recurse(node, data);
344 }
345
346 @Override
347 public Void visitAnonymousObjectCreationExpression(AnonymousObjectCreationExpression node, List<Annotation> data) {
348 return recurse(node, data);
349 }
350
351 @Override
352 public Void visitWildcardType(WildcardType node, List<Annotation> data) {
353 return recurse(node, data);
354 }
355
356 @Override
357 public Void visitMethodGroupExpression(MethodGroupExpression node, List<Annotation> data) {
358 return recurse(node, data);
359 }
360
361 @Override
362 public Void visitAssertStatement(AssertStatement node, List<Annotation> data) {
363 return recurse(node, data);
364 }
365
366 @Override
367 public Void visitLambdaExpression(LambdaExpression node, List<Annotation> data) {
368 return recurse(node, data);
369 }
370
371 @Override
372 public Void visitLocalTypeDeclarationStatement(LocalTypeDeclarationStatement node, List<Annotation> data) {
373 return recurse(node, data);
374 }
375}
diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndex.java b/src/main/java/cuchaz/enigma/analysis/SourceIndex.java
index 719930e9..d7bbafa9 100644
--- a/src/main/java/cuchaz/enigma/analysis/SourceIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/SourceIndex.java
@@ -14,18 +14,16 @@ import com.google.common.collect.HashMultimap;
14import com.google.common.collect.Lists; 14import com.google.common.collect.Lists;
15import com.google.common.collect.Maps; 15import com.google.common.collect.Maps;
16import com.google.common.collect.Multimap; 16import com.google.common.collect.Multimap;
17
18import com.strobel.decompiler.languages.Region; 17import com.strobel.decompiler.languages.Region;
19import com.strobel.decompiler.languages.java.ast.AstNode; 18import com.strobel.decompiler.languages.java.ast.AstNode;
20import com.strobel.decompiler.languages.java.ast.Identifier; 19import com.strobel.decompiler.languages.java.ast.Identifier;
20import cuchaz.enigma.mapping.Entry;
21 21
22import java.util.Collection; 22import java.util.Collection;
23import java.util.List; 23import java.util.List;
24import java.util.Map; 24import java.util.Map;
25import java.util.TreeMap; 25import java.util.TreeMap;
26 26
27import cuchaz.enigma.mapping.Entry;
28
29public class SourceIndex { 27public class SourceIndex {
30 28
31 private String source; 29 private String source;
@@ -56,10 +54,27 @@ public class SourceIndex {
56 } 54 }
57 } 55 }
58 56
57 public void setSource(String source)
58 {
59 this.source = source;
60 }
61
59 public String getSource() { 62 public String getSource() {
60 return this.source; 63 return this.source;
61 } 64 }
62 65
66 public int getLineNumber(int offset)
67 {
68 int i = 0;
69 for (Integer lineOffset : lineOffsets)
70 {
71 if (lineOffset <= offset)
72 return i;
73 i++;
74 }
75 return i;
76 }
77
63 public Token getToken(AstNode node) { 78 public Token getToken(AstNode node) {
64 79
65 // get the text of the node 80 // get the text of the node
@@ -75,7 +90,7 @@ public class SourceIndex {
75 System.err.println(String.format("WARNING: %s \"%s\" has invalid region: %s", node.getNodeType(), name, region)); 90 System.err.println(String.format("WARNING: %s \"%s\" has invalid region: %s", node.getNodeType(), name, region));
76 return null; 91 return null;
77 } 92 }
78 Token token = new Token(toPos(region.getBeginLine(), region.getBeginColumn()), toPos(region.getEndLine(), region.getEndColumn()), this.source); 93 Token token = new Token(this, region, this.source);
79 if (token.start == 0) { 94 if (token.start == 0) {
80 // DEBUG 95 // DEBUG
81 System.err.println(String.format("WARNING: %s \"%s\" has invalid start: %s", node.getNodeType(), name, region)); 96 System.err.println(String.format("WARNING: %s \"%s\" has invalid start: %s", node.getNodeType(), name, region));
@@ -157,24 +172,12 @@ public class SourceIndex {
157 return this.declarationToToken.get(deobfEntry); 172 return this.declarationToToken.get(deobfEntry);
158 } 173 }
159 174
160 public int getLineNumber(int pos) {
161 // line number is 1-based
162 int line = 0;
163 for (Integer offset : this.lineOffsets) {
164 if (offset > pos) {
165 break;
166 }
167 line++;
168 }
169 return line;
170 }
171
172 public int getColumnNumber(int pos) { 175 public int getColumnNumber(int pos) {
173 // column number is 1-based 176 // column number is 1-based
174 return pos - this.lineOffsets.get(getLineNumber(pos) - 1) + 1; 177 return pos - this.lineOffsets.get(getLineNumber(pos) - 1) + 1;
175 } 178 }
176 179
177 private int toPos(int line, int col) { 180 public int toPos(int line, int col) {
178 // line and col are 1-based 181 // line and col are 1-based
179 return this.lineOffsets.get(line - 1) + col - 1; 182 return this.lineOffsets.get(line - 1) + col - 1;
180 } 183 }
diff --git a/src/main/java/cuchaz/enigma/analysis/Token.java b/src/main/java/cuchaz/enigma/analysis/Token.java
index 419842af..0f730cb4 100644
--- a/src/main/java/cuchaz/enigma/analysis/Token.java
+++ b/src/main/java/cuchaz/enigma/analysis/Token.java
@@ -10,18 +10,48 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.analysis; 11package cuchaz.enigma.analysis;
12 12
13import com.strobel.decompiler.languages.Region;
14
13public class Token implements Comparable<Token> { 15public class Token implements Comparable<Token> {
14 16
15 public int start; 17 public int start;
16 public int end; 18 public int end;
19 public int offsetLine;
20 public int offsetColum;
17 public String text; 21 public String text;
22 private Region region;
23 private SourceIndex index;
24
25 public Token(SourceIndex index, Region region, String source)
26 {
27 this(index.toPos(region.getBeginLine(), region.getBeginColumn()), index
28 .toPos(region.getEndLine(), region.getEndColumn()), source);
29 this.region = region;
30 this.index = index;
31 //toPos(region.getBeginLine(), region.getBeginColumn()), toPos(region.getEndLine(), region.getEndColumn())
32 }
33
34 public void computePos()
35 {
36 if (region == null)
37 return;
38 this.start = index.toPos(region.getBeginLine() + offsetLine, region.getBeginColumn() + offsetColum);
39 this.end = index.toPos(region.getEndLine() + offsetLine, region.getEndColumn() + offsetColum);
40 this.offsetLine = 0;
41 this.offsetColum = 0;
42 this.region = null;
43 }
44
45 public Region getRegion()
46 {
47 return region;
48 }
18 49
19 public Token(int start, int end, String source) { 50 public Token(int start, int end, String source) {
20 this.start = start; 51 this.start = start;
21 this.end = end; 52 this.end = end;
22 if (source != null) { 53 if (source != null)
23 this.text = source.substring(start, end); 54 this.text = source.substring(start, end);
24 }
25 } 55 }
26 56
27 public boolean contains(int pos) { 57 public boolean contains(int pos) {
diff --git a/src/main/java/cuchaz/enigma/bytecode/ClassTranslator.java b/src/main/java/cuchaz/enigma/bytecode/ClassTranslator.java
index 6c05b838..7f8779fc 100644
--- a/src/main/java/cuchaz/enigma/bytecode/ClassTranslator.java
+++ b/src/main/java/cuchaz/enigma/bytecode/ClassTranslator.java
@@ -11,6 +11,7 @@
11package cuchaz.enigma.bytecode; 11package cuchaz.enigma.bytecode;
12 12
13import cuchaz.enigma.mapping.*; 13import cuchaz.enigma.mapping.*;
14import cuchaz.enigma.mapping.javadoc.JavaDocMapping;
14import javassist.CtBehavior; 15import javassist.CtBehavior;
15import javassist.CtClass; 16import javassist.CtClass;
16import javassist.CtField; 17import javassist.CtField;
@@ -22,10 +23,13 @@ import javassist.bytecode.SourceFileAttribute;
22 23
23public class ClassTranslator { 24public class ClassTranslator {
24 25
26 private JavaDocMapping docMapping;
25 private Translator translator; 27 private Translator translator;
26 28
27 public ClassTranslator(Translator translator) { 29 public ClassTranslator(Translator translator, JavaDocMapping docMapping) {
28 this.translator = translator; 30 this.translator = translator;
31 this.docMapping = docMapping == null ? new JavaDocMapping() : docMapping;
32 this.docMapping.setTranslator(translator);
29 } 33 }
30 34
31 public void translate(CtClass c) { 35 public void translate(CtClass c) {
@@ -75,14 +79,22 @@ public class ClassTranslator {
75 79
76 ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(c.getName())); 80 ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(c.getName()));
77 81
82 // Try to add javadoc to constructor
83 docMapping.tryToAddJavaDoc(c, classEntry);
78 // translate all the fields 84 // translate all the fields
79 for (CtField field : c.getDeclaredFields()) { 85 for (CtField field : c.getDeclaredFields()) {
80 86
81 // translate the name 87 // translate the name
82 FieldEntry entry = EntryFactory.getFieldEntry(field); 88 FieldEntry entry = EntryFactory.getFieldEntry(field);
83 String translatedName = this.translator.translate(entry); 89 String translatedName = this.translator.translate(entry);
90
91 // Try to add javadoc as ob
92 docMapping.tryToAddJavaDoc(field, entry);
84 if (translatedName != null) { 93 if (translatedName != null) {
85 field.setName(translatedName); 94 field.setName(translatedName);
95
96 // Try to add javadoc as ob
97 docMapping.tryToAddJavaDoc(field, entry);
86 } 98 }
87 99
88 // translate the type 100 // translate the type
@@ -98,12 +110,22 @@ public class ClassTranslator {
98 if (behavior instanceof CtMethod) { 110 if (behavior instanceof CtMethod) {
99 CtMethod method = (CtMethod) behavior; 111 CtMethod method = (CtMethod) behavior;
100 112
113 // Try to add javadoc as ob
114 docMapping.tryToAddJavaDoc(method, entry);
101 // translate the name 115 // translate the name
102 String translatedName = this.translator.translate(entry); 116 String translatedName = this.translator.translate(entry);
103 if (translatedName != null) { 117 if (translatedName != null) {
118 MethodEntry deObfuscatedMethod = new MethodEntry(entry.getClassEntry(), translatedName, entry.getSignature());
104 method.setName(translatedName); 119 method.setName(translatedName);
120 // Try to add javadoc as ob
121 docMapping.tryToAddJavaDoc(method, entry, deObfuscatedMethod);
105 } 122 }
106 } 123 }
124 else
125 {
126 // Try to add javadoc to constructor
127 docMapping.tryToAddJavaDoc(behavior, entry);
128 }
107 129
108 if (entry.getSignature() != null) { 130 if (entry.getSignature() != null) {
109 // translate the signature 131 // translate the signature
diff --git a/src/main/java/cuchaz/enigma/convert/ClassIdentifier.java b/src/main/java/cuchaz/enigma/convert/ClassIdentifier.java
index 557e6083..ce1e1dc3 100644
--- a/src/main/java/cuchaz/enigma/convert/ClassIdentifier.java
+++ b/src/main/java/cuchaz/enigma/convert/ClassIdentifier.java
@@ -35,7 +35,7 @@ public class ClassIdentifier {
35 this.index = index; 35 this.index = index;
36 this.namer = namer; 36 this.namer = namer;
37 this.useReferences = useReferences; 37 this.useReferences = useReferences;
38 this.loader = new TranslatingTypeLoader(jar, index, new Translator(), new Translator()); 38 this.loader = new TranslatingTypeLoader(jar, index, new Translator(), new Translator(), null);
39 this.cache = Maps.newHashMap(); 39 this.cache = Maps.newHashMap();
40 } 40 }
41 41
diff --git a/src/main/java/cuchaz/enigma/mapping/javadoc/BaseJavaDocEntry.java b/src/main/java/cuchaz/enigma/mapping/javadoc/BaseJavaDocEntry.java
new file mode 100644
index 00000000..fa373a57
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/mapping/javadoc/BaseJavaDocEntry.java
@@ -0,0 +1,50 @@
1package cuchaz.enigma.mapping.javadoc;
2
3import cuchaz.enigma.mapping.Entry;
4import cuchaz.enigma.mapping.Type;
5
6/**
7 * Base of any JavaDoc entry
8 * Created by Thog
9 * 19/08/2016
10 */
11public abstract class BaseJavaDocEntry
12{
13 private String identifier;
14 private String comment;
15
16 public BaseJavaDocEntry(String identifier, String comment)
17 {
18 this.identifier = identifier;
19 this.comment = comment;
20 }
21
22 public void setIdentifier(String identifier)
23 {
24 this.identifier = identifier;
25 }
26
27 public String getIdentifier()
28 {
29 return identifier;
30 }
31
32 public void setComment(String comment)
33 {
34 this.comment = comment;
35 }
36
37 public String getComment()
38 {
39 return comment;
40 }
41
42 public Type getType()
43 {
44 return new Type(getIdentifier());
45 }
46
47 public abstract JavaDocClass getClassDocEntry();
48
49 public abstract Entry getEntry();
50}
diff --git a/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocClass.java b/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocClass.java
new file mode 100644
index 00000000..9bc7e734
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocClass.java
@@ -0,0 +1,29 @@
1package cuchaz.enigma.mapping.javadoc;
2
3import cuchaz.enigma.mapping.ClassEntry;
4import cuchaz.enigma.mapping.Entry;
5
6/**
7 * JavaDoc representation of a class
8 * Created by Thog
9 * 19/08/2016
10 */
11public class JavaDocClass extends BaseJavaDocEntry
12{
13
14 public JavaDocClass(String identifier, String comment)
15 {
16 super(identifier, comment);
17 }
18
19 @Override public JavaDocClass getClassDocEntry()
20 {
21 return this;
22 }
23
24 @Override
25 public Entry getEntry()
26 {
27 return new ClassEntry(getIdentifier());
28 }
29}
diff --git a/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocField.java b/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocField.java
new file mode 100644
index 00000000..a2a67f45
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocField.java
@@ -0,0 +1,32 @@
1package cuchaz.enigma.mapping.javadoc;
2
3import cuchaz.enigma.mapping.ClassEntry;
4import cuchaz.enigma.mapping.Entry;
5import cuchaz.enigma.mapping.FieldEntry;
6
7/**
8 * JavaDoc of a Field
9 * Created by Thog
10 * 19/08/2016
11 */
12public class JavaDocField extends BaseJavaDocEntry
13{
14 private final JavaDocClass classDocEntry;
15 private final String name;
16 public JavaDocField(JavaDocClass classDocEntry, String name, String identifier, String comment)
17 {
18 super(identifier, comment);
19 this.name = name;
20 this.classDocEntry = classDocEntry;
21 }
22
23 @Override public JavaDocClass getClassDocEntry()
24 {
25 return classDocEntry;
26 }
27
28 @Override public Entry getEntry()
29 {
30 return new FieldEntry((ClassEntry) classDocEntry.getEntry(), name, getType());
31 }
32}
diff --git a/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocMapping.java b/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocMapping.java
new file mode 100644
index 00000000..98996fdb
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocMapping.java
@@ -0,0 +1,263 @@
1package cuchaz.enigma.mapping.javadoc;
2
3import com.strobel.decompiler.languages.java.ast.*;
4import cuchaz.enigma.mapping.*;
5import javassist.CtBehavior;
6import javassist.CtClass;
7import javassist.CtField;
8import javassist.bytecode.AnnotationsAttribute;
9import javassist.bytecode.ConstPool;
10import javassist.bytecode.annotation.*;
11import javassist.bytecode.annotation.Annotation;
12
13import java.io.File;
14import java.util.*;
15
16/**
17 * Representation of a javadoc mapping
18 * Created by Thog
19 * 19/08/2016
20 */
21public class JavaDocMapping
22{
23 private final Map<ClassEntry, JavaDocClass> javaDocClassByID;
24 private final Map<FieldEntry, JavaDocField> javaDocFieldByID;
25 private final Map<BehaviorEntry, JavaDocMethod> javaDocMethodByID;
26 private final List<BehaviorEntry> behaviorByID;
27 private Translator translator;
28
29 public JavaDocMapping()
30 {
31 this.javaDocClassByID = new HashMap<>();
32 this.javaDocFieldByID = new HashMap<>();
33 this.javaDocMethodByID = new HashMap<>();
34 this.behaviorByID = new ArrayList<>();
35
36 // TODO: File format
37 addField("a", "none/akw", "Lnone/kp;", "Hello from Enigma");
38 addMethod("<init>", "none/akw", "(Lnone/ayo;)V", "You know what? I love constructors!", "The material of the block!");
39 addClass("none/akw", "HEY I'M A BLOCK YOU KNOW THAT?!");
40 }
41
42 private void addClass(String className, String comment)
43 {
44 this.javaDocClassByID.put(new ClassEntry(className), new JavaDocClass(className, comment));
45 }
46
47 public void addField(String fieldName, String className, String type, String comment)
48 {
49 this.javaDocFieldByID.put(new FieldEntry(new ClassEntry(className), fieldName, new Type(type)), new JavaDocField(new JavaDocClass(className, "LOL"), fieldName, type, comment));
50 }
51
52 public void addMethod(String methodName, String className, String signature, String comment, String... argComment)
53 {
54 BehaviorEntry behaviorEntry;
55 if (methodName.equals("<init>"))
56 behaviorEntry = new ConstructorEntry(new ClassEntry(className), new Signature(signature));
57 else
58 behaviorEntry = new MethodEntry(new ClassEntry(className), methodName, new Signature(signature));
59
60 this.javaDocMethodByID.put(behaviorEntry, new JavaDocMethod(new JavaDocClass(className, "LOL"), methodName, signature, comment,
61 Arrays.asList(argComment)));
62 }
63
64 public void cleanBehaviors()
65 {
66 behaviorByID.clear();
67 }
68
69 public void loadMapping(File mappingDirectory)
70 {
71 // NOP
72 }
73
74 public void closeMapping()
75 {
76 behaviorByID.clear();
77 javaDocClassByID.clear();
78 javaDocFieldByID.clear();
79 javaDocMethodByID.clear();
80 }
81
82 public CtClass tryToAddJavaDoc(CtClass ctClass, ClassEntry entry)
83 {
84 if (javaDocClassByID.containsKey(entry))
85 {
86 JavaDocClass javaDocClass = javaDocClassByID.get(entry);
87
88 // Get the constant pool
89 ConstPool constpool = ctClass.getClassFile().getConstPool();
90
91 // Prepare the annotation
92 AnnotationsAttribute attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
93 Annotation annot = new Annotation("enigma.remapper.ClassDoc", constpool);
94 annot.addMemberValue("comment", new StringMemberValue(javaDocClass.getComment(), constpool));
95 attr.addAnnotation(annot);
96 ctClass.getClassFile().addAttribute(attr);
97 }
98 return ctClass;
99 }
100
101 public CtBehavior tryToAddJavaDoc(CtBehavior ctBehavior, BehaviorEntry obEntry, BehaviorEntry deobEntry)
102 {
103 if (javaDocMethodByID.containsKey(obEntry))
104 {
105 int id = getEntryID(obEntry);
106 if (id != -1)
107 behaviorByID.set(id, deobEntry);
108 }
109 return tryToAddJavaDoc(ctBehavior, deobEntry);
110 }
111
112 public CtBehavior tryToAddJavaDoc(CtBehavior ctBehavior, BehaviorEntry entry)
113 {
114 if (javaDocMethodByID.containsKey(entry))
115 {
116 JavaDocMethod javaDocMethod = javaDocMethodByID.get(entry);
117
118 // Get the constant pool
119 ConstPool constpool = ctBehavior.getDeclaringClass().getClassFile().getConstPool();
120
121 // Prepare the annotation
122 AnnotationsAttribute attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
123 Annotation annot = new Annotation("enigma.remapper.MethodDoc", constpool);
124 annot.addMemberValue("comment", new StringMemberValue(javaDocMethod.getComment(), constpool));
125 behaviorByID.add(entry);
126 annot.addMemberValue("behavior", new IntegerMemberValue(constpool, behaviorByID.size() - 1));
127 annot.addMemberValue("args", translateStringArray(constpool, javaDocMethod.getArgsComments()));
128 attr.addAnnotation(annot);
129 ctBehavior.getMethodInfo().addAttribute(attr);
130 }
131 return ctBehavior;
132 }
133
134 public CtField tryToAddJavaDoc(CtField ctField, FieldEntry entry)
135 {
136 if (javaDocFieldByID.containsKey(entry))
137 {
138 JavaDocField javaDocField = javaDocFieldByID.get(entry);
139
140 // Get the constant pool
141 ConstPool constpool = ctField.getDeclaringClass().getClassFile().getConstPool();
142
143 // Prepare the annotation
144 AnnotationsAttribute attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
145 Annotation annot = new Annotation("enigma.remapper.FieldDoc", constpool);
146 annot.addMemberValue("comment", new StringMemberValue(javaDocField.getComment(), constpool));
147 attr.addAnnotation(annot);
148 ctField.getFieldInfo().addAttribute(attr);
149 }
150 return ctField;
151 }
152
153 private MemberValue[] toMemberValue(ConstPool pool, String[] args)
154 {
155 MemberValue[] result = new MemberValue[args.length];
156 for (int i = 0; i < result.length; i++)
157 result[i] = new StringMemberValue(args[i], pool);
158
159 return result;
160 }
161
162 private ArrayMemberValue translateStringArray(ConstPool pool, String[] args)
163 {
164 ArrayMemberValue res = new ArrayMemberValue(new StringMemberValue(pool), pool);
165 res.setValue(toMemberValue(pool, args));
166 return res;
167 }
168
169 public BehaviorEntry getEntry(int id)
170 {
171 if (id == -1)
172 return null;
173 return this.behaviorByID.get(id);
174 }
175
176 public int getEntryID(BehaviorEntry taget)
177 {
178 for (int i = 0; i < behaviorByID.size(); i++)
179 if (behaviorByID.get(i).equals(taget))
180 return i;
181 return -1;
182 }
183
184 /**
185 *
186 * @param annotation
187 * @param spacesCount
188 * @return
189 */
190 public String convertAnnotationToJavaDoc(com.strobel.decompiler.languages.java.ast.Annotation annotation, int spacesCount)
191 {
192 int behaviorID = -1;
193 StringBuilder builder = new StringBuilder();
194 String spaces = buildLineSpace(spacesCount);
195 builder.append("/**\n");
196 AstNodeCollection<Expression> annotationArgs = annotation.getArguments();
197 for (Expression expression : annotationArgs)
198 {
199 String id = expression.getFirstChild().toString();
200 for (AstNode child : expression.getChildren())
201 {
202 if (child instanceof PrimitiveExpression)
203 {
204 PrimitiveExpression data = (PrimitiveExpression) child;
205 if (id.equals("comment"))
206 {
207 builder.append(spaces);
208 builder.append(" * ");
209 builder.append(data.getValue());
210 builder.append("\n");
211 }
212 else if (id.equals("behavior"))
213 behaviorID = (Integer) data.getValue();
214 }
215 else if (child instanceof ArrayInitializerExpression)
216 {
217 ArrayInitializerExpression data = (ArrayInitializerExpression) child;
218 if (id.equals("args"))
219 {
220 BehaviorEntry entry = getEntry(behaviorID);
221 if (entry == null)
222 System.err.println("(SEVERE): CANNOT FIND BEHAVIOR ENTRY FOR ID " + behaviorID);
223
224 int i = 0;
225 for (Expression expArg : data.getElements())
226 {
227 if (expArg instanceof PrimitiveExpression)
228 {
229 PrimitiveExpression primitiveExpression = (PrimitiveExpression) expArg;
230 String argName = entry == null ? null : this.translator.translate(new ArgumentEntry(entry, i, ""));
231 if (argName == null)
232 argName = "a" + (i + 1);
233 builder.append(spaces);
234 builder.append(" * @param ");
235 builder.append(argName);
236 builder.append(" ");
237 builder.append(primitiveExpression.getValue());
238 builder.append("\n");
239 }
240 i++;
241 }
242 }
243 }
244 }
245 }
246 builder.append(spaces);
247 builder.append(" */");
248 return builder.toString();
249 }
250
251 private String buildLineSpace(int spacesCount)
252 {
253 StringBuilder builder = new StringBuilder();
254 for (int i = 0; i< spacesCount; i++)
255 builder.append(" ");
256 return builder.toString();
257 }
258
259 public void setTranslator(Translator translator)
260 {
261 this.translator = translator;
262 }
263}
diff --git a/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocMethod.java b/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocMethod.java
new file mode 100644
index 00000000..1508aede
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/mapping/javadoc/JavaDocMethod.java
@@ -0,0 +1,49 @@
1package cuchaz.enigma.mapping.javadoc;
2
3import cuchaz.enigma.mapping.ClassEntry;
4import cuchaz.enigma.mapping.Entry;
5import cuchaz.enigma.mapping.MethodEntry;
6import cuchaz.enigma.mapping.Signature;
7
8import java.util.List;
9
10/**
11 * Javadoc of a Method
12 * TODO: @return
13 * Created by Thog
14 * 19/08/2016
15 */
16public class JavaDocMethod extends BaseJavaDocEntry
17{
18 private final JavaDocClass classDocEntry;
19 private final String name;
20 private final List<String> argsComments;
21
22 public JavaDocMethod(JavaDocClass classDocEntry, String name, String identifier, String comment, List<String> argsComments)
23 {
24 super(identifier, comment);
25 this.name = name;
26 this.classDocEntry = classDocEntry;
27 this.argsComments = argsComments;
28 }
29
30 @Override public JavaDocClass getClassDocEntry()
31 {
32 return classDocEntry;
33 }
34
35 @Override public Entry getEntry()
36 {
37 return new MethodEntry((ClassEntry) classDocEntry.getEntry(), name, new Signature(getIdentifier()));
38 }
39
40 public String[] getArgsComments()
41 {
42 return argsComments.toArray(new String[argsComments.size()]);
43 }
44
45 public String getArgsComment(int id)
46 {
47 return argsComments.size() > id ? argsComments.get(id) : null;
48 }
49}