diff options
| author | 2019-12-02 15:43:23 +0200 | |
|---|---|---|
| committer | 2019-12-02 13:43:23 +0000 | |
| commit | a9e03fa0e75b5b338021de982acbbb8277e08706 (patch) | |
| tree | 94233d173c5937584a3376895bf864fb24697a8c /src/main/java/cuchaz/enigma/translation/mapping | |
| parent | Correctly decompile bridges, and add command to add bridges to mappings (#180) (diff) | |
| download | enigma-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/mapping')
11 files changed, 225 insertions, 66 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 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping; | 1 | package cuchaz.enigma.translation.mapping; |
| 2 | 2 | ||
| 3 | import javax.annotation.Nonnull; | 3 | import javax.annotation.Nonnull; |
| 4 | import javax.annotation.Nullable; | ||
| 4 | 5 | ||
| 5 | public class EntryMapping { | 6 | public 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 | ||
| 12 | import javax.annotation.Nullable; | 12 | import javax.annotation.Nullable; |
| 13 | import java.util.Collection; | 13 | import java.util.Collection; |
| 14 | import java.util.function.UnaryOperator; | ||
| 14 | import java.util.stream.Stream; | 15 | import java.util.stream.Stream; |
| 15 | 16 | ||
| 16 | public class EntryRemapper { | 17 | public 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 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde; | ||
| 2 | |||
| 3 | public 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 | ||
| 12 | package cuchaz.enigma.translation.mapping.serde; | 12 | package cuchaz.enigma.translation.mapping.serde; |
| 13 | 13 | ||
| 14 | import cuchaz.enigma.ProgressListener; | ||
| 15 | import cuchaz.enigma.translation.MappingTranslator; | ||
| 16 | import cuchaz.enigma.translation.Translator; | ||
| 17 | import cuchaz.enigma.translation.mapping.*; | ||
| 18 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 19 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | ||
| 20 | import cuchaz.enigma.translation.representation.entry.*; | ||
| 21 | import cuchaz.enigma.utils.LFPrintWriter; | ||
| 22 | |||
| 23 | import java.io.IOException; | 14 | import java.io.IOException; |
| 24 | import java.io.PrintWriter; | 15 | import java.io.PrintWriter; |
| 25 | import java.nio.file.DirectoryStream; | 16 | import java.nio.file.DirectoryStream; |
| @@ -33,6 +24,24 @@ import java.util.concurrent.atomic.AtomicInteger; | |||
| 33 | import java.util.stream.Collectors; | 24 | import java.util.stream.Collectors; |
| 34 | import java.util.stream.Stream; | 25 | import java.util.stream.Stream; |
| 35 | 26 | ||
| 27 | import cuchaz.enigma.ProgressListener; | ||
| 28 | import cuchaz.enigma.translation.MappingTranslator; | ||
| 29 | import cuchaz.enigma.translation.Translator; | ||
| 30 | import cuchaz.enigma.translation.mapping.AccessModifier; | ||
| 31 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 32 | import cuchaz.enigma.translation.mapping.MappingDelta; | ||
| 33 | import cuchaz.enigma.translation.mapping.MappingFileNameFormat; | ||
| 34 | import cuchaz.enigma.translation.mapping.MappingSaveParameters; | ||
| 35 | import cuchaz.enigma.translation.mapping.VoidEntryResolver; | ||
| 36 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 37 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | ||
| 38 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 39 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 40 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 41 | import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; | ||
| 42 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 43 | import cuchaz.enigma.utils.LFPrintWriter; | ||
| 44 | |||
| 36 | public enum EnigmaMappingsWriter implements MappingsWriter { | 45 | public 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 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde; | ||
| 2 | |||
| 3 | public 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 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde; | 1 | package cuchaz.enigma.translation.mapping.serde; |
| 2 | 2 | ||
| 3 | import com.google.common.base.Strings; | ||
| 4 | import cuchaz.enigma.translation.mapping.AccessModifier; | 3 | import cuchaz.enigma.translation.mapping.AccessModifier; |
| 5 | import cuchaz.enigma.translation.mapping.EntryMapping; | 4 | import cuchaz.enigma.translation.mapping.EntryMapping; |
| 6 | 5 | ||
| 6 | import java.util.ArrayList; | ||
| 7 | import java.util.List; | ||
| 8 | |||
| 7 | final class RawEntryMapping { | 9 | final 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) { |