summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorGravatar Fudge2019-12-02 15:43:23 +0200
committerGravatar modmuss502019-12-02 13:43:23 +0000
commita9e03fa0e75b5b338021de982acbbb8277e08706 (patch)
tree94233d173c5937584a3376895bf864fb24697a8c /src/main
parentCorrectly decompile bridges, and add command to add bridges to mappings (#180) (diff)
downloadenigma-a9e03fa0e75b5b338021de982acbbb8277e08706.tar.gz
enigma-a9e03fa0e75b5b338021de982acbbb8277e08706.tar.xz
enigma-a9e03fa0e75b5b338021de982acbbb8277e08706.zip
Allow attaching class, method, field, and parameter javadocs (#185)
* bring liach pr to modern enigma * bump version * fuck off vscode * switch to COMMENT and write comments before * it was already after, what do you want * oops * put inner classes at the end * remove indents and use all caps * add refreshmappings command * Update src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java * Delete RefreshEnigmaMappingsCommand.java * Update CommandMain.java * ok
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/cuchaz/enigma/SourceProvider.java17
-rw-r--r--src/main/java/cuchaz/enigma/analysis/AddJavadocsAstTransform.java135
-rw-r--r--src/main/java/cuchaz/enigma/analysis/SourceIndexClassVisitor.java8
-rw-r--r--src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java20
-rw-r--r--src/main/java/cuchaz/enigma/analysis/SourceIndexVisitor.java356
-rw-r--r--src/main/java/cuchaz/enigma/analysis/TreeDumpVisitor.java354
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java2
-rw-r--r--src/main/java/cuchaz/enigma/gui/Gui.java45
-rw-r--r--src/main/java/cuchaz/enigma/gui/GuiController.java35
-rw-r--r--src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java88
-rw-r--r--src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java9
-rw-r--r--src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java4
-rw-r--r--src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java2
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java28
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java9
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaFormat.java9
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java79
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java67
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java1
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java51
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java11
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java2
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java22
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java12
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java16
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java15
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java2
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java17
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java15
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java11
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java11
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java17
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java15
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java10
34 files changed, 667 insertions, 828 deletions
diff --git a/src/main/java/cuchaz/enigma/SourceProvider.java b/src/main/java/cuchaz/enigma/SourceProvider.java
index 704424aa..d3d30038 100644
--- a/src/main/java/cuchaz/enigma/SourceProvider.java
+++ b/src/main/java/cuchaz/enigma/SourceProvider.java
@@ -19,8 +19,10 @@ import oml.ast.transformers.*;
19 19
20import java.io.StringWriter; 20import java.io.StringWriter;
21import java.io.Writer; 21import java.io.Writer;
22import java.lang.ref.WeakReference;
22import java.util.Arrays; 23import java.util.Arrays;
23import java.util.List; 24import java.util.List;
25import java.util.Objects;
24 26
25public class SourceProvider { 27public class SourceProvider {
26 private final DecompilerSettings settings; 28 private final DecompilerSettings settings;
@@ -28,6 +30,9 @@ public class SourceProvider {
28 private final ITypeLoader typeLoader; 30 private final ITypeLoader typeLoader;
29 private final MetadataSystem metadataSystem; 31 private final MetadataSystem metadataSystem;
30 32
33 private String lastLookUpName;
34 private WeakReference<CompilationUnit> lastDecompiled;
35
31 public SourceProvider(DecompilerSettings settings, ITypeLoader typeLoader, MetadataSystem metadataSystem) { 36 public SourceProvider(DecompilerSettings settings, ITypeLoader typeLoader, MetadataSystem metadataSystem) {
32 this.settings = settings; 37 this.settings = settings;
33 this.typeLoader = typeLoader; 38 this.typeLoader = typeLoader;
@@ -55,6 +60,13 @@ public class SourceProvider {
55 } 60 }
56 61
57 public CompilationUnit getSources(String name) { 62 public CompilationUnit getSources(String name) {
63 // Optimization for javadoc-caused decompilations
64 if (Objects.equals(lastLookUpName, name)) {
65 CompilationUnit last = lastDecompiled.get();
66 if (last != null)
67 return last;
68 }
69
58 TypeReference type = metadataSystem.lookupType(name); 70 TypeReference type = metadataSystem.lookupType(name);
59 if (type == null) { 71 if (type == null) {
60 throw new Error(String.format("Unable to find desc: %s", name)); 72 throw new Error(String.format("Unable to find desc: %s", name));
@@ -74,7 +86,10 @@ public class SourceProvider {
74 builder.runTransformations(null); 86 builder.runTransformations(null);
75 runCustomTransforms(builder, context); 87 runCustomTransforms(builder, context);
76 88
77 return builder.getCompilationUnit(); 89 CompilationUnit ret = builder.getCompilationUnit();
90 lastLookUpName = name;
91 lastDecompiled = new WeakReference<>(ret);
92 return ret;
78 } 93 }
79 94
80 public void writeSource(Writer writer, CompilationUnit sourceTree) { 95 public void writeSource(Writer writer, CompilationUnit sourceTree) {
diff --git a/src/main/java/cuchaz/enigma/analysis/AddJavadocsAstTransform.java b/src/main/java/cuchaz/enigma/analysis/AddJavadocsAstTransform.java
new file mode 100644
index 00000000..17ae63df
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/analysis/AddJavadocsAstTransform.java
@@ -0,0 +1,135 @@
1package cuchaz.enigma.analysis;
2
3import com.google.common.base.Function;
4import com.google.common.base.Strings;
5import com.strobel.assembler.metadata.ParameterDefinition;
6import com.strobel.decompiler.languages.java.ast.*;
7import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform;
8import cuchaz.enigma.translation.mapping.EntryMapping;
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.*;
14
15import java.util.ArrayList;
16import java.util.Collections;
17import java.util.List;
18import java.util.Objects;
19import java.util.stream.Stream;
20
21public final class AddJavadocsAstTransform implements IAstTransform {
22
23 private final EntryRemapper remapper;
24
25 public AddJavadocsAstTransform(EntryRemapper remapper) {
26 this.remapper = remapper;
27 }
28
29 @Override
30 public void run(AstNode compilationUnit) {
31 compilationUnit.acceptVisitor(new Visitor(remapper), null);
32 }
33
34 static class Visitor extends DepthFirstAstVisitor<Void, Void> {
35
36 private final EntryRemapper remapper;
37
38 Visitor(EntryRemapper remapper) {
39 this.remapper = remapper;
40 }
41
42 private <T extends AstNode> void addDoc(T node, Function<T, Entry<?>> retriever) {
43 final Comment[] comments = getComments(node, retriever);
44 if (comments != null) {
45 node.insertChildrenBefore(node.getFirstChild(), Roles.COMMENT, comments);
46 }
47 }
48
49 private <T extends AstNode> Comment[] getComments(T node, Function<T, Entry<?>> retriever) {
50 final EntryMapping mapping = remapper.getDeobfMapping(retriever.apply(node));
51 final String docs = mapping == null ? null : Strings.emptyToNull(mapping.getJavadoc());
52 return docs == null ? null : Stream.of(docs.split("\\R")).map(st -> new Comment(st,
53 CommentType.Documentation)).toArray(Comment[]::new);
54 }
55
56 private Comment[] getParameterComments(ParameterDeclaration node, Function<ParameterDeclaration, Entry<?>> retriever) {
57 final EntryMapping mapping = remapper.getDeobfMapping(retriever.apply(node));
58 final Comment[] ret = getComments(node, retriever);
59 if (ret != null) {
60 final String paramPrefix = "@param " + mapping.getTargetName() + " ";
61 final String indent = Strings.repeat(" ", paramPrefix.length());
62 ret[0].setContent(paramPrefix + ret[0].getContent());
63 for (int i = 1; i < ret.length; i++) {
64 ret[i].setContent(indent + ret[i].getContent());
65 }
66 }
67 return ret;
68 }
69
70 private void visitMethod(AstNode node) {
71 final MethodDefEntry methodDefEntry = MethodDefEntry.parse(node.getUserData(Keys.METHOD_DEFINITION));
72 final Comment[] baseComments = getComments(node, $ -> methodDefEntry);
73 List<Comment> comments = new ArrayList<>();
74 if (baseComments != null)
75 Collections.addAll(comments, baseComments);
76
77 for (ParameterDeclaration dec : node.getChildrenByRole(Roles.PARAMETER)) {
78 ParameterDefinition def = dec.getUserData(Keys.PARAMETER_DEFINITION);
79 final Comment[] paramComments = getParameterComments(dec, $ -> new LocalVariableDefEntry(methodDefEntry, def.getSlot(), def.getName(),
80 true,
81 TypeDescriptor.parse(def.getParameterType()), null));
82 if (paramComments != null)
83 Collections.addAll(comments, paramComments);
84 }
85
86 if (!comments.isEmpty()) {
87 if (remapper.getObfResolver().resolveEntry(methodDefEntry, ResolutionStrategy.RESOLVE_ROOT).stream().noneMatch(e -> Objects.equals(e, methodDefEntry))) {
88 comments.add(0, new Comment("{@inheritDoc}", CommentType.Documentation));
89 }
90 final AstNode oldFirst = node.getFirstChild();
91 for (Comment comment : comments) {
92 node.insertChildBefore(oldFirst, comment, Roles.COMMENT);
93 }
94 }
95 }
96
97 @Override
98 protected Void visitChildren(AstNode node, Void data) {
99 for (final AstNode child : node.getChildren()) {
100 child.acceptVisitor(this, data);
101 }
102 return null;
103 }
104
105 @Override
106 public Void visitMethodDeclaration(MethodDeclaration node, Void data) {
107 visitMethod(node);
108 return super.visitMethodDeclaration(node, data);
109 }
110
111 @Override
112 public Void visitConstructorDeclaration(ConstructorDeclaration node, Void data) {
113 visitMethod(node);
114 return super.visitConstructorDeclaration(node, data);
115 }
116
117 @Override
118 public Void visitFieldDeclaration(FieldDeclaration node, Void data) {
119 addDoc(node, dec -> FieldDefEntry.parse(dec.getUserData(Keys.FIELD_DEFINITION)));
120 return super.visitFieldDeclaration(node, data);
121 }
122
123 @Override
124 public Void visitTypeDeclaration(TypeDeclaration node, Void data) {
125 addDoc(node, dec -> ClassDefEntry.parse(dec.getUserData(Keys.TYPE_DEFINITION)));
126 return super.visitTypeDeclaration(node, data);
127 }
128
129 @Override
130 public Void visitEnumValueDeclaration(EnumValueDeclaration node, Void data) {
131 addDoc(node, dec -> FieldDefEntry.parse(dec.getUserData(Keys.FIELD_DEFINITION)));
132 return super.visitEnumValueDeclaration(node, data);
133 }
134 }
135}
diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndexClassVisitor.java b/src/main/java/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
index c9777030..2a72cb1a 100644
--- a/src/main/java/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
+++ b/src/main/java/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
@@ -40,7 +40,7 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor {
40 return node.acceptVisitor(new SourceIndexClassVisitor(classEntry), index); 40 return node.acceptVisitor(new SourceIndexClassVisitor(classEntry), index);
41 } 41 }
42 42
43 return recurse(node, index); 43 return visitChildren(node, index);
44 } 44 }
45 45
46 @Override 46 @Override
@@ -51,7 +51,7 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor {
51 index.addReference(node.getIdentifierToken(), classEntry, this.classEntry); 51 index.addReference(node.getIdentifierToken(), classEntry, this.classEntry);
52 } 52 }
53 53
54 return recurse(node, index); 54 return visitChildren(node, index);
55 } 55 }
56 56
57 @Override 57 @Override
@@ -82,7 +82,7 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor {
82 assert (node.getVariables().size() == 1); 82 assert (node.getVariables().size() == 1);
83 VariableInitializer variable = node.getVariables().firstOrNullObject(); 83 VariableInitializer variable = node.getVariables().firstOrNullObject();
84 index.addDeclaration(variable.getNameToken(), fieldEntry); 84 index.addDeclaration(variable.getNameToken(), fieldEntry);
85 return recurse(node, index); 85 return visitChildren(node, index);
86 } 86 }
87 87
88 @Override 88 @Override
@@ -91,6 +91,6 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor {
91 FieldDefinition def = node.getUserData(Keys.FIELD_DEFINITION); 91 FieldDefinition def = node.getUserData(Keys.FIELD_DEFINITION);
92 FieldDefEntry fieldEntry = FieldDefEntry.parse(def); 92 FieldDefEntry fieldEntry = FieldDefEntry.parse(def);
93 index.addDeclaration(node.getNameToken(), fieldEntry); 93 index.addDeclaration(node.getNameToken(), fieldEntry);
94 return recurse(node, index); 94 return visitChildren(node, index);
95 } 95 }
96} 96}
diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java b/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java
index fde6edf9..dfe58bad 100644
--- a/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java
+++ b/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java
@@ -63,7 +63,7 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
63 // Check for identifier 63 // Check for identifier
64 node.getArguments().stream().filter(expression -> expression instanceof IdentifierExpression) 64 node.getArguments().stream().filter(expression -> expression instanceof IdentifierExpression)
65 .forEach(expression -> this.checkIdentifier((IdentifierExpression) expression, index)); 65 .forEach(expression -> this.checkIdentifier((IdentifierExpression) expression, index));
66 return recurse(node, index); 66 return visitChildren(node, index);
67 } 67 }
68 68
69 @Override 69 @Override
@@ -81,7 +81,7 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
81 index.addReference(node.getMemberNameToken(), fieldEntry, this.methodEntry); 81 index.addReference(node.getMemberNameToken(), fieldEntry, this.methodEntry);
82 } 82 }
83 83
84 return recurse(node, index); 84 return visitChildren(node, index);
85 } 85 }
86 86
87 @Override 87 @Override
@@ -92,7 +92,7 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
92 index.addReference(node.getIdentifierToken(), classEntry, this.methodEntry); 92 index.addReference(node.getIdentifierToken(), classEntry, this.methodEntry);
93 } 93 }
94 94
95 return recurse(node, index); 95 return visitChildren(node, index);
96 } 96 }
97 97
98 @Override 98 @Override
@@ -107,14 +107,14 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
107 } 107 }
108 108
109 TypeDescriptor parameterType = TypeDescriptor.parse(def.getParameterType()); 109 TypeDescriptor parameterType = TypeDescriptor.parse(def.getParameterType());
110 LocalVariableDefEntry localVariableEntry = new LocalVariableDefEntry(ownerMethod, parameterIndex, node.getName(), true, parameterType); 110 LocalVariableDefEntry localVariableEntry = new LocalVariableDefEntry(ownerMethod, parameterIndex, node.getName(), true, parameterType, null);
111 Identifier identifier = node.getNameToken(); 111 Identifier identifier = node.getNameToken();
112 // cache the argument entry and the identifier 112 // cache the argument entry and the identifier
113 identifierEntryCache.put(identifier.getName(), localVariableEntry); 113 identifierEntryCache.put(identifier.getName(), localVariableEntry);
114 index.addDeclaration(identifier, localVariableEntry); 114 index.addDeclaration(identifier, localVariableEntry);
115 } 115 }
116 116
117 return recurse(node, index); 117 return visitChildren(node, index);
118 } 118 }
119 119
120 @Override 120 @Override
@@ -126,7 +126,7 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
126 index.addReference(node.getIdentifierToken(), fieldEntry, this.methodEntry); 126 index.addReference(node.getIdentifierToken(), fieldEntry, this.methodEntry);
127 } else 127 } else
128 this.checkIdentifier(node, index); 128 this.checkIdentifier(node, index);
129 return recurse(node, index); 129 return visitChildren(node, index);
130 } 130 }
131 131
132 private void checkIdentifier(IdentifierExpression node, SourceIndex index) { 132 private void checkIdentifier(IdentifierExpression node, SourceIndex index) {
@@ -157,7 +157,7 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
157 index.addReference(simpleTypeNode.getIdentifierToken(), constructorEntry, this.methodEntry); 157 index.addReference(simpleTypeNode.getIdentifierToken(), constructorEntry, this.methodEntry);
158 } 158 }
159 159
160 return recurse(node, index); 160 return visitChildren(node, index);
161 } 161 }
162 162
163 @Override 163 @Override
@@ -177,7 +177,7 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
177 if (variableIndex >= 0) { 177 if (variableIndex >= 0) {
178 MethodDefEntry ownerMethod = MethodDefEntry.parse(originalVariable.getDeclaringMethod()); 178 MethodDefEntry ownerMethod = MethodDefEntry.parse(originalVariable.getDeclaringMethod());
179 TypeDescriptor variableType = TypeDescriptor.parse(originalVariable.getVariableType()); 179 TypeDescriptor variableType = TypeDescriptor.parse(originalVariable.getVariableType());
180 LocalVariableDefEntry localVariableEntry = new LocalVariableDefEntry(ownerMethod, variableIndex, initializer.getName(), false, variableType); 180 LocalVariableDefEntry localVariableEntry = new LocalVariableDefEntry(ownerMethod, variableIndex, initializer.getName(), false, variableType, null);
181 identifierEntryCache.put(identifier.getName(), localVariableEntry); 181 identifierEntryCache.put(identifier.getName(), localVariableEntry);
182 addDeclarationToUnmatched(identifier.getName(), index); 182 addDeclarationToUnmatched(identifier.getName(), index);
183 index.addDeclaration(identifier, localVariableEntry); 183 index.addDeclaration(identifier, localVariableEntry);
@@ -186,7 +186,7 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
186 } 186 }
187 } 187 }
188 } 188 }
189 return recurse(node, index); 189 return visitChildren(node, index);
190 } 190 }
191 191
192 @Override 192 @Override
@@ -211,6 +211,6 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
211 } 211 }
212 } 212 }
213 213
214 return recurse(node, index); 214 return visitChildren(node, index);
215 } 215 }
216} 216}
diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndexVisitor.java b/src/main/java/cuchaz/enigma/analysis/SourceIndexVisitor.java
index 75a66a2d..8bd00a86 100644
--- a/src/main/java/cuchaz/enigma/analysis/SourceIndexVisitor.java
+++ b/src/main/java/cuchaz/enigma/analysis/SourceIndexVisitor.java
@@ -12,11 +12,13 @@
12package cuchaz.enigma.analysis; 12package cuchaz.enigma.analysis;
13 13
14import com.strobel.assembler.metadata.TypeDefinition; 14import com.strobel.assembler.metadata.TypeDefinition;
15import com.strobel.decompiler.languages.java.ast.*; 15import com.strobel.decompiler.languages.java.ast.AstNode;
16import com.strobel.decompiler.patterns.Pattern; 16import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor;
17import com.strobel.decompiler.languages.java.ast.Keys;
18import com.strobel.decompiler.languages.java.ast.TypeDeclaration;
17import cuchaz.enigma.translation.representation.entry.ClassDefEntry; 19import cuchaz.enigma.translation.representation.entry.ClassDefEntry;
18 20
19public class SourceIndexVisitor implements IAstVisitor<SourceIndex, Void> { 21public class SourceIndexVisitor extends DepthFirstAstVisitor<SourceIndex, Void> {
20 @Override 22 @Override
21 public Void visitTypeDeclaration(TypeDeclaration node, SourceIndex index) { 23 public Void visitTypeDeclaration(TypeDeclaration node, SourceIndex index) {
22 TypeDefinition def = node.getUserData(Keys.TYPE_DEFINITION); 24 TypeDefinition def = node.getUserData(Keys.TYPE_DEFINITION);
@@ -26,355 +28,11 @@ public class SourceIndexVisitor implements IAstVisitor<SourceIndex, Void> {
26 return node.acceptVisitor(new SourceIndexClassVisitor(classEntry), index); 28 return node.acceptVisitor(new SourceIndexClassVisitor(classEntry), index);
27 } 29 }
28 30
29 protected Void recurse(AstNode node, SourceIndex index) { 31 @Override
32 protected Void visitChildren(AstNode node, SourceIndex index) {
30 for (final AstNode child : node.getChildren()) { 33 for (final AstNode child : node.getChildren()) {
31 child.acceptVisitor(this, index); 34 child.acceptVisitor(this, index);
32 } 35 }
33 return null; 36 return null;
34 } 37 }
35
36 @Override
37 public Void visitMethodDeclaration(MethodDeclaration node, SourceIndex index) {
38 return recurse(node, index);
39 }
40
41 @Override
42 public Void visitConstructorDeclaration(ConstructorDeclaration node, SourceIndex index) {
43 return recurse(node, index);
44 }
45
46 @Override
47 public Void visitFieldDeclaration(FieldDeclaration node, SourceIndex index) {
48 return recurse(node, index);
49 }
50
51 @Override
52 public Void visitEnumValueDeclaration(EnumValueDeclaration node, SourceIndex index) {
53 return recurse(node, index);
54 }
55
56 @Override
57 public Void visitParameterDeclaration(ParameterDeclaration node, SourceIndex index) {
58 return recurse(node, index);
59 }
60
61 @Override
62 public Void visitInvocationExpression(InvocationExpression node, SourceIndex index) {
63 return recurse(node, index);
64 }
65
66 @Override
67 public Void visitMemberReferenceExpression(MemberReferenceExpression node, SourceIndex index) {
68 return recurse(node, index);
69 }
70
71 @Override
72 public Void visitSimpleType(SimpleType node, SourceIndex index) {
73 return recurse(node, index);
74 }
75
76 @Override
77 public Void visitIdentifierExpression(IdentifierExpression node, SourceIndex index) {
78 return recurse(node, index);
79 }
80
81 @Override
82 public Void visitComment(Comment node, SourceIndex index) {
83 return recurse(node, index);
84 }
85
86 @Override
87 public Void visitPatternPlaceholder(AstNode node, Pattern pattern, SourceIndex index) {
88 return recurse(node, index);
89 }
90
91 @Override
92 public Void visitTypeReference(TypeReferenceExpression node, SourceIndex index) {
93 return recurse(node, index);
94 }
95
96 @Override
97 public Void visitJavaTokenNode(JavaTokenNode node, SourceIndex index) {
98 return recurse(node, index);
99 }
100
101 @Override
102 public Void visitIdentifier(Identifier node, SourceIndex index) {
103 return recurse(node, index);
104 }
105
106 @Override
107 public Void visitNullReferenceExpression(NullReferenceExpression node, SourceIndex index) {
108 return recurse(node, index);
109 }
110
111 @Override
112 public Void visitThisReferenceExpression(ThisReferenceExpression node, SourceIndex index) {
113 return recurse(node, index);
114 }
115
116 @Override
117 public Void visitSuperReferenceExpression(SuperReferenceExpression node, SourceIndex index) {
118 return recurse(node, index);
119 }
120
121 @Override
122 public Void visitClassOfExpression(ClassOfExpression node, SourceIndex index) {
123 return recurse(node, index);
124 }
125
126 @Override
127 public Void visitBlockStatement(BlockStatement node, SourceIndex index) {
128 return recurse(node, index);
129 }
130
131 @Override
132 public Void visitExpressionStatement(ExpressionStatement node, SourceIndex index) {
133 return recurse(node, index);
134 }
135
136 @Override
137 public Void visitBreakStatement(BreakStatement node, SourceIndex index) {
138 return recurse(node, index);
139 }
140
141 @Override
142 public Void visitContinueStatement(ContinueStatement node, SourceIndex index) {
143 return recurse(node, index);
144 }
145
146 @Override
147 public Void visitDoWhileStatement(DoWhileStatement node, SourceIndex index) {
148 return recurse(node, index);
149 }
150
151 @Override
152 public Void visitEmptyStatement(EmptyStatement node, SourceIndex index) {
153 return recurse(node, index);
154 }
155
156 @Override
157 public Void visitIfElseStatement(IfElseStatement node, SourceIndex index) {
158 return recurse(node, index);
159 }
160
161 @Override
162 public Void visitLabelStatement(LabelStatement node, SourceIndex index) {
163 return recurse(node, index);
164 }
165
166 @Override
167 public Void visitLabeledStatement(LabeledStatement node, SourceIndex index) {
168 return recurse(node, index);
169 }
170
171 @Override
172 public Void visitReturnStatement(ReturnStatement node, SourceIndex index) {
173 return recurse(node, index);
174 }
175
176 @Override
177 public Void visitSwitchStatement(SwitchStatement node, SourceIndex index) {
178 return recurse(node, index);
179 }
180
181 @Override
182 public Void visitSwitchSection(SwitchSection node, SourceIndex index) {
183 return recurse(node, index);
184 }
185
186 @Override
187 public Void visitCaseLabel(CaseLabel node, SourceIndex index) {
188 return recurse(node, index);
189 }
190
191 @Override
192 public Void visitThrowStatement(ThrowStatement node, SourceIndex index) {
193 return recurse(node, index);
194 }
195
196 @Override
197 public Void visitCatchClause(CatchClause node, SourceIndex index) {
198 return recurse(node, index);
199 }
200
201 @Override
202 public Void visitAnnotation(Annotation node, SourceIndex index) {
203 return recurse(node, index);
204 }
205
206 @Override
207 public Void visitNewLine(NewLineNode node, SourceIndex index) {
208 return recurse(node, index);
209 }
210
211 @Override
212 public Void visitVariableDeclaration(VariableDeclarationStatement node, SourceIndex index) {
213 return recurse(node, index);
214 }
215
216 @Override
217 public Void visitVariableInitializer(VariableInitializer node, SourceIndex index) {
218 return recurse(node, index);
219 }
220
221 @Override
222 public Void visitText(TextNode node, SourceIndex index) {
223 return recurse(node, index);
224 }
225
226 @Override
227 public Void visitImportDeclaration(ImportDeclaration node, SourceIndex index) {
228 return recurse(node, index);
229 }
230
231 @Override
232 public Void visitInitializerBlock(InstanceInitializer node, SourceIndex index) {
233 return recurse(node, index);
234 }
235
236 @Override
237 public Void visitTypeParameterDeclaration(TypeParameterDeclaration node, SourceIndex index) {
238 return recurse(node, index);
239 }
240
241 @Override
242 public Void visitCompilationUnit(CompilationUnit node, SourceIndex index) {
243 return recurse(node, index);
244 }
245
246 @Override
247 public Void visitPackageDeclaration(PackageDeclaration node, SourceIndex index) {
248 return recurse(node, index);
249 }
250
251 @Override
252 public Void visitArraySpecifier(ArraySpecifier node, SourceIndex index) {
253 return recurse(node, index);
254 }
255
256 @Override
257 public Void visitComposedType(ComposedType node, SourceIndex index) {
258 return recurse(node, index);
259 }
260
261 @Override
262 public Void visitWhileStatement(WhileStatement node, SourceIndex index) {
263 return recurse(node, index);
264 }
265
266 @Override
267 public Void visitPrimitiveExpression(PrimitiveExpression node, SourceIndex index) {
268 return recurse(node, index);
269 }
270
271 @Override
272 public Void visitCastExpression(CastExpression node, SourceIndex index) {
273 return recurse(node, index);
274 }
275
276 @Override
277 public Void visitBinaryOperatorExpression(BinaryOperatorExpression node, SourceIndex index) {
278 return recurse(node, index);
279 }
280
281 @Override
282 public Void visitInstanceOfExpression(InstanceOfExpression node, SourceIndex index) {
283 return recurse(node, index);
284 }
285
286 @Override
287 public Void visitIndexerExpression(IndexerExpression node, SourceIndex index) {
288 return recurse(node, index);
289 }
290
291 @Override
292 public Void visitUnaryOperatorExpression(UnaryOperatorExpression node, SourceIndex index) {
293 return recurse(node, index);
294 }
295
296 @Override
297 public Void visitConditionalExpression(ConditionalExpression node, SourceIndex index) {
298 return recurse(node, index);
299 }
300
301 @Override
302 public Void visitArrayInitializerExpression(ArrayInitializerExpression node, SourceIndex index) {
303 return recurse(node, index);
304 }
305
306 @Override
307 public Void visitObjectCreationExpression(ObjectCreationExpression node, SourceIndex index) {
308 return recurse(node, index);
309 }
310
311 @Override
312 public Void visitArrayCreationExpression(ArrayCreationExpression node, SourceIndex index) {
313 return recurse(node, index);
314 }
315
316 @Override
317 public Void visitAssignmentExpression(AssignmentExpression node, SourceIndex index) {
318 return recurse(node, index);
319 }
320
321 @Override
322 public Void visitForStatement(ForStatement node, SourceIndex index) {
323 return recurse(node, index);
324 }
325
326 @Override
327 public Void visitForEachStatement(ForEachStatement node, SourceIndex index) {
328 return recurse(node, index);
329 }
330
331 @Override
332 public Void visitTryCatchStatement(TryCatchStatement node, SourceIndex index) {
333 return recurse(node, index);
334 }
335
336 @Override
337 public Void visitGotoStatement(GotoStatement node, SourceIndex index) {
338 return recurse(node, index);
339 }
340
341 @Override
342 public Void visitParenthesizedExpression(ParenthesizedExpression node, SourceIndex index) {
343 return recurse(node, index);
344 }
345
346 @Override
347 public Void visitSynchronizedStatement(SynchronizedStatement node, SourceIndex index) {
348 return recurse(node, index);
349 }
350
351 @Override
352 public Void visitAnonymousObjectCreationExpression(AnonymousObjectCreationExpression node, SourceIndex index) {
353 return recurse(node, index);
354 }
355
356 @Override
357 public Void visitWildcardType(WildcardType node, SourceIndex index) {
358 return recurse(node, index);
359 }
360
361 @Override
362 public Void visitMethodGroupExpression(MethodGroupExpression node, SourceIndex index) {
363 return recurse(node, index);
364 }
365
366 @Override
367 public Void visitAssertStatement(AssertStatement node, SourceIndex index) {
368 return recurse(node, index);
369 }
370
371 @Override
372 public Void visitLambdaExpression(LambdaExpression node, SourceIndex index) {
373 return recurse(node, index);
374 }
375
376 @Override
377 public Void visitLocalTypeDeclarationStatement(LocalTypeDeclarationStatement node, SourceIndex index) {
378 return recurse(node, index);
379 }
380} 38}
diff --git a/src/main/java/cuchaz/enigma/analysis/TreeDumpVisitor.java b/src/main/java/cuchaz/enigma/analysis/TreeDumpVisitor.java
index c98fb9ef..c85d97a5 100644
--- a/src/main/java/cuchaz/enigma/analysis/TreeDumpVisitor.java
+++ b/src/main/java/cuchaz/enigma/analysis/TreeDumpVisitor.java
@@ -18,7 +18,7 @@ import com.strobel.decompiler.patterns.Pattern;
18import java.io.*; 18import java.io.*;
19import java.nio.charset.Charset; 19import java.nio.charset.Charset;
20 20
21public class TreeDumpVisitor implements IAstVisitor<Void, Void> { 21public class TreeDumpVisitor extends DepthFirstAstVisitor<Void, Void> {
22 22
23 private File file; 23 private File file;
24 private Writer out; 24 private Writer out;
@@ -31,7 +31,7 @@ public class TreeDumpVisitor implements IAstVisitor<Void, Void> {
31 public Void visitCompilationUnit(CompilationUnit node, Void ignored) { 31 public Void visitCompilationUnit(CompilationUnit node, Void ignored) {
32 try { 32 try {
33 out = new OutputStreamWriter(new FileOutputStream(file), Charset.forName("UTF-8")); 33 out = new OutputStreamWriter(new FileOutputStream(file), Charset.forName("UTF-8"));
34 recurse(node, ignored); 34 visitChildren(node, ignored);
35 out.close(); 35 out.close();
36 return null; 36 return null;
37 } catch (IOException ex) { 37 } catch (IOException ex) {
@@ -39,7 +39,8 @@ public class TreeDumpVisitor implements IAstVisitor<Void, Void> {
39 } 39 }
40 } 40 }
41 41
42 private Void recurse(AstNode node, Void ignored) { 42 @Override
43 protected Void visitChildren(AstNode node, Void ignored) {
43 // show the tree 44 // show the tree
44 try { 45 try {
45 out.write(getIndent(node) + node.getClass().getSimpleName() + " " + getText(node) + " " + dumpUserData(node) + " " + node.getRegion() + "\n"); 46 out.write(getIndent(node) + node.getClass().getSimpleName() + " " + getText(node) + " " + dumpUserData(node) + " " + node.getRegion() + "\n");
@@ -89,351 +90,4 @@ public class TreeDumpVisitor implements IAstVisitor<Void, Void> {
89 } 90 }
90 return depth; 91 return depth;
91 } 92 }
92
93 // OVERRIDES WE DON'T CARE ABOUT
94
95 @Override
96 public Void visitInvocationExpression(InvocationExpression node, Void ignored) {
97 return recurse(node, ignored);
98 }
99
100 @Override
101 public Void visitMemberReferenceExpression(MemberReferenceExpression node, Void ignored) {
102 return recurse(node, ignored);
103 }
104
105 @Override
106 public Void visitSimpleType(SimpleType node, Void ignored) {
107 return recurse(node, ignored);
108 }
109
110 @Override
111 public Void visitMethodDeclaration(MethodDeclaration node, Void ignored) {
112 return recurse(node, ignored);
113 }
114
115 @Override
116 public Void visitConstructorDeclaration(ConstructorDeclaration node, Void ignored) {
117 return recurse(node, ignored);
118 }
119
120 @Override
121 public Void visitParameterDeclaration(ParameterDeclaration node, Void ignored) {
122 return recurse(node, ignored);
123 }
124
125 @Override
126 public Void visitFieldDeclaration(FieldDeclaration node, Void ignored) {
127 return recurse(node, ignored);
128 }
129
130 @Override
131 public Void visitTypeDeclaration(TypeDeclaration node, Void ignored) {
132 return recurse(node, ignored);
133 }
134
135 @Override
136 public Void visitComment(Comment node, Void ignored) {
137 return recurse(node, ignored);
138 }
139
140 @Override
141 public Void visitPatternPlaceholder(AstNode node, Pattern pattern, Void ignored) {
142 return recurse(node, ignored);
143 }
144
145 @Override
146 public Void visitTypeReference(TypeReferenceExpression node, Void ignored) {
147 return recurse(node, ignored);
148 }
149
150 @Override
151 public Void visitJavaTokenNode(JavaTokenNode node, Void ignored) {
152 return recurse(node, ignored);
153 }
154
155 @Override
156 public Void visitIdentifier(Identifier node, Void ignored) {
157 return recurse(node, ignored);
158 }
159
160 @Override
161 public Void visitNullReferenceExpression(NullReferenceExpression node, Void ignored) {
162 return recurse(node, ignored);
163 }
164
165 @Override
166 public Void visitThisReferenceExpression(ThisReferenceExpression node, Void ignored) {
167 return recurse(node, ignored);
168 }
169
170 @Override
171 public Void visitSuperReferenceExpression(SuperReferenceExpression node, Void ignored) {
172 return recurse(node, ignored);
173 }
174
175 @Override
176 public Void visitClassOfExpression(ClassOfExpression node, Void ignored) {
177 return recurse(node, ignored);
178 }
179
180 @Override
181 public Void visitBlockStatement(BlockStatement node, Void ignored) {
182 return recurse(node, ignored);
183 }
184
185 @Override
186 public Void visitExpressionStatement(ExpressionStatement node, Void ignored) {
187 return recurse(node, ignored);
188 }
189
190 @Override
191 public Void visitBreakStatement(BreakStatement node, Void ignored) {
192 return recurse(node, ignored);
193 }
194
195 @Override
196 public Void visitContinueStatement(ContinueStatement node, Void ignored) {
197 return recurse(node, ignored);
198 }
199
200 @Override
201 public Void visitDoWhileStatement(DoWhileStatement node, Void ignored) {
202 return recurse(node, ignored);
203 }
204
205 @Override
206 public Void visitEmptyStatement(EmptyStatement node, Void ignored) {
207 return recurse(node, ignored);
208 }
209
210 @Override
211 public Void visitIfElseStatement(IfElseStatement node, Void ignored) {
212 return recurse(node, ignored);
213 }
214
215 @Override
216 public Void visitLabelStatement(LabelStatement node, Void ignored) {
217 return recurse(node, ignored);
218 }
219
220 @Override
221 public Void visitLabeledStatement(LabeledStatement node, Void ignored) {
222 return recurse(node, ignored);
223 }
224
225 @Override
226 public Void visitReturnStatement(ReturnStatement node, Void ignored) {
227 return recurse(node, ignored);
228 }
229
230 @Override
231 public Void visitSwitchStatement(SwitchStatement node, Void ignored) {
232 return recurse(node, ignored);
233 }
234
235 @Override
236 public Void visitSwitchSection(SwitchSection node, Void ignored) {
237 return recurse(node, ignored);
238 }
239
240 @Override
241 public Void visitCaseLabel(CaseLabel node, Void ignored) {
242 return recurse(node, ignored);
243 }
244
245 @Override
246 public Void visitThrowStatement(ThrowStatement node, Void ignored) {
247 return recurse(node, ignored);
248 }
249
250 @Override
251 public Void visitCatchClause(CatchClause node, Void ignored) {
252 return recurse(node, ignored);
253 }
254
255 @Override
256 public Void visitAnnotation(Annotation node, Void ignored) {
257 return recurse(node, ignored);
258 }
259
260 @Override
261 public Void visitNewLine(NewLineNode node, Void ignored) {
262 return recurse(node, ignored);
263 }
264
265 @Override
266 public Void visitVariableDeclaration(VariableDeclarationStatement node, Void ignored) {
267 return recurse(node, ignored);
268 }
269
270 @Override
271 public Void visitVariableInitializer(VariableInitializer node, Void ignored) {
272 return recurse(node, ignored);
273 }
274
275 @Override
276 public Void visitText(TextNode node, Void ignored) {
277 return recurse(node, ignored);
278 }
279
280 @Override
281 public Void visitImportDeclaration(ImportDeclaration node, Void ignored) {
282 return recurse(node, ignored);
283 }
284
285 @Override
286 public Void visitInitializerBlock(InstanceInitializer node, Void ignored) {
287 return recurse(node, ignored);
288 }
289
290 @Override
291 public Void visitTypeParameterDeclaration(TypeParameterDeclaration node, Void ignored) {
292 return recurse(node, ignored);
293 }
294
295 @Override
296 public Void visitPackageDeclaration(PackageDeclaration node, Void ignored) {
297 return recurse(node, ignored);
298 }
299
300 @Override
301 public Void visitArraySpecifier(ArraySpecifier node, Void ignored) {
302 return recurse(node, ignored);
303 }
304
305 @Override
306 public Void visitComposedType(ComposedType node, Void ignored) {
307 return recurse(node, ignored);
308 }
309
310 @Override
311 public Void visitWhileStatement(WhileStatement node, Void ignored) {
312 return recurse(node, ignored);
313 }
314
315 @Override
316 public Void visitPrimitiveExpression(PrimitiveExpression node, Void ignored) {
317 return recurse(node, ignored);
318 }
319
320 @Override
321 public Void visitCastExpression(CastExpression node, Void ignored) {
322 return recurse(node, ignored);
323 }
324
325 @Override
326 public Void visitBinaryOperatorExpression(BinaryOperatorExpression node, Void ignored) {
327 return recurse(node, ignored);
328 }
329
330 @Override
331 public Void visitInstanceOfExpression(InstanceOfExpression node, Void ignored) {
332 return recurse(node, ignored);
333 }
334
335 @Override
336 public Void visitIndexerExpression(IndexerExpression node, Void ignored) {
337 return recurse(node, ignored);
338 }
339
340 @Override
341 public Void visitIdentifierExpression(IdentifierExpression node, Void ignored) {
342 return recurse(node, ignored);
343 }
344
345 @Override
346 public Void visitUnaryOperatorExpression(UnaryOperatorExpression node, Void ignored) {
347 return recurse(node, ignored);
348 }
349
350 @Override
351 public Void visitConditionalExpression(ConditionalExpression node, Void ignored) {
352 return recurse(node, ignored);
353 }
354
355 @Override
356 public Void visitArrayInitializerExpression(ArrayInitializerExpression node, Void ignored) {
357 return recurse(node, ignored);
358 }
359
360 @Override
361 public Void visitObjectCreationExpression(ObjectCreationExpression node, Void ignored) {
362 return recurse(node, ignored);
363 }
364
365 @Override
366 public Void visitArrayCreationExpression(ArrayCreationExpression node, Void ignored) {
367 return recurse(node, ignored);
368 }
369
370 @Override
371 public Void visitAssignmentExpression(AssignmentExpression node, Void ignored) {
372 return recurse(node, ignored);
373 }
374
375 @Override
376 public Void visitForStatement(ForStatement node, Void ignored) {
377 return recurse(node, ignored);
378 }
379
380 @Override
381 public Void visitForEachStatement(ForEachStatement node, Void ignored) {
382 return recurse(node, ignored);
383 }
384
385 @Override
386 public Void visitTryCatchStatement(TryCatchStatement node, Void ignored) {
387 return recurse(node, ignored);
388 }
389
390 @Override
391 public Void visitGotoStatement(GotoStatement node, Void ignored) {
392 return recurse(node, ignored);
393 }
394
395 @Override
396 public Void visitParenthesizedExpression(ParenthesizedExpression node, Void ignored) {
397 return recurse(node, ignored);
398 }
399
400 @Override
401 public Void visitSynchronizedStatement(SynchronizedStatement node, Void ignored) {
402 return recurse(node, ignored);
403 }
404
405 @Override
406 public Void visitAnonymousObjectCreationExpression(AnonymousObjectCreationExpression node, Void ignored) {
407 return recurse(node, ignored);
408 }
409
410 @Override
411 public Void visitWildcardType(WildcardType node, Void ignored) {
412 return recurse(node, ignored);
413 }
414
415 @Override
416 public Void visitMethodGroupExpression(MethodGroupExpression node, Void ignored) {
417 return recurse(node, ignored);
418 }
419
420 @Override
421 public Void visitEnumValueDeclaration(EnumValueDeclaration node, Void ignored) {
422 return recurse(node, ignored);
423 }
424
425 @Override
426 public Void visitAssertStatement(AssertStatement node, Void ignored) {
427 return recurse(node, ignored);
428 }
429
430 @Override
431 public Void visitLambdaExpression(LambdaExpression node, Void ignored) {
432 return recurse(node, ignored);
433 }
434
435 @Override
436 public Void visitLocalTypeDeclarationStatement(LocalTypeDeclarationStatement node, Void ignored) {
437 return recurse(node, ignored);
438 }
439} 93}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
index 4bce5333..a82df1b0 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
@@ -132,7 +132,7 @@ public class TranslationMethodVisitor extends MethodVisitor {
132 } 132 }
133 133
134 private String translateVariableName(int index, String name) { 134 private String translateVariableName(int index, String name) {
135 LocalVariableEntry entry = new LocalVariableEntry(methodEntry, index, "", true); 135 LocalVariableEntry entry = new LocalVariableEntry(methodEntry, index, "", true,null);
136 LocalVariableEntry translatedEntry = translator.translate(entry); 136 LocalVariableEntry translatedEntry = translator.translate(entry);
137 String translatedName = translatedEntry.getName(); 137 String translatedName = translatedEntry.getName();
138 138
diff --git a/src/main/java/cuchaz/enigma/gui/Gui.java b/src/main/java/cuchaz/enigma/gui/Gui.java
index 3ab1ceea..1ea3e44f 100644
--- a/src/main/java/cuchaz/enigma/gui/Gui.java
+++ b/src/main/java/cuchaz/enigma/gui/Gui.java
@@ -11,6 +11,7 @@
11 11
12package cuchaz.enigma.gui; 12package cuchaz.enigma.gui;
13 13
14import com.google.common.base.Strings;
14import com.google.common.collect.Lists; 15import com.google.common.collect.Lists;
15import cuchaz.enigma.Constants; 16import cuchaz.enigma.Constants;
16import cuchaz.enigma.EnigmaProfile; 17import cuchaz.enigma.EnigmaProfile;
@@ -19,6 +20,7 @@ import cuchaz.enigma.analysis.*;
19import cuchaz.enigma.config.Config; 20import cuchaz.enigma.config.Config;
20import cuchaz.enigma.config.Themes; 21import cuchaz.enigma.config.Themes;
21import cuchaz.enigma.gui.dialog.CrashDialog; 22import cuchaz.enigma.gui.dialog.CrashDialog;
23import cuchaz.enigma.gui.dialog.JavadocDialog;
22import cuchaz.enigma.gui.elements.MenuBar; 24import cuchaz.enigma.gui.elements.MenuBar;
23import cuchaz.enigma.gui.elements.PopupMenuBar; 25import cuchaz.enigma.gui.elements.PopupMenuBar;
24import cuchaz.enigma.gui.filechooser.FileChooserAny; 26import cuchaz.enigma.gui.filechooser.FileChooserAny;
@@ -82,6 +84,7 @@ public class Gui {
82 private JTabbedPane tabs; 84 private JTabbedPane tabs;
83 85
84 public JTextField renameTextField; 86 public JTextField renameTextField;
87 public JTextArea javadocTextArea;
85 88
86 public void setEditorTheme(Config.LookAndFeel feel) { 89 public void setEditorTheme(Config.LookAndFeel feel) {
87 if (editor != null && (editorFeel == null || editorFeel != feel)) { 90 if (editor != null && (editorFeel == null || editorFeel != feel)) {
@@ -559,6 +562,7 @@ public class Gui {
559 } 562 }
560 563
561 this.popupMenu.renameMenu.setEnabled(isRenamable); 564 this.popupMenu.renameMenu.setEnabled(isRenamable);
565 this.popupMenu.editJavadocMenu.setEnabled(isRenamable);
562 this.popupMenu.showInheritanceMenu.setEnabled(isClassEntry || isMethodEntry || isConstructorEntry); 566 this.popupMenu.showInheritanceMenu.setEnabled(isClassEntry || isMethodEntry || isConstructorEntry);
563 this.popupMenu.showImplementationsMenu.setEnabled(isClassEntry || isMethodEntry); 567 this.popupMenu.showImplementationsMenu.setEnabled(isClassEntry || isMethodEntry);
564 this.popupMenu.showCallsMenu.setEnabled(isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry); 568 this.popupMenu.showCallsMenu.setEnabled(isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry);
@@ -575,6 +579,47 @@ public class Gui {
575 } 579 }
576 } 580 }
577 581
582 public void startDocChange() {
583
584 // init the text box
585 javadocTextArea = new JTextArea(10, 40);
586
587 EntryReference<Entry<?>, Entry<?>> translatedReference = controller.project.getMapper().deobfuscate(cursorReference);
588 javadocTextArea.setText(Strings.nullToEmpty(translatedReference.entry.getJavadocs()));
589
590 JavadocDialog.init(frame, javadocTextArea, this::finishDocChange);
591 javadocTextArea.grabFocus();
592
593 redraw();
594 }
595
596 private void finishDocChange(JFrame ui, boolean saveName) {
597 String newName = javadocTextArea.getText();
598 if (saveName) {
599 try {
600 this.controller.changeDocs(cursorReference, newName);
601 } catch (IllegalNameException ex) {
602 javadocTextArea.setBorder(BorderFactory.createLineBorder(Color.red, 1));
603 javadocTextArea.setToolTipText(ex.getReason());
604 Utils.showToolTipNow(javadocTextArea);
605 return;
606 }
607
608 ui.setVisible(false);
609 showCursorReference(cursorReference);
610 return;
611 }
612
613 // abort the jd change
614 javadocTextArea = null;
615 ui.setVisible(false);
616 showCursorReference(cursorReference);
617
618 this.editor.grabFocus();
619
620 redraw();
621 }
622
578 public void startRename() { 623 public void startRename() {
579 624
580 // init the text box 625 // init the text box
diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java
index 69f12e2e..0b2fe27d 100644
--- a/src/main/java/cuchaz/enigma/gui/GuiController.java
+++ b/src/main/java/cuchaz/enigma/gui/GuiController.java
@@ -368,20 +368,29 @@ public class GuiController {
368 } 368 }
369 369
370 private void refreshCurrentClass(EntryReference<Entry<?>, Entry<?>> reference) { 370 private void refreshCurrentClass(EntryReference<Entry<?>, Entry<?>> reference) {
371 refreshCurrentClass(reference, false);
372 }
373
374 private void refreshCurrentClass(EntryReference<Entry<?>, Entry<?>> reference, boolean forceDecomp) {
371 if (currentSource != null) { 375 if (currentSource != null) {
372 loadClass(currentSource.getEntry(), () -> { 376 loadClass(currentSource.getEntry(), () -> {
373 if (reference != null) { 377 if (reference != null) {
374 showReference(reference); 378 showReference(reference);
375 } 379 }
376 }); 380 }, forceDecomp);
377 } 381 }
378 } 382 }
379 383
380 private void loadClass(ClassEntry classEntry, Runnable callback) { 384 private void loadClass(ClassEntry classEntry, Runnable callback) {
385 loadClass(classEntry, callback, false);
386 }
387
388 private void loadClass(ClassEntry classEntry, Runnable callback, boolean forceDecomp) {
381 ClassEntry targetClass = classEntry.getOutermostClass(); 389 ClassEntry targetClass = classEntry.getOutermostClass();
382 390
383 boolean requiresDecompile = currentSource == null || !currentSource.getEntry().equals(targetClass); 391 boolean requiresDecompile = forceDecomp || currentSource == null || !currentSource.getEntry().equals(targetClass);
384 if (requiresDecompile) { 392 if (requiresDecompile) {
393 currentSource = null; // Or the GUI may try to find a nonexistent token
385 gui.setEditorText("(decompiling...)"); 394 gui.setEditorText("(decompiling...)");
386 } 395 }
387 396
@@ -402,7 +411,7 @@ public class GuiController {
402 411
403 private DecompiledClassSource decompileSource(ClassEntry targetClass) { 412 private DecompiledClassSource decompileSource(ClassEntry targetClass) {
404 try { 413 try {
405 CompilationUnit sourceTree = sourceProvider.getSources(targetClass.getFullName()); 414 CompilationUnit sourceTree = (CompilationUnit) sourceProvider.getSources(targetClass.getFullName()).clone();
406 if (sourceTree == null) { 415 if (sourceTree == null) {
407 gui.setEditorText("Unable to find class: " + targetClass); 416 gui.setEditorText("Unable to find class: " + targetClass);
408 return DecompiledClassSource.text(targetClass, "Unable to find class"); 417 return DecompiledClassSource.text(targetClass, "Unable to find class");
@@ -410,6 +419,7 @@ public class GuiController {
410 419
411 DropImportAstTransform.INSTANCE.run(sourceTree); 420 DropImportAstTransform.INSTANCE.run(sourceTree);
412 DropVarModifiersAstTransform.INSTANCE.run(sourceTree); 421 DropVarModifiersAstTransform.INSTANCE.run(sourceTree);
422 new AddJavadocsAstTransform(project.getMapper()).run(sourceTree);
413 423
414 String sourceString = sourceProvider.writeSourceToString(sourceTree); 424 String sourceString = sourceProvider.writeSourceToString(sourceTree);
415 425
@@ -521,6 +531,25 @@ public class GuiController {
521 refreshCurrentClass(reference); 531 refreshCurrentClass(reference);
522 } 532 }
523 533
534 public void changeDocs(EntryReference<Entry<?>, Entry<?>> reference, String updatedDocs) {
535 changeDoc(reference.getNameableEntry(), updatedDocs);
536
537 refreshCurrentClass(reference, true);
538 }
539
540 public void changeDoc(Entry<?> obfEntry, String newDoc) {
541 EntryRemapper mapper = project.getMapper();
542 if (mapper.getDeobfMapping(obfEntry) == null) {
543 markAsDeobfuscated(obfEntry,false); // NPE
544 }
545 mapper.mapFromObf(obfEntry, mapper.getDeobfMapping(obfEntry).withDocs(newDoc), false);
546 }
547
548 public void markAsDeobfuscated(Entry<?> obfEntry, boolean renaming) {
549 EntryRemapper mapper = project.getMapper();
550 mapper.mapFromObf(obfEntry, new EntryMapping(mapper.deobfuscate(obfEntry).getName()), renaming);
551 }
552
524 public void markAsDeobfuscated(EntryReference<Entry<?>, Entry<?>> reference) { 553 public void markAsDeobfuscated(EntryReference<Entry<?>, Entry<?>> reference) {
525 EntryRemapper mapper = project.getMapper(); 554 EntryRemapper mapper = project.getMapper();
526 Entry<?> entry = reference.getNameableEntry(); 555 Entry<?> entry = reference.getNameableEntry();
diff --git a/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java
new file mode 100644
index 00000000..84e4d8fc
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java
@@ -0,0 +1,88 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 * <p>
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11
12package cuchaz.enigma.gui.dialog;
13
14import cuchaz.enigma.utils.Utils;
15
16import javax.swing.*;
17import java.awt.*;
18import java.awt.event.KeyAdapter;
19import java.awt.event.KeyEvent;
20
21public class JavadocDialog {
22
23 private static JavadocDialog instance = null;
24
25 private JFrame frame;
26
27 private JavadocDialog(JFrame parent, JTextArea text, Callback callback) {
28 // init frame
29 frame = new JFrame("Edit Javadocs");
30 final Container pane = frame.getContentPane();
31 pane.setLayout(new BorderLayout());
32
33 // editor panel
34 text.setTabSize(2);
35 pane.add(new JScrollPane(text), BorderLayout.CENTER);
36 text.addKeyListener(new KeyAdapter() {
37 @Override
38 public void keyPressed(KeyEvent event) {
39 switch (event.getKeyCode()) {
40 case KeyEvent.VK_ENTER:
41 if (event.isControlDown())
42 callback.closeUi(frame, true);
43 break;
44 case KeyEvent.VK_ESCAPE:
45 callback.closeUi(frame, false);
46 break;
47 default:
48 break;
49 }
50 }
51 });
52
53 // buttons panel
54 JPanel buttonsPanel = new JPanel();
55 FlowLayout buttonsLayout = new FlowLayout();
56 buttonsLayout.setAlignment(FlowLayout.RIGHT);
57 buttonsPanel.setLayout(buttonsLayout);
58 buttonsPanel.add(Utils.unboldLabel(new JLabel("Edit javadocs here.")));
59 JButton cancelButton = new JButton("Cancel");
60 cancelButton.addActionListener(event -> {
61 // close (hide) the dialog
62 callback.closeUi(frame, false);
63 });
64 buttonsPanel.add(cancelButton);
65 JButton saveButton = new JButton("Save");
66 saveButton.addActionListener(event -> {
67 // exit enigma
68 callback.closeUi(frame, true);
69 });
70 buttonsPanel.add(saveButton);
71 pane.add(buttonsPanel, BorderLayout.SOUTH);
72
73 // show the frame
74 frame.setSize(600, 400);
75 frame.setLocationRelativeTo(parent);
76 frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
77 }
78
79 public static void init(JFrame parent, JTextArea area, Callback callback) {
80 instance = new JavadocDialog(parent, area, callback);
81 instance.frame.doLayout();
82 instance.frame.setVisible(true);
83 }
84
85 public interface Callback {
86 void closeUi(JFrame frame, boolean save);
87 }
88}
diff --git a/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java
index fbf39ac6..b9d459f3 100644
--- a/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java
+++ b/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java
@@ -9,6 +9,7 @@ import java.awt.event.KeyEvent;
9public class PopupMenuBar extends JPopupMenu { 9public class PopupMenuBar extends JPopupMenu {
10 10
11 public final JMenuItem renameMenu; 11 public final JMenuItem renameMenu;
12 public final JMenuItem editJavadocMenu;
12 public final JMenuItem showInheritanceMenu; 13 public final JMenuItem showInheritanceMenu;
13 public final JMenuItem showImplementationsMenu; 14 public final JMenuItem showImplementationsMenu;
14 public final JMenuItem showCallsMenu; 15 public final JMenuItem showCallsMenu;
@@ -28,6 +29,14 @@ public class PopupMenuBar extends JPopupMenu {
28 this.renameMenu = menu; 29 this.renameMenu = menu;
29 } 30 }
30 { 31 {
32 JMenuItem menu = new JMenuItem("Edit Javadoc");
33 menu.addActionListener(event -> gui.startDocChange());
34 menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0));
35 menu.setEnabled(false);
36 this.add(menu);
37 this.editJavadocMenu = menu;
38 }
39 {
31 JMenuItem menu = new JMenuItem("Show Inheritance"); 40 JMenuItem menu = new JMenuItem("Show Inheritance");
32 menu.addActionListener(event -> gui.showInheritance()); 41 menu.addActionListener(event -> gui.showInheritance());
33 menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, 0)); 42 menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, 0));
diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java b/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java
index 9e29699b..71ee34cd 100644
--- a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java
+++ b/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java
@@ -87,6 +87,10 @@ public class PanelEditor extends JEditorPane {
87 gui.popupMenu.renameMenu.doClick(); 87 gui.popupMenu.renameMenu.doClick();
88 break; 88 break;
89 89
90 case KeyEvent.VK_D:
91 gui.popupMenu.editJavadocMenu.doClick();
92 break;
93
90 case KeyEvent.VK_F5: 94 case KeyEvent.VK_F5:
91 gui.getController().refreshCurrentClass(); 95 gui.getController().refreshCurrentClass();
92 break; 96 break;
diff --git a/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java b/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java
index 88ed96f4..a6e465d3 100644
--- a/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java
+++ b/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java
@@ -67,7 +67,7 @@ public class StatsGenerator {
67 if (includedMembers.contains(StatsMember.PARAMETERS)) { 67 if (includedMembers.contains(StatsMember.PARAMETERS)) {
68 int index = ((MethodDefEntry) method).getAccess().isStatic() ? 0 : 1; 68 int index = ((MethodDefEntry) method).getAccess().isStatic() ? 0 : 1;
69 for (TypeDescriptor argument : method.getDesc().getArgumentDescs()) { 69 for (TypeDescriptor argument : method.getDesc().getArgumentDescs()) {
70 update(counts, new LocalVariableEntry(method, index, "", true)); 70 update(counts, new LocalVariableEntry(method, index, "", true,null));
71 index += argument.getSize(); 71 index += argument.getSize();
72 } 72 }
73 } 73 }
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java b/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java
index b74cc0b3..c607817c 100644
--- a/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java
+++ b/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java
@@ -1,18 +1,29 @@
1package cuchaz.enigma.translation.mapping; 1package cuchaz.enigma.translation.mapping;
2 2
3import javax.annotation.Nonnull; 3import javax.annotation.Nonnull;
4import javax.annotation.Nullable;
4 5
5public class EntryMapping { 6public class EntryMapping {
6 private final String targetName; 7 private final String targetName;
7 private final AccessModifier accessModifier; 8 private final AccessModifier accessModifier;
9 private final @Nullable String javadoc;
8 10
9 public EntryMapping(@Nonnull String targetName) { 11 public EntryMapping(@Nonnull String targetName) {
10 this(targetName, AccessModifier.UNCHANGED); 12 this(targetName, AccessModifier.UNCHANGED);
11 } 13 }
12 14
15 public EntryMapping(@Nonnull String targetName, @Nullable String javadoc) {
16 this(targetName, AccessModifier.UNCHANGED, javadoc);
17 }
18
13 public EntryMapping(@Nonnull String targetName, AccessModifier accessModifier) { 19 public EntryMapping(@Nonnull String targetName, AccessModifier accessModifier) {
20 this(targetName, accessModifier, null);
21 }
22
23 public EntryMapping(@Nonnull String targetName, AccessModifier accessModifier, @Nullable String javadoc) {
14 this.targetName = targetName; 24 this.targetName = targetName;
15 this.accessModifier = accessModifier; 25 this.accessModifier = accessModifier;
26 this.javadoc = javadoc;
16 } 27 }
17 28
18 @Nonnull 29 @Nonnull
@@ -28,6 +39,23 @@ public class EntryMapping {
28 return accessModifier; 39 return accessModifier;
29 } 40 }
30 41
42 @Nullable
43 public String getJavadoc() {
44 return javadoc;
45 }
46
47 public EntryMapping withName(String newName) {
48 return new EntryMapping(newName, accessModifier, javadoc);
49 }
50
51 public EntryMapping withModifier(AccessModifier newModifier) {
52 return new EntryMapping(targetName, newModifier, javadoc);
53 }
54
55 public EntryMapping withDocs(String newDocs) {
56 return new EntryMapping(targetName, accessModifier, newDocs);
57 }
58
31 @Override 59 @Override
32 public boolean equals(Object obj) { 60 public boolean equals(Object obj) {
33 if (obj == this) return true; 61 if (obj == this) return true;
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java b/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java
index c9808cc9..ad36c97f 100644
--- a/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java
+++ b/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java
@@ -11,6 +11,7 @@ import cuchaz.enigma.translation.representation.entry.Entry;
11 11
12import javax.annotation.Nullable; 12import javax.annotation.Nullable;
13import java.util.Collection; 13import java.util.Collection;
14import java.util.function.UnaryOperator;
14import java.util.stream.Stream; 15import java.util.stream.Stream;
15 16
16public class EntryRemapper { 17public class EntryRemapper {
@@ -40,9 +41,13 @@ public class EntryRemapper {
40 } 41 }
41 42
42 public <E extends Entry<?>> void mapFromObf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping) { 43 public <E extends Entry<?>> void mapFromObf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping) {
43 Collection<E> resolvedEntries = obfResolver.resolveEntry(obfuscatedEntry, ResolutionStrategy.RESOLVE_ROOT); 44 mapFromObf(obfuscatedEntry, deobfMapping, true);
45 }
46
47 public <E extends Entry<?>> void mapFromObf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping, boolean renaming) {
48 Collection<E> resolvedEntries = obfResolver.resolveEntry(obfuscatedEntry, renaming ? ResolutionStrategy.RESOLVE_ROOT : ResolutionStrategy.RESOLVE_CLOSEST);
44 49
45 if (deobfMapping != null) { 50 if (renaming && deobfMapping != null) {
46 for (E resolvedEntry : resolvedEntries) { 51 for (E resolvedEntry : resolvedEntries) {
47 validator.validateRename(resolvedEntry, deobfMapping.getTargetName()); 52 validator.validateRename(resolvedEntry, deobfMapping.getTargetName());
48 } 53 }
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaFormat.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaFormat.java
new file mode 100644
index 00000000..af92ffbe
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaFormat.java
@@ -0,0 +1,9 @@
1package cuchaz.enigma.translation.mapping.serde;
2
3public class EnigmaFormat {
4 public static final String COMMENT = "COMMENT";
5 public static final String CLASS = "CLASS";
6 public static final String FIELD = "FIELD";
7 public static final String METHOD = "METHOD";
8 public static final String PARAMETER = "ARG";
9}
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java
index 1e4c442c..2c993f44 100644
--- a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java
@@ -64,7 +64,7 @@ public enum EnigmaMappingsReader implements MappingsReader {
64 64
65 protected void readFile(Path path, EntryTree<EntryMapping> mappings) throws IOException, MappingParseException { 65 protected void readFile(Path path, EntryTree<EntryMapping> mappings) throws IOException, MappingParseException {
66 List<String> lines = Files.readAllLines(path, Charsets.UTF_8); 66 List<String> lines = Files.readAllLines(path, Charsets.UTF_8);
67 Deque<Entry<?>> mappingStack = new ArrayDeque<>(); 67 Deque<MappingPair<?, RawEntryMapping>> mappingStack = new ArrayDeque<>();
68 68
69 for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { 69 for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) {
70 String line = lines.get(lineNumber); 70 String line = lines.get(lineNumber);
@@ -75,21 +75,33 @@ public enum EnigmaMappingsReader implements MappingsReader {
75 continue; 75 continue;
76 } 76 }
77 77
78 while (indentation < mappingStack.size()) { 78 cleanMappingStack(indentation, mappingStack, mappings);
79 mappingStack.pop();
80 }
81 79
82 try { 80 try {
83 MappingPair<?, EntryMapping> pair = parseLine(mappingStack.peek(), line); 81 MappingPair<?, RawEntryMapping> pair = parseLine(mappingStack.peek(), line);
84 mappingStack.push(pair.getEntry()); 82 if (pair != null) {
85 if (pair.getMapping() != null) { 83 mappingStack.push(pair);
86 mappings.insert(pair.getEntry(), pair.getMapping()); 84 if (pair.getMapping() != null) {
85
86 }
87 } 87 }
88 } catch (Throwable t) { 88 } catch (Throwable t) {
89 t.printStackTrace(); 89 t.printStackTrace();
90 throw new MappingParseException(path::toString, lineNumber, t.toString()); 90 throw new MappingParseException(path::toString, lineNumber, t.toString());
91 } 91 }
92 } 92 }
93
94 // Clean up rest
95 cleanMappingStack(0, mappingStack, mappings);
96 }
97
98 private void cleanMappingStack(int indentation, Deque<MappingPair<?, RawEntryMapping>> mappingStack, EntryTree<EntryMapping> mappings) {
99 while (indentation < mappingStack.size()) {
100 MappingPair<?, RawEntryMapping> pair = mappingStack.pop();
101 if (pair.getMapping() != null) {
102 mappings.insert(pair.getEntry(), pair.getMapping().bake());
103 }
104 }
93 } 105 }
94 106
95 @Nullable 107 @Nullable
@@ -123,25 +135,38 @@ public enum EnigmaMappingsReader implements MappingsReader {
123 return indent; 135 return indent;
124 } 136 }
125 137
126 private MappingPair<?, EntryMapping> parseLine(@Nullable Entry<?> parent, String line) { 138 private MappingPair<?, RawEntryMapping> parseLine(@Nullable MappingPair<?, RawEntryMapping> parent, String line) {
127 String[] tokens = line.trim().split("\\s"); 139 String[] tokens = line.trim().split("\\s");
128 String keyToken = tokens[0].toLowerCase(Locale.ROOT); 140 String keyToken = tokens[0].toUpperCase(Locale.ROOT);
141 Entry<?> parentEntry = parent == null ? null : parent.getEntry();
129 142
130 switch (keyToken) { 143 switch (keyToken) {
131 case "class": 144 case EnigmaFormat.CLASS:
132 return parseClass(parent, tokens); 145 return parseClass(parentEntry, tokens);
133 case "field": 146 case EnigmaFormat.FIELD:
134 return parseField(parent, tokens); 147 return parseField(parentEntry, tokens);
135 case "method": 148 case EnigmaFormat.METHOD:
136 return parseMethod(parent, tokens); 149 return parseMethod(parentEntry, tokens);
137 case "arg": 150 case EnigmaFormat.PARAMETER:
138 return parseArgument(parent, tokens); 151 return parseArgument(parentEntry, tokens);
152 case EnigmaFormat.COMMENT:
153 readJavadoc(parent, tokens);
154 return null;
139 default: 155 default:
140 throw new RuntimeException("Unknown token '" + keyToken + "'"); 156 throw new RuntimeException("Unknown token '" + keyToken + "'");
141 } 157 }
142 } 158 }
159
160 private void readJavadoc(MappingPair<?, RawEntryMapping> parent, String[] tokens) {
161 if (parent == null)
162 throw new IllegalStateException("Javadoc has no parent!");
163 String jdLine = tokens.length > 1 ? tokens[1] : ""; // Empty string to concat
164 if (parent.getMapping() == null)
165 throw new IllegalStateException("Javadoc requires a mapping!");
166 parent.getMapping().addJavadocLine(MappingHelper.unescape(jdLine));
167 }
143 168
144 private MappingPair<ClassEntry, EntryMapping> parseClass(@Nullable Entry<?> parent, String[] tokens) { 169 private MappingPair<ClassEntry, RawEntryMapping> parseClass(@Nullable Entry<?> parent, String[] tokens) {
145 String obfuscatedName = ClassEntry.getInnerName(tokens[1]); 170 String obfuscatedName = ClassEntry.getInnerName(tokens[1]);
146 ClassEntry obfuscatedEntry; 171 ClassEntry obfuscatedEntry;
147 if (parent instanceof ClassEntry) { 172 if (parent instanceof ClassEntry) {
@@ -167,13 +192,13 @@ public enum EnigmaMappingsReader implements MappingsReader {
167 } 192 }
168 193
169 if (mapping != null) { 194 if (mapping != null) {
170 return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping, modifier)); 195 return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier));
171 } else { 196 } else {
172 return new MappingPair<>(obfuscatedEntry); 197 return new MappingPair<>(obfuscatedEntry);
173 } 198 }
174 } 199 }
175 200
176 private MappingPair<FieldEntry, EntryMapping> parseField(@Nullable Entry<?> parent, String[] tokens) { 201 private MappingPair<FieldEntry, RawEntryMapping> parseField(@Nullable Entry<?> parent, String[] tokens) {
177 if (!(parent instanceof ClassEntry)) { 202 if (!(parent instanceof ClassEntry)) {
178 throw new RuntimeException("Field must be a child of a class!"); 203 throw new RuntimeException("Field must be a child of a class!");
179 } 204 }
@@ -204,13 +229,13 @@ public enum EnigmaMappingsReader implements MappingsReader {
204 229
205 FieldEntry obfuscatedEntry = new FieldEntry(ownerEntry, obfuscatedName, descriptor); 230 FieldEntry obfuscatedEntry = new FieldEntry(ownerEntry, obfuscatedName, descriptor);
206 if (mapping != null) { 231 if (mapping != null) {
207 return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping, modifier)); 232 return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier));
208 } else { 233 } else {
209 return new MappingPair<>(obfuscatedEntry); 234 return new MappingPair<>(obfuscatedEntry);
210 } 235 }
211 } 236 }
212 237
213 private MappingPair<MethodEntry, EntryMapping> parseMethod(@Nullable Entry<?> parent, String[] tokens) { 238 private MappingPair<MethodEntry, RawEntryMapping> parseMethod(@Nullable Entry<?> parent, String[] tokens) {
214 if (!(parent instanceof ClassEntry)) { 239 if (!(parent instanceof ClassEntry)) {
215 throw new RuntimeException("Method must be a child of a class!"); 240 throw new RuntimeException("Method must be a child of a class!");
216 } 241 }
@@ -244,22 +269,22 @@ public enum EnigmaMappingsReader implements MappingsReader {
244 269
245 MethodEntry obfuscatedEntry = new MethodEntry(ownerEntry, obfuscatedName, descriptor); 270 MethodEntry obfuscatedEntry = new MethodEntry(ownerEntry, obfuscatedName, descriptor);
246 if (mapping != null) { 271 if (mapping != null) {
247 return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping, modifier)); 272 return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier));
248 } else { 273 } else {
249 return new MappingPair<>(obfuscatedEntry); 274 return new MappingPair<>(obfuscatedEntry);
250 } 275 }
251 } 276 }
252 277
253 private MappingPair<LocalVariableEntry, EntryMapping> parseArgument(@Nullable Entry<?> parent, String[] tokens) { 278 private MappingPair<LocalVariableEntry, RawEntryMapping> parseArgument(@Nullable Entry<?> parent, String[] tokens) {
254 if (!(parent instanceof MethodEntry)) { 279 if (!(parent instanceof MethodEntry)) {
255 throw new RuntimeException("Method arg must be a child of a method!"); 280 throw new RuntimeException("Method arg must be a child of a method!");
256 } 281 }
257 282
258 MethodEntry ownerEntry = (MethodEntry) parent; 283 MethodEntry ownerEntry = (MethodEntry) parent;
259 LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerEntry, Integer.parseInt(tokens[1]), "", true); 284 LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerEntry, Integer.parseInt(tokens[1]), "", true, null);
260 String mapping = tokens[2]; 285 String mapping = tokens[2];
261 286
262 return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); 287 return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping));
263 } 288 }
264 289
265 @Nullable 290 @Nullable
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java
index 7199be88..f490b1da 100644
--- a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java
@@ -11,15 +11,6 @@
11 11
12package cuchaz.enigma.translation.mapping.serde; 12package cuchaz.enigma.translation.mapping.serde;
13 13
14import cuchaz.enigma.ProgressListener;
15import cuchaz.enigma.translation.MappingTranslator;
16import cuchaz.enigma.translation.Translator;
17import cuchaz.enigma.translation.mapping.*;
18import cuchaz.enigma.translation.mapping.tree.EntryTree;
19import cuchaz.enigma.translation.mapping.tree.EntryTreeNode;
20import cuchaz.enigma.translation.representation.entry.*;
21import cuchaz.enigma.utils.LFPrintWriter;
22
23import java.io.IOException; 14import java.io.IOException;
24import java.io.PrintWriter; 15import java.io.PrintWriter;
25import java.nio.file.DirectoryStream; 16import java.nio.file.DirectoryStream;
@@ -33,6 +24,24 @@ import java.util.concurrent.atomic.AtomicInteger;
33import java.util.stream.Collectors; 24import java.util.stream.Collectors;
34import java.util.stream.Stream; 25import java.util.stream.Stream;
35 26
27import cuchaz.enigma.ProgressListener;
28import cuchaz.enigma.translation.MappingTranslator;
29import cuchaz.enigma.translation.Translator;
30import cuchaz.enigma.translation.mapping.AccessModifier;
31import cuchaz.enigma.translation.mapping.EntryMapping;
32import cuchaz.enigma.translation.mapping.MappingDelta;
33import cuchaz.enigma.translation.mapping.MappingFileNameFormat;
34import cuchaz.enigma.translation.mapping.MappingSaveParameters;
35import cuchaz.enigma.translation.mapping.VoidEntryResolver;
36import cuchaz.enigma.translation.mapping.tree.EntryTree;
37import cuchaz.enigma.translation.mapping.tree.EntryTreeNode;
38import cuchaz.enigma.translation.representation.entry.ClassEntry;
39import cuchaz.enigma.translation.representation.entry.Entry;
40import cuchaz.enigma.translation.representation.entry.FieldEntry;
41import cuchaz.enigma.translation.representation.entry.LocalVariableEntry;
42import cuchaz.enigma.translation.representation.entry.MethodEntry;
43import cuchaz.enigma.utils.LFPrintWriter;
44
36public enum EnigmaMappingsWriter implements MappingsWriter { 45public enum EnigmaMappingsWriter implements MappingsWriter {
37 FILE { 46 FILE {
38 @Override 47 @Override
@@ -154,10 +163,26 @@ public enum EnigmaMappingsWriter implements MappingsWriter {
154 protected void writeRoot(PrintWriter writer, EntryTree<EntryMapping> mappings, ClassEntry classEntry) { 163 protected void writeRoot(PrintWriter writer, EntryTree<EntryMapping> mappings, ClassEntry classEntry) {
155 Collection<Entry<?>> children = groupChildren(mappings.getChildren(classEntry)); 164 Collection<Entry<?>> children = groupChildren(mappings.getChildren(classEntry));
156 165
157 writer.println(writeClass(classEntry, mappings.get(classEntry)).trim()); 166 EntryMapping classEntryMapping = mappings.get(classEntry);
167
168 writer.println(writeClass(classEntry, classEntryMapping).trim());
169 if (classEntryMapping != null && classEntryMapping.getJavadoc() != null) {
170 writeDocs(writer, classEntryMapping, 0);
171 }
172
158 for (Entry<?> child : children) { 173 for (Entry<?> child : children) {
159 writeEntry(writer, mappings, child, 1); 174 writeEntry(writer, mappings, child, 1);
160 } 175 }
176
177 }
178
179 private void writeDocs(PrintWriter writer, EntryMapping mapping, int depth) {
180 String jd = mapping.getJavadoc();
181 if (jd != null) {
182 for (String line : jd.split("\\R")) {
183 writer.println(indent(EnigmaFormat.COMMENT + " " + MappingHelper.escape(line), depth + 1));
184 }
185 }
161 } 186 }
162 187
163 protected void writeEntry(PrintWriter writer, EntryTree<EntryMapping> mappings, Entry<?> entry, int depth) { 188 protected void writeEntry(PrintWriter writer, EntryTree<EntryMapping> mappings, Entry<?> entry, int depth) {
@@ -167,6 +192,7 @@ public enum EnigmaMappingsWriter implements MappingsWriter {
167 } 192 }
168 193
169 EntryMapping mapping = node.getValue(); 194 EntryMapping mapping = node.getValue();
195
170 if (entry instanceof ClassEntry) { 196 if (entry instanceof ClassEntry) {
171 String line = writeClass((ClassEntry) entry, mapping); 197 String line = writeClass((ClassEntry) entry, mapping);
172 writer.println(indent(line, depth)); 198 writer.println(indent(line, depth));
@@ -180,6 +206,9 @@ public enum EnigmaMappingsWriter implements MappingsWriter {
180 String line = writeArgument((LocalVariableEntry) entry, mapping); 206 String line = writeArgument((LocalVariableEntry) entry, mapping);
181 writer.println(indent(line, depth)); 207 writer.println(indent(line, depth));
182 } 208 }
209 if (mapping != null && mapping.getJavadoc() != null) {
210 writeDocs(writer, mapping, depth);
211 }
183 212
184 Collection<Entry<?>> children = groupChildren(node.getChildren()); 213 Collection<Entry<?>> children = groupChildren(node.getChildren());
185 for (Entry<?> child : children) { 214 for (Entry<?> child : children) {
@@ -190,11 +219,6 @@ public enum EnigmaMappingsWriter implements MappingsWriter {
190 private Collection<Entry<?>> groupChildren(Collection<Entry<?>> children) { 219 private Collection<Entry<?>> groupChildren(Collection<Entry<?>> children) {
191 Collection<Entry<?>> result = new ArrayList<>(children.size()); 220 Collection<Entry<?>> result = new ArrayList<>(children.size());
192 221
193 children.stream().filter(e -> e instanceof ClassEntry)
194 .map(e -> (ClassEntry) e)
195 .sorted()
196 .forEach(result::add);
197
198 children.stream().filter(e -> e instanceof FieldEntry) 222 children.stream().filter(e -> e instanceof FieldEntry)
199 .map(e -> (FieldEntry) e) 223 .map(e -> (FieldEntry) e)
200 .sorted() 224 .sorted()
@@ -210,11 +234,16 @@ public enum EnigmaMappingsWriter implements MappingsWriter {
210 .sorted() 234 .sorted()
211 .forEach(result::add); 235 .forEach(result::add);
212 236
237 children.stream().filter(e -> e instanceof ClassEntry)
238 .map(e -> (ClassEntry) e)
239 .sorted()
240 .forEach(result::add);
241
213 return result; 242 return result;
214 } 243 }
215 244
216 protected String writeClass(ClassEntry entry, EntryMapping mapping) { 245 protected String writeClass(ClassEntry entry, EntryMapping mapping) {
217 StringBuilder builder = new StringBuilder("CLASS "); 246 StringBuilder builder = new StringBuilder(EnigmaFormat.CLASS +" ");
218 builder.append(entry.getName()).append(' '); 247 builder.append(entry.getName()).append(' ');
219 writeMapping(builder, mapping); 248 writeMapping(builder, mapping);
220 249
@@ -222,7 +251,7 @@ public enum EnigmaMappingsWriter implements MappingsWriter {
222 } 251 }
223 252
224 protected String writeMethod(MethodEntry entry, EntryMapping mapping) { 253 protected String writeMethod(MethodEntry entry, EntryMapping mapping) {
225 StringBuilder builder = new StringBuilder("METHOD "); 254 StringBuilder builder = new StringBuilder(EnigmaFormat.METHOD + " ");
226 builder.append(entry.getName()).append(' '); 255 builder.append(entry.getName()).append(' ');
227 writeMapping(builder, mapping); 256 writeMapping(builder, mapping);
228 257
@@ -232,7 +261,7 @@ public enum EnigmaMappingsWriter implements MappingsWriter {
232 } 261 }
233 262
234 protected String writeField(FieldEntry entry, EntryMapping mapping) { 263 protected String writeField(FieldEntry entry, EntryMapping mapping) {
235 StringBuilder builder = new StringBuilder("FIELD "); 264 StringBuilder builder = new StringBuilder(EnigmaFormat.FIELD + " ");
236 builder.append(entry.getName()).append(' '); 265 builder.append(entry.getName()).append(' ');
237 writeMapping(builder, mapping); 266 writeMapping(builder, mapping);
238 267
@@ -242,7 +271,7 @@ public enum EnigmaMappingsWriter implements MappingsWriter {
242 } 271 }
243 272
244 protected String writeArgument(LocalVariableEntry entry, EntryMapping mapping) { 273 protected String writeArgument(LocalVariableEntry entry, EntryMapping mapping) {
245 return "ARG " + entry.getIndex() + ' ' + mapping.getTargetName(); 274 return EnigmaFormat.PARAMETER + " " + entry.getIndex() + ' ' + mapping.getTargetName();
246 } 275 }
247 276
248 private void writeMapping(StringBuilder builder, EntryMapping mapping) { 277 private void writeMapping(StringBuilder builder, EntryMapping mapping) {
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java
index 7eae1c01..c04eec5e 100644
--- a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java
@@ -19,6 +19,7 @@ public enum MappingFormat {
19 SRG_FILE(SrgMappingsWriter.INSTANCE, null), 19 SRG_FILE(SrgMappingsWriter.INSTANCE, null),
20 PROGUARD(null, ProguardMappingsReader.INSTANCE); 20 PROGUARD(null, ProguardMappingsReader.INSTANCE);
21 21
22
22 private final MappingsWriter writer; 23 private final MappingsWriter writer;
23 private final MappingsReader reader; 24 private final MappingsReader reader;
24 25
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java
new file mode 100644
index 00000000..7c8f6cc6
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java
@@ -0,0 +1,51 @@
1package cuchaz.enigma.translation.mapping.serde;
2
3public final class MappingHelper {
4 private static final String TO_ESCAPE = "\\\n\r\0\t";
5 private static final String ESCAPED = "\\nr0t";
6
7 public static String escape(String raw) {
8 StringBuilder builder = new StringBuilder(raw.length() + 1);
9 for (int i = 0; i < raw.length(); i++) {
10 final char c = raw.charAt(i);
11 final int r = TO_ESCAPE.indexOf(c);
12 if (r < 0) {
13 builder.append(c);
14 } else {
15 builder.append('\\').append(ESCAPED.charAt(r));
16 }
17 }
18 return builder.toString();
19 }
20
21 public static String unescape(String str) {
22 int pos = str.indexOf('\\');
23 if (pos < 0) return str;
24
25 StringBuilder ret = new StringBuilder(str.length() - 1);
26 int start = 0;
27
28 do {
29 ret.append(str, start, pos);
30 pos++;
31 int type;
32
33 if (pos >= str.length()) {
34 throw new RuntimeException("incomplete escape sequence at the end");
35 } else if ((type = ESCAPED.indexOf(str.charAt(pos))) < 0) {
36 throw new RuntimeException("invalid escape character: \\" + str.charAt(pos));
37 } else {
38 ret.append(TO_ESCAPE.charAt(type));
39 }
40
41 start = pos + 1;
42 } while ((pos = str.indexOf('\\', start)) >= 0);
43
44 ret.append(str, start, str.length());
45
46 return ret.toString();
47 }
48
49 private MappingHelper() {
50 }
51}
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java
index 5d63f38f..afb40e9a 100644
--- a/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java
@@ -1,12 +1,15 @@
1package cuchaz.enigma.translation.mapping.serde; 1package cuchaz.enigma.translation.mapping.serde;
2 2
3import com.google.common.base.Strings;
4import cuchaz.enigma.translation.mapping.AccessModifier; 3import cuchaz.enigma.translation.mapping.AccessModifier;
5import cuchaz.enigma.translation.mapping.EntryMapping; 4import cuchaz.enigma.translation.mapping.EntryMapping;
6 5
6import java.util.ArrayList;
7import java.util.List;
8
7final class RawEntryMapping { 9final class RawEntryMapping {
8 private final String targetName; 10 private final String targetName;
9 private final AccessModifier access; 11 private final AccessModifier access;
12 private List<String> javadocs = new ArrayList<>();
10 13
11 RawEntryMapping(String targetName) { 14 RawEntryMapping(String targetName) {
12 this(targetName, null); 15 this(targetName, null);
@@ -17,7 +20,11 @@ final class RawEntryMapping {
17 this.targetName = targetName; 20 this.targetName = targetName;
18 } 21 }
19 22
23 void addJavadocLine(String line) {
24 javadocs.add(line);
25 }
26
20 EntryMapping bake() { 27 EntryMapping bake() {
21 return Strings.isNullOrEmpty(targetName) ? null : new EntryMapping(targetName, access); 28 return new EntryMapping(targetName, access, javadocs.isEmpty() ? null : String.join("\n", javadocs));
22 } 29 }
23} 30}
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java
index 81d181ba..aceb02f0 100644
--- a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java
@@ -108,7 +108,7 @@ public enum TinyMappingsReader implements MappingsReader {
108 int variableIndex = Integer.parseInt(tokens[4]); 108 int variableIndex = Integer.parseInt(tokens[4]);
109 109
110 String mapping = tokens[5]; 110 String mapping = tokens[5];
111 LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true); 111 LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true, null);
112 return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); 112 return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping));
113 } 113 }
114} 114}
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java
index 2621f310..c0488e93 100644
--- a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java
@@ -200,14 +200,6 @@ final class TinyV2Reader implements MappingsReader {
200 addJavadoc(pair, parts[1]); 200 addJavadoc(pair, parts[1]);
201 } 201 }
202 202
203 private void addJavadoc(MappingPair<? extends Entry, RawEntryMapping> pair, String javadoc) {
204 RawEntryMapping mapping = pair.getMapping();
205 if (mapping == null) {
206 throw new IllegalArgumentException("Javadoc requires a mapping in enigma!");
207 }
208// mapping.addJavadocLine(javadoc); todo javadocs
209 }
210
211 private MappingPair<ClassEntry, RawEntryMapping> parseClass(String[] tokens, boolean escapeNames) { 203 private MappingPair<ClassEntry, RawEntryMapping> parseClass(String[] tokens, boolean escapeNames) {
212 ClassEntry obfuscatedEntry = new ClassEntry(unescapeOpt(tokens[1], escapeNames)); 204 ClassEntry obfuscatedEntry = new ClassEntry(unescapeOpt(tokens[1], escapeNames));
213 if (tokens.length <= 2) 205 if (tokens.length <= 2)
@@ -239,13 +231,25 @@ final class TinyV2Reader implements MappingsReader {
239 return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); 231 return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping));
240 } 232 }
241 233
234
235
236 private void addJavadoc(MappingPair<? extends Entry, RawEntryMapping> pair, String javadoc) {
237 RawEntryMapping mapping = pair.getMapping();
238 if (mapping == null) {
239 throw new IllegalArgumentException("Javadoc requires a mapping in enigma!");
240 }
241 mapping.addJavadocLine(javadoc);
242 }
243
244
245
242 private MappingPair<LocalVariableEntry, RawEntryMapping> parseArgument(MappingPair<? extends Entry, RawEntryMapping> parent, String[] tokens, boolean escapeNames) { 246 private MappingPair<LocalVariableEntry, RawEntryMapping> parseArgument(MappingPair<? extends Entry, RawEntryMapping> parent, String[] tokens, boolean escapeNames) {
243 MethodEntry ownerMethod = (MethodEntry) parent.getEntry(); 247 MethodEntry ownerMethod = (MethodEntry) parent.getEntry();
244 int variableIndex = Integer.parseInt(tokens[1]); 248 int variableIndex = Integer.parseInt(tokens[1]);
245 249
246 // tokens[2] is the useless obf name 250 // tokens[2] is the useless obf name
247 251
248 LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true); 252 LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true, null);
249 if (tokens.length <= 3) 253 if (tokens.length <= 3)
250 return new MappingPair<>(obfuscatedEntry); 254 return new MappingPair<>(obfuscatedEntry);
251 String mapping = unescapeOpt(tokens[3], escapeNames); 255 String mapping = unescapeOpt(tokens[3], escapeNames);
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java
index a734ca2d..95e04c34 100644
--- a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java
@@ -155,12 +155,12 @@ public final class TinyV2Writer implements MappingsWriter {
155 } 155 }
156 156
157 private void writeComment(PrintWriter writer, EntryMapping mapping, int indent) { 157 private void writeComment(PrintWriter writer, EntryMapping mapping, int indent) {
158// if (mapping != null && mapping.getJavadoc() != null) { todo javadocs 158 if (mapping != null && mapping.getJavadoc() != null) {
159// writer.print(indent(indent)); 159 writer.print(indent(indent));
160// writer.print("c\t"); 160 writer.print("c\t");
161// writer.print(MappingHelper.escape(mapping.getJavadoc())); 161 writer.print(MappingHelper.escape(mapping.getJavadoc()));
162// writer.println(); 162 writer.println();
163// } 163 }
164 } 164 }
165 165
166 private String indent(int level) { 166 private String indent(int level) {
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java
index c4df891c..4b245bcb 100644
--- a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java
+++ b/src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java
@@ -28,11 +28,16 @@ public class ClassDefEntry extends ClassEntry implements DefEntry<ClassEntry> {
28 private final ClassEntry[] interfaces; 28 private final ClassEntry[] interfaces;
29 29
30 public ClassDefEntry(String className, Signature signature, AccessFlags access, @Nullable ClassEntry superClass, ClassEntry[] interfaces) { 30 public ClassDefEntry(String className, Signature signature, AccessFlags access, @Nullable ClassEntry superClass, ClassEntry[] interfaces) {
31 this(getOuterClass(className), getInnerName(className), signature, access, superClass, interfaces); 31 this(getOuterClass(className), getInnerName(className), signature, access, superClass, interfaces, null);
32 } 32 }
33 33
34 public ClassDefEntry(ClassEntry parent, String className, Signature signature, AccessFlags access, @Nullable ClassEntry superClass, ClassEntry[] interfaces) { 34 public ClassDefEntry(ClassEntry parent, String className, Signature signature, AccessFlags access, @Nullable ClassEntry superClass, ClassEntry[] interfaces) {
35 super(parent, className); 35 this(parent, className, signature, access, superClass, interfaces, null);
36 }
37
38 public ClassDefEntry(ClassEntry parent, String className, Signature signature, AccessFlags access, @Nullable ClassEntry superClass,
39 ClassEntry[] interfaces, String javadocs) {
40 super(parent, className, javadocs);
36 Preconditions.checkNotNull(signature, "Class signature cannot be null"); 41 Preconditions.checkNotNull(signature, "Class signature cannot be null");
37 Preconditions.checkNotNull(access, "Class access cannot be null"); 42 Preconditions.checkNotNull(access, "Class access cannot be null");
38 43
@@ -82,16 +87,17 @@ public class ClassDefEntry extends ClassEntry implements DefEntry<ClassEntry> {
82 AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access; 87 AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access;
83 ClassEntry translatedSuper = translator.translate(superClass); 88 ClassEntry translatedSuper = translator.translate(superClass);
84 ClassEntry[] translatedInterfaces = Arrays.stream(interfaces).map(translator::translate).toArray(ClassEntry[]::new); 89 ClassEntry[] translatedInterfaces = Arrays.stream(interfaces).map(translator::translate).toArray(ClassEntry[]::new);
85 return new ClassDefEntry(parent, translatedName, translatedSignature, translatedAccess, translatedSuper, translatedInterfaces); 90 String docs = mapping != null ? mapping.getJavadoc() : null;
91 return new ClassDefEntry(parent, translatedName, translatedSignature, translatedAccess, translatedSuper, translatedInterfaces, docs);
86 } 92 }
87 93
88 @Override 94 @Override
89 public ClassDefEntry withName(String name) { 95 public ClassDefEntry withName(String name) {
90 return new ClassDefEntry(parent, name, signature, access, superClass, interfaces); 96 return new ClassDefEntry(parent, name, signature, access, superClass, interfaces, javadocs);
91 } 97 }
92 98
93 @Override 99 @Override
94 public ClassDefEntry withParent(ClassEntry parent) { 100 public ClassDefEntry withParent(ClassEntry parent) {
95 return new ClassDefEntry(parent, name, signature, access, superClass, interfaces); 101 return new ClassDefEntry(parent, name, signature, access, superClass, interfaces, javadocs);
96 } 102 }
97} 103}
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java
index 6bf4f964..23ce4a24 100644
--- a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java
+++ b/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java
@@ -27,11 +27,15 @@ public class ClassEntry extends ParentedEntry<ClassEntry> implements Comparable<
27 private final String fullName; 27 private final String fullName;
28 28
29 public ClassEntry(String className) { 29 public ClassEntry(String className) {
30 this(getOuterClass(className), getInnerName(className)); 30 this(getOuterClass(className), getInnerName(className), null);
31 } 31 }
32 32
33 public ClassEntry(@Nullable ClassEntry parent, String className) { 33 public ClassEntry(@Nullable ClassEntry parent, String className) {
34 super(parent, className); 34 this(parent, className, null);
35 }
36
37 public ClassEntry(@Nullable ClassEntry parent, String className, @Nullable String javadocs) {
38 super(parent, className, javadocs);
35 if (parent != null) { 39 if (parent != null) {
36 fullName = parent.getFullName() + "$" + name; 40 fullName = parent.getFullName() + "$" + name;
37 } else { 41 } else {
@@ -69,7 +73,8 @@ public class ClassEntry extends ParentedEntry<ClassEntry> implements Comparable<
69 } 73 }
70 74
71 String translatedName = mapping != null ? mapping.getTargetName() : name; 75 String translatedName = mapping != null ? mapping.getTargetName() : name;
72 return new ClassEntry(parent, translatedName); 76 String docs = mapping != null ? mapping.getJavadoc() : null;
77 return new ClassEntry(parent, translatedName, docs);
73 } 78 }
74 79
75 @Override 80 @Override
@@ -103,12 +108,12 @@ public class ClassEntry extends ParentedEntry<ClassEntry> implements Comparable<
103 108
104 @Override 109 @Override
105 public ClassEntry withName(String name) { 110 public ClassEntry withName(String name) {
106 return new ClassEntry(parent, name); 111 return new ClassEntry(parent, name, javadocs);
107 } 112 }
108 113
109 @Override 114 @Override
110 public ClassEntry withParent(ClassEntry parent) { 115 public ClassEntry withParent(ClassEntry parent) {
111 return new ClassEntry(parent, name); 116 return new ClassEntry(parent, name, javadocs);
112 } 117 }
113 118
114 @Override 119 @Override
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java
index 29a55d89..72b03913 100644
--- a/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java
+++ b/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java
@@ -22,6 +22,8 @@ import java.util.List;
22public interface Entry<P extends Entry<?>> extends Translatable { 22public interface Entry<P extends Entry<?>> extends Translatable {
23 String getName(); 23 String getName();
24 24
25 String getJavadocs();
26
25 default String getSourceRemapName() { 27 default String getSourceRemapName() {
26 return getName(); 28 return getName();
27 } 29 }
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java
index 74176fda..46c0b003 100644
--- a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java
+++ b/src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java
@@ -26,7 +26,11 @@ public class FieldDefEntry extends FieldEntry implements DefEntry<ClassEntry> {
26 private final Signature signature; 26 private final Signature signature;
27 27
28 public FieldDefEntry(ClassEntry owner, String name, TypeDescriptor desc, Signature signature, AccessFlags access) { 28 public FieldDefEntry(ClassEntry owner, String name, TypeDescriptor desc, Signature signature, AccessFlags access) {
29 super(owner, name, desc); 29 this(owner, name, desc, signature, access, null);
30 }
31
32 public FieldDefEntry(ClassEntry owner, String name, TypeDescriptor desc, Signature signature, AccessFlags access, String javadocs) {
33 super(owner, name, desc, javadocs);
30 Preconditions.checkNotNull(access, "Field access cannot be null"); 34 Preconditions.checkNotNull(access, "Field access cannot be null");
31 Preconditions.checkNotNull(signature, "Field signature cannot be null"); 35 Preconditions.checkNotNull(signature, "Field signature cannot be null");
32 this.access = access; 36 this.access = access;
@@ -34,7 +38,7 @@ public class FieldDefEntry extends FieldEntry implements DefEntry<ClassEntry> {
34 } 38 }
35 39
36 public static FieldDefEntry parse(ClassEntry owner, int access, String name, String desc, String signature) { 40 public static FieldDefEntry parse(ClassEntry owner, int access, String name, String desc, String signature) {
37 return new FieldDefEntry(owner, name, new TypeDescriptor(desc), Signature.createTypedSignature(signature), new AccessFlags(access)); 41 return new FieldDefEntry(owner, name, new TypeDescriptor(desc), Signature.createTypedSignature(signature), new AccessFlags(access), null);
38 } 42 }
39 43
40 public static FieldDefEntry parse(FieldDefinition definition) { 44 public static FieldDefEntry parse(FieldDefinition definition) {
@@ -42,7 +46,7 @@ public class FieldDefEntry extends FieldEntry implements DefEntry<ClassEntry> {
42 TypeDescriptor descriptor = new TypeDescriptor(definition.getErasedSignature()); 46 TypeDescriptor descriptor = new TypeDescriptor(definition.getErasedSignature());
43 Signature signature = Signature.createTypedSignature(definition.getSignature()); 47 Signature signature = Signature.createTypedSignature(definition.getSignature());
44 AccessFlags access = new AccessFlags(definition.getModifiers()); 48 AccessFlags access = new AccessFlags(definition.getModifiers());
45 return new FieldDefEntry(owner, definition.getName(), descriptor, signature, access); 49 return new FieldDefEntry(owner, definition.getName(), descriptor, signature, access, null);
46 } 50 }
47 51
48 @Override 52 @Override
@@ -60,16 +64,17 @@ public class FieldDefEntry extends FieldEntry implements DefEntry<ClassEntry> {
60 Signature translatedSignature = translator.translate(signature); 64 Signature translatedSignature = translator.translate(signature);
61 String translatedName = mapping != null ? mapping.getTargetName() : name; 65 String translatedName = mapping != null ? mapping.getTargetName() : name;
62 AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access; 66 AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access;
63 return new FieldDefEntry(parent, translatedName, translatedDesc, translatedSignature, translatedAccess); 67 String docs = mapping != null ? mapping.getJavadoc() : null;
68 return new FieldDefEntry(parent, translatedName, translatedDesc, translatedSignature, translatedAccess, docs);
64 } 69 }
65 70
66 @Override 71 @Override
67 public FieldDefEntry withName(String name) { 72 public FieldDefEntry withName(String name) {
68 return new FieldDefEntry(parent, name, desc, signature, access); 73 return new FieldDefEntry(parent, name, desc, signature, access, javadocs);
69 } 74 }
70 75
71 @Override 76 @Override
72 public FieldDefEntry withParent(ClassEntry owner) { 77 public FieldDefEntry withParent(ClassEntry owner) {
73 return new FieldDefEntry(owner, this.name, this.desc, signature, access); 78 return new FieldDefEntry(owner, this.name, this.desc, signature, access, javadocs);
74 } 79 }
75} 80}
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java
index 700512e2..bef0edf4 100644
--- a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java
+++ b/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java
@@ -23,7 +23,11 @@ public class FieldEntry extends ParentedEntry<ClassEntry> implements Comparable<
23 protected final TypeDescriptor desc; 23 protected final TypeDescriptor desc;
24 24
25 public FieldEntry(ClassEntry parent, String name, TypeDescriptor desc) { 25 public FieldEntry(ClassEntry parent, String name, TypeDescriptor desc) {
26 super(parent, name); 26 this(parent, name, desc, null);
27 }
28
29 public FieldEntry(ClassEntry parent, String name, TypeDescriptor desc, String javadocs) {
30 super(parent, name, javadocs);
27 31
28 Preconditions.checkNotNull(parent, "Owner cannot be null"); 32 Preconditions.checkNotNull(parent, "Owner cannot be null");
29 Preconditions.checkNotNull(desc, "Field descriptor cannot be null"); 33 Preconditions.checkNotNull(desc, "Field descriptor cannot be null");
@@ -32,7 +36,7 @@ public class FieldEntry extends ParentedEntry<ClassEntry> implements Comparable<
32 } 36 }
33 37
34 public static FieldEntry parse(String owner, String name, String desc) { 38 public static FieldEntry parse(String owner, String name, String desc) {
35 return new FieldEntry(new ClassEntry(owner), name, new TypeDescriptor(desc)); 39 return new FieldEntry(new ClassEntry(owner), name, new TypeDescriptor(desc), null);
36 } 40 }
37 41
38 @Override 42 @Override
@@ -46,18 +50,19 @@ public class FieldEntry extends ParentedEntry<ClassEntry> implements Comparable<
46 50
47 @Override 51 @Override
48 public FieldEntry withName(String name) { 52 public FieldEntry withName(String name) {
49 return new FieldEntry(parent, name, desc); 53 return new FieldEntry(parent, name, desc, null);
50 } 54 }
51 55
52 @Override 56 @Override
53 public FieldEntry withParent(ClassEntry parent) { 57 public FieldEntry withParent(ClassEntry parent) {
54 return new FieldEntry(parent, this.name, this.desc); 58 return new FieldEntry(parent, this.name, this.desc, null);
55 } 59 }
56 60
57 @Override 61 @Override
58 protected FieldEntry translate(Translator translator, @Nullable EntryMapping mapping) { 62 protected FieldEntry translate(Translator translator, @Nullable EntryMapping mapping) {
59 String translatedName = mapping != null ? mapping.getTargetName() : name; 63 String translatedName = mapping != null ? mapping.getTargetName() : name;
60 return new FieldEntry(parent, translatedName, translator.translate(desc)); 64 String docs = mapping != null ? mapping.getJavadoc() : null;
65 return new FieldEntry(parent, translatedName, translator.translate(desc), docs);
61 } 66 }
62 67
63 @Override 68 @Override
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java
index c6f32b62..aad4236d 100644
--- a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java
+++ b/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java
@@ -15,8 +15,8 @@ import javax.annotation.Nullable;
15public class LocalVariableDefEntry extends LocalVariableEntry { 15public class LocalVariableDefEntry extends LocalVariableEntry {
16 protected final TypeDescriptor desc; 16 protected final TypeDescriptor desc;
17 17
18 public LocalVariableDefEntry(MethodEntry ownerEntry, int index, String name, boolean parameter, TypeDescriptor desc) { 18 public LocalVariableDefEntry(MethodEntry ownerEntry, int index, String name, boolean parameter, TypeDescriptor desc, String javadoc) {
19 super(ownerEntry, index, name, parameter); 19 super(ownerEntry, index, name, parameter, javadoc);
20 Preconditions.checkNotNull(desc, "Variable desc cannot be null"); 20 Preconditions.checkNotNull(desc, "Variable desc cannot be null");
21 21
22 this.desc = desc; 22 this.desc = desc;
@@ -30,17 +30,18 @@ public class LocalVariableDefEntry extends LocalVariableEntry {
30 public LocalVariableDefEntry translate(Translator translator, @Nullable EntryMapping mapping) { 30 public LocalVariableDefEntry translate(Translator translator, @Nullable EntryMapping mapping) {
31 TypeDescriptor translatedDesc = translator.translate(desc); 31 TypeDescriptor translatedDesc = translator.translate(desc);
32 String translatedName = mapping != null ? mapping.getTargetName() : name; 32 String translatedName = mapping != null ? mapping.getTargetName() : name;
33 return new LocalVariableDefEntry(parent, index, translatedName, parameter, translatedDesc); 33 String javadoc = mapping != null ? mapping.getJavadoc() : javadocs;
34 return new LocalVariableDefEntry(parent, index, translatedName, parameter, translatedDesc, javadoc);
34 } 35 }
35 36
36 @Override 37 @Override
37 public LocalVariableDefEntry withName(String name) { 38 public LocalVariableDefEntry withName(String name) {
38 return new LocalVariableDefEntry(parent, index, name, parameter, desc); 39 return new LocalVariableDefEntry(parent, index, name, parameter, desc, javadocs);
39 } 40 }
40 41
41 @Override 42 @Override
42 public LocalVariableDefEntry withParent(MethodEntry entry) { 43 public LocalVariableDefEntry withParent(MethodEntry entry) {
43 return new LocalVariableDefEntry(entry, index, name, parameter, desc); 44 return new LocalVariableDefEntry(entry, index, name, parameter, desc, javadocs);
44 } 45 }
45 46
46 @Override 47 @Override
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java
index 6fdb79fe..3ccb1fa1 100644
--- a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java
+++ b/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java
@@ -17,8 +17,8 @@ public class LocalVariableEntry extends ParentedEntry<MethodEntry> implements Co
17 protected final int index; 17 protected final int index;
18 protected final boolean parameter; 18 protected final boolean parameter;
19 19
20 public LocalVariableEntry(MethodEntry parent, int index, String name, boolean parameter) { 20 public LocalVariableEntry(MethodEntry parent, int index, String name, boolean parameter, String javadoc) {
21 super(parent, name); 21 super(parent, name, javadoc);
22 22
23 Preconditions.checkNotNull(parent, "Variable owner cannot be null"); 23 Preconditions.checkNotNull(parent, "Variable owner cannot be null");
24 Preconditions.checkArgument(index >= 0, "Index must be positive"); 24 Preconditions.checkArgument(index >= 0, "Index must be positive");
@@ -48,17 +48,18 @@ public class LocalVariableEntry extends ParentedEntry<MethodEntry> implements Co
48 @Override 48 @Override
49 public LocalVariableEntry translate(Translator translator, @Nullable EntryMapping mapping) { 49 public LocalVariableEntry translate(Translator translator, @Nullable EntryMapping mapping) {
50 String translatedName = mapping != null ? mapping.getTargetName() : name; 50 String translatedName = mapping != null ? mapping.getTargetName() : name;
51 return new LocalVariableEntry(parent, index, translatedName, parameter); 51 String javadoc = mapping != null ? mapping.getJavadoc() : null;
52 return new LocalVariableEntry(parent, index, translatedName, parameter, javadoc);
52 } 53 }
53 54
54 @Override 55 @Override
55 public LocalVariableEntry withName(String name) { 56 public LocalVariableEntry withName(String name) {
56 return new LocalVariableEntry(parent, index, name, parameter); 57 return new LocalVariableEntry(parent, index, name, parameter, javadocs);
57 } 58 }
58 59
59 @Override 60 @Override
60 public LocalVariableEntry withParent(MethodEntry parent) { 61 public LocalVariableEntry withParent(MethodEntry parent) {
61 return new LocalVariableEntry(parent, index, name, parameter); 62 return new LocalVariableEntry(parent, index, name, parameter, javadocs);
62 } 63 }
63 64
64 @Override 65 @Override
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java
index 7e89f6a6..280b605d 100644
--- a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java
+++ b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java
@@ -26,7 +26,11 @@ public class MethodDefEntry extends MethodEntry implements DefEntry<ClassEntry>
26 private final Signature signature; 26 private final Signature signature;
27 27
28 public MethodDefEntry(ClassEntry owner, String name, MethodDescriptor descriptor, Signature signature, AccessFlags access) { 28 public MethodDefEntry(ClassEntry owner, String name, MethodDescriptor descriptor, Signature signature, AccessFlags access) {
29 super(owner, name, descriptor); 29 this(owner, name, descriptor, signature, access, null);
30 }
31
32 public MethodDefEntry(ClassEntry owner, String name, MethodDescriptor descriptor, Signature signature, AccessFlags access, String docs) {
33 super(owner, name, descriptor, docs);
30 Preconditions.checkNotNull(access, "Method access cannot be null"); 34 Preconditions.checkNotNull(access, "Method access cannot be null");
31 Preconditions.checkNotNull(signature, "Method signature cannot be null"); 35 Preconditions.checkNotNull(signature, "Method signature cannot be null");
32 this.access = access; 36 this.access = access;
@@ -34,7 +38,7 @@ public class MethodDefEntry extends MethodEntry implements DefEntry<ClassEntry>
34 } 38 }
35 39
36 public static MethodDefEntry parse(ClassEntry owner, int access, String name, String desc, String signature) { 40 public static MethodDefEntry parse(ClassEntry owner, int access, String name, String desc, String signature) {
37 return new MethodDefEntry(owner, name, new MethodDescriptor(desc), Signature.createSignature(signature), new AccessFlags(access)); 41 return new MethodDefEntry(owner, name, new MethodDescriptor(desc), Signature.createSignature(signature), new AccessFlags(access), null);
38 } 42 }
39 43
40 public static MethodDefEntry parse(MethodDefinition definition) { 44 public static MethodDefEntry parse(MethodDefinition definition) {
@@ -42,7 +46,7 @@ public class MethodDefEntry extends MethodEntry implements DefEntry<ClassEntry>
42 MethodDescriptor descriptor = new MethodDescriptor(definition.getErasedSignature()); 46 MethodDescriptor descriptor = new MethodDescriptor(definition.getErasedSignature());
43 Signature signature = Signature.createSignature(definition.getSignature()); 47 Signature signature = Signature.createSignature(definition.getSignature());
44 AccessFlags access = new AccessFlags(definition.getModifiers()); 48 AccessFlags access = new AccessFlags(definition.getModifiers());
45 return new MethodDefEntry(classEntry, definition.getName(), descriptor, signature, access); 49 return new MethodDefEntry(classEntry, definition.getName(), descriptor, signature, access, null);
46 } 50 }
47 51
48 @Override 52 @Override
@@ -60,16 +64,17 @@ public class MethodDefEntry extends MethodEntry implements DefEntry<ClassEntry>
60 Signature translatedSignature = translator.translate(signature); 64 Signature translatedSignature = translator.translate(signature);
61 String translatedName = mapping != null ? mapping.getTargetName() : name; 65 String translatedName = mapping != null ? mapping.getTargetName() : name;
62 AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access; 66 AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access;
63 return new MethodDefEntry(parent, translatedName, translatedDesc, translatedSignature, translatedAccess); 67 String docs = mapping != null ? mapping.getJavadoc() : null;
68 return new MethodDefEntry(parent, translatedName, translatedDesc, translatedSignature, translatedAccess, docs);
64 } 69 }
65 70
66 @Override 71 @Override
67 public MethodDefEntry withName(String name) { 72 public MethodDefEntry withName(String name) {
68 return new MethodDefEntry(parent, name, descriptor, signature, access); 73 return new MethodDefEntry(parent, name, descriptor, signature, access, javadocs);
69 } 74 }
70 75
71 @Override 76 @Override
72 public MethodDefEntry withParent(ClassEntry parent) { 77 public MethodDefEntry withParent(ClassEntry parent) {
73 return new MethodDefEntry(new ClassEntry(parent.getFullName()), name, descriptor, signature, access); 78 return new MethodDefEntry(new ClassEntry(parent.getFullName()), name, descriptor, signature, access, javadocs);
74 } 79 }
75} 80}
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java
index f5d5c744..e1ffad37 100644
--- a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java
+++ b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java
@@ -24,7 +24,11 @@ public class MethodEntry extends ParentedEntry<ClassEntry> implements Comparable
24 protected final MethodDescriptor descriptor; 24 protected final MethodDescriptor descriptor;
25 25
26 public MethodEntry(ClassEntry parent, String name, MethodDescriptor descriptor) { 26 public MethodEntry(ClassEntry parent, String name, MethodDescriptor descriptor) {
27 super(parent, name); 27 this(parent, name, descriptor, null);
28 }
29
30 public MethodEntry(ClassEntry parent, String name, MethodDescriptor descriptor, String javadocs) {
31 super(parent, name, javadocs);
28 32
29 Preconditions.checkNotNull(parent, "Parent cannot be null"); 33 Preconditions.checkNotNull(parent, "Parent cannot be null");
30 Preconditions.checkNotNull(descriptor, "Method descriptor cannot be null"); 34 Preconditions.checkNotNull(descriptor, "Method descriptor cannot be null");
@@ -33,7 +37,7 @@ public class MethodEntry extends ParentedEntry<ClassEntry> implements Comparable
33 } 37 }
34 38
35 public static MethodEntry parse(String owner, String name, String desc) { 39 public static MethodEntry parse(String owner, String name, String desc) {
36 return new MethodEntry(new ClassEntry(owner), name, new MethodDescriptor(desc)); 40 return new MethodEntry(new ClassEntry(owner), name, new MethodDescriptor(desc), null);
37 } 41 }
38 42
39 @Override 43 @Override
@@ -52,17 +56,18 @@ public class MethodEntry extends ParentedEntry<ClassEntry> implements Comparable
52 @Override 56 @Override
53 public MethodEntry translate(Translator translator, @Nullable EntryMapping mapping) { 57 public MethodEntry translate(Translator translator, @Nullable EntryMapping mapping) {
54 String translatedName = mapping != null ? mapping.getTargetName() : name; 58 String translatedName = mapping != null ? mapping.getTargetName() : name;
55 return new MethodEntry(parent, translatedName, translator.translate(descriptor)); 59 String docs = mapping != null ? mapping.getJavadoc() : null;
60 return new MethodEntry(parent, translatedName, translator.translate(descriptor), docs);
56 } 61 }
57 62
58 @Override 63 @Override
59 public MethodEntry withName(String name) { 64 public MethodEntry withName(String name) {
60 return new MethodEntry(parent, name, descriptor); 65 return new MethodEntry(parent, name, descriptor, javadocs);
61 } 66 }
62 67
63 @Override 68 @Override
64 public MethodEntry withParent(ClassEntry parent) { 69 public MethodEntry withParent(ClassEntry parent) {
65 return new MethodEntry(new ClassEntry(parent.getFullName()), name, descriptor); 70 return new MethodEntry(new ClassEntry(parent.getFullName()), name, descriptor, javadocs);
66 } 71 }
67 72
68 @Override 73 @Override
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java
index b753d3a3..cbc5faf5 100644
--- a/src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java
+++ b/src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java
@@ -24,10 +24,12 @@ import javax.annotation.Nullable;
24public abstract class ParentedEntry<P extends Entry<?>> implements Entry<P> { 24public abstract class ParentedEntry<P extends Entry<?>> implements Entry<P> {
25 protected final P parent; 25 protected final P parent;
26 protected final String name; 26 protected final String name;
27 protected final @Nullable String javadocs;
27 28
28 protected ParentedEntry(P parent, String name) { 29 protected ParentedEntry(P parent, String name, String javadocs) {
29 this.parent = parent; 30 this.parent = parent;
30 this.name = name; 31 this.name = name;
32 this.javadocs = javadocs;
31 33
32 Preconditions.checkNotNull(name, "Name cannot be null"); 34 Preconditions.checkNotNull(name, "Name cannot be null");
33 } 35 }
@@ -51,6 +53,12 @@ public abstract class ParentedEntry<P extends Entry<?>> implements Entry<P> {
51 return parent; 53 return parent;
52 } 54 }
53 55
56 @Nullable
57 @Override
58 public String getJavadocs() {
59 return javadocs;
60 }
61
54 @Override 62 @Override
55 public ParentedEntry<P> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) { 63 public ParentedEntry<P> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) {
56 P parent = getParent(); 64 P parent = getParent();