summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/translation
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/java/cuchaz/enigma/translation
parentCorrectly decompile bridges, and add command to add bridges to mappings (#180) (diff)
downloadenigma-fork-a9e03fa0e75b5b338021de982acbbb8277e08706.tar.gz
enigma-fork-a9e03fa0e75b5b338021de982acbbb8277e08706.tar.xz
enigma-fork-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/java/cuchaz/enigma/translation')
-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
21 files changed, 311 insertions, 109 deletions
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java b/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java
index b74cc0b..c607817 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 c9808cc..ad36c97 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 0000000..af92ffb
--- /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 1e4c442..2c993f4 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 7199be8..f490b1d 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 7eae1c0..c04eec5 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 0000000..7c8f6cc
--- /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 5d63f38..afb40e9 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 81d181b..aceb02f 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 2621f31..c0488e9 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 a734ca2..95e04c3 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 c4df891..4b245bc 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 6bf4f96..23ce4a2 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 29a55d8..72b0391 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 74176fd..46c0b00 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 700512e..bef0edf 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 c6f32b6..aad4236 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 6fdb79f..3ccb1fa 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 7e89f6a..280b605 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 f5d5c74..e1ffad3 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 b753d3a..cbc5faf 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();