From 72176117bf75866fc702bbb094e7adc6661f2b01 Mon Sep 17 00:00:00 2001 From: Toshimichi0915 Date: Sun, 12 Jun 2022 21:24:41 +0900 Subject: Add Recaf format support (#451) * Add Recaf format support * Update language files Co-authored-by: 2xsaiko --- .../translation/mapping/serde/MappingFormat.java | 4 +- .../mapping/serde/recaf/RecafMappingsReader.java | 61 ++++++++++++++++ .../mapping/serde/recaf/RecafMappingsWriter.java | 85 ++++++++++++++++++++++ 3 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/recaf/RecafMappingsReader.java create mode 100644 enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/recaf/RecafMappingsWriter.java (limited to 'enigma/src/main/java/cuchaz') diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java index ca275eb..062c877 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java @@ -6,6 +6,7 @@ import cuchaz.enigma.translation.mapping.MappingDelta; import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsReader; import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsWriter; import cuchaz.enigma.translation.mapping.serde.proguard.ProguardMappingsReader; +import cuchaz.enigma.translation.mapping.serde.recaf.RecafMappingsReader; import cuchaz.enigma.translation.mapping.serde.srg.SrgMappingsWriter; import cuchaz.enigma.translation.mapping.serde.tiny.TinyMappingsReader; import cuchaz.enigma.translation.mapping.serde.tiny.TinyMappingsWriter; @@ -24,7 +25,8 @@ public enum MappingFormat { TINY_V2(new TinyV2Writer("intermediary", "named"), new TinyV2Reader()), TINY_FILE(TinyMappingsWriter.INSTANCE, TinyMappingsReader.INSTANCE), SRG_FILE(SrgMappingsWriter.INSTANCE, null), - PROGUARD(null, ProguardMappingsReader.INSTANCE); + PROGUARD(null, ProguardMappingsReader.INSTANCE), + RECAF(null, RecafMappingsReader.INSTANCE); private final MappingsWriter writer; diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/recaf/RecafMappingsReader.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/recaf/RecafMappingsReader.java new file mode 100644 index 0000000..483e4e4 --- /dev/null +++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/recaf/RecafMappingsReader.java @@ -0,0 +1,61 @@ +package cuchaz.enigma.translation.mapping.serde.recaf; + +import cuchaz.enigma.ProgressListener; +import cuchaz.enigma.translation.mapping.EntryMapping; +import cuchaz.enigma.translation.mapping.serde.MappingParseException; +import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; +import cuchaz.enigma.translation.mapping.serde.MappingsReader; +import cuchaz.enigma.translation.mapping.tree.EntryTree; +import cuchaz.enigma.translation.mapping.tree.HashEntryTree; +import cuchaz.enigma.translation.representation.MethodDescriptor; +import cuchaz.enigma.translation.representation.TypeDescriptor; +import cuchaz.enigma.translation.representation.entry.ClassEntry; +import cuchaz.enigma.translation.representation.entry.FieldEntry; +import cuchaz.enigma.translation.representation.entry.MethodEntry; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RecafMappingsReader implements MappingsReader { + + public static final RecafMappingsReader INSTANCE = new RecafMappingsReader(); + private static final Pattern METHOD_PATTERN = Pattern.compile("(.*?)\\.(.*?)(\\(.*?) (.*)"); + private static final Pattern FIELD_PATTERN = Pattern.compile("(.*?)\\.(.*?) (.*?) (.*)"); + private static final Pattern CLASS_PATTERN = Pattern.compile("(.*?) (.*)"); + + @Override + public EntryTree read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws MappingParseException, IOException { + EntryTree mappings = new HashEntryTree<>(); + List lines = Files.readAllLines(path); + + for (String line : lines) { + Matcher methodMatcher = METHOD_PATTERN.matcher(line); + if (methodMatcher.find()) { + ClassEntry owner = new ClassEntry(methodMatcher.group(1)); + String name = methodMatcher.group(2); + MethodDescriptor desc = new MethodDescriptor(methodMatcher.group(3)); + mappings.insert(new MethodEntry(owner, name, desc), new EntryMapping(methodMatcher.group(4))); + continue; + } + + Matcher fieldMatcher = FIELD_PATTERN.matcher(line); + if (fieldMatcher.find()) { + ClassEntry owner = new ClassEntry(fieldMatcher.group(1)); + String name = fieldMatcher.group(2); + TypeDescriptor desc = new TypeDescriptor(fieldMatcher.group(3)); + mappings.insert(new FieldEntry(owner, name, desc), new EntryMapping(fieldMatcher.group(4))); + continue; + } + + Matcher classMatcher = CLASS_PATTERN.matcher(line); + if (classMatcher.find()) { + mappings.insert(new ClassEntry(classMatcher.group(1)), new EntryMapping(classMatcher.group(2))); + } + } + return mappings; + } +} diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/recaf/RecafMappingsWriter.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/recaf/RecafMappingsWriter.java new file mode 100644 index 0000000..aa29ff6 --- /dev/null +++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/recaf/RecafMappingsWriter.java @@ -0,0 +1,85 @@ +package cuchaz.enigma.translation.mapping.serde.recaf; + +import com.google.common.collect.Lists; +import cuchaz.enigma.ProgressListener; +import cuchaz.enigma.translation.mapping.EntryMapping; +import cuchaz.enigma.translation.mapping.MappingDelta; +import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; +import cuchaz.enigma.translation.mapping.serde.MappingsWriter; +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.MethodEntry; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; + +public class RecafMappingsWriter implements MappingsWriter { + + public static final RecafMappingsWriter INSTANCE = new RecafMappingsWriter(); + + @Override + public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { + try { + Files.deleteIfExists(path); + Files.createFile(path); + } catch (IOException e) { + e.printStackTrace(); + } + + try (BufferedWriter writer = Files.newBufferedWriter(path)) { + Lists.newArrayList(mappings) + .stream() + .map(EntryTreeNode::getEntry) + .forEach(entry -> writeEntry(writer, mappings, entry)); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void writeEntry(Writer writer, EntryTree mappings, Entry entry) { + EntryTreeNode node = mappings.findNode(entry); + if (node == null) { + return; + } + + EntryMapping mapping = mappings.get(entry); + + try { + if (mapping != null && mapping.targetName() != null) { + if (entry instanceof ClassEntry classEntry) { + + writer.write(classEntry.getFullName()); + writer.write(" "); + writer.write(mapping.targetName()); + + } else if (entry instanceof FieldEntry fieldEntry) { + + writer.write(fieldEntry.getFullName()); + writer.write(" "); + writer.write(fieldEntry.getDesc().toString()); + writer.write(" "); + writer.write(mapping.targetName()); + + } else if (entry instanceof MethodEntry methodEntry) { + + writer.write(methodEntry.getFullName()); + writer.write(methodEntry.getDesc().toString()); + writer.write(" "); + writer.write(mapping.targetName()); + + } + writer.write("\n"); + } + } catch (IOException e) { + e.printStackTrace(); + } + + node.getChildren().forEach(child -> writeEntry(writer, mappings, child)); + } +} -- cgit v1.2.3