From a9e03fa0e75b5b338021de982acbbb8277e08706 Mon Sep 17 00:00:00 2001 From: Fudge Date: Mon, 2 Dec 2019 15:43:23 +0200 Subject: 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 --- .../enigma/translation/mapping/EntryMapping.java | 28 ++++++++ .../enigma/translation/mapping/EntryRemapper.java | 9 ++- .../translation/mapping/serde/EnigmaFormat.java | 9 +++ .../mapping/serde/EnigmaMappingsReader.java | 79 ++++++++++++++-------- .../mapping/serde/EnigmaMappingsWriter.java | 67 ++++++++++++------ .../translation/mapping/serde/MappingFormat.java | 1 + .../translation/mapping/serde/MappingHelper.java | 51 ++++++++++++++ .../translation/mapping/serde/RawEntryMapping.java | 11 ++- .../mapping/serde/TinyMappingsReader.java | 2 +- .../translation/mapping/serde/TinyV2Reader.java | 22 +++--- .../translation/mapping/serde/TinyV2Writer.java | 12 ++-- .../representation/entry/ClassDefEntry.java | 16 +++-- .../representation/entry/ClassEntry.java | 15 ++-- .../translation/representation/entry/Entry.java | 2 + .../representation/entry/FieldDefEntry.java | 17 +++-- .../representation/entry/FieldEntry.java | 15 ++-- .../entry/LocalVariableDefEntry.java | 11 +-- .../representation/entry/LocalVariableEntry.java | 11 +-- .../representation/entry/MethodDefEntry.java | 17 +++-- .../representation/entry/MethodEntry.java | 15 ++-- .../representation/entry/ParentedEntry.java | 10 ++- 21 files changed, 311 insertions(+), 109 deletions(-) create mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaFormat.java create mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java (limited to 'src/main/java/cuchaz/enigma/translation') 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 @@ package cuchaz.enigma.translation.mapping; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class EntryMapping { private final String targetName; private final AccessModifier accessModifier; + private final @Nullable String javadoc; public EntryMapping(@Nonnull String targetName) { this(targetName, AccessModifier.UNCHANGED); } + public EntryMapping(@Nonnull String targetName, @Nullable String javadoc) { + this(targetName, AccessModifier.UNCHANGED, javadoc); + } + public EntryMapping(@Nonnull String targetName, AccessModifier accessModifier) { + this(targetName, accessModifier, null); + } + + public EntryMapping(@Nonnull String targetName, AccessModifier accessModifier, @Nullable String javadoc) { this.targetName = targetName; this.accessModifier = accessModifier; + this.javadoc = javadoc; } @Nonnull @@ -28,6 +39,23 @@ public class EntryMapping { return accessModifier; } + @Nullable + public String getJavadoc() { + return javadoc; + } + + public EntryMapping withName(String newName) { + return new EntryMapping(newName, accessModifier, javadoc); + } + + public EntryMapping withModifier(AccessModifier newModifier) { + return new EntryMapping(targetName, newModifier, javadoc); + } + + public EntryMapping withDocs(String newDocs) { + return new EntryMapping(targetName, accessModifier, newDocs); + } + @Override public boolean equals(Object obj) { 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; import javax.annotation.Nullable; import java.util.Collection; +import java.util.function.UnaryOperator; import java.util.stream.Stream; public class EntryRemapper { @@ -40,9 +41,13 @@ public class EntryRemapper { } public > void mapFromObf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping) { - Collection resolvedEntries = obfResolver.resolveEntry(obfuscatedEntry, ResolutionStrategy.RESOLVE_ROOT); + mapFromObf(obfuscatedEntry, deobfMapping, true); + } + + public > void mapFromObf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping, boolean renaming) { + Collection resolvedEntries = obfResolver.resolveEntry(obfuscatedEntry, renaming ? ResolutionStrategy.RESOLVE_ROOT : ResolutionStrategy.RESOLVE_CLOSEST); - if (deobfMapping != null) { + if (renaming && deobfMapping != null) { for (E resolvedEntry : resolvedEntries) { validator.validateRename(resolvedEntry, deobfMapping.getTargetName()); } 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 @@ +package cuchaz.enigma.translation.mapping.serde; + +public class EnigmaFormat { + public static final String COMMENT = "COMMENT"; + public static final String CLASS = "CLASS"; + public static final String FIELD = "FIELD"; + public static final String METHOD = "METHOD"; + public static final String PARAMETER = "ARG"; +} 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 { protected void readFile(Path path, EntryTree mappings) throws IOException, MappingParseException { List lines = Files.readAllLines(path, Charsets.UTF_8); - Deque> mappingStack = new ArrayDeque<>(); + Deque> mappingStack = new ArrayDeque<>(); for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { String line = lines.get(lineNumber); @@ -75,21 +75,33 @@ public enum EnigmaMappingsReader implements MappingsReader { continue; } - while (indentation < mappingStack.size()) { - mappingStack.pop(); - } + cleanMappingStack(indentation, mappingStack, mappings); try { - MappingPair pair = parseLine(mappingStack.peek(), line); - mappingStack.push(pair.getEntry()); - if (pair.getMapping() != null) { - mappings.insert(pair.getEntry(), pair.getMapping()); + MappingPair pair = parseLine(mappingStack.peek(), line); + if (pair != null) { + mappingStack.push(pair); + if (pair.getMapping() != null) { + + } } } catch (Throwable t) { t.printStackTrace(); throw new MappingParseException(path::toString, lineNumber, t.toString()); } } + + // Clean up rest + cleanMappingStack(0, mappingStack, mappings); + } + + private void cleanMappingStack(int indentation, Deque> mappingStack, EntryTree mappings) { + while (indentation < mappingStack.size()) { + MappingPair pair = mappingStack.pop(); + if (pair.getMapping() != null) { + mappings.insert(pair.getEntry(), pair.getMapping().bake()); + } + } } @Nullable @@ -123,25 +135,38 @@ public enum EnigmaMappingsReader implements MappingsReader { return indent; } - private MappingPair parseLine(@Nullable Entry parent, String line) { + private MappingPair parseLine(@Nullable MappingPair parent, String line) { String[] tokens = line.trim().split("\\s"); - String keyToken = tokens[0].toLowerCase(Locale.ROOT); + String keyToken = tokens[0].toUpperCase(Locale.ROOT); + Entry parentEntry = parent == null ? null : parent.getEntry(); switch (keyToken) { - case "class": - return parseClass(parent, tokens); - case "field": - return parseField(parent, tokens); - case "method": - return parseMethod(parent, tokens); - case "arg": - return parseArgument(parent, tokens); + case EnigmaFormat.CLASS: + return parseClass(parentEntry, tokens); + case EnigmaFormat.FIELD: + return parseField(parentEntry, tokens); + case EnigmaFormat.METHOD: + return parseMethod(parentEntry, tokens); + case EnigmaFormat.PARAMETER: + return parseArgument(parentEntry, tokens); + case EnigmaFormat.COMMENT: + readJavadoc(parent, tokens); + return null; default: throw new RuntimeException("Unknown token '" + keyToken + "'"); } } + + private void readJavadoc(MappingPair parent, String[] tokens) { + if (parent == null) + throw new IllegalStateException("Javadoc has no parent!"); + String jdLine = tokens.length > 1 ? tokens[1] : ""; // Empty string to concat + if (parent.getMapping() == null) + throw new IllegalStateException("Javadoc requires a mapping!"); + parent.getMapping().addJavadocLine(MappingHelper.unescape(jdLine)); + } - private MappingPair parseClass(@Nullable Entry parent, String[] tokens) { + private MappingPair parseClass(@Nullable Entry parent, String[] tokens) { String obfuscatedName = ClassEntry.getInnerName(tokens[1]); ClassEntry obfuscatedEntry; if (parent instanceof ClassEntry) { @@ -167,13 +192,13 @@ public enum EnigmaMappingsReader implements MappingsReader { } if (mapping != null) { - return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping, modifier)); + return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier)); } else { return new MappingPair<>(obfuscatedEntry); } } - private MappingPair parseField(@Nullable Entry parent, String[] tokens) { + private MappingPair parseField(@Nullable Entry parent, String[] tokens) { if (!(parent instanceof ClassEntry)) { throw new RuntimeException("Field must be a child of a class!"); } @@ -204,13 +229,13 @@ public enum EnigmaMappingsReader implements MappingsReader { FieldEntry obfuscatedEntry = new FieldEntry(ownerEntry, obfuscatedName, descriptor); if (mapping != null) { - return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping, modifier)); + return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier)); } else { return new MappingPair<>(obfuscatedEntry); } } - private MappingPair parseMethod(@Nullable Entry parent, String[] tokens) { + private MappingPair parseMethod(@Nullable Entry parent, String[] tokens) { if (!(parent instanceof ClassEntry)) { throw new RuntimeException("Method must be a child of a class!"); } @@ -244,22 +269,22 @@ public enum EnigmaMappingsReader implements MappingsReader { MethodEntry obfuscatedEntry = new MethodEntry(ownerEntry, obfuscatedName, descriptor); if (mapping != null) { - return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping, modifier)); + return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier)); } else { return new MappingPair<>(obfuscatedEntry); } } - private MappingPair parseArgument(@Nullable Entry parent, String[] tokens) { + private MappingPair parseArgument(@Nullable Entry parent, String[] tokens) { if (!(parent instanceof MethodEntry)) { throw new RuntimeException("Method arg must be a child of a method!"); } MethodEntry ownerEntry = (MethodEntry) parent; - LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerEntry, Integer.parseInt(tokens[1]), "", true); + LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerEntry, Integer.parseInt(tokens[1]), "", true, null); String mapping = tokens[2]; - return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); + return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); } @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 @@ package cuchaz.enigma.translation.mapping.serde; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.translation.MappingTranslator; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.*; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; -import cuchaz.enigma.translation.representation.entry.*; -import cuchaz.enigma.utils.LFPrintWriter; - import java.io.IOException; import java.io.PrintWriter; import java.nio.file.DirectoryStream; @@ -33,6 +24,24 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import java.util.stream.Stream; +import cuchaz.enigma.ProgressListener; +import cuchaz.enigma.translation.MappingTranslator; +import cuchaz.enigma.translation.Translator; +import cuchaz.enigma.translation.mapping.AccessModifier; +import cuchaz.enigma.translation.mapping.EntryMapping; +import cuchaz.enigma.translation.mapping.MappingDelta; +import cuchaz.enigma.translation.mapping.MappingFileNameFormat; +import cuchaz.enigma.translation.mapping.MappingSaveParameters; +import cuchaz.enigma.translation.mapping.VoidEntryResolver; +import cuchaz.enigma.translation.mapping.tree.EntryTree; +import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; +import cuchaz.enigma.translation.representation.entry.ClassEntry; +import cuchaz.enigma.translation.representation.entry.Entry; +import cuchaz.enigma.translation.representation.entry.FieldEntry; +import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; +import cuchaz.enigma.translation.representation.entry.MethodEntry; +import cuchaz.enigma.utils.LFPrintWriter; + public enum EnigmaMappingsWriter implements MappingsWriter { FILE { @Override @@ -154,10 +163,26 @@ public enum EnigmaMappingsWriter implements MappingsWriter { protected void writeRoot(PrintWriter writer, EntryTree mappings, ClassEntry classEntry) { Collection> children = groupChildren(mappings.getChildren(classEntry)); - writer.println(writeClass(classEntry, mappings.get(classEntry)).trim()); + EntryMapping classEntryMapping = mappings.get(classEntry); + + writer.println(writeClass(classEntry, classEntryMapping).trim()); + if (classEntryMapping != null && classEntryMapping.getJavadoc() != null) { + writeDocs(writer, classEntryMapping, 0); + } + for (Entry child : children) { writeEntry(writer, mappings, child, 1); } + + } + + private void writeDocs(PrintWriter writer, EntryMapping mapping, int depth) { + String jd = mapping.getJavadoc(); + if (jd != null) { + for (String line : jd.split("\\R")) { + writer.println(indent(EnigmaFormat.COMMENT + " " + MappingHelper.escape(line), depth + 1)); + } + } } protected void writeEntry(PrintWriter writer, EntryTree mappings, Entry entry, int depth) { @@ -167,6 +192,7 @@ public enum EnigmaMappingsWriter implements MappingsWriter { } EntryMapping mapping = node.getValue(); + if (entry instanceof ClassEntry) { String line = writeClass((ClassEntry) entry, mapping); writer.println(indent(line, depth)); @@ -180,6 +206,9 @@ public enum EnigmaMappingsWriter implements MappingsWriter { String line = writeArgument((LocalVariableEntry) entry, mapping); writer.println(indent(line, depth)); } + if (mapping != null && mapping.getJavadoc() != null) { + writeDocs(writer, mapping, depth); + } Collection> children = groupChildren(node.getChildren()); for (Entry child : children) { @@ -190,11 +219,6 @@ public enum EnigmaMappingsWriter implements MappingsWriter { private Collection> groupChildren(Collection> children) { Collection> result = new ArrayList<>(children.size()); - children.stream().filter(e -> e instanceof ClassEntry) - .map(e -> (ClassEntry) e) - .sorted() - .forEach(result::add); - children.stream().filter(e -> e instanceof FieldEntry) .map(e -> (FieldEntry) e) .sorted() @@ -210,11 +234,16 @@ public enum EnigmaMappingsWriter implements MappingsWriter { .sorted() .forEach(result::add); + children.stream().filter(e -> e instanceof ClassEntry) + .map(e -> (ClassEntry) e) + .sorted() + .forEach(result::add); + return result; } protected String writeClass(ClassEntry entry, EntryMapping mapping) { - StringBuilder builder = new StringBuilder("CLASS "); + StringBuilder builder = new StringBuilder(EnigmaFormat.CLASS +" "); builder.append(entry.getName()).append(' '); writeMapping(builder, mapping); @@ -222,7 +251,7 @@ public enum EnigmaMappingsWriter implements MappingsWriter { } protected String writeMethod(MethodEntry entry, EntryMapping mapping) { - StringBuilder builder = new StringBuilder("METHOD "); + StringBuilder builder = new StringBuilder(EnigmaFormat.METHOD + " "); builder.append(entry.getName()).append(' '); writeMapping(builder, mapping); @@ -232,7 +261,7 @@ public enum EnigmaMappingsWriter implements MappingsWriter { } protected String writeField(FieldEntry entry, EntryMapping mapping) { - StringBuilder builder = new StringBuilder("FIELD "); + StringBuilder builder = new StringBuilder(EnigmaFormat.FIELD + " "); builder.append(entry.getName()).append(' '); writeMapping(builder, mapping); @@ -242,7 +271,7 @@ public enum EnigmaMappingsWriter implements MappingsWriter { } protected String writeArgument(LocalVariableEntry entry, EntryMapping mapping) { - return "ARG " + entry.getIndex() + ' ' + mapping.getTargetName(); + return EnigmaFormat.PARAMETER + " " + entry.getIndex() + ' ' + mapping.getTargetName(); } 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 { SRG_FILE(SrgMappingsWriter.INSTANCE, null), PROGUARD(null, ProguardMappingsReader.INSTANCE); + private final MappingsWriter writer; private final MappingsReader reader; 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 @@ +package cuchaz.enigma.translation.mapping.serde; + +public final class MappingHelper { + private static final String TO_ESCAPE = "\\\n\r\0\t"; + private static final String ESCAPED = "\\nr0t"; + + public static String escape(String raw) { + StringBuilder builder = new StringBuilder(raw.length() + 1); + for (int i = 0; i < raw.length(); i++) { + final char c = raw.charAt(i); + final int r = TO_ESCAPE.indexOf(c); + if (r < 0) { + builder.append(c); + } else { + builder.append('\\').append(ESCAPED.charAt(r)); + } + } + return builder.toString(); + } + + public static String unescape(String str) { + int pos = str.indexOf('\\'); + if (pos < 0) return str; + + StringBuilder ret = new StringBuilder(str.length() - 1); + int start = 0; + + do { + ret.append(str, start, pos); + pos++; + int type; + + if (pos >= str.length()) { + throw new RuntimeException("incomplete escape sequence at the end"); + } else if ((type = ESCAPED.indexOf(str.charAt(pos))) < 0) { + throw new RuntimeException("invalid escape character: \\" + str.charAt(pos)); + } else { + ret.append(TO_ESCAPE.charAt(type)); + } + + start = pos + 1; + } while ((pos = str.indexOf('\\', start)) >= 0); + + ret.append(str, start, str.length()); + + return ret.toString(); + } + + private MappingHelper() { + } +} 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 @@ package cuchaz.enigma.translation.mapping.serde; -import com.google.common.base.Strings; import cuchaz.enigma.translation.mapping.AccessModifier; import cuchaz.enigma.translation.mapping.EntryMapping; +import java.util.ArrayList; +import java.util.List; + final class RawEntryMapping { private final String targetName; private final AccessModifier access; + private List javadocs = new ArrayList<>(); RawEntryMapping(String targetName) { this(targetName, null); @@ -17,7 +20,11 @@ final class RawEntryMapping { this.targetName = targetName; } + void addJavadocLine(String line) { + javadocs.add(line); + } + EntryMapping bake() { - return Strings.isNullOrEmpty(targetName) ? null : new EntryMapping(targetName, access); + return new EntryMapping(targetName, access, javadocs.isEmpty() ? null : String.join("\n", javadocs)); } } 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 { int variableIndex = Integer.parseInt(tokens[4]); String mapping = tokens[5]; - LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true); + LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true, null); return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); } } 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 { addJavadoc(pair, parts[1]); } - private void addJavadoc(MappingPair pair, String javadoc) { - RawEntryMapping mapping = pair.getMapping(); - if (mapping == null) { - throw new IllegalArgumentException("Javadoc requires a mapping in enigma!"); - } -// mapping.addJavadocLine(javadoc); todo javadocs - } - private MappingPair parseClass(String[] tokens, boolean escapeNames) { ClassEntry obfuscatedEntry = new ClassEntry(unescapeOpt(tokens[1], escapeNames)); if (tokens.length <= 2) @@ -239,13 +231,25 @@ final class TinyV2Reader implements MappingsReader { return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); } + + + private void addJavadoc(MappingPair pair, String javadoc) { + RawEntryMapping mapping = pair.getMapping(); + if (mapping == null) { + throw new IllegalArgumentException("Javadoc requires a mapping in enigma!"); + } + mapping.addJavadocLine(javadoc); + } + + + private MappingPair parseArgument(MappingPair parent, String[] tokens, boolean escapeNames) { MethodEntry ownerMethod = (MethodEntry) parent.getEntry(); int variableIndex = Integer.parseInt(tokens[1]); // tokens[2] is the useless obf name - LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true); + LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true, null); if (tokens.length <= 3) return new MappingPair<>(obfuscatedEntry); 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 { } private void writeComment(PrintWriter writer, EntryMapping mapping, int indent) { -// if (mapping != null && mapping.getJavadoc() != null) { todo javadocs -// writer.print(indent(indent)); -// writer.print("c\t"); -// writer.print(MappingHelper.escape(mapping.getJavadoc())); -// writer.println(); -// } + if (mapping != null && mapping.getJavadoc() != null) { + writer.print(indent(indent)); + writer.print("c\t"); + writer.print(MappingHelper.escape(mapping.getJavadoc())); + writer.println(); + } } 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 { private final ClassEntry[] interfaces; public ClassDefEntry(String className, Signature signature, AccessFlags access, @Nullable ClassEntry superClass, ClassEntry[] interfaces) { - this(getOuterClass(className), getInnerName(className), signature, access, superClass, interfaces); + this(getOuterClass(className), getInnerName(className), signature, access, superClass, interfaces, null); } public ClassDefEntry(ClassEntry parent, String className, Signature signature, AccessFlags access, @Nullable ClassEntry superClass, ClassEntry[] interfaces) { - super(parent, className); + this(parent, className, signature, access, superClass, interfaces, null); + } + + public ClassDefEntry(ClassEntry parent, String className, Signature signature, AccessFlags access, @Nullable ClassEntry superClass, + ClassEntry[] interfaces, String javadocs) { + super(parent, className, javadocs); Preconditions.checkNotNull(signature, "Class signature cannot be null"); Preconditions.checkNotNull(access, "Class access cannot be null"); @@ -82,16 +87,17 @@ public class ClassDefEntry extends ClassEntry implements DefEntry { AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access; ClassEntry translatedSuper = translator.translate(superClass); ClassEntry[] translatedInterfaces = Arrays.stream(interfaces).map(translator::translate).toArray(ClassEntry[]::new); - return new ClassDefEntry(parent, translatedName, translatedSignature, translatedAccess, translatedSuper, translatedInterfaces); + String docs = mapping != null ? mapping.getJavadoc() : null; + return new ClassDefEntry(parent, translatedName, translatedSignature, translatedAccess, translatedSuper, translatedInterfaces, docs); } @Override public ClassDefEntry withName(String name) { - return new ClassDefEntry(parent, name, signature, access, superClass, interfaces); + return new ClassDefEntry(parent, name, signature, access, superClass, interfaces, javadocs); } @Override public ClassDefEntry withParent(ClassEntry parent) { - return new ClassDefEntry(parent, name, signature, access, superClass, interfaces); + return new ClassDefEntry(parent, name, signature, access, superClass, interfaces, javadocs); } } 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 implements Comparable< private final String fullName; public ClassEntry(String className) { - this(getOuterClass(className), getInnerName(className)); + this(getOuterClass(className), getInnerName(className), null); } public ClassEntry(@Nullable ClassEntry parent, String className) { - super(parent, className); + this(parent, className, null); + } + + public ClassEntry(@Nullable ClassEntry parent, String className, @Nullable String javadocs) { + super(parent, className, javadocs); if (parent != null) { fullName = parent.getFullName() + "$" + name; } else { @@ -69,7 +73,8 @@ public class ClassEntry extends ParentedEntry implements Comparable< } String translatedName = mapping != null ? mapping.getTargetName() : name; - return new ClassEntry(parent, translatedName); + String docs = mapping != null ? mapping.getJavadoc() : null; + return new ClassEntry(parent, translatedName, docs); } @Override @@ -103,12 +108,12 @@ public class ClassEntry extends ParentedEntry implements Comparable< @Override public ClassEntry withName(String name) { - return new ClassEntry(parent, name); + return new ClassEntry(parent, name, javadocs); } @Override public ClassEntry withParent(ClassEntry parent) { - return new ClassEntry(parent, name); + return new ClassEntry(parent, name, javadocs); } @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; public interface Entry

> extends Translatable { String getName(); + String getJavadocs(); + default String getSourceRemapName() { return getName(); } 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 { private final Signature signature; public FieldDefEntry(ClassEntry owner, String name, TypeDescriptor desc, Signature signature, AccessFlags access) { - super(owner, name, desc); + this(owner, name, desc, signature, access, null); + } + + public FieldDefEntry(ClassEntry owner, String name, TypeDescriptor desc, Signature signature, AccessFlags access, String javadocs) { + super(owner, name, desc, javadocs); Preconditions.checkNotNull(access, "Field access cannot be null"); Preconditions.checkNotNull(signature, "Field signature cannot be null"); this.access = access; @@ -34,7 +38,7 @@ public class FieldDefEntry extends FieldEntry implements DefEntry { } public static FieldDefEntry parse(ClassEntry owner, int access, String name, String desc, String signature) { - return new FieldDefEntry(owner, name, new TypeDescriptor(desc), Signature.createTypedSignature(signature), new AccessFlags(access)); + return new FieldDefEntry(owner, name, new TypeDescriptor(desc), Signature.createTypedSignature(signature), new AccessFlags(access), null); } public static FieldDefEntry parse(FieldDefinition definition) { @@ -42,7 +46,7 @@ public class FieldDefEntry extends FieldEntry implements DefEntry { TypeDescriptor descriptor = new TypeDescriptor(definition.getErasedSignature()); Signature signature = Signature.createTypedSignature(definition.getSignature()); AccessFlags access = new AccessFlags(definition.getModifiers()); - return new FieldDefEntry(owner, definition.getName(), descriptor, signature, access); + return new FieldDefEntry(owner, definition.getName(), descriptor, signature, access, null); } @Override @@ -60,16 +64,17 @@ public class FieldDefEntry extends FieldEntry implements DefEntry { Signature translatedSignature = translator.translate(signature); String translatedName = mapping != null ? mapping.getTargetName() : name; AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access; - return new FieldDefEntry(parent, translatedName, translatedDesc, translatedSignature, translatedAccess); + String docs = mapping != null ? mapping.getJavadoc() : null; + return new FieldDefEntry(parent, translatedName, translatedDesc, translatedSignature, translatedAccess, docs); } @Override public FieldDefEntry withName(String name) { - return new FieldDefEntry(parent, name, desc, signature, access); + return new FieldDefEntry(parent, name, desc, signature, access, javadocs); } @Override public FieldDefEntry withParent(ClassEntry owner) { - return new FieldDefEntry(owner, this.name, this.desc, signature, access); + return new FieldDefEntry(owner, this.name, this.desc, signature, access, javadocs); } } 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 implements Comparable< protected final TypeDescriptor desc; public FieldEntry(ClassEntry parent, String name, TypeDescriptor desc) { - super(parent, name); + this(parent, name, desc, null); + } + + public FieldEntry(ClassEntry parent, String name, TypeDescriptor desc, String javadocs) { + super(parent, name, javadocs); Preconditions.checkNotNull(parent, "Owner cannot be null"); Preconditions.checkNotNull(desc, "Field descriptor cannot be null"); @@ -32,7 +36,7 @@ public class FieldEntry extends ParentedEntry implements Comparable< } public static FieldEntry parse(String owner, String name, String desc) { - return new FieldEntry(new ClassEntry(owner), name, new TypeDescriptor(desc)); + return new FieldEntry(new ClassEntry(owner), name, new TypeDescriptor(desc), null); } @Override @@ -46,18 +50,19 @@ public class FieldEntry extends ParentedEntry implements Comparable< @Override public FieldEntry withName(String name) { - return new FieldEntry(parent, name, desc); + return new FieldEntry(parent, name, desc, null); } @Override public FieldEntry withParent(ClassEntry parent) { - return new FieldEntry(parent, this.name, this.desc); + return new FieldEntry(parent, this.name, this.desc, null); } @Override protected FieldEntry translate(Translator translator, @Nullable EntryMapping mapping) { String translatedName = mapping != null ? mapping.getTargetName() : name; - return new FieldEntry(parent, translatedName, translator.translate(desc)); + String docs = mapping != null ? mapping.getJavadoc() : null; + return new FieldEntry(parent, translatedName, translator.translate(desc), docs); } @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; public class LocalVariableDefEntry extends LocalVariableEntry { protected final TypeDescriptor desc; - public LocalVariableDefEntry(MethodEntry ownerEntry, int index, String name, boolean parameter, TypeDescriptor desc) { - super(ownerEntry, index, name, parameter); + public LocalVariableDefEntry(MethodEntry ownerEntry, int index, String name, boolean parameter, TypeDescriptor desc, String javadoc) { + super(ownerEntry, index, name, parameter, javadoc); Preconditions.checkNotNull(desc, "Variable desc cannot be null"); this.desc = desc; @@ -30,17 +30,18 @@ public class LocalVariableDefEntry extends LocalVariableEntry { public LocalVariableDefEntry translate(Translator translator, @Nullable EntryMapping mapping) { TypeDescriptor translatedDesc = translator.translate(desc); String translatedName = mapping != null ? mapping.getTargetName() : name; - return new LocalVariableDefEntry(parent, index, translatedName, parameter, translatedDesc); + String javadoc = mapping != null ? mapping.getJavadoc() : javadocs; + return new LocalVariableDefEntry(parent, index, translatedName, parameter, translatedDesc, javadoc); } @Override public LocalVariableDefEntry withName(String name) { - return new LocalVariableDefEntry(parent, index, name, parameter, desc); + return new LocalVariableDefEntry(parent, index, name, parameter, desc, javadocs); } @Override public LocalVariableDefEntry withParent(MethodEntry entry) { - return new LocalVariableDefEntry(entry, index, name, parameter, desc); + return new LocalVariableDefEntry(entry, index, name, parameter, desc, javadocs); } @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 implements Co protected final int index; protected final boolean parameter; - public LocalVariableEntry(MethodEntry parent, int index, String name, boolean parameter) { - super(parent, name); + public LocalVariableEntry(MethodEntry parent, int index, String name, boolean parameter, String javadoc) { + super(parent, name, javadoc); Preconditions.checkNotNull(parent, "Variable owner cannot be null"); Preconditions.checkArgument(index >= 0, "Index must be positive"); @@ -48,17 +48,18 @@ public class LocalVariableEntry extends ParentedEntry implements Co @Override public LocalVariableEntry translate(Translator translator, @Nullable EntryMapping mapping) { String translatedName = mapping != null ? mapping.getTargetName() : name; - return new LocalVariableEntry(parent, index, translatedName, parameter); + String javadoc = mapping != null ? mapping.getJavadoc() : null; + return new LocalVariableEntry(parent, index, translatedName, parameter, javadoc); } @Override public LocalVariableEntry withName(String name) { - return new LocalVariableEntry(parent, index, name, parameter); + return new LocalVariableEntry(parent, index, name, parameter, javadocs); } @Override public LocalVariableEntry withParent(MethodEntry parent) { - return new LocalVariableEntry(parent, index, name, parameter); + return new LocalVariableEntry(parent, index, name, parameter, javadocs); } @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 private final Signature signature; public MethodDefEntry(ClassEntry owner, String name, MethodDescriptor descriptor, Signature signature, AccessFlags access) { - super(owner, name, descriptor); + this(owner, name, descriptor, signature, access, null); + } + + public MethodDefEntry(ClassEntry owner, String name, MethodDescriptor descriptor, Signature signature, AccessFlags access, String docs) { + super(owner, name, descriptor, docs); Preconditions.checkNotNull(access, "Method access cannot be null"); Preconditions.checkNotNull(signature, "Method signature cannot be null"); this.access = access; @@ -34,7 +38,7 @@ public class MethodDefEntry extends MethodEntry implements DefEntry } public static MethodDefEntry parse(ClassEntry owner, int access, String name, String desc, String signature) { - return new MethodDefEntry(owner, name, new MethodDescriptor(desc), Signature.createSignature(signature), new AccessFlags(access)); + return new MethodDefEntry(owner, name, new MethodDescriptor(desc), Signature.createSignature(signature), new AccessFlags(access), null); } public static MethodDefEntry parse(MethodDefinition definition) { @@ -42,7 +46,7 @@ public class MethodDefEntry extends MethodEntry implements DefEntry MethodDescriptor descriptor = new MethodDescriptor(definition.getErasedSignature()); Signature signature = Signature.createSignature(definition.getSignature()); AccessFlags access = new AccessFlags(definition.getModifiers()); - return new MethodDefEntry(classEntry, definition.getName(), descriptor, signature, access); + return new MethodDefEntry(classEntry, definition.getName(), descriptor, signature, access, null); } @Override @@ -60,16 +64,17 @@ public class MethodDefEntry extends MethodEntry implements DefEntry Signature translatedSignature = translator.translate(signature); String translatedName = mapping != null ? mapping.getTargetName() : name; AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access; - return new MethodDefEntry(parent, translatedName, translatedDesc, translatedSignature, translatedAccess); + String docs = mapping != null ? mapping.getJavadoc() : null; + return new MethodDefEntry(parent, translatedName, translatedDesc, translatedSignature, translatedAccess, docs); } @Override public MethodDefEntry withName(String name) { - return new MethodDefEntry(parent, name, descriptor, signature, access); + return new MethodDefEntry(parent, name, descriptor, signature, access, javadocs); } @Override public MethodDefEntry withParent(ClassEntry parent) { - return new MethodDefEntry(new ClassEntry(parent.getFullName()), name, descriptor, signature, access); + return new MethodDefEntry(new ClassEntry(parent.getFullName()), name, descriptor, signature, access, javadocs); } } 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 implements Comparable protected final MethodDescriptor descriptor; public MethodEntry(ClassEntry parent, String name, MethodDescriptor descriptor) { - super(parent, name); + this(parent, name, descriptor, null); + } + + public MethodEntry(ClassEntry parent, String name, MethodDescriptor descriptor, String javadocs) { + super(parent, name, javadocs); Preconditions.checkNotNull(parent, "Parent cannot be null"); Preconditions.checkNotNull(descriptor, "Method descriptor cannot be null"); @@ -33,7 +37,7 @@ public class MethodEntry extends ParentedEntry implements Comparable } public static MethodEntry parse(String owner, String name, String desc) { - return new MethodEntry(new ClassEntry(owner), name, new MethodDescriptor(desc)); + return new MethodEntry(new ClassEntry(owner), name, new MethodDescriptor(desc), null); } @Override @@ -52,17 +56,18 @@ public class MethodEntry extends ParentedEntry implements Comparable @Override public MethodEntry translate(Translator translator, @Nullable EntryMapping mapping) { String translatedName = mapping != null ? mapping.getTargetName() : name; - return new MethodEntry(parent, translatedName, translator.translate(descriptor)); + String docs = mapping != null ? mapping.getJavadoc() : null; + return new MethodEntry(parent, translatedName, translator.translate(descriptor), docs); } @Override public MethodEntry withName(String name) { - return new MethodEntry(parent, name, descriptor); + return new MethodEntry(parent, name, descriptor, javadocs); } @Override public MethodEntry withParent(ClassEntry parent) { - return new MethodEntry(new ClassEntry(parent.getFullName()), name, descriptor); + return new MethodEntry(new ClassEntry(parent.getFullName()), name, descriptor, javadocs); } @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; public abstract class ParentedEntry

> implements Entry

{ protected final P parent; protected final String name; + protected final @Nullable String javadocs; - protected ParentedEntry(P parent, String name) { + protected ParentedEntry(P parent, String name, String javadocs) { this.parent = parent; this.name = name; + this.javadocs = javadocs; Preconditions.checkNotNull(name, "Name cannot be null"); } @@ -51,6 +53,12 @@ public abstract class ParentedEntry

> implements Entry

{ return parent; } + @Nullable + @Override + public String getJavadocs() { + return javadocs; + } + @Override public ParentedEntry

translate(Translator translator, EntryResolver resolver, EntryMap mappings) { P parent = getParent(); -- cgit v1.2.3