Skip to content

Commit

Permalink
Documented component rework
Browse files Browse the repository at this point in the history
Now docs are correctly escaped and unescaped in tiny v2 format
  • Loading branch information
XiaoPangxie732 committed Aug 23, 2024
1 parent 68cf047 commit b200fad
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class MinecraftDecompilerCommandLine {
private static final Logger LOGGER = LogManager.getLogger("CommandLine");

public static void main(String[] args) throws Throwable {
if (Constants.IS_DEV) LOGGER.info("MCD Begin");// Used to measure time
OptionParser parser = new OptionParser();
ArgumentAcceptingOptionSpec<SideType> sideTypeO = parser.acceptsAll(of("s", "side"), "Side to deobfuscate/" +
"decompile. Values are \"CLIENT\" and \"SERVER\". With this option, you must specify --version option and can't " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,6 @@ public NamespacedMapping(String[] namespaces, String[] names, int nameStart, Com
if (namespaces.length != (names.length - Objects.checkIndex(nameStart, names.length)))
throw new IllegalArgumentException();
for (int i = 0; i < namespaces.length; i++) {
// var n = i + nameStart;// FIXME: Maybe useless?
// this.names.put(Objects.requireNonNull(namespaces[i]), n >= names.length ? names[names.length - 1] : names[n]);
this.names.put(Objects.requireNonNull(namespaces[i]), names[i + nameStart]);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@
* Base component class. Every component must implement this interface
*/
public interface Component {
/**
* Validates this component.
* @throws IllegalStateException if the validation fails
*/
default void validate() throws IllegalStateException {// TODO
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,63 @@

package cn.maxpixel.mcdecompiler.mapping.component;

import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.Objects;

/**
* The component that holds documentation about a class, field, method, or parameter.
*
* @apiNote The content is a list of strings, which each element represents exactly <b>one</b> line,
* so {@code \n} and {@code \r} are not allowed. An empty line must be represented by {@code ""}.
* {@code null} elements are prohibited
*/
public class Documented implements Component {
private String doc;
/**
* The contents
*/
public final ObjectArrayList<String> contents = new ObjectArrayList<>();

/**
* Gets the contents
* @return The contents
*/
public List<String> getContents() {
return contents;
}

public String getDoc() {
return doc;
/**
* Join the contents with {@code \n}
* @return the joined string
*/
public @NotNull String getContentString() {
if (contents.isEmpty()) return "";
return String.join("\n", contents);
}

public void setDoc(String doc) {
this.doc = Objects.requireNonNull(doc, "null documentation isn't meaningful huh?");
/**
* Breaks the string into lines and sets them as contents
* @param content the string
*/
public void setContents(@NotNull String content) {
int mark = 0;
for (int i = content.indexOf('\n'); i >= 0; i = content.indexOf('\n', mark)) {
contents.add(content.substring(mark, content.charAt(i - 1) == '\r' ? i - 1 : i));
mark = i + 1;
}
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Documented that)) return false;
return Objects.equals(doc, that.doc);
return Objects.equals(contents, that.contents);
}

@Override
public int hashCode() {
return Objects.hashCode(doc);
return Objects.hashCode(contents);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import cn.maxpixel.mcdecompiler.mapping.remapper.ClassifiedMappingRemapper;
import cn.maxpixel.mcdecompiler.mapping.trait.NamespacedTrait;
import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil;
import cn.maxpixel.mcdecompiler.mapping.util.TinyUtil;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectList;

Expand Down Expand Up @@ -339,8 +340,8 @@ public ObjectList<String> generate(ClassifiedMapping<NamespacedMapping> mappings
synchronized (lines) {
lines.add("\tf\t" + desc + '\t' + NamingUtil.concatNamespaces(namespaces, field::getName, "\t"));
if (field.hasComponent(Documented.class)) {
String doc = field.getComponent(Documented.class).getDoc();
if (doc != null && !doc.isBlank()) lines.add("\t\tc\t" + doc);
String doc = field.getComponent(Documented.class).getContentString();
if (!doc.isBlank()) lines.add("\t\tc\t" + TinyUtil.escape(doc));
}
}
});
Expand All @@ -349,8 +350,8 @@ public ObjectList<String> generate(ClassifiedMapping<NamespacedMapping> mappings
synchronized (lines) {
lines.add("\tm\t" + desc + '\t' + NamingUtil.concatNamespaces(namespaces, method::getName, "\t"));
if (method.hasComponent(Documented.class)) {
String doc = method.getComponent(Documented.class).getDoc();
if (doc != null && !doc.isBlank()) lines.add("\t\tc\t" + doc);
String doc = method.getComponent(Documented.class).getContentString();
if (!doc.isBlank()) lines.add("\t\tc\t" + TinyUtil.escape(doc));
}
if (method.hasComponent(LocalVariableTable.Namespaced.class)) {
LocalVariableTable.Namespaced lvt = method.getComponent(LocalVariableTable.Namespaced.class);
Expand All @@ -364,9 +365,9 @@ public ObjectList<String> generate(ClassifiedMapping<NamespacedMapping> mappings
return name;
}, "\t");
lines.add("\t\tp\t" + index + '\t' + names);
if(localVariable.hasComponent(Documented.class)) {
String doc = localVariable.getComponent(Documented.class).getDoc();
if(doc != null && !doc.isBlank()) lines.add("\t\t\tc\t" + doc);
if (localVariable.hasComponent(Documented.class)) {
String doc = localVariable.getComponent(Documented.class).getContentString();
if (!doc.isBlank()) lines.add("\t\t\tc\t" + TinyUtil.escape(doc));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats;
import cn.maxpixel.mcdecompiler.mapping.trait.NamespacedTrait;
import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil;
import cn.maxpixel.mcdecompiler.mapping.util.TinyUtil;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectList;

Expand Down Expand Up @@ -424,7 +425,7 @@ private static int processTree(int index, int size, String[] namespaces, ObjectL
if (s.charAt(0) == '\t') {
String[] sa = MappingUtil.split(s.substring(3), '\t');
switch (s.charAt(1)) {
case 'c' -> classMapping.mapping.getComponent(Documented.class).setDoc(sa[0]);
case 'c' -> classMapping.mapping.getComponent(Documented.class).setContents(TinyUtil.unescape(sa[0]));
case 'f' -> {
NamespacedMapping fieldMapping = MappingUtil.Namespaced.dduo(namespaces, sa, 1, namespaces[0], sa[0]);
index = processTree1(index, size, namespaces, content, fieldMapping);
Expand All @@ -448,7 +449,7 @@ private static int processTree1(int index, int size, String[] namespaces, Object
String s = content.get(index);
if (s.charAt(1) == '\t' && s.charAt(0) == '\t') {
switch (s.charAt(2)) {
case 'c' -> mapping.getComponent(Documented.class).setDoc(s.substring(4));
case 'c' -> mapping.getComponent(Documented.class).setContents(TinyUtil.unescape(s.substring(4)));
case 'p' -> {
String[] sa = MappingUtil.split(s.substring(4), '\t');
NamespacedMapping localVariable = MappingUtil.Namespaced.d(namespaces, sa, 1);
Expand All @@ -467,7 +468,7 @@ private static int processTree2(int index, int size, ObjectList<String> content,
if (++index < size) {
String s = content.get(index);
if (s.charAt(2) == '\t' && s.charAt(1) == '\t' && s.charAt(0) == '\t') {
if(s.charAt(3) == 'c') localVariable.getComponent(Documented.class).setDoc(s.substring(5));
if (s.charAt(3) == 'c') localVariable.getComponent(Documented.class).setContents(TinyUtil.unescape(s.substring(5)));
else error();
return index;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
/**
* Lightweight remapper for descriptors in place of the general heavyweight {@link cn.maxpixel.mcdecompiler.mapping.remapper.MappingRemapper}s.
*/
public class DescriptorRemapper {// TODO
public class DescriptorRemapper {
private final Object2ObjectOpenHashMap<String, ? extends ClassMapping<? extends Mapping>> mappingByUnm;
private final Object2ObjectOpenHashMap<String, ? extends ClassMapping<? extends Mapping>> mappingByMap;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package cn.maxpixel.mcdecompiler.mapping.util;

public final class TinyUtil {
private TinyUtil() {
throw new AssertionError("No instances");
}

public static String escape(String unescaped) {
StringBuilder sb = new StringBuilder(unescaped.length() + 16);
int mark = 0;
for (int i = 0; i < unescaped.length(); i++) {
char escaped = switch (unescaped.charAt(i)) {
case '\\' -> '\\';
case '\n' -> 'n';
case '\r' -> 'r';
case '\t' -> 't';
case '\0' -> '0';
default -> '\0';
};
if (escaped != 0) {
if (mark < i) sb.append(unescaped, mark, i);
mark = i + 1;
sb.append('\\').append(escaped);
}
}
return sb.append(unescaped, mark, unescaped.length()).toString();
}

public static String unescape(String escaped) {
StringBuilder sb = new StringBuilder(escaped.length());
int mark = 0;
for (int i = escaped.indexOf('\\'); i >= 0; i = escaped.indexOf('\\', mark)) {
char unescaped = switch (escaped.charAt(++i)) {
case '\\' -> '\\';
case 'n' -> '\n';
case 'r' -> '\r';
case 't' -> '\t';
case '0' -> '\0';
default -> throw new IllegalArgumentException("Unknown escape character: \\" + escaped.charAt(i));
};
if (mark < i - 1) sb.append(escaped, mark, i - 1);
mark = i + 1;
sb.append(unescaped);
}
return sb.append(escaped, mark, escaped.length()).toString();
}
}

0 comments on commit b200fad

Please sign in to comment.