diff options
31 files changed, 34 insertions, 2016 deletions
diff --git a/enigma-cli/src/main/java/cuchaz/enigma/command/Command.java b/enigma-cli/src/main/java/cuchaz/enigma/command/Command.java index 7f42f3aa..30afb2c2 100644 --- a/enigma-cli/src/main/java/cuchaz/enigma/command/Command.java +++ b/enigma-cli/src/main/java/cuchaz/enigma/command/Command.java | |||
| @@ -7,7 +7,6 @@ import java.nio.file.Path; | |||
| 7 | import java.nio.file.Paths; | 7 | import java.nio.file.Paths; |
| 8 | import java.util.ArrayList; | 8 | import java.util.ArrayList; |
| 9 | import java.util.List; | 9 | import java.util.List; |
| 10 | import java.util.Locale; | ||
| 11 | 10 | ||
| 12 | import net.fabricmc.mappingio.MappingReader; | 11 | import net.fabricmc.mappingio.MappingReader; |
| 13 | import net.fabricmc.mappingio.tree.MemoryMappingTree; | 12 | import net.fabricmc.mappingio.tree.MemoryMappingTree; |
| @@ -17,7 +16,6 @@ import cuchaz.enigma.Enigma; | |||
| 17 | import cuchaz.enigma.EnigmaProject; | 16 | import cuchaz.enigma.EnigmaProject; |
| 18 | import cuchaz.enigma.ProgressListener; | 17 | import cuchaz.enigma.ProgressListener; |
| 19 | import cuchaz.enigma.translation.mapping.EntryMapping; | 18 | import cuchaz.enigma.translation.mapping.EntryMapping; |
| 20 | import cuchaz.enigma.translation.mapping.serde.MappingFormat; | ||
| 21 | import cuchaz.enigma.translation.mapping.serde.MappingIoConverter; | 19 | import cuchaz.enigma.translation.mapping.serde.MappingIoConverter; |
| 22 | import cuchaz.enigma.translation.mapping.serde.MappingParseException; | 20 | import cuchaz.enigma.translation.mapping.serde.MappingParseException; |
| 23 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | 21 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; |
| @@ -57,11 +55,6 @@ public abstract class Command { | |||
| 57 | } | 55 | } |
| 58 | 56 | ||
| 59 | protected static EntryTree<EntryMapping> readMappings(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException { | 57 | protected static EntryTree<EntryMapping> readMappings(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException { |
| 60 | // Legacy | ||
| 61 | if (path.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".zip")) { | ||
| 62 | return MappingFormat.ENIGMA_ZIP.read(path, progress, saveParameters, null); | ||
| 63 | } | ||
| 64 | |||
| 65 | net.fabricmc.mappingio.format.MappingFormat format = MappingReader.detectFormat(path); | 58 | net.fabricmc.mappingio.format.MappingFormat format = MappingReader.detectFormat(path); |
| 66 | if (format == null) throw new IllegalArgumentException("Unknown mapping format!"); | 59 | if (format == null) throw new IllegalArgumentException("Unknown mapping format!"); |
| 67 | 60 | ||
diff --git a/enigma-cli/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java b/enigma-cli/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java index 7c6bf436..1bd72ac4 100644 --- a/enigma-cli/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java +++ b/enigma-cli/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java | |||
| @@ -15,8 +15,6 @@ import cuchaz.enigma.translation.mapping.serde.MappingFormat; | |||
| 15 | import cuchaz.enigma.translation.mapping.serde.MappingIoConverter; | 15 | import cuchaz.enigma.translation.mapping.serde.MappingIoConverter; |
| 16 | import cuchaz.enigma.translation.mapping.serde.MappingParseException; | 16 | import cuchaz.enigma.translation.mapping.serde.MappingParseException; |
| 17 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | 17 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; |
| 18 | import cuchaz.enigma.translation.mapping.serde.tiny.TinyMappingsWriter; | ||
| 19 | import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Writer; | ||
| 20 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 18 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 21 | 19 | ||
| 22 | public final class MappingCommandsUtil { | 20 | public final class MappingCommandsUtil { |
| @@ -25,7 +23,7 @@ public final class MappingCommandsUtil { | |||
| 25 | 23 | ||
| 26 | public static EntryTree<EntryMapping> read(String type, Path path, MappingSaveParameters saveParameters) throws MappingParseException, IOException { | 24 | public static EntryTree<EntryMapping> read(String type, Path path, MappingSaveParameters saveParameters) throws MappingParseException, IOException { |
| 27 | if (type.equals("enigma")) { | 25 | if (type.equals("enigma")) { |
| 28 | return (Files.isDirectory(path) ? MappingFormat.ENIGMA_DIRECTORY : MappingFormat.ENIGMA_ZIP).read(path, ProgressListener.none(), saveParameters, null); | 26 | return (Files.isDirectory(path) ? MappingFormat.ENIGMA_DIRECTORY : MappingFormat.ENIGMA_FILE).read(path, ProgressListener.none(), saveParameters, null); |
| 29 | } | 27 | } |
| 30 | 28 | ||
| 31 | if (type.equals("tiny")) { | 29 | if (type.equals("tiny")) { |
| @@ -62,11 +60,6 @@ public final class MappingCommandsUtil { | |||
| 62 | throw new IllegalArgumentException("specify column names as 'tinyv2:from_namespace:to_namespace'"); | 60 | throw new IllegalArgumentException("specify column names as 'tinyv2:from_namespace:to_namespace'"); |
| 63 | } | 61 | } |
| 64 | 62 | ||
| 65 | if (!System.getProperty("enigma.use_mappingio", "true").equals("true")) { | ||
| 66 | new TinyV2Writer(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters); | ||
| 67 | return; | ||
| 68 | } | ||
| 69 | |||
| 70 | try { | 63 | try { |
| 71 | VisitableMappingTree tree = MappingIoConverter.toMappingIo(mappings, ProgressListener.none(), split[1], split[2]); | 64 | VisitableMappingTree tree = MappingIoConverter.toMappingIo(mappings, ProgressListener.none(), split[1], split[2]); |
| 72 | tree.accept(MappingWriter.create(path, net.fabricmc.mappingio.format.MappingFormat.TINY_2_FILE)); | 65 | tree.accept(MappingWriter.create(path, net.fabricmc.mappingio.format.MappingFormat.TINY_2_FILE)); |
| @@ -84,11 +77,6 @@ public final class MappingCommandsUtil { | |||
| 84 | throw new IllegalArgumentException("specify column names as 'tiny:from_column:to_column'"); | 77 | throw new IllegalArgumentException("specify column names as 'tiny:from_column:to_column'"); |
| 85 | } | 78 | } |
| 86 | 79 | ||
| 87 | if (!System.getProperty("enigma.use_mappingio", "true").equals("true")) { | ||
| 88 | new TinyMappingsWriter(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters); | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | |||
| 92 | try { | 80 | try { |
| 93 | VisitableMappingTree tree = MappingIoConverter.toMappingIo(mappings, ProgressListener.none(), split[1], split[2]); | 81 | VisitableMappingTree tree = MappingIoConverter.toMappingIo(mappings, ProgressListener.none(), split[1], split[2]); |
| 94 | tree.accept(MappingWriter.create(path, net.fabricmc.mappingio.format.MappingFormat.TINY_FILE)); | 82 | tree.accept(MappingWriter.create(path, net.fabricmc.mappingio.format.MappingFormat.TINY_FILE)); |
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/DedicatedEnigmaServer.java b/enigma-server/src/main/java/cuchaz/enigma/network/DedicatedEnigmaServer.java index 24fd9ff3..f7112cff 100644 --- a/enigma-server/src/main/java/cuchaz/enigma/network/DedicatedEnigmaServer.java +++ b/enigma-server/src/main/java/cuchaz/enigma/network/DedicatedEnigmaServer.java | |||
| @@ -6,7 +6,6 @@ import java.nio.file.Files; | |||
| 6 | import java.nio.file.Path; | 6 | import java.nio.file.Path; |
| 7 | import java.nio.file.Paths; | 7 | import java.nio.file.Paths; |
| 8 | import java.util.List; | 8 | import java.util.List; |
| 9 | import java.util.Locale; | ||
| 10 | import java.util.concurrent.BlockingQueue; | 9 | import java.util.concurrent.BlockingQueue; |
| 11 | import java.util.concurrent.Executors; | 10 | import java.util.concurrent.Executors; |
| 12 | import java.util.concurrent.LinkedBlockingDeque; | 11 | import java.util.concurrent.LinkedBlockingDeque; |
| @@ -104,8 +103,6 @@ public class DedicatedEnigmaServer extends EnigmaServer { | |||
| 104 | 103 | ||
| 105 | if (Files.isDirectory(mappingsFile)) { | 104 | if (Files.isDirectory(mappingsFile)) { |
| 106 | mappingFormat = MappingFormat.ENIGMA_DIRECTORY; | 105 | mappingFormat = MappingFormat.ENIGMA_DIRECTORY; |
| 107 | } else if (mappingsFile.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".zip")) { | ||
| 108 | mappingFormat = MappingFormat.ENIGMA_ZIP; | ||
| 109 | } else { | 106 | } else { |
| 110 | mappingFormat = MappingFormat.ENIGMA_FILE; | 107 | mappingFormat = MappingFormat.ENIGMA_FILE; |
| 111 | } | 108 | } |
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java index 1853a9fc..a2b3bd9d 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java | |||
| @@ -31,7 +31,6 @@ import javax.swing.JFrame; | |||
| 31 | import javax.swing.JOptionPane; | 31 | import javax.swing.JOptionPane; |
| 32 | import javax.swing.SwingUtilities; | 32 | import javax.swing.SwingUtilities; |
| 33 | 33 | ||
| 34 | import org.jetbrains.annotations.ApiStatus; | ||
| 35 | import org.jetbrains.annotations.Nullable; | 34 | import org.jetbrains.annotations.Nullable; |
| 36 | 35 | ||
| 37 | import cuchaz.enigma.Enigma; | 36 | import cuchaz.enigma.Enigma; |
| @@ -172,12 +171,6 @@ public class GuiController implements ClientPacketHandler, GuiView, DataInvalida | |||
| 172 | this.gui.onCloseJar(); | 171 | this.gui.onCloseJar(); |
| 173 | } | 172 | } |
| 174 | 173 | ||
| 175 | @ApiStatus.Internal | ||
| 176 | public CompletableFuture<Void> openMappings(MappingFormat format, Path path, boolean useMappingIo) { | ||
| 177 | System.getProperties().setProperty("enigma.use_mappingio", useMappingIo ? "true" : "false"); | ||
| 178 | return openMappings(format, path); | ||
| 179 | } | ||
| 180 | |||
| 181 | public CompletableFuture<Void> openMappings(MappingFormat format, Path path) { | 174 | public CompletableFuture<Void> openMappings(MappingFormat format, Path path) { |
| 182 | if (project == null) { | 175 | if (project == null) { |
| 183 | return CompletableFuture.completedFuture(null); | 176 | return CompletableFuture.completedFuture(null); |
| @@ -220,12 +213,6 @@ public class GuiController implements ClientPacketHandler, GuiView, DataInvalida | |||
| 220 | return saveMappings(path, loadedMappingFormat); | 213 | return saveMappings(path, loadedMappingFormat); |
| 221 | } | 214 | } |
| 222 | 215 | ||
| 223 | @ApiStatus.Internal | ||
| 224 | public CompletableFuture<Void> saveMappings(Path path, MappingFormat format, boolean useMappingIo) { | ||
| 225 | System.getProperties().setProperty("enigma.use_mappingio", useMappingIo ? "true" : "false"); | ||
| 226 | return saveMappings(path, format); | ||
| 227 | } | ||
| 228 | |||
| 229 | /** | 216 | /** |
| 230 | * Saves the mappings, with a dialog popping up, showing the progress. | 217 | * Saves the mappings, with a dialog popping up, showing the progress. |
| 231 | * | 218 | * |
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/Main.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/Main.java index b9ad19e8..0ed500e3 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/Main.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/Main.java | |||
| @@ -18,7 +18,6 @@ import java.nio.file.Path; | |||
| 18 | import java.nio.file.Paths; | 18 | import java.nio.file.Paths; |
| 19 | import java.util.EnumSet; | 19 | import java.util.EnumSet; |
| 20 | import java.util.List; | 20 | import java.util.List; |
| 21 | import java.util.Locale; | ||
| 22 | import java.util.Set; | 21 | import java.util.Set; |
| 23 | 22 | ||
| 24 | import joptsimple.OptionException; | 23 | import joptsimple.OptionException; |
| @@ -148,8 +147,6 @@ public class Main { | |||
| 148 | 147 | ||
| 149 | if (Files.isDirectory(mappingsPath)) { | 148 | if (Files.isDirectory(mappingsPath)) { |
| 150 | controller.openMappings(MappingFormat.ENIGMA_DIRECTORY, mappingsPath); | 149 | controller.openMappings(MappingFormat.ENIGMA_DIRECTORY, mappingsPath); |
| 151 | } else if (mappingsPath.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".zip")) { | ||
| 152 | controller.openMappings(MappingFormat.ENIGMA_ZIP, mappingsPath); | ||
| 153 | } else { | 150 | } else { |
| 154 | controller.openMappings(MappingFormat.ENIGMA_FILE, mappingsPath); | 151 | controller.openMappings(MappingFormat.ENIGMA_FILE, mappingsPath); |
| 155 | } | 152 | } |
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java index 02fa9e36..e8917864 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java | |||
| @@ -405,28 +405,13 @@ public class MenuBar { | |||
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | private static void prepareOpenMappingsMenu(JMenu openMappingsMenu, Gui gui) { | 407 | private static void prepareOpenMappingsMenu(JMenu openMappingsMenu, Gui gui) { |
| 408 | // Mapping-IO readers | 408 | for (MappingFormat format : MappingFormat.getReadableFormats()) { |
| 409 | for (MappingFormat format : MappingFormat.values()) { | 409 | addOpenMappingsMenuEntry(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT)), |
| 410 | if (format.getMappingIoCounterpart() != null) { | 410 | format, openMappingsMenu, gui); |
| 411 | addOpenMappingsMenuEntry(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT)), | ||
| 412 | format, true, openMappingsMenu, gui); | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 416 | openMappingsMenu.addSeparator(); | ||
| 417 | |||
| 418 | // Enigma's own readers | ||
| 419 | String legacySuffix = " (" + I18n.translate("legacy") + ")"; | ||
| 420 | |||
| 421 | for (MappingFormat format : MappingFormat.values()) { | ||
| 422 | if (format.getReader() != null) { | ||
| 423 | addOpenMappingsMenuEntry(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT)) + legacySuffix, | ||
| 424 | format, false, openMappingsMenu, gui); | ||
| 425 | } | ||
| 426 | } | 411 | } |
| 427 | } | 412 | } |
| 428 | 413 | ||
| 429 | private static void addOpenMappingsMenuEntry(String text, MappingFormat format, boolean mappingIo, JMenu openMappingsMenu, Gui gui) { | 414 | private static void addOpenMappingsMenuEntry(String text, MappingFormat format, JMenu openMappingsMenu, Gui gui) { |
| 430 | JMenuItem item = new JMenuItem(text); | 415 | JMenuItem item = new JMenuItem(text); |
| 431 | item.addActionListener(event -> { | 416 | item.addActionListener(event -> { |
| 432 | ExtensionFileFilter.setupFileChooser(gui.mappingsFileChooser, format); | 417 | ExtensionFileFilter.setupFileChooser(gui.mappingsFileChooser, format); |
| @@ -434,7 +419,7 @@ public class MenuBar { | |||
| 434 | 419 | ||
| 435 | if (gui.mappingsFileChooser.showOpenDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) { | 420 | if (gui.mappingsFileChooser.showOpenDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) { |
| 436 | File selectedFile = gui.mappingsFileChooser.getSelectedFile(); | 421 | File selectedFile = gui.mappingsFileChooser.getSelectedFile(); |
| 437 | gui.getController().openMappings(format, selectedFile.toPath(), mappingIo); | 422 | gui.getController().openMappings(format, selectedFile.toPath()); |
| 438 | UiConfig.setLastSelectedDir(gui.mappingsFileChooser.getCurrentDirectory().toString()); | 423 | UiConfig.setLastSelectedDir(gui.mappingsFileChooser.getCurrentDirectory().toString()); |
| 439 | } | 424 | } |
| 440 | }); | 425 | }); |
| @@ -442,28 +427,13 @@ public class MenuBar { | |||
| 442 | } | 427 | } |
| 443 | 428 | ||
| 444 | private static void prepareSaveMappingsAsMenu(JMenu saveMappingsAsMenu, JMenuItem saveMappingsItem, Gui gui) { | 429 | private static void prepareSaveMappingsAsMenu(JMenu saveMappingsAsMenu, JMenuItem saveMappingsItem, Gui gui) { |
| 445 | // Mapping-IO writers | 430 | for (MappingFormat format : MappingFormat.getWritableFormats()) { |
| 446 | for (MappingFormat format : MappingFormat.values()) { | 431 | addSaveMappingsAsMenuEntry(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT)), |
| 447 | if (format.hasMappingIoWriter()) { | 432 | format, saveMappingsAsMenu, saveMappingsItem, gui); |
| 448 | addSaveMappingsAsMenuEntry(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT)), | ||
| 449 | format, true, saveMappingsAsMenu, saveMappingsItem, gui); | ||
| 450 | } | ||
| 451 | } | ||
| 452 | |||
| 453 | saveMappingsAsMenu.addSeparator(); | ||
| 454 | |||
| 455 | // Enigma's own writers | ||
| 456 | String legacySuffix = " (" + I18n.translate("legacy") + ")"; | ||
| 457 | |||
| 458 | for (MappingFormat format : MappingFormat.values()) { | ||
| 459 | if (format.getWriter() != null) { | ||
| 460 | addSaveMappingsAsMenuEntry(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT)) + legacySuffix, | ||
| 461 | format, false, saveMappingsAsMenu, saveMappingsItem, gui); | ||
| 462 | } | ||
| 463 | } | 433 | } |
| 464 | } | 434 | } |
| 465 | 435 | ||
| 466 | private static void addSaveMappingsAsMenuEntry(String text, MappingFormat format, boolean mappingIo, JMenu saveMappingsAsMenu, JMenuItem saveMappingsItem, Gui gui) { | 436 | private static void addSaveMappingsAsMenuEntry(String text, MappingFormat format, JMenu saveMappingsAsMenu, JMenuItem saveMappingsItem, Gui gui) { |
| 467 | JMenuItem item = new JMenuItem(text); | 437 | JMenuItem item = new JMenuItem(text); |
| 468 | item.addActionListener(event -> { | 438 | item.addActionListener(event -> { |
| 469 | JFileChooser fileChooser = gui.mappingsFileChooser; | 439 | JFileChooser fileChooser = gui.mappingsFileChooser; |
| @@ -475,7 +445,7 @@ public class MenuBar { | |||
| 475 | 445 | ||
| 476 | if (fileChooser.showSaveDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) { | 446 | if (fileChooser.showSaveDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) { |
| 477 | Path savePath = ExtensionFileFilter.getSavePath(fileChooser); | 447 | Path savePath = ExtensionFileFilter.getSavePath(fileChooser); |
| 478 | gui.getController().saveMappings(savePath, format, mappingIo); | 448 | gui.getController().saveMappings(savePath, format); |
| 479 | saveMappingsItem.setEnabled(true); | 449 | saveMappingsItem.setEnabled(true); |
| 480 | UiConfig.setLastSelectedDir(fileChooser.getCurrentDirectory().toString()); | 450 | UiConfig.setLastSelectedDir(fileChooser.getCurrentDirectory().toString()); |
| 481 | } | 451 | } |
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 ec36d47d..b891f438 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 | |||
| @@ -5,6 +5,7 @@ import java.io.UncheckedIOException; | |||
| 5 | import java.nio.file.Path; | 5 | import java.nio.file.Path; |
| 6 | import java.util.Arrays; | 6 | import java.util.Arrays; |
| 7 | import java.util.List; | 7 | import java.util.List; |
| 8 | import java.util.Objects; | ||
| 8 | 9 | ||
| 9 | import net.fabricmc.mappingio.MappingReader; | 10 | import net.fabricmc.mappingio.MappingReader; |
| 10 | import net.fabricmc.mappingio.MappingWriter; | 11 | import net.fabricmc.mappingio.MappingWriter; |
| @@ -12,56 +13,39 @@ import net.fabricmc.mappingio.tree.MemoryMappingTree; | |||
| 12 | import net.fabricmc.mappingio.tree.VisitOrder; | 13 | import net.fabricmc.mappingio.tree.VisitOrder; |
| 13 | import net.fabricmc.mappingio.tree.VisitableMappingTree; | 14 | import net.fabricmc.mappingio.tree.VisitableMappingTree; |
| 14 | import org.jetbrains.annotations.ApiStatus; | 15 | import org.jetbrains.annotations.ApiStatus; |
| 15 | import org.jetbrains.annotations.Nullable; | ||
| 16 | 16 | ||
| 17 | import cuchaz.enigma.ProgressListener; | 17 | import cuchaz.enigma.ProgressListener; |
| 18 | import cuchaz.enigma.analysis.index.JarIndex; | 18 | import cuchaz.enigma.analysis.index.JarIndex; |
| 19 | import cuchaz.enigma.translation.mapping.EntryMapping; | 19 | import cuchaz.enigma.translation.mapping.EntryMapping; |
| 20 | import cuchaz.enigma.translation.mapping.MappingDelta; | 20 | import cuchaz.enigma.translation.mapping.MappingDelta; |
| 21 | import cuchaz.enigma.translation.mapping.MappingOperations; | 21 | import cuchaz.enigma.translation.mapping.MappingOperations; |
| 22 | import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsReader; | ||
| 23 | import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsWriter; | 22 | import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsWriter; |
| 24 | import cuchaz.enigma.translation.mapping.serde.proguard.ProguardMappingsReader; | ||
| 25 | import cuchaz.enigma.translation.mapping.serde.recaf.RecafMappingsReader; | ||
| 26 | import cuchaz.enigma.translation.mapping.serde.recaf.RecafMappingsWriter; | ||
| 27 | import cuchaz.enigma.translation.mapping.serde.srg.SrgMappingsWriter; | ||
| 28 | import cuchaz.enigma.translation.mapping.serde.tiny.TinyMappingsReader; | ||
| 29 | import cuchaz.enigma.translation.mapping.serde.tiny.TinyMappingsWriter; | ||
| 30 | import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Reader; | ||
| 31 | import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Writer; | ||
| 32 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 23 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 33 | import cuchaz.enigma.utils.I18n; | 24 | import cuchaz.enigma.utils.I18n; |
| 34 | 25 | ||
| 35 | public enum MappingFormat { | 26 | public enum MappingFormat { |
| 36 | ENIGMA_FILE(EnigmaMappingsWriter.FILE, EnigmaMappingsReader.FILE, FileType.MAPPING, net.fabricmc.mappingio.format.MappingFormat.ENIGMA_FILE), | 27 | ENIGMA_FILE(FileType.MAPPING, net.fabricmc.mappingio.format.MappingFormat.ENIGMA_FILE), |
| 37 | ENIGMA_DIRECTORY(EnigmaMappingsWriter.DIRECTORY, EnigmaMappingsReader.DIRECTORY, FileType.DIRECTORY, net.fabricmc.mappingio.format.MappingFormat.ENIGMA_DIR), | 28 | ENIGMA_DIRECTORY(FileType.DIRECTORY, net.fabricmc.mappingio.format.MappingFormat.ENIGMA_DIR), |
| 38 | ENIGMA_ZIP(EnigmaMappingsWriter.ZIP, EnigmaMappingsReader.ZIP, FileType.ZIP, null), | 29 | TINY_V2(FileType.TINY, net.fabricmc.mappingio.format.MappingFormat.TINY_2_FILE), |
| 39 | TINY_V2(new TinyV2Writer("intermediary", "named"), new TinyV2Reader(), FileType.TINY, net.fabricmc.mappingio.format.MappingFormat.TINY_2_FILE), | 30 | TINY_FILE(FileType.TINY, net.fabricmc.mappingio.format.MappingFormat.TINY_FILE), |
| 40 | TINY_FILE(TinyMappingsWriter.INSTANCE, TinyMappingsReader.INSTANCE, FileType.TINY, net.fabricmc.mappingio.format.MappingFormat.TINY_FILE), | 31 | SRG_FILE(FileType.SRG, net.fabricmc.mappingio.format.MappingFormat.SRG_FILE), |
| 41 | SRG_FILE(SrgMappingsWriter.INSTANCE, null, FileType.SRG, net.fabricmc.mappingio.format.MappingFormat.SRG_FILE), | 32 | XSRG_FILE(FileType.XSRG, net.fabricmc.mappingio.format.MappingFormat.XSRG_FILE), |
| 42 | XSRG_FILE(null, null, FileType.XSRG, net.fabricmc.mappingio.format.MappingFormat.XSRG_FILE), | 33 | JAM_FILE(FileType.JAM, net.fabricmc.mappingio.format.MappingFormat.JAM_FILE), |
| 43 | JAM_FILE(null, null, FileType.JAM, net.fabricmc.mappingio.format.MappingFormat.JAM_FILE), | 34 | CSRG_FILE(FileType.CSRG, net.fabricmc.mappingio.format.MappingFormat.CSRG_FILE), |
| 44 | CSRG_FILE(null, null, FileType.CSRG, net.fabricmc.mappingio.format.MappingFormat.CSRG_FILE), | 35 | TSRG_FILE(FileType.TSRG, net.fabricmc.mappingio.format.MappingFormat.TSRG_FILE), |
| 45 | TSRG_FILE(null, null, FileType.TSRG, net.fabricmc.mappingio.format.MappingFormat.TSRG_FILE), | 36 | TSRG_2_FILE(FileType.TSRG, net.fabricmc.mappingio.format.MappingFormat.TSRG_2_FILE), |
| 46 | TSRG_2_FILE(null, null, FileType.TSRG, net.fabricmc.mappingio.format.MappingFormat.TSRG_2_FILE), | 37 | PROGUARD(FileType.TXT, net.fabricmc.mappingio.format.MappingFormat.PROGUARD_FILE), |
| 47 | PROGUARD(null, ProguardMappingsReader.INSTANCE, FileType.TXT, net.fabricmc.mappingio.format.MappingFormat.PROGUARD_FILE), | 38 | RECAF(FileType.TXT, net.fabricmc.mappingio.format.MappingFormat.RECAF_SIMPLE_FILE), |
| 48 | RECAF(RecafMappingsWriter.INSTANCE, RecafMappingsReader.INSTANCE, FileType.TXT, net.fabricmc.mappingio.format.MappingFormat.RECAF_SIMPLE_FILE), | 39 | JOBF_FILE(FileType.JOBF, net.fabricmc.mappingio.format.MappingFormat.JOBF_FILE), |
| 49 | JOBF_FILE(null, null, FileType.JOBF, net.fabricmc.mappingio.format.MappingFormat.JOBF_FILE), | 40 | INTELLIJ_MIGRATION_MAP_FILE(FileType.XML, net.fabricmc.mappingio.format.MappingFormat.INTELLIJ_MIGRATION_MAP_FILE); |
| 50 | INTELLIJ_MIGRATION_MAP_FILE(null, null, FileType.XML, net.fabricmc.mappingio.format.MappingFormat.INTELLIJ_MIGRATION_MAP_FILE); | 41 | |
| 51 | |||
| 52 | private final MappingsWriter writer; | ||
| 53 | private final MappingsReader reader; | ||
| 54 | private final FileType fileType; | 42 | private final FileType fileType; |
| 55 | private final net.fabricmc.mappingio.format.MappingFormat mappingIoCounterpart; | 43 | private final net.fabricmc.mappingio.format.MappingFormat mappingIoCounterpart; |
| 56 | private final boolean hasMappingIoWriter; | ||
| 57 | private boolean usedMappingIoWriterLast; | 44 | private boolean usedMappingIoWriterLast; |
| 58 | 45 | ||
| 59 | MappingFormat(MappingsWriter writer, MappingsReader reader, FileType fileType, net.fabricmc.mappingio.format.MappingFormat mappingIoCounterpart) { | 46 | MappingFormat(FileType fileType, net.fabricmc.mappingio.format.MappingFormat mappingIoCounterpart) { |
| 60 | this.writer = writer; | ||
| 61 | this.reader = reader; | ||
| 62 | this.fileType = fileType; | 47 | this.fileType = fileType; |
| 63 | this.mappingIoCounterpart = mappingIoCounterpart; | 48 | this.mappingIoCounterpart = Objects.requireNonNull(mappingIoCounterpart); |
| 64 | this.hasMappingIoWriter = mappingIoCounterpart == null ? false : mappingIoCounterpart.hasWriter; | ||
| 65 | } | 49 | } |
| 66 | 50 | ||
| 67 | public void write(EntryTree<EntryMapping> mappings, Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) { | 51 | public void write(EntryTree<EntryMapping> mappings, Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) { |
| @@ -69,10 +53,8 @@ public enum MappingFormat { | |||
| 69 | } | 53 | } |
| 70 | 54 | ||
| 71 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) { | 55 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) { |
| 72 | if (!hasMappingIoWriter || (!useMappingIo() && writer != null)) { | 56 | if (!isWritable()) { |
| 73 | writer.write(mappings, usedMappingIoWriterLast ? MappingDelta.added(mappings) : delta, path, progressListener, saveParameters); | 57 | throw new UnsupportedOperationException("Mapping format " + this + " does not support writing"); |
| 74 | usedMappingIoWriterLast = false; | ||
| 75 | return; | ||
| 76 | } | 58 | } |
| 77 | 59 | ||
| 78 | try { | 60 | try { |
| @@ -103,10 +85,6 @@ public enum MappingFormat { | |||
| 103 | } | 85 | } |
| 104 | 86 | ||
| 105 | public EntryTree<EntryMapping> read(Path path, ProgressListener progressListener, MappingSaveParameters saveParameters, JarIndex index) throws IOException, MappingParseException { | 87 | public EntryTree<EntryMapping> read(Path path, ProgressListener progressListener, MappingSaveParameters saveParameters, JarIndex index) throws IOException, MappingParseException { |
| 106 | if (mappingIoCounterpart == null || (!useMappingIo() && reader != null)) { | ||
| 107 | return reader.read(path, progressListener, saveParameters); | ||
| 108 | } | ||
| 109 | |||
| 110 | String loadingMessage; | 88 | String loadingMessage; |
| 111 | 89 | ||
| 112 | if (mappingIoCounterpart.hasSingleFile()) { | 90 | if (mappingIoCounterpart.hasSingleFile()) { |
| @@ -124,56 +102,17 @@ public enum MappingFormat { | |||
| 124 | return this == PROGUARD ? MappingOperations.invert(mappings) : mappings; | 102 | return this == PROGUARD ? MappingOperations.invert(mappings) : mappings; |
| 125 | } | 103 | } |
| 126 | 104 | ||
| 127 | /** | ||
| 128 | * @return Enigma's native writer for the format, or {@code null} if none exists. | ||
| 129 | * | ||
| 130 | * @deprecated Use {@link #isWritable()} and {@link #write(EntryTree, Path, ProgressListener, MappingSaveParameters)} instead, | ||
| 131 | * which take the new Mapping-IO equivalents (and eventual replacements) into account. | ||
| 132 | */ | ||
| 133 | @Nullable | ||
| 134 | @Deprecated | ||
| 135 | public MappingsWriter getWriter() { | ||
| 136 | return writer; | ||
| 137 | } | ||
| 138 | |||
| 139 | /** | ||
| 140 | * @return Enigma's native reader for the format, or {@code null} if none exists. | ||
| 141 | * | ||
| 142 | * @deprecated Use {@link #isReadable()} and {@link #read(Path, ProgressListener, MappingSaveParameters, JarIndex)} instead, | ||
| 143 | * which take the new Mapping-IO equivalents (and eventual replacements) into account. | ||
| 144 | */ | ||
| 145 | @Nullable | ||
| 146 | @Deprecated | ||
| 147 | public MappingsReader getReader() { | ||
| 148 | return reader; | ||
| 149 | } | ||
| 150 | |||
| 151 | @ApiStatus.Internal | 105 | @ApiStatus.Internal |
| 152 | public FileType getFileType() { | 106 | public FileType getFileType() { |
| 153 | return fileType; | 107 | return fileType; |
| 154 | } | 108 | } |
| 155 | 109 | ||
| 156 | @Nullable | ||
| 157 | @ApiStatus.Internal | ||
| 158 | public net.fabricmc.mappingio.format.MappingFormat getMappingIoCounterpart() { | ||
| 159 | return mappingIoCounterpart; | ||
| 160 | } | ||
| 161 | |||
| 162 | @ApiStatus.Internal | ||
| 163 | public boolean hasMappingIoWriter() { | ||
| 164 | return hasMappingIoWriter; | ||
| 165 | } | ||
| 166 | |||
| 167 | public boolean isReadable() { | 110 | public boolean isReadable() { |
| 168 | return reader != null || mappingIoCounterpart != null; | 111 | return true; |
| 169 | } | 112 | } |
| 170 | 113 | ||
| 171 | public boolean isWritable() { | 114 | public boolean isWritable() { |
| 172 | return writer != null || hasMappingIoWriter; | 115 | return mappingIoCounterpart.hasWriter; |
| 173 | } | ||
| 174 | |||
| 175 | private boolean useMappingIo() { | ||
| 176 | return System.getProperty("enigma.use_mappingio", "true").equals("true"); | ||
| 177 | } | 116 | } |
| 178 | 117 | ||
| 179 | public static List<MappingFormat> getReadableFormats() { | 118 | public static List<MappingFormat> getReadableFormats() { |
| @@ -199,7 +138,6 @@ public enum MappingFormat { | |||
| 199 | @ApiStatus.Internal | 138 | @ApiStatus.Internal |
| 200 | public record FileType(List<String> extensions) { | 139 | public record FileType(List<String> extensions) { |
| 201 | public static final FileType DIRECTORY = new FileType(); | 140 | public static final FileType DIRECTORY = new FileType(); |
| 202 | public static final FileType ZIP = new FileType(".zip"); | ||
| 203 | public static final FileType MAPPING = new FileType(".mapping", ".mappings"); | 141 | public static final FileType MAPPING = new FileType(".mapping", ".mappings"); |
| 204 | public static final FileType TINY = new FileType(".tiny"); | 142 | public static final FileType TINY = new FileType(".tiny"); |
| 205 | public static final FileType SRG = new FileType(".srg"); | 143 | public static final FileType SRG = new FileType(".srg"); |
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java index 5f466bba..d89205c5 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java | |||
| @@ -21,37 +21,6 @@ public final class MappingHelper { | |||
| 21 | return builder.toString(); | 21 | return builder.toString(); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | public static String unescape(String str) { | ||
| 25 | int pos = str.indexOf('\\'); | ||
| 26 | |||
| 27 | if (pos < 0) { | ||
| 28 | return str; | ||
| 29 | } | ||
| 30 | |||
| 31 | StringBuilder ret = new StringBuilder(str.length() - 1); | ||
| 32 | int start = 0; | ||
| 33 | |||
| 34 | do { | ||
| 35 | ret.append(str, start, pos); | ||
| 36 | pos++; | ||
| 37 | int type; | ||
| 38 | |||
| 39 | if (pos >= str.length()) { | ||
| 40 | throw new RuntimeException("incomplete escape sequence at the end"); | ||
| 41 | } else if ((type = ESCAPED.indexOf(str.charAt(pos))) < 0) { | ||
| 42 | throw new RuntimeException("invalid escape character: \\" + str.charAt(pos)); | ||
| 43 | } else { | ||
| 44 | ret.append(TO_ESCAPE.charAt(type)); | ||
| 45 | } | ||
| 46 | |||
| 47 | start = pos + 1; | ||
| 48 | } while ((pos = str.indexOf('\\', start)) >= 0); | ||
| 49 | |||
| 50 | ret.append(str, start, str.length()); | ||
| 51 | |||
| 52 | return ret.toString(); | ||
| 53 | } | ||
| 54 | |||
| 55 | private MappingHelper() { | 24 | private MappingHelper() { |
| 56 | } | 25 | } |
| 57 | } | 26 | } |
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsReader.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsReader.java deleted file mode 100644 index 4fdfdcba..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsReader.java +++ /dev/null | |||
| @@ -1,12 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde; | ||
| 2 | |||
| 3 | import java.io.IOException; | ||
| 4 | import java.nio.file.Path; | ||
| 5 | |||
| 6 | import cuchaz.enigma.ProgressListener; | ||
| 7 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 8 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 9 | |||
| 10 | public interface MappingsReader { | ||
| 11 | EntryTree<EntryMapping> read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws MappingParseException, IOException; | ||
| 12 | } | ||
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java deleted file mode 100644 index 5c273ad3..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde; | ||
| 2 | |||
| 3 | import java.nio.file.Path; | ||
| 4 | |||
| 5 | import cuchaz.enigma.ProgressListener; | ||
| 6 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 7 | import cuchaz.enigma.translation.mapping.MappingDelta; | ||
| 8 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 9 | |||
| 10 | public interface MappingsWriter { | ||
| 11 | void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters); | ||
| 12 | |||
| 13 | default void write(EntryTree<EntryMapping> mappings, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { | ||
| 14 | write(mappings, MappingDelta.added(mappings), path, progress, saveParameters); | ||
| 15 | } | ||
| 16 | } | ||
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java deleted file mode 100644 index 6465008b..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java +++ /dev/null | |||
| @@ -1,30 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde; | ||
| 2 | |||
| 3 | import java.util.ArrayList; | ||
| 4 | import java.util.List; | ||
| 5 | |||
| 6 | import cuchaz.enigma.translation.mapping.AccessModifier; | ||
| 7 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 8 | |||
| 9 | public final class RawEntryMapping { | ||
| 10 | private final String targetName; | ||
| 11 | private final AccessModifier access; | ||
| 12 | private final List<String> javadocs = new ArrayList<>(); | ||
| 13 | |||
| 14 | public RawEntryMapping(String targetName) { | ||
| 15 | this(targetName, AccessModifier.UNCHANGED); | ||
| 16 | } | ||
| 17 | |||
| 18 | public RawEntryMapping(String targetName, AccessModifier access) { | ||
| 19 | this.access = access; | ||
| 20 | this.targetName = targetName != null && !targetName.equals("-") ? targetName : null; | ||
| 21 | } | ||
| 22 | |||
| 23 | public void addJavadocLine(String line) { | ||
| 24 | javadocs.add(line); | ||
| 25 | } | ||
| 26 | |||
| 27 | public EntryMapping bake() { | ||
| 28 | return new EntryMapping(targetName, access, javadocs.isEmpty() ? null : String.join("\n", javadocs)); | ||
| 29 | } | ||
| 30 | } | ||
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/enigma/EnigmaMappingsReader.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/enigma/EnigmaMappingsReader.java deleted file mode 100644 index 08d0e575..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/enigma/EnigmaMappingsReader.java +++ /dev/null | |||
| @@ -1,361 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde.enigma; | ||
| 2 | |||
| 3 | import java.io.IOException; | ||
| 4 | import java.nio.charset.StandardCharsets; | ||
| 5 | import java.nio.file.FileSystem; | ||
| 6 | import java.nio.file.FileSystems; | ||
| 7 | import java.nio.file.Files; | ||
| 8 | import java.nio.file.NotDirectoryException; | ||
| 9 | import java.nio.file.Path; | ||
| 10 | import java.util.ArrayDeque; | ||
| 11 | import java.util.Arrays; | ||
| 12 | import java.util.Deque; | ||
| 13 | import java.util.List; | ||
| 14 | import java.util.Locale; | ||
| 15 | |||
| 16 | import org.jetbrains.annotations.Nullable; | ||
| 17 | |||
| 18 | import cuchaz.enigma.ProgressListener; | ||
| 19 | import cuchaz.enigma.translation.mapping.AccessModifier; | ||
| 20 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 21 | import cuchaz.enigma.translation.mapping.MappingPair; | ||
| 22 | import cuchaz.enigma.translation.mapping.serde.MappingHelper; | ||
| 23 | import cuchaz.enigma.translation.mapping.serde.MappingParseException; | ||
| 24 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 25 | import cuchaz.enigma.translation.mapping.serde.MappingsReader; | ||
| 26 | import cuchaz.enigma.translation.mapping.serde.RawEntryMapping; | ||
| 27 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 28 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 29 | import cuchaz.enigma.translation.representation.MethodDescriptor; | ||
| 30 | import cuchaz.enigma.translation.representation.TypeDescriptor; | ||
| 31 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 32 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 33 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 34 | import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; | ||
| 35 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 36 | import cuchaz.enigma.utils.I18n; | ||
| 37 | |||
| 38 | public enum EnigmaMappingsReader implements MappingsReader { | ||
| 39 | FILE { | ||
| 40 | @Override | ||
| 41 | public EntryTree<EntryMapping> read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException { | ||
| 42 | progress.init(1, I18n.translate("progress.mappings.loading_file")); | ||
| 43 | |||
| 44 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); | ||
| 45 | readFile(path, mappings); | ||
| 46 | |||
| 47 | progress.step(1, I18n.translate("progress.done")); | ||
| 48 | |||
| 49 | return mappings; | ||
| 50 | } | ||
| 51 | }, | ||
| 52 | DIRECTORY { | ||
| 53 | @Override | ||
| 54 | public EntryTree<EntryMapping> read(Path root, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException { | ||
| 55 | if (!Files.isDirectory(root)) { | ||
| 56 | throw new NotDirectoryException(root.toString()); | ||
| 57 | } | ||
| 58 | |||
| 59 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); | ||
| 60 | List<Path> files = Files.walk(root).filter(f -> !Files.isDirectory(f)).filter(f -> f.toString().endsWith(".mapping")).toList(); | ||
| 61 | |||
| 62 | progress.init(files.size(), I18n.translate("progress.mappings.loading_directory")); | ||
| 63 | int step = 0; | ||
| 64 | |||
| 65 | for (Path file : files) { | ||
| 66 | progress.step(step++, root.relativize(file).toString()); | ||
| 67 | |||
| 68 | if (Files.isHidden(file)) { | ||
| 69 | continue; | ||
| 70 | } | ||
| 71 | |||
| 72 | readFile(file, mappings); | ||
| 73 | } | ||
| 74 | |||
| 75 | return mappings; | ||
| 76 | } | ||
| 77 | }, | ||
| 78 | ZIP { | ||
| 79 | @Override | ||
| 80 | public EntryTree<EntryMapping> read(Path zip, ProgressListener progress, MappingSaveParameters saveParameters) throws MappingParseException, IOException { | ||
| 81 | try (FileSystem fs = FileSystems.newFileSystem(zip, (ClassLoader) null)) { | ||
| 82 | return DIRECTORY.read(fs.getPath("/"), progress, saveParameters); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | }; | ||
| 86 | |||
| 87 | /** | ||
| 88 | * Reads multiple Enigma mapping files. | ||
| 89 | * | ||
| 90 | * @param progress the progress listener | ||
| 91 | * @param paths the Enigma files to read; cannot be empty | ||
| 92 | * @return the parsed mappings | ||
| 93 | * @throws MappingParseException if a mapping file cannot be parsed | ||
| 94 | * @throws IOException if an IO error occurs | ||
| 95 | * @throws IllegalArgumentException if there are no paths to read | ||
| 96 | */ | ||
| 97 | public static EntryTree<EntryMapping> readFiles(ProgressListener progress, Path... paths) throws MappingParseException, IOException { | ||
| 98 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); | ||
| 99 | |||
| 100 | if (paths.length == 0) { | ||
| 101 | throw new IllegalArgumentException("No paths to read mappings from"); | ||
| 102 | } | ||
| 103 | |||
| 104 | progress.init(paths.length, I18n.translate("progress.mappings.loading_directory")); | ||
| 105 | int step = 0; | ||
| 106 | |||
| 107 | for (Path file : paths) { | ||
| 108 | progress.step(step++, paths.toString()); | ||
| 109 | readFile(file, mappings); | ||
| 110 | } | ||
| 111 | |||
| 112 | return mappings; | ||
| 113 | } | ||
| 114 | |||
| 115 | private static void readFile(Path path, EntryTree<EntryMapping> mappings) throws IOException, MappingParseException { | ||
| 116 | List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8); | ||
| 117 | Deque<MappingPair<?, RawEntryMapping>> mappingStack = new ArrayDeque<>(); | ||
| 118 | |||
| 119 | for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { | ||
| 120 | String line = lines.get(lineNumber); | ||
| 121 | int indentation = countIndentation(line, path, lineNumber); | ||
| 122 | |||
| 123 | line = formatLine(line); | ||
| 124 | |||
| 125 | if (line == null) { | ||
| 126 | continue; | ||
| 127 | } | ||
| 128 | |||
| 129 | cleanMappingStack(indentation, mappingStack, mappings); | ||
| 130 | |||
| 131 | try { | ||
| 132 | MappingPair<?, RawEntryMapping> pair = parseLine(mappingStack.peek(), line); | ||
| 133 | |||
| 134 | if (pair != null) { | ||
| 135 | mappingStack.push(pair); | ||
| 136 | } | ||
| 137 | } catch (Throwable t) { | ||
| 138 | throw new MappingParseException(path, lineNumber + 1, t); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | // Clean up rest | ||
| 143 | cleanMappingStack(0, mappingStack, mappings); | ||
| 144 | } | ||
| 145 | |||
| 146 | private static void cleanMappingStack(int indentation, Deque<MappingPair<?, RawEntryMapping>> mappingStack, EntryTree<EntryMapping> mappings) { | ||
| 147 | while (indentation < mappingStack.size()) { | ||
| 148 | MappingPair<?, RawEntryMapping> pair = mappingStack.pop(); | ||
| 149 | |||
| 150 | if (pair.getMapping() != null) { | ||
| 151 | mappings.insert(pair.getEntry(), pair.getMapping().bake()); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | @Nullable | ||
| 157 | private static String formatLine(String line) { | ||
| 158 | line = stripComment(line); | ||
| 159 | line = line.trim(); | ||
| 160 | |||
| 161 | if (line.isEmpty()) { | ||
| 162 | return null; | ||
| 163 | } | ||
| 164 | |||
| 165 | return line; | ||
| 166 | } | ||
| 167 | |||
| 168 | private static String stripComment(String line) { | ||
| 169 | //Dont support comments on javadoc lines | ||
| 170 | if (line.trim().startsWith(EnigmaFormat.COMMENT)) { | ||
| 171 | return line; | ||
| 172 | } | ||
| 173 | |||
| 174 | int commentPos = line.indexOf('#'); | ||
| 175 | |||
| 176 | if (commentPos >= 0) { | ||
| 177 | return line.substring(0, commentPos); | ||
| 178 | } | ||
| 179 | |||
| 180 | return line; | ||
| 181 | } | ||
| 182 | |||
| 183 | private static int countIndentation(String line, Path path, int lineNumber) throws MappingParseException { | ||
| 184 | int indent = 0; | ||
| 185 | |||
| 186 | for (int i = 0; i < line.length(); i++) { | ||
| 187 | if (line.charAt(i) == ' ') { | ||
| 188 | throw new MappingParseException(path, lineNumber + 1, "Spaces must not be used to indent lines!"); | ||
| 189 | } | ||
| 190 | |||
| 191 | if (line.charAt(i) != '\t') { | ||
| 192 | break; | ||
| 193 | } | ||
| 194 | |||
| 195 | indent++; | ||
| 196 | } | ||
| 197 | |||
| 198 | return indent; | ||
| 199 | } | ||
| 200 | |||
| 201 | private static MappingPair<?, RawEntryMapping> parseLine(@Nullable MappingPair<?, RawEntryMapping> parent, String line) { | ||
| 202 | String[] tokens = line.trim().split("\\s"); | ||
| 203 | String keyToken = tokens[0].toUpperCase(Locale.ROOT); | ||
| 204 | Entry<?> parentEntry = parent == null ? null : parent.getEntry(); | ||
| 205 | |||
| 206 | switch (keyToken) { | ||
| 207 | case EnigmaFormat.CLASS: | ||
| 208 | return parseClass(parentEntry, tokens); | ||
| 209 | case EnigmaFormat.FIELD: | ||
| 210 | return parseField(parentEntry, tokens); | ||
| 211 | case EnigmaFormat.METHOD: | ||
| 212 | return parseMethod(parentEntry, tokens); | ||
| 213 | case EnigmaFormat.PARAMETER: | ||
| 214 | return parseArgument(parentEntry, tokens); | ||
| 215 | case EnigmaFormat.COMMENT: | ||
| 216 | readJavadoc(parent, tokens); | ||
| 217 | return null; | ||
| 218 | default: | ||
| 219 | throw new RuntimeException("Unknown token '" + keyToken + "'"); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | private static void readJavadoc(MappingPair<?, RawEntryMapping> parent, String[] tokens) { | ||
| 224 | if (parent == null) { | ||
| 225 | throw new IllegalStateException("Javadoc has no parent!"); | ||
| 226 | } | ||
| 227 | |||
| 228 | // Empty string to concat | ||
| 229 | String jdLine = tokens.length > 1 ? String.join(" ", Arrays.copyOfRange(tokens, 1, tokens.length)) : ""; | ||
| 230 | |||
| 231 | if (parent.getMapping() == null) { | ||
| 232 | parent.setMapping(new RawEntryMapping(parent.getEntry().getName(), AccessModifier.UNCHANGED)); | ||
| 233 | } | ||
| 234 | |||
| 235 | parent.getMapping().addJavadocLine(MappingHelper.unescape(jdLine)); | ||
| 236 | } | ||
| 237 | |||
| 238 | private static MappingPair<ClassEntry, RawEntryMapping> parseClass(@Nullable Entry<?> parent, String[] tokens) { | ||
| 239 | String obfuscatedName = ClassEntry.getInnerName(tokens[1]); | ||
| 240 | ClassEntry obfuscatedEntry; | ||
| 241 | |||
| 242 | if (parent instanceof ClassEntry) { | ||
| 243 | obfuscatedEntry = new ClassEntry((ClassEntry) parent, obfuscatedName); | ||
| 244 | } else { | ||
| 245 | obfuscatedEntry = new ClassEntry(obfuscatedName); | ||
| 246 | } | ||
| 247 | |||
| 248 | String mapping = null; | ||
| 249 | AccessModifier modifier = AccessModifier.UNCHANGED; | ||
| 250 | |||
| 251 | if (tokens.length == 3) { | ||
| 252 | AccessModifier parsedModifier = parseModifier(tokens[2]); | ||
| 253 | |||
| 254 | if (parsedModifier != null) { | ||
| 255 | modifier = parsedModifier; | ||
| 256 | mapping = obfuscatedName; | ||
| 257 | } else { | ||
| 258 | mapping = tokens[2]; | ||
| 259 | } | ||
| 260 | } else if (tokens.length == 4) { | ||
| 261 | mapping = tokens[2]; | ||
| 262 | modifier = parseModifier(tokens[3]); | ||
| 263 | } | ||
| 264 | |||
| 265 | return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier)); | ||
| 266 | } | ||
| 267 | |||
| 268 | private static MappingPair<FieldEntry, RawEntryMapping> parseField(@Nullable Entry<?> parent, String[] tokens) { | ||
| 269 | if (!(parent instanceof ClassEntry)) { | ||
| 270 | throw new RuntimeException("Field must be a child of a class!"); | ||
| 271 | } | ||
| 272 | |||
| 273 | ClassEntry ownerEntry = (ClassEntry) parent; | ||
| 274 | |||
| 275 | String obfuscatedName = tokens[1]; | ||
| 276 | String mapping = null; | ||
| 277 | AccessModifier modifier = AccessModifier.UNCHANGED; | ||
| 278 | TypeDescriptor descriptor; | ||
| 279 | |||
| 280 | if (tokens.length == 3) { | ||
| 281 | descriptor = new TypeDescriptor(tokens[2]); | ||
| 282 | } else if (tokens.length == 4) { | ||
| 283 | AccessModifier parsedModifier = parseModifier(tokens[3]); | ||
| 284 | |||
| 285 | if (parsedModifier != null) { | ||
| 286 | descriptor = new TypeDescriptor(tokens[2]); | ||
| 287 | modifier = parsedModifier; | ||
| 288 | } else { | ||
| 289 | mapping = tokens[2]; | ||
| 290 | descriptor = new TypeDescriptor(tokens[3]); | ||
| 291 | } | ||
| 292 | } else if (tokens.length == 5) { | ||
| 293 | mapping = tokens[2]; | ||
| 294 | modifier = parseModifier(tokens[3]); | ||
| 295 | descriptor = new TypeDescriptor(tokens[4]); | ||
| 296 | } else { | ||
| 297 | throw new RuntimeException("Invalid field declaration"); | ||
| 298 | } | ||
| 299 | |||
| 300 | FieldEntry obfuscatedEntry = new FieldEntry(ownerEntry, obfuscatedName, descriptor); | ||
| 301 | return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier)); | ||
| 302 | } | ||
| 303 | |||
| 304 | private static MappingPair<MethodEntry, RawEntryMapping> parseMethod(@Nullable Entry<?> parent, String[] tokens) { | ||
| 305 | if (!(parent instanceof ClassEntry)) { | ||
| 306 | throw new RuntimeException("Method must be a child of a class!"); | ||
| 307 | } | ||
| 308 | |||
| 309 | ClassEntry ownerEntry = (ClassEntry) parent; | ||
| 310 | |||
| 311 | String obfuscatedName = tokens[1]; | ||
| 312 | String mapping = null; | ||
| 313 | AccessModifier modifier = AccessModifier.UNCHANGED; | ||
| 314 | MethodDescriptor descriptor; | ||
| 315 | |||
| 316 | if (tokens.length == 3) { | ||
| 317 | descriptor = new MethodDescriptor(tokens[2]); | ||
| 318 | } else if (tokens.length == 4) { | ||
| 319 | AccessModifier parsedModifier = parseModifier(tokens[3]); | ||
| 320 | |||
| 321 | if (parsedModifier != null) { | ||
| 322 | modifier = parsedModifier; | ||
| 323 | mapping = obfuscatedName; | ||
| 324 | descriptor = new MethodDescriptor(tokens[2]); | ||
| 325 | } else { | ||
| 326 | mapping = tokens[2]; | ||
| 327 | descriptor = new MethodDescriptor(tokens[3]); | ||
| 328 | } | ||
| 329 | } else if (tokens.length == 5) { | ||
| 330 | mapping = tokens[2]; | ||
| 331 | modifier = parseModifier(tokens[4]); | ||
| 332 | descriptor = new MethodDescriptor(tokens[3]); | ||
| 333 | } else { | ||
| 334 | throw new RuntimeException("Invalid method declaration"); | ||
| 335 | } | ||
| 336 | |||
| 337 | MethodEntry obfuscatedEntry = new MethodEntry(ownerEntry, obfuscatedName, descriptor); | ||
| 338 | return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier)); | ||
| 339 | } | ||
| 340 | |||
| 341 | private static MappingPair<LocalVariableEntry, RawEntryMapping> parseArgument(@Nullable Entry<?> parent, String[] tokens) { | ||
| 342 | if (!(parent instanceof MethodEntry)) { | ||
| 343 | throw new RuntimeException("Method arg must be a child of a method!"); | ||
| 344 | } | ||
| 345 | |||
| 346 | MethodEntry ownerEntry = (MethodEntry) parent; | ||
| 347 | LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerEntry, Integer.parseInt(tokens[1]), "", true, null); | ||
| 348 | String mapping = tokens[2]; | ||
| 349 | |||
| 350 | return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); | ||
| 351 | } | ||
| 352 | |||
| 353 | @Nullable | ||
| 354 | private static AccessModifier parseModifier(String token) { | ||
| 355 | if (token.startsWith("ACC:")) { | ||
| 356 | return AccessModifier.valueOf(token.substring(4)); | ||
| 357 | } | ||
| 358 | |||
| 359 | return null; | ||
| 360 | } | ||
| 361 | } | ||
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/enigma/EnigmaMappingsWriter.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/enigma/EnigmaMappingsWriter.java index 266668dd..b90bb7f2 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/enigma/EnigmaMappingsWriter.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/enigma/EnigmaMappingsWriter.java | |||
| @@ -13,17 +13,12 @@ package cuchaz.enigma.translation.mapping.serde.enigma; | |||
| 13 | 13 | ||
| 14 | import java.io.IOException; | 14 | import java.io.IOException; |
| 15 | import java.io.PrintWriter; | 15 | import java.io.PrintWriter; |
| 16 | import java.net.URI; | ||
| 17 | import java.net.URISyntaxException; | ||
| 18 | import java.nio.file.DirectoryStream; | 16 | import java.nio.file.DirectoryStream; |
| 19 | import java.nio.file.FileSystem; | ||
| 20 | import java.nio.file.FileSystems; | ||
| 21 | import java.nio.file.Files; | 17 | import java.nio.file.Files; |
| 22 | import java.nio.file.Path; | 18 | import java.nio.file.Path; |
| 23 | import java.nio.file.Paths; | 19 | import java.nio.file.Paths; |
| 24 | import java.util.ArrayList; | 20 | import java.util.ArrayList; |
| 25 | import java.util.Collection; | 21 | import java.util.Collection; |
| 26 | import java.util.Collections; | ||
| 27 | import java.util.HashSet; | 22 | import java.util.HashSet; |
| 28 | import java.util.Objects; | 23 | import java.util.Objects; |
| 29 | import java.util.Set; | 24 | import java.util.Set; |
| @@ -50,7 +45,6 @@ import cuchaz.enigma.translation.mapping.serde.MappingFileNameFormat; | |||
| 50 | import cuchaz.enigma.translation.mapping.serde.MappingHelper; | 45 | import cuchaz.enigma.translation.mapping.serde.MappingHelper; |
| 51 | import cuchaz.enigma.translation.mapping.serde.MappingIoConverter; | 46 | import cuchaz.enigma.translation.mapping.serde.MappingIoConverter; |
| 52 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | 47 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; |
| 53 | import cuchaz.enigma.translation.mapping.serde.MappingsWriter; | ||
| 54 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 48 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 55 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | 49 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; |
| 56 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | 50 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; |
| @@ -61,33 +55,9 @@ import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; | |||
| 61 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | 55 | import cuchaz.enigma.translation.representation.entry.MethodEntry; |
| 62 | import cuchaz.enigma.utils.I18n; | 56 | import cuchaz.enigma.utils.I18n; |
| 63 | 57 | ||
| 64 | public enum EnigmaMappingsWriter implements MappingsWriter { | 58 | public enum EnigmaMappingsWriter { |
| 65 | FILE { | ||
| 66 | @Override | ||
| 67 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { | ||
| 68 | Collection<ClassEntry> classes = mappings.getRootNodes().filter(entry -> entry.getEntry() instanceof ClassEntry).map(entry -> (ClassEntry) entry.getEntry()).toList(); | ||
| 69 | |||
| 70 | progress.init(classes.size(), I18n.translate("progress.mappings.writing")); | ||
| 71 | |||
| 72 | int steps = 0; | ||
| 73 | |||
| 74 | try (PrintWriter writer = new LfPrintWriter(Files.newBufferedWriter(path))) { | ||
| 75 | for (ClassEntry classEntry : classes) { | ||
| 76 | progress.step(steps++, classEntry.getFullName()); | ||
| 77 | writeRoot(writer, mappings, classEntry); | ||
| 78 | } | ||
| 79 | } catch (IOException e) { | ||
| 80 | e.printStackTrace(); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | }, | ||
| 84 | DIRECTORY { | 59 | DIRECTORY { |
| 85 | @Override | 60 | @Override |
| 86 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { | ||
| 87 | write(mappings, delta, path, progress, saveParameters, false); | ||
| 88 | } | ||
| 89 | |||
| 90 | @Override | ||
| 91 | @ApiStatus.Internal | 61 | @ApiStatus.Internal |
| 92 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters, boolean useMio) { | 62 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters, boolean useMio) { |
| 93 | Collection<ClassEntry> changedClasses = delta.getChangedRoots().filter(entry -> entry instanceof ClassEntry).map(entry -> (ClassEntry) entry).toList(); | 63 | Collection<ClassEntry> changedClasses = delta.getChangedRoots().filter(entry -> entry instanceof ClassEntry).map(entry -> (ClassEntry) entry).toList(); |
| @@ -199,18 +169,6 @@ public enum EnigmaMappingsWriter implements MappingsWriter { | |||
| 199 | private Path resolve(Path root, ClassEntry classEntry) { | 169 | private Path resolve(Path root, ClassEntry classEntry) { |
| 200 | return root.resolve(classEntry.getFullName() + ".mapping"); | 170 | return root.resolve(classEntry.getFullName() + ".mapping"); |
| 201 | } | 171 | } |
| 202 | }, | ||
| 203 | ZIP { | ||
| 204 | @Override | ||
| 205 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path zip, ProgressListener progress, MappingSaveParameters saveParameters) { | ||
| 206 | try (FileSystem fs = FileSystems.newFileSystem(new URI("jar:file", null, zip.toUri().getPath(), ""), Collections.singletonMap("create", "true"))) { | ||
| 207 | DIRECTORY.write(mappings, delta, fs.getPath("/"), progress, saveParameters); | ||
| 208 | } catch (IOException e) { | ||
| 209 | e.printStackTrace(); | ||
| 210 | } catch (URISyntaxException e) { | ||
| 211 | throw new RuntimeException("Unexpected error creating URI for " + zip, e); | ||
| 212 | } | ||
| 213 | } | ||
| 214 | }; | 172 | }; |
| 215 | 173 | ||
| 216 | protected void writeRoot(PrintWriter writer, EntryTree<EntryMapping> mappings, ClassEntry classEntry) { | 174 | protected void writeRoot(PrintWriter writer, EntryTree<EntryMapping> mappings, ClassEntry classEntry) { |
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/proguard/ProguardMappingsReader.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/proguard/ProguardMappingsReader.java deleted file mode 100644 index b839c079..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/proguard/ProguardMappingsReader.java +++ /dev/null | |||
| @@ -1,137 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde.proguard; | ||
| 2 | |||
| 3 | import java.io.IOException; | ||
| 4 | import java.nio.charset.StandardCharsets; | ||
| 5 | import java.nio.file.Files; | ||
| 6 | import java.nio.file.Path; | ||
| 7 | import java.util.regex.Matcher; | ||
| 8 | import java.util.regex.Pattern; | ||
| 9 | |||
| 10 | import cuchaz.enigma.ProgressListener; | ||
| 11 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 12 | import cuchaz.enigma.translation.mapping.MappingOperations; | ||
| 13 | import cuchaz.enigma.translation.mapping.serde.MappingParseException; | ||
| 14 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 15 | import cuchaz.enigma.translation.mapping.serde.MappingsReader; | ||
| 16 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 17 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 18 | import cuchaz.enigma.translation.representation.MethodDescriptor; | ||
| 19 | import cuchaz.enigma.translation.representation.TypeDescriptor; | ||
| 20 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 21 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 22 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 23 | |||
| 24 | public class ProguardMappingsReader implements MappingsReader { | ||
| 25 | public static final ProguardMappingsReader INSTANCE = new ProguardMappingsReader(); | ||
| 26 | private static final String NAME = "[a-zA-Z0-9_\\-.$<>]+"; | ||
| 27 | private static final String TYPE = NAME + "(?:\\[])*"; | ||
| 28 | private static final String TYPE_LIST = "|(?:(?:" + TYPE + ",)*" + TYPE + ")"; | ||
| 29 | private static final Pattern CLASS = Pattern.compile("(" + NAME + ") -> (" + NAME + "):"); | ||
| 30 | private static final Pattern FIELD = Pattern.compile(" {4}(" + TYPE + ") (" + NAME + ") -> (" + NAME + ")"); | ||
| 31 | private static final Pattern METHOD = Pattern.compile(" {4}(?:[0-9]+:[0-9]+:)?(" + TYPE + ") (" + NAME + ")\\((" + TYPE_LIST + ")\\) -> (" + NAME + ")"); | ||
| 32 | |||
| 33 | public ProguardMappingsReader() { | ||
| 34 | } | ||
| 35 | |||
| 36 | @Override | ||
| 37 | public EntryTree<EntryMapping> read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws MappingParseException, IOException { | ||
| 38 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); | ||
| 39 | |||
| 40 | int lineNumber = 0; | ||
| 41 | ClassEntry currentClass = null; | ||
| 42 | |||
| 43 | for (String line : Files.readAllLines(path, StandardCharsets.UTF_8)) { | ||
| 44 | lineNumber++; | ||
| 45 | |||
| 46 | if (line.startsWith("#") || line.isEmpty()) { | ||
| 47 | continue; | ||
| 48 | } | ||
| 49 | |||
| 50 | Matcher classMatcher = CLASS.matcher(line); | ||
| 51 | Matcher fieldMatcher = FIELD.matcher(line); | ||
| 52 | Matcher methodMatcher = METHOD.matcher(line); | ||
| 53 | |||
| 54 | if (classMatcher.matches()) { | ||
| 55 | String name = classMatcher.group(1); | ||
| 56 | String targetName = classMatcher.group(2); | ||
| 57 | |||
| 58 | mappings.insert(currentClass = new ClassEntry(name.replace('.', '/')), new EntryMapping(ClassEntry.getInnerName(targetName.replace('.', '/')))); | ||
| 59 | } else if (fieldMatcher.matches()) { | ||
| 60 | String type = fieldMatcher.group(1); | ||
| 61 | String name = fieldMatcher.group(2); | ||
| 62 | String targetName = fieldMatcher.group(3); | ||
| 63 | |||
| 64 | if (currentClass == null) { | ||
| 65 | throw new MappingParseException(path, lineNumber, "field mapping not inside class: " + line); | ||
| 66 | } | ||
| 67 | |||
| 68 | mappings.insert(new FieldEntry(currentClass, name, new TypeDescriptor(getDescriptor(type))), new EntryMapping(targetName)); | ||
| 69 | } else if (methodMatcher.matches()) { | ||
| 70 | String returnType = methodMatcher.group(1); | ||
| 71 | String name = methodMatcher.group(2); | ||
| 72 | String[] parameterTypes = methodMatcher.group(3).isEmpty() ? new String[0] : methodMatcher.group(3).split(","); | ||
| 73 | String targetName = methodMatcher.group(4); | ||
| 74 | |||
| 75 | if (currentClass == null) { | ||
| 76 | throw new MappingParseException(path, lineNumber, "method mapping not inside class: " + line); | ||
| 77 | } | ||
| 78 | |||
| 79 | mappings.insert(new MethodEntry(currentClass, name, new MethodDescriptor(getDescriptor(returnType, parameterTypes))), new EntryMapping(targetName)); | ||
| 80 | } else { | ||
| 81 | throw new MappingParseException(path, lineNumber, "invalid mapping line: " + line); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | return MappingOperations.invert(mappings); | ||
| 86 | } | ||
| 87 | |||
| 88 | private String getDescriptor(String type) { | ||
| 89 | StringBuilder descriptor = new StringBuilder(); | ||
| 90 | |||
| 91 | while (type.endsWith("[]")) { | ||
| 92 | descriptor.append("["); | ||
| 93 | type = type.substring(0, type.length() - 2); | ||
| 94 | } | ||
| 95 | |||
| 96 | switch (type) { | ||
| 97 | case "byte": | ||
| 98 | return descriptor + "B"; | ||
| 99 | case "char": | ||
| 100 | return descriptor + "C"; | ||
| 101 | case "short": | ||
| 102 | return descriptor + "S"; | ||
| 103 | case "int": | ||
| 104 | return descriptor + "I"; | ||
| 105 | case "long": | ||
| 106 | return descriptor + "J"; | ||
| 107 | case "float": | ||
| 108 | return descriptor + "F"; | ||
| 109 | case "double": | ||
| 110 | return descriptor + "D"; | ||
| 111 | case "boolean": | ||
| 112 | return descriptor + "Z"; | ||
| 113 | case "void": | ||
| 114 | return descriptor + "V"; | ||
| 115 | } | ||
| 116 | |||
| 117 | descriptor.append("L"); | ||
| 118 | descriptor.append(type.replace('.', '/')); | ||
| 119 | descriptor.append(";"); | ||
| 120 | |||
| 121 | return descriptor.toString(); | ||
| 122 | } | ||
| 123 | |||
| 124 | private String getDescriptor(String returnType, String[] parameterTypes) { | ||
| 125 | StringBuilder descriptor = new StringBuilder(); | ||
| 126 | descriptor.append('('); | ||
| 127 | |||
| 128 | for (String parameterType : parameterTypes) { | ||
| 129 | descriptor.append(getDescriptor(parameterType)); | ||
| 130 | } | ||
| 131 | |||
| 132 | descriptor.append(')'); | ||
| 133 | descriptor.append(getDescriptor(returnType)); | ||
| 134 | |||
| 135 | return descriptor.toString(); | ||
| 136 | } | ||
| 137 | } | ||
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 deleted file mode 100644 index ce54feae..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/recaf/RecafMappingsReader.java +++ /dev/null | |||
| @@ -1,64 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde.recaf; | ||
| 2 | |||
| 3 | import java.io.IOException; | ||
| 4 | import java.nio.file.Files; | ||
| 5 | import java.nio.file.Path; | ||
| 6 | import java.util.List; | ||
| 7 | import java.util.regex.Matcher; | ||
| 8 | import java.util.regex.Pattern; | ||
| 9 | |||
| 10 | import cuchaz.enigma.ProgressListener; | ||
| 11 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 12 | import cuchaz.enigma.translation.mapping.serde.MappingParseException; | ||
| 13 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 14 | import cuchaz.enigma.translation.mapping.serde.MappingsReader; | ||
| 15 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 16 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 17 | import cuchaz.enigma.translation.representation.MethodDescriptor; | ||
| 18 | import cuchaz.enigma.translation.representation.TypeDescriptor; | ||
| 19 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 20 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 21 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 22 | |||
| 23 | public class RecafMappingsReader implements MappingsReader { | ||
| 24 | public static final RecafMappingsReader INSTANCE = new RecafMappingsReader(); | ||
| 25 | private static final Pattern METHOD_PATTERN = Pattern.compile("(.*?)\\.(.*?)(\\(.*?) (.*)"); | ||
| 26 | private static final Pattern FIELD_PATTERN = Pattern.compile("(.*?)\\.(.*?) (.*?) (.*)"); | ||
| 27 | private static final Pattern CLASS_PATTERN = Pattern.compile("(.*?) (.*)"); | ||
| 28 | |||
| 29 | @Override | ||
| 30 | public EntryTree<EntryMapping> read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws MappingParseException, IOException { | ||
| 31 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); | ||
| 32 | List<String> lines = Files.readAllLines(path); | ||
| 33 | |||
| 34 | for (String line : lines) { | ||
| 35 | Matcher methodMatcher = METHOD_PATTERN.matcher(line); | ||
| 36 | |||
| 37 | if (methodMatcher.find()) { | ||
| 38 | ClassEntry owner = new ClassEntry(methodMatcher.group(1)); | ||
| 39 | String name = methodMatcher.group(2); | ||
| 40 | MethodDescriptor desc = new MethodDescriptor(methodMatcher.group(3)); | ||
| 41 | mappings.insert(new MethodEntry(owner, name, desc), new EntryMapping(methodMatcher.group(4))); | ||
| 42 | continue; | ||
| 43 | } | ||
| 44 | |||
| 45 | Matcher fieldMatcher = FIELD_PATTERN.matcher(line); | ||
| 46 | |||
| 47 | if (fieldMatcher.find()) { | ||
| 48 | ClassEntry owner = new ClassEntry(fieldMatcher.group(1)); | ||
| 49 | String name = fieldMatcher.group(2); | ||
| 50 | TypeDescriptor desc = new TypeDescriptor(fieldMatcher.group(3)); | ||
| 51 | mappings.insert(new FieldEntry(owner, name, desc), new EntryMapping(fieldMatcher.group(4))); | ||
| 52 | continue; | ||
| 53 | } | ||
| 54 | |||
| 55 | Matcher classMatcher = CLASS_PATTERN.matcher(line); | ||
| 56 | |||
| 57 | if (classMatcher.find()) { | ||
| 58 | mappings.insert(new ClassEntry(classMatcher.group(1)), new EntryMapping(classMatcher.group(2))); | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | return mappings; | ||
| 63 | } | ||
| 64 | } | ||
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 deleted file mode 100644 index 26a29bf1..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/recaf/RecafMappingsWriter.java +++ /dev/null | |||
| @@ -1,77 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde.recaf; | ||
| 2 | |||
| 3 | import java.io.BufferedWriter; | ||
| 4 | import java.io.IOException; | ||
| 5 | import java.io.Writer; | ||
| 6 | import java.nio.file.Files; | ||
| 7 | import java.nio.file.Path; | ||
| 8 | import java.util.ArrayList; | ||
| 9 | |||
| 10 | import cuchaz.enigma.ProgressListener; | ||
| 11 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 12 | import cuchaz.enigma.translation.mapping.MappingDelta; | ||
| 13 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 14 | import cuchaz.enigma.translation.mapping.serde.MappingsWriter; | ||
| 15 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 16 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | ||
| 17 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 18 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 19 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 20 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 21 | |||
| 22 | public class RecafMappingsWriter implements MappingsWriter { | ||
| 23 | public static final RecafMappingsWriter INSTANCE = new RecafMappingsWriter(); | ||
| 24 | |||
| 25 | @Override | ||
| 26 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { | ||
| 27 | try { | ||
| 28 | Files.deleteIfExists(path); | ||
| 29 | Files.createFile(path); | ||
| 30 | } catch (IOException e) { | ||
| 31 | e.printStackTrace(); | ||
| 32 | } | ||
| 33 | |||
| 34 | try (BufferedWriter writer = Files.newBufferedWriter(path)) { | ||
| 35 | new ArrayList<>(mappings).stream().map(EntryTreeNode::getEntry).forEach(entry -> writeEntry(writer, mappings, entry)); | ||
| 36 | } catch (IOException e) { | ||
| 37 | e.printStackTrace(); | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | private void writeEntry(Writer writer, EntryTree<EntryMapping> mappings, Entry<?> entry) { | ||
| 42 | EntryTreeNode<EntryMapping> node = mappings.findNode(entry); | ||
| 43 | |||
| 44 | if (node == null) { | ||
| 45 | return; | ||
| 46 | } | ||
| 47 | |||
| 48 | EntryMapping mapping = mappings.get(entry); | ||
| 49 | |||
| 50 | try { | ||
| 51 | if (mapping != null && mapping.targetName() != null) { | ||
| 52 | if (entry instanceof ClassEntry classEntry) { | ||
| 53 | writer.write(classEntry.getFullName()); | ||
| 54 | writer.write(" "); | ||
| 55 | writer.write(mapping.targetName()); | ||
| 56 | } else if (entry instanceof FieldEntry fieldEntry) { | ||
| 57 | writer.write(fieldEntry.getFullName()); | ||
| 58 | writer.write(" "); | ||
| 59 | writer.write(fieldEntry.getDesc().toString()); | ||
| 60 | writer.write(" "); | ||
| 61 | writer.write(mapping.targetName()); | ||
| 62 | } else if (entry instanceof MethodEntry methodEntry) { | ||
| 63 | writer.write(methodEntry.getFullName()); | ||
| 64 | writer.write(methodEntry.getDesc().toString()); | ||
| 65 | writer.write(" "); | ||
| 66 | writer.write(mapping.targetName()); | ||
| 67 | } | ||
| 68 | |||
| 69 | writer.write("\n"); | ||
| 70 | } | ||
| 71 | } catch (IOException e) { | ||
| 72 | e.printStackTrace(); | ||
| 73 | } | ||
| 74 | |||
| 75 | node.getChildren().forEach(child -> writeEntry(writer, mappings, child)); | ||
| 76 | } | ||
| 77 | } | ||
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/srg/SrgMappingsWriter.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/srg/SrgMappingsWriter.java deleted file mode 100644 index 42372373..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/srg/SrgMappingsWriter.java +++ /dev/null | |||
| @@ -1,119 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde.srg; | ||
| 2 | |||
| 3 | import java.io.IOException; | ||
| 4 | import java.io.PrintWriter; | ||
| 5 | import java.nio.file.Files; | ||
| 6 | import java.nio.file.Path; | ||
| 7 | import java.util.ArrayList; | ||
| 8 | import java.util.Collection; | ||
| 9 | import java.util.Comparator; | ||
| 10 | import java.util.List; | ||
| 11 | |||
| 12 | import cuchaz.enigma.ProgressListener; | ||
| 13 | import cuchaz.enigma.translation.MappingTranslator; | ||
| 14 | import cuchaz.enigma.translation.Translator; | ||
| 15 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 16 | import cuchaz.enigma.translation.mapping.MappingDelta; | ||
| 17 | import cuchaz.enigma.translation.mapping.VoidEntryResolver; | ||
| 18 | import cuchaz.enigma.translation.mapping.serde.LfPrintWriter; | ||
| 19 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 20 | import cuchaz.enigma.translation.mapping.serde.MappingsWriter; | ||
| 21 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 22 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | ||
| 23 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 24 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 25 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 26 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 27 | import cuchaz.enigma.utils.I18n; | ||
| 28 | |||
| 29 | public enum SrgMappingsWriter implements MappingsWriter { | ||
| 30 | INSTANCE; | ||
| 31 | |||
| 32 | @Override | ||
| 33 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { | ||
| 34 | try { | ||
| 35 | Files.deleteIfExists(path); | ||
| 36 | Files.createFile(path); | ||
| 37 | } catch (IOException e) { | ||
| 38 | e.printStackTrace(); | ||
| 39 | } | ||
| 40 | |||
| 41 | List<String> classLines = new ArrayList<>(); | ||
| 42 | List<String> fieldLines = new ArrayList<>(); | ||
| 43 | List<String> methodLines = new ArrayList<>(); | ||
| 44 | |||
| 45 | List<? extends Entry<?>> rootEntries = new ArrayList<>(mappings).stream().map(EntryTreeNode::getEntry).toList(); | ||
| 46 | progress.init(rootEntries.size(), I18n.translate("progress.mappings.converting")); | ||
| 47 | |||
| 48 | int steps = 0; | ||
| 49 | |||
| 50 | for (Entry<?> entry : sorted(rootEntries)) { | ||
| 51 | progress.step(steps++, entry.getName()); | ||
| 52 | writeEntry(classLines, fieldLines, methodLines, mappings, entry); | ||
| 53 | } | ||
| 54 | |||
| 55 | progress.init(3, I18n.translate("progress.mappings.writing")); | ||
| 56 | |||
| 57 | try (PrintWriter writer = new LfPrintWriter(Files.newBufferedWriter(path))) { | ||
| 58 | progress.step(0, I18n.translate("type.classes")); | ||
| 59 | classLines.forEach(writer::println); | ||
| 60 | progress.step(1, I18n.translate("type.fields")); | ||
| 61 | fieldLines.forEach(writer::println); | ||
| 62 | progress.step(2, I18n.translate("type.methods")); | ||
| 63 | methodLines.forEach(writer::println); | ||
| 64 | } catch (IOException e) { | ||
| 65 | e.printStackTrace(); | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | private void writeEntry(List<String> classes, List<String> fields, List<String> methods, EntryTree<EntryMapping> mappings, Entry<?> entry) { | ||
| 70 | EntryTreeNode<EntryMapping> node = mappings.findNode(entry); | ||
| 71 | |||
| 72 | if (node == null) { | ||
| 73 | return; | ||
| 74 | } | ||
| 75 | |||
| 76 | Translator translator = new MappingTranslator(mappings, VoidEntryResolver.INSTANCE); | ||
| 77 | |||
| 78 | if (entry instanceof ClassEntry) { | ||
| 79 | classes.add(generateClassLine((ClassEntry) entry, translator)); | ||
| 80 | } else if (entry instanceof FieldEntry) { | ||
| 81 | fields.add(generateFieldLine((FieldEntry) entry, translator)); | ||
| 82 | } else if (entry instanceof MethodEntry) { | ||
| 83 | methods.add(generateMethodLine((MethodEntry) entry, translator)); | ||
| 84 | } | ||
| 85 | |||
| 86 | for (Entry<?> child : sorted(node.getChildren())) { | ||
| 87 | writeEntry(classes, fields, methods, mappings, child); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | private String generateClassLine(ClassEntry sourceEntry, Translator translator) { | ||
| 92 | ClassEntry targetEntry = translator.translate(sourceEntry); | ||
| 93 | return "CL: " + sourceEntry.getFullName() + " " + targetEntry.getFullName(); | ||
| 94 | } | ||
| 95 | |||
| 96 | private String generateMethodLine(MethodEntry sourceEntry, Translator translator) { | ||
| 97 | MethodEntry targetEntry = translator.translate(sourceEntry); | ||
| 98 | return "MD: " + describeMethod(sourceEntry) + " " + describeMethod(targetEntry); | ||
| 99 | } | ||
| 100 | |||
| 101 | private String describeMethod(MethodEntry entry) { | ||
| 102 | return entry.getParent().getFullName() + "/" + entry.getName() + " " + entry.getDesc(); | ||
| 103 | } | ||
| 104 | |||
| 105 | private String generateFieldLine(FieldEntry sourceEntry, Translator translator) { | ||
| 106 | FieldEntry targetEntry = translator.translate(sourceEntry); | ||
| 107 | return "FD: " + describeField(sourceEntry) + " " + describeField(targetEntry); | ||
| 108 | } | ||
| 109 | |||
| 110 | private String describeField(FieldEntry entry) { | ||
| 111 | return entry.getParent().getFullName() + "/" + entry.getName(); | ||
| 112 | } | ||
| 113 | |||
| 114 | private Collection<Entry<?>> sorted(Collection<? extends Entry<?>> collection) { | ||
| 115 | ArrayList<Entry<?>> sorted = new ArrayList<>(collection); | ||
| 116 | sorted.sort(Comparator.comparing(Entry::getName)); | ||
| 117 | return sorted; | ||
| 118 | } | ||
| 119 | } | ||
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tiny/TinyMappingsReader.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tiny/TinyMappingsReader.java deleted file mode 100644 index ae003003..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tiny/TinyMappingsReader.java +++ /dev/null | |||
| @@ -1,117 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde.tiny; | ||
| 2 | |||
| 3 | import java.io.IOException; | ||
| 4 | import java.nio.charset.StandardCharsets; | ||
| 5 | import java.nio.file.Files; | ||
| 6 | import java.nio.file.Path; | ||
| 7 | import java.util.List; | ||
| 8 | |||
| 9 | import cuchaz.enigma.ProgressListener; | ||
| 10 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 11 | import cuchaz.enigma.translation.mapping.MappingPair; | ||
| 12 | import cuchaz.enigma.translation.mapping.serde.MappingParseException; | ||
| 13 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 14 | import cuchaz.enigma.translation.mapping.serde.MappingsReader; | ||
| 15 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 16 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 17 | import cuchaz.enigma.translation.representation.MethodDescriptor; | ||
| 18 | import cuchaz.enigma.translation.representation.TypeDescriptor; | ||
| 19 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 20 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 21 | import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; | ||
| 22 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 23 | import cuchaz.enigma.utils.I18n; | ||
| 24 | |||
| 25 | public enum TinyMappingsReader implements MappingsReader { | ||
| 26 | INSTANCE; | ||
| 27 | |||
| 28 | @Override | ||
| 29 | public EntryTree<EntryMapping> read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException { | ||
| 30 | return read(path, Files.readAllLines(path, StandardCharsets.UTF_8), progress); | ||
| 31 | } | ||
| 32 | |||
| 33 | private EntryTree<EntryMapping> read(Path path, List<String> lines, ProgressListener progress) throws MappingParseException { | ||
| 34 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); | ||
| 35 | lines.remove(0); | ||
| 36 | |||
| 37 | progress.init(lines.size(), I18n.translate("progress.mappings.loading_file")); | ||
| 38 | |||
| 39 | for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { | ||
| 40 | progress.step(lineNumber, ""); | ||
| 41 | |||
| 42 | String line = lines.get(lineNumber); | ||
| 43 | |||
| 44 | if (line.trim().startsWith("#")) { | ||
| 45 | continue; | ||
| 46 | } | ||
| 47 | |||
| 48 | try { | ||
| 49 | MappingPair<?, EntryMapping> mapping = parseLine(line); | ||
| 50 | mappings.insert(mapping.getEntry(), mapping.getMapping()); | ||
| 51 | } catch (Throwable t) { | ||
| 52 | throw new MappingParseException(path, lineNumber, t); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | return mappings; | ||
| 57 | } | ||
| 58 | |||
| 59 | private MappingPair<?, EntryMapping> parseLine(String line) { | ||
| 60 | String[] tokens = line.split("\t"); | ||
| 61 | |||
| 62 | String key = tokens[0]; | ||
| 63 | switch (key) { | ||
| 64 | case "CLASS": | ||
| 65 | return parseClass(tokens); | ||
| 66 | case "FIELD": | ||
| 67 | return parseField(tokens); | ||
| 68 | case "METHOD": | ||
| 69 | return parseMethod(tokens); | ||
| 70 | case "MTH-ARG": | ||
| 71 | return parseArgument(tokens); | ||
| 72 | default: | ||
| 73 | throw new RuntimeException("Unknown token '" + key + "'!"); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | private MappingPair<ClassEntry, EntryMapping> parseClass(String[] tokens) { | ||
| 78 | ClassEntry obfuscatedEntry = new ClassEntry(tokens[1]); | ||
| 79 | String mapping = tokens[2]; | ||
| 80 | |||
| 81 | if (mapping.indexOf('$') > 0) { | ||
| 82 | // inner classes should map to only the final part | ||
| 83 | mapping = mapping.substring(mapping.lastIndexOf('$') + 1); | ||
| 84 | } | ||
| 85 | |||
| 86 | return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); | ||
| 87 | } | ||
| 88 | |||
| 89 | private MappingPair<FieldEntry, EntryMapping> parseField(String[] tokens) { | ||
| 90 | ClassEntry ownerClass = new ClassEntry(tokens[1]); | ||
| 91 | TypeDescriptor descriptor = new TypeDescriptor(tokens[2]); | ||
| 92 | |||
| 93 | FieldEntry obfuscatedEntry = new FieldEntry(ownerClass, tokens[3], descriptor); | ||
| 94 | String mapping = tokens[4]; | ||
| 95 | return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); | ||
| 96 | } | ||
| 97 | |||
| 98 | private MappingPair<MethodEntry, EntryMapping> parseMethod(String[] tokens) { | ||
| 99 | ClassEntry ownerClass = new ClassEntry(tokens[1]); | ||
| 100 | MethodDescriptor descriptor = new MethodDescriptor(tokens[2]); | ||
| 101 | |||
| 102 | MethodEntry obfuscatedEntry = new MethodEntry(ownerClass, tokens[3], descriptor); | ||
| 103 | String mapping = tokens[4]; | ||
| 104 | return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); | ||
| 105 | } | ||
| 106 | |||
| 107 | private MappingPair<LocalVariableEntry, EntryMapping> parseArgument(String[] tokens) { | ||
| 108 | ClassEntry ownerClass = new ClassEntry(tokens[1]); | ||
| 109 | MethodDescriptor ownerDescriptor = new MethodDescriptor(tokens[2]); | ||
| 110 | MethodEntry ownerMethod = new MethodEntry(ownerClass, tokens[3], ownerDescriptor); | ||
| 111 | int variableIndex = Integer.parseInt(tokens[4]); | ||
| 112 | |||
| 113 | String mapping = tokens[5]; | ||
| 114 | LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true, null); | ||
| 115 | return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); | ||
| 116 | } | ||
| 117 | } | ||
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tiny/TinyMappingsWriter.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tiny/TinyMappingsWriter.java deleted file mode 100644 index 67582be0..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tiny/TinyMappingsWriter.java +++ /dev/null | |||
| @@ -1,144 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde.tiny; | ||
| 2 | |||
| 3 | import java.io.BufferedWriter; | ||
| 4 | import java.io.IOException; | ||
| 5 | import java.io.Writer; | ||
| 6 | import java.nio.charset.StandardCharsets; | ||
| 7 | import java.nio.file.Files; | ||
| 8 | import java.nio.file.Path; | ||
| 9 | import java.util.ArrayList; | ||
| 10 | import java.util.Comparator; | ||
| 11 | import java.util.HashSet; | ||
| 12 | import java.util.Set; | ||
| 13 | |||
| 14 | import cuchaz.enigma.ProgressListener; | ||
| 15 | import cuchaz.enigma.translation.MappingTranslator; | ||
| 16 | import cuchaz.enigma.translation.Translator; | ||
| 17 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 18 | import cuchaz.enigma.translation.mapping.MappingDelta; | ||
| 19 | import cuchaz.enigma.translation.mapping.VoidEntryResolver; | ||
| 20 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 21 | import cuchaz.enigma.translation.mapping.serde.MappingsWriter; | ||
| 22 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 23 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | ||
| 24 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 25 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 26 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 27 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 28 | |||
| 29 | public class TinyMappingsWriter implements MappingsWriter { | ||
| 30 | private static final String VERSION_CONSTANT = "v1"; | ||
| 31 | |||
| 32 | //Possibly add a gui or a way to select the namespaces when exporting from the gui | ||
| 33 | public static final TinyMappingsWriter INSTANCE = new TinyMappingsWriter("intermediary", "named"); | ||
| 34 | |||
| 35 | // HACK: as of enigma 0.13.1, some fields seem to appear duplicated? | ||
| 36 | private final Set<String> writtenLines = new HashSet<>(); | ||
| 37 | private final String nameObf; | ||
| 38 | private final String nameDeobf; | ||
| 39 | |||
| 40 | public TinyMappingsWriter(String nameObf, String nameDeobf) { | ||
| 41 | this.nameObf = nameObf; | ||
| 42 | this.nameDeobf = nameDeobf; | ||
| 43 | } | ||
| 44 | |||
| 45 | @Override | ||
| 46 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { | ||
| 47 | try { | ||
| 48 | Files.deleteIfExists(path); | ||
| 49 | Files.createFile(path); | ||
| 50 | } catch (IOException e) { | ||
| 51 | e.printStackTrace(); | ||
| 52 | } | ||
| 53 | |||
| 54 | try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { | ||
| 55 | writeLine(writer, new String[]{VERSION_CONSTANT, nameObf, nameDeobf}); | ||
| 56 | |||
| 57 | new ArrayList<>(mappings).stream().map(EntryTreeNode::getEntry).sorted(Comparator.comparing(Object::toString)).forEach(entry -> writeEntry(writer, mappings, entry)); | ||
| 58 | } catch (IOException e) { | ||
| 59 | e.printStackTrace(); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | private void writeEntry(Writer writer, EntryTree<EntryMapping> mappings, Entry<?> entry) { | ||
| 64 | EntryTreeNode<EntryMapping> node = mappings.findNode(entry); | ||
| 65 | |||
| 66 | if (node == null) { | ||
| 67 | return; | ||
| 68 | } | ||
| 69 | |||
| 70 | Translator translator = new MappingTranslator(mappings, VoidEntryResolver.INSTANCE); | ||
| 71 | |||
| 72 | EntryMapping mapping = mappings.get(entry); | ||
| 73 | |||
| 74 | // Do not write mappings without deobfuscated name since tiny v1 doesn't | ||
| 75 | // support comments anyway | ||
| 76 | if (mapping != null && mapping.targetName() != null) { | ||
| 77 | if (entry instanceof ClassEntry) { | ||
| 78 | writeClass(writer, (ClassEntry) entry, translator); | ||
| 79 | } else if (entry instanceof FieldEntry) { | ||
| 80 | writeLine(writer, serializeEntry(entry, mapping.targetName())); | ||
| 81 | } else if (entry instanceof MethodEntry) { | ||
| 82 | writeLine(writer, serializeEntry(entry, mapping.targetName())); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | writeChildren(writer, mappings, node); | ||
| 87 | } | ||
| 88 | |||
| 89 | private void writeChildren(Writer writer, EntryTree<EntryMapping> mappings, EntryTreeNode<EntryMapping> node) { | ||
| 90 | node.getChildren().stream().filter(e -> e instanceof FieldEntry).sorted().forEach(child -> writeEntry(writer, mappings, child)); | ||
| 91 | |||
| 92 | node.getChildren().stream().filter(e -> e instanceof MethodEntry).sorted().forEach(child -> writeEntry(writer, mappings, child)); | ||
| 93 | |||
| 94 | node.getChildren().stream().filter(e -> e instanceof ClassEntry).sorted().forEach(child -> writeEntry(writer, mappings, child)); | ||
| 95 | } | ||
| 96 | |||
| 97 | private void writeClass(Writer writer, ClassEntry entry, Translator translator) { | ||
| 98 | ClassEntry translatedEntry = translator.translate(entry); | ||
| 99 | |||
| 100 | String obfClassName = entry.getFullName(); | ||
| 101 | String deobfClassName = translatedEntry.getFullName(); | ||
| 102 | writeLine(writer, new String[]{"CLASS", obfClassName, deobfClassName}); | ||
| 103 | } | ||
| 104 | |||
| 105 | private void writeLine(Writer writer, String[] data) { | ||
| 106 | try { | ||
| 107 | String line = String.join("\t", data) + "\n"; | ||
| 108 | |||
| 109 | if (writtenLines.add(line)) { | ||
| 110 | writer.write(line); | ||
| 111 | } | ||
| 112 | } catch (IOException e) { | ||
| 113 | throw new RuntimeException(e); | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | private String[] serializeEntry(Entry<?> entry, String... extraFields) { | ||
| 118 | String[] data = null; | ||
| 119 | |||
| 120 | if (entry instanceof FieldEntry) { | ||
| 121 | data = new String[4 + extraFields.length]; | ||
| 122 | data[0] = "FIELD"; | ||
| 123 | data[1] = entry.getContainingClass().getFullName(); | ||
| 124 | data[2] = ((FieldEntry) entry).getDesc().toString(); | ||
| 125 | data[3] = entry.getName(); | ||
| 126 | } else if (entry instanceof MethodEntry) { | ||
| 127 | data = new String[4 + extraFields.length]; | ||
| 128 | data[0] = "METHOD"; | ||
| 129 | data[1] = entry.getContainingClass().getFullName(); | ||
| 130 | data[2] = ((MethodEntry) entry).getDesc().toString(); | ||
| 131 | data[3] = entry.getName(); | ||
| 132 | } else if (entry instanceof ClassEntry) { | ||
| 133 | data = new String[2 + extraFields.length]; | ||
| 134 | data[0] = "CLASS"; | ||
| 135 | data[1] = ((ClassEntry) entry).getFullName(); | ||
| 136 | } | ||
| 137 | |||
| 138 | if (data != null) { | ||
| 139 | System.arraycopy(extraFields, 0, data, data.length - extraFields.length, extraFields.length); | ||
| 140 | } | ||
| 141 | |||
| 142 | return data; | ||
| 143 | } | ||
| 144 | } | ||
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tinyv2/TinyV2Reader.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tinyv2/TinyV2Reader.java deleted file mode 100644 index 28185f58..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tinyv2/TinyV2Reader.java +++ /dev/null | |||
| @@ -1,332 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde.tinyv2; | ||
| 2 | |||
| 3 | import java.io.IOException; | ||
| 4 | import java.nio.charset.StandardCharsets; | ||
| 5 | import java.nio.file.Files; | ||
| 6 | import java.nio.file.Path; | ||
| 7 | import java.util.BitSet; | ||
| 8 | import java.util.List; | ||
| 9 | |||
| 10 | import cuchaz.enigma.ProgressListener; | ||
| 11 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 12 | import cuchaz.enigma.translation.mapping.MappingPair; | ||
| 13 | import cuchaz.enigma.translation.mapping.serde.MappingParseException; | ||
| 14 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 15 | import cuchaz.enigma.translation.mapping.serde.MappingsReader; | ||
| 16 | import cuchaz.enigma.translation.mapping.serde.RawEntryMapping; | ||
| 17 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 18 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 19 | import cuchaz.enigma.translation.representation.MethodDescriptor; | ||
| 20 | import cuchaz.enigma.translation.representation.TypeDescriptor; | ||
| 21 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 22 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 23 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 24 | import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; | ||
| 25 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 26 | |||
| 27 | public final class TinyV2Reader implements MappingsReader { | ||
| 28 | private static final String MINOR_VERSION = "0"; | ||
| 29 | // 0 indent | ||
| 30 | private static final int IN_HEADER = 0; | ||
| 31 | private static final int IN_CLASS = IN_HEADER + 1; | ||
| 32 | // 1 indent | ||
| 33 | private static final int IN_METHOD = IN_CLASS + 1; | ||
| 34 | private static final int IN_FIELD = IN_METHOD + 1; | ||
| 35 | // 2 indent | ||
| 36 | private static final int IN_PARAMETER = IN_FIELD + 1; | ||
| 37 | // general properties | ||
| 38 | private static final int STATE_SIZE = IN_PARAMETER + 1; | ||
| 39 | private static final int[] INDENT_CLEAR_START = {IN_HEADER, IN_METHOD, IN_PARAMETER, STATE_SIZE}; | ||
| 40 | |||
| 41 | @Override | ||
| 42 | public EntryTree<EntryMapping> read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException { | ||
| 43 | return read(path, Files.readAllLines(path, StandardCharsets.UTF_8), progress); | ||
| 44 | } | ||
| 45 | |||
| 46 | private EntryTree<EntryMapping> read(Path path, List<String> lines, ProgressListener progress) throws MappingParseException { | ||
| 47 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); | ||
| 48 | |||
| 49 | progress.init(lines.size(), "progress.mappings.loading_file"); | ||
| 50 | |||
| 51 | BitSet state = new BitSet(STATE_SIZE); | ||
| 52 | @SuppressWarnings({"unchecked", "rawtypes"}) MappingPair<? extends Entry<?>, RawEntryMapping>[] holds = new MappingPair[STATE_SIZE]; | ||
| 53 | boolean escapeNames = false; | ||
| 54 | |||
| 55 | for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { | ||
| 56 | try { | ||
| 57 | progress.step(lineNumber, ""); | ||
| 58 | String line = lines.get(lineNumber); | ||
| 59 | |||
| 60 | int indent = 0; | ||
| 61 | |||
| 62 | while (line.charAt(indent) == '\t') { | ||
| 63 | indent++; | ||
| 64 | } | ||
| 65 | |||
| 66 | String[] parts = line.substring(indent).split("\t", -1); | ||
| 67 | |||
| 68 | if (parts.length == 0 || indent >= INDENT_CLEAR_START.length) { | ||
| 69 | throw new IllegalArgumentException("Invalid format"); | ||
| 70 | } | ||
| 71 | |||
| 72 | // clean and register stuff in stack | ||
| 73 | for (int i = INDENT_CLEAR_START[indent]; i < STATE_SIZE; i++) { | ||
| 74 | state.clear(i); | ||
| 75 | |||
| 76 | if (holds[i] != null) { | ||
| 77 | bakeHeld(mappings, holds[i]); | ||
| 78 | holds[i] = null; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | switch (indent) { | ||
| 83 | case 0: | ||
| 84 | switch (parts[0]) { | ||
| 85 | case "tiny": // header | ||
| 86 | if (lineNumber != 0) { | ||
| 87 | throw new IllegalArgumentException("Header can only be on the first line"); | ||
| 88 | } | ||
| 89 | |||
| 90 | if (parts.length < 5) { | ||
| 91 | throw new IllegalArgumentException("Not enough header columns, needs at least 5"); | ||
| 92 | } | ||
| 93 | |||
| 94 | if (!"2".equals(parts[1]) || !MINOR_VERSION.equals(parts[2])) { | ||
| 95 | throw new IllegalArgumentException("Unsupported TinyV2 version, requires major " + "2" + " and minor " + MINOR_VERSION + ""); | ||
| 96 | } | ||
| 97 | |||
| 98 | state.set(IN_HEADER); | ||
| 99 | break; | ||
| 100 | case "c": // class | ||
| 101 | state.set(IN_CLASS); | ||
| 102 | holds[IN_CLASS] = parseClass(parts, escapeNames); | ||
| 103 | break; | ||
| 104 | default: | ||
| 105 | unsupportKey(parts); | ||
| 106 | } | ||
| 107 | |||
| 108 | break; | ||
| 109 | case 1: | ||
| 110 | if (state.get(IN_HEADER)) { | ||
| 111 | if (parts[0].equals("esacpe-names")) { | ||
| 112 | escapeNames = true; | ||
| 113 | } | ||
| 114 | |||
| 115 | break; | ||
| 116 | } | ||
| 117 | |||
| 118 | if (state.get(IN_CLASS)) { | ||
| 119 | switch (parts[0]) { | ||
| 120 | case "m": // method | ||
| 121 | state.set(IN_METHOD); | ||
| 122 | holds[IN_METHOD] = parseMethod(holds[IN_CLASS], parts, escapeNames); | ||
| 123 | break; | ||
| 124 | case "f": // field | ||
| 125 | state.set(IN_FIELD); | ||
| 126 | holds[IN_FIELD] = parseField(holds[IN_CLASS], parts, escapeNames); | ||
| 127 | break; | ||
| 128 | case "c": // class javadoc | ||
| 129 | addJavadoc(holds[IN_CLASS], parts); | ||
| 130 | break; | ||
| 131 | default: | ||
| 132 | unsupportKey(parts); | ||
| 133 | } | ||
| 134 | |||
| 135 | break; | ||
| 136 | } | ||
| 137 | |||
| 138 | unsupportKey(parts); | ||
| 139 | case 2: | ||
| 140 | if (state.get(IN_METHOD)) { | ||
| 141 | switch (parts[0]) { | ||
| 142 | case "p": // parameter | ||
| 143 | state.set(IN_PARAMETER); | ||
| 144 | holds[IN_PARAMETER] = parseArgument(holds[IN_METHOD], parts, escapeNames); | ||
| 145 | break; | ||
| 146 | case "v": // local variable | ||
| 147 | // TODO add local var mapping | ||
| 148 | break; | ||
| 149 | case "c": // method javadoc | ||
| 150 | addJavadoc(holds[IN_METHOD], parts); | ||
| 151 | break; | ||
| 152 | default: | ||
| 153 | unsupportKey(parts); | ||
| 154 | } | ||
| 155 | |||
| 156 | break; | ||
| 157 | } | ||
| 158 | |||
| 159 | if (state.get(IN_FIELD)) { | ||
| 160 | switch (parts[0]) { | ||
| 161 | case "c": // field javadoc | ||
| 162 | addJavadoc(holds[IN_FIELD], parts); | ||
| 163 | break; | ||
| 164 | default: | ||
| 165 | unsupportKey(parts); | ||
| 166 | } | ||
| 167 | |||
| 168 | break; | ||
| 169 | } | ||
| 170 | |||
| 171 | unsupportKey(parts); | ||
| 172 | case 3: | ||
| 173 | if (state.get(IN_PARAMETER)) { | ||
| 174 | switch (parts[0]) { | ||
| 175 | case "c": | ||
| 176 | addJavadoc(holds[IN_PARAMETER], parts); | ||
| 177 | break; | ||
| 178 | default: | ||
| 179 | unsupportKey(parts); | ||
| 180 | } | ||
| 181 | |||
| 182 | break; | ||
| 183 | } | ||
| 184 | |||
| 185 | unsupportKey(parts); | ||
| 186 | default: | ||
| 187 | unsupportKey(parts); | ||
| 188 | } | ||
| 189 | } catch (Throwable t) { | ||
| 190 | throw new MappingParseException(path, lineNumber + 1, t); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | //bake any remainders | ||
| 195 | for (MappingPair<? extends Entry<?>, RawEntryMapping> hold : holds) { | ||
| 196 | if (hold != null) { | ||
| 197 | bakeHeld(mappings, hold); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | return mappings; | ||
| 202 | } | ||
| 203 | |||
| 204 | private static void bakeHeld(EntryTree<EntryMapping> mappings, MappingPair<? extends Entry<?>, RawEntryMapping> hold2) { | ||
| 205 | RawEntryMapping mapping = hold2.getMapping(); | ||
| 206 | |||
| 207 | if (mapping != null) { | ||
| 208 | EntryMapping baked = mapping.bake(); | ||
| 209 | |||
| 210 | if (baked != null) { | ||
| 211 | mappings.insert(hold2.getEntry(), baked); | ||
| 212 | } | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | private void unsupportKey(String[] parts) { | ||
| 217 | throw new IllegalArgumentException("Unsupported key " + parts[0]); | ||
| 218 | } | ||
| 219 | |||
| 220 | private void addJavadoc(MappingPair<? extends Entry, RawEntryMapping> pair, String[] parts) { | ||
| 221 | if (parts.length != 2) { | ||
| 222 | throw new IllegalArgumentException("Invalid javadoc declaration"); | ||
| 223 | } | ||
| 224 | |||
| 225 | addJavadoc(pair, parts[1]); | ||
| 226 | } | ||
| 227 | |||
| 228 | private MappingPair<ClassEntry, RawEntryMapping> parseClass(String[] tokens, boolean escapeNames) { | ||
| 229 | ClassEntry obfuscatedEntry = new ClassEntry(unescapeOpt(tokens[1], escapeNames)); | ||
| 230 | |||
| 231 | if (tokens.length <= 2) { | ||
| 232 | return new MappingPair<>(obfuscatedEntry); | ||
| 233 | } | ||
| 234 | |||
| 235 | String token2 = unescapeOpt(tokens[2], escapeNames); | ||
| 236 | String mapping = token2.substring(token2.lastIndexOf('$') + 1); | ||
| 237 | return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); | ||
| 238 | } | ||
| 239 | |||
| 240 | private MappingPair<FieldEntry, RawEntryMapping> parseField(MappingPair<? extends Entry, RawEntryMapping> parent, String[] tokens, boolean escapeNames) { | ||
| 241 | ClassEntry ownerClass = (ClassEntry) parent.getEntry(); | ||
| 242 | TypeDescriptor descriptor = new TypeDescriptor(unescapeOpt(tokens[1], escapeNames)); | ||
| 243 | |||
| 244 | FieldEntry obfuscatedEntry = new FieldEntry(ownerClass, unescapeOpt(tokens[2], escapeNames), descriptor); | ||
| 245 | |||
| 246 | if (tokens.length <= 3) { | ||
| 247 | return new MappingPair<>(obfuscatedEntry); | ||
| 248 | } | ||
| 249 | |||
| 250 | String mapping = unescapeOpt(tokens[3], escapeNames); | ||
| 251 | return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); | ||
| 252 | } | ||
| 253 | |||
| 254 | private MappingPair<MethodEntry, RawEntryMapping> parseMethod(MappingPair<? extends Entry, RawEntryMapping> parent, String[] tokens, boolean escapeNames) { | ||
| 255 | ClassEntry ownerClass = (ClassEntry) parent.getEntry(); | ||
| 256 | MethodDescriptor descriptor = new MethodDescriptor(unescapeOpt(tokens[1], escapeNames)); | ||
| 257 | |||
| 258 | MethodEntry obfuscatedEntry = new MethodEntry(ownerClass, unescapeOpt(tokens[2], escapeNames), descriptor); | ||
| 259 | |||
| 260 | if (tokens.length <= 3) { | ||
| 261 | return new MappingPair<>(obfuscatedEntry); | ||
| 262 | } | ||
| 263 | |||
| 264 | String mapping = unescapeOpt(tokens[3], escapeNames); | ||
| 265 | return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); | ||
| 266 | } | ||
| 267 | |||
| 268 | private void addJavadoc(MappingPair<? extends Entry, RawEntryMapping> pair, String javadoc) { | ||
| 269 | RawEntryMapping mapping = pair.getMapping(); | ||
| 270 | |||
| 271 | if (mapping == null) { | ||
| 272 | throw new IllegalArgumentException("Javadoc requires a mapping in enigma!"); | ||
| 273 | } | ||
| 274 | |||
| 275 | mapping.addJavadocLine(unescape(javadoc)); | ||
| 276 | } | ||
| 277 | |||
| 278 | private MappingPair<LocalVariableEntry, RawEntryMapping> parseArgument(MappingPair<? extends Entry, RawEntryMapping> parent, String[] tokens, boolean escapeNames) { | ||
| 279 | MethodEntry ownerMethod = (MethodEntry) parent.getEntry(); | ||
| 280 | int variableIndex = Integer.parseInt(tokens[1]); | ||
| 281 | |||
| 282 | // tokens[2] is the useless obf name | ||
| 283 | |||
| 284 | LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true, null); | ||
| 285 | |||
| 286 | if (tokens.length <= 3) { | ||
| 287 | return new MappingPair<>(obfuscatedEntry); | ||
| 288 | } | ||
| 289 | |||
| 290 | String mapping = unescapeOpt(tokens[3], escapeNames); | ||
| 291 | return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); | ||
| 292 | } | ||
| 293 | |||
| 294 | private static final String TO_ESCAPE = "\\\n\r\0\t"; | ||
| 295 | private static final String ESCAPED = "\\nr0t"; | ||
| 296 | |||
| 297 | private static String unescapeOpt(String raw, boolean escapedStrings) { | ||
| 298 | return escapedStrings ? unescape(raw) : raw; | ||
| 299 | } | ||
| 300 | |||
| 301 | private static String unescape(String str) { | ||
| 302 | // copied from matcher, lazy! | ||
| 303 | int pos = str.indexOf('\\'); | ||
| 304 | |||
| 305 | if (pos < 0) { | ||
| 306 | return str; | ||
| 307 | } | ||
| 308 | |||
| 309 | StringBuilder ret = new StringBuilder(str.length() - 1); | ||
| 310 | int start = 0; | ||
| 311 | |||
| 312 | do { | ||
| 313 | ret.append(str, start, pos); | ||
| 314 | pos++; | ||
| 315 | int type; | ||
| 316 | |||
| 317 | if (pos >= str.length()) { | ||
| 318 | throw new RuntimeException("incomplete escape sequence at the end"); | ||
| 319 | } else if ((type = ESCAPED.indexOf(str.charAt(pos))) < 0) { | ||
| 320 | throw new RuntimeException("invalid escape character: \\" + str.charAt(pos)); | ||
| 321 | } else { | ||
| 322 | ret.append(TO_ESCAPE.charAt(type)); | ||
| 323 | } | ||
| 324 | |||
| 325 | start = pos + 1; | ||
| 326 | } while ((pos = str.indexOf('\\', start)) >= 0); | ||
| 327 | |||
| 328 | ret.append(str, start, str.length()); | ||
| 329 | |||
| 330 | return ret.toString(); | ||
| 331 | } | ||
| 332 | } | ||
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tinyv2/TinyV2Writer.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tinyv2/TinyV2Writer.java deleted file mode 100644 index d85ed6e5..00000000 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tinyv2/TinyV2Writer.java +++ /dev/null | |||
| @@ -1,187 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde.tinyv2; | ||
| 2 | |||
| 3 | import java.io.IOException; | ||
| 4 | import java.io.PrintWriter; | ||
| 5 | import java.nio.file.Files; | ||
| 6 | import java.nio.file.Path; | ||
| 7 | import java.util.Deque; | ||
| 8 | import java.util.LinkedList; | ||
| 9 | import java.util.List; | ||
| 10 | import java.util.stream.StreamSupport; | ||
| 11 | |||
| 12 | import cuchaz.enigma.ProgressListener; | ||
| 13 | import cuchaz.enigma.translation.mapping.EntryMap; | ||
| 14 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 15 | import cuchaz.enigma.translation.mapping.MappingDelta; | ||
| 16 | import cuchaz.enigma.translation.mapping.serde.LfPrintWriter; | ||
| 17 | import cuchaz.enigma.translation.mapping.serde.MappingHelper; | ||
| 18 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 19 | import cuchaz.enigma.translation.mapping.serde.MappingsWriter; | ||
| 20 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 21 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | ||
| 22 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 23 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 24 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 25 | import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; | ||
| 26 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 27 | |||
| 28 | public final class TinyV2Writer implements MappingsWriter { | ||
| 29 | private static final String MINOR_VERSION = "0"; | ||
| 30 | private final String obfHeader; | ||
| 31 | private final String deobfHeader; | ||
| 32 | |||
| 33 | public TinyV2Writer(String obfHeader, String deobfHeader) { | ||
| 34 | this.obfHeader = obfHeader; | ||
| 35 | this.deobfHeader = deobfHeader; | ||
| 36 | } | ||
| 37 | |||
| 38 | @Override | ||
| 39 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters parameters) { | ||
| 40 | List<EntryTreeNode<EntryMapping>> classes = StreamSupport.stream(mappings.spliterator(), false).filter(node -> node.getEntry() instanceof ClassEntry).toList(); | ||
| 41 | |||
| 42 | try (PrintWriter writer = new LfPrintWriter(Files.newBufferedWriter(path))) { | ||
| 43 | writer.println("tiny\t2\t" + MINOR_VERSION + "\t" + obfHeader + "\t" + deobfHeader); | ||
| 44 | |||
| 45 | // no escape names | ||
| 46 | |||
| 47 | for (EntryTreeNode<EntryMapping> node : classes) { | ||
| 48 | writeClass(writer, node, mappings); | ||
| 49 | } | ||
| 50 | } catch (IOException ex) { | ||
| 51 | ex.printStackTrace(); // TODO add some better logging system | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | private void writeClass(PrintWriter writer, EntryTreeNode<EntryMapping> node, EntryMap<EntryMapping> tree) { | ||
| 56 | writer.print("c\t"); | ||
| 57 | ClassEntry classEntry = (ClassEntry) node.getEntry(); | ||
| 58 | String fullName = classEntry.getFullName(); | ||
| 59 | writer.print(fullName); | ||
| 60 | Deque<String> parts = new LinkedList<>(); | ||
| 61 | |||
| 62 | do { | ||
| 63 | EntryMapping mapping = tree.get(classEntry); | ||
| 64 | |||
| 65 | if (mapping != null && mapping.targetName() != null) { | ||
| 66 | parts.addFirst(mapping.targetName()); | ||
| 67 | } else { | ||
| 68 | parts.addFirst(classEntry.getName()); | ||
| 69 | } | ||
| 70 | |||
| 71 | classEntry = classEntry.getOuterClass(); | ||
| 72 | } while (classEntry != null); | ||
| 73 | |||
| 74 | String mappedName = String.join("$", parts); | ||
| 75 | |||
| 76 | writer.print("\t"); | ||
| 77 | |||
| 78 | writer.print(mappedName); // todo escaping when we have v2 fixed later | ||
| 79 | |||
| 80 | writer.println(); | ||
| 81 | |||
| 82 | writeComment(writer, node.getValue(), 1); | ||
| 83 | |||
| 84 | for (EntryTreeNode<EntryMapping> child : node.getChildNodes()) { | ||
| 85 | Entry<?> entry = child.getEntry(); | ||
| 86 | |||
| 87 | if (entry instanceof FieldEntry) { | ||
| 88 | writeField(writer, child); | ||
| 89 | } else if (entry instanceof MethodEntry) { | ||
| 90 | writeMethod(writer, child); | ||
| 91 | } | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | private void writeMethod(PrintWriter writer, EntryTreeNode<EntryMapping> node) { | ||
| 96 | writer.print(indent(1)); | ||
| 97 | writer.print("m\t"); | ||
| 98 | writer.print(((MethodEntry) node.getEntry()).getDesc().toString()); | ||
| 99 | writer.print("\t"); | ||
| 100 | writer.print(node.getEntry().getName()); | ||
| 101 | writer.print("\t"); | ||
| 102 | EntryMapping mapping = node.getValue(); | ||
| 103 | |||
| 104 | if (mapping == null) { | ||
| 105 | mapping = EntryMapping.DEFAULT; | ||
| 106 | } | ||
| 107 | |||
| 108 | if (mapping.targetName() != null) { | ||
| 109 | writer.println(mapping.targetName()); | ||
| 110 | } else { | ||
| 111 | writer.println(node.getEntry().getName()); // todo fix v2 name inference | ||
| 112 | } | ||
| 113 | |||
| 114 | writeComment(writer, mapping, 2); | ||
| 115 | |||
| 116 | for (EntryTreeNode<EntryMapping> child : node.getChildNodes()) { | ||
| 117 | Entry<?> entry = child.getEntry(); | ||
| 118 | |||
| 119 | if (entry instanceof LocalVariableEntry) { | ||
| 120 | writeParameter(writer, child); | ||
| 121 | } | ||
| 122 | |||
| 123 | // TODO write actual local variables | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | private void writeField(PrintWriter writer, EntryTreeNode<EntryMapping> node) { | ||
| 128 | if (node.getValue() == null || node.getValue().equals(EntryMapping.DEFAULT)) { | ||
| 129 | return; // Shortcut | ||
| 130 | } | ||
| 131 | |||
| 132 | writer.print(indent(1)); | ||
| 133 | writer.print("f\t"); | ||
| 134 | writer.print(((FieldEntry) node.getEntry()).getDesc().toString()); | ||
| 135 | writer.print("\t"); | ||
| 136 | writer.print(node.getEntry().getName()); | ||
| 137 | writer.print("\t"); | ||
| 138 | EntryMapping mapping = node.getValue(); | ||
| 139 | |||
| 140 | if (mapping == null) { | ||
| 141 | mapping = EntryMapping.DEFAULT; | ||
| 142 | } | ||
| 143 | |||
| 144 | if (mapping.targetName() != null) { | ||
| 145 | writer.println(mapping.targetName()); | ||
| 146 | } else { | ||
| 147 | writer.println(node.getEntry().getName()); // todo fix v2 name inference | ||
| 148 | } | ||
| 149 | |||
| 150 | writeComment(writer, mapping, 2); | ||
| 151 | } | ||
| 152 | |||
| 153 | private void writeParameter(PrintWriter writer, EntryTreeNode<EntryMapping> node) { | ||
| 154 | if (node.getValue() == null || node.getValue().equals(EntryMapping.DEFAULT)) { | ||
| 155 | return; // Shortcut | ||
| 156 | } | ||
| 157 | |||
| 158 | writer.print(indent(2)); | ||
| 159 | writer.print("p\t"); | ||
| 160 | writer.print(((LocalVariableEntry) node.getEntry()).getIndex()); | ||
| 161 | writer.print("\t"); | ||
| 162 | writer.print(node.getEntry().getName()); | ||
| 163 | writer.print("\t"); | ||
| 164 | EntryMapping mapping = node.getValue(); | ||
| 165 | |||
| 166 | if (mapping == null || mapping.targetName() == null) { | ||
| 167 | writer.println(); // todo ??? | ||
| 168 | } else { | ||
| 169 | writer.println(mapping.targetName()); | ||
| 170 | |||
| 171 | writeComment(writer, mapping, 3); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | private void writeComment(PrintWriter writer, EntryMapping mapping, int indent) { | ||
| 176 | if (mapping != null && mapping.javadoc() != null) { | ||
| 177 | writer.print(indent(indent)); | ||
| 178 | writer.print("c\t"); | ||
| 179 | writer.print(MappingHelper.escape(mapping.javadoc())); | ||
| 180 | writer.println(); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | private String indent(int level) { | ||
| 185 | return "\t".repeat(level); | ||
| 186 | } | ||
| 187 | } | ||
diff --git a/enigma/src/main/resources/lang/en_us.json b/enigma/src/main/resources/lang/en_us.json index e0882b9a..a9c7ac91 100644 --- a/enigma/src/main/resources/lang/en_us.json +++ b/enigma/src/main/resources/lang/en_us.json | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | "mapping_format.recaf": "Recaf Simple File", | 16 | "mapping_format.recaf": "Recaf Simple File", |
| 17 | "mapping_format.jobf_file": "JOBF File", | 17 | "mapping_format.jobf_file": "JOBF File", |
| 18 | "mapping_format.intellij_migration_map_file": "IntelliJ Migration Map File", | 18 | "mapping_format.intellij_migration_map_file": "IntelliJ Migration Map File", |
| 19 | "legacy": "legacy", | ||
| 20 | 19 | ||
| 21 | "type.methods": "Methods", | 20 | "type.methods": "Methods", |
| 22 | "type.fields": "Fields", | 21 | "type.fields": "Fields", |
diff --git a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestComments.java b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestComments.java deleted file mode 100644 index 15ec44e4..00000000 --- a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestComments.java +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping; | ||
| 2 | |||
| 3 | import java.io.IOException; | ||
| 4 | import java.net.URISyntaxException; | ||
| 5 | import java.nio.file.Path; | ||
| 6 | import java.nio.file.Paths; | ||
| 7 | |||
| 8 | import org.junit.Test; | ||
| 9 | |||
| 10 | import cuchaz.enigma.ProgressListener; | ||
| 11 | import cuchaz.enigma.translation.mapping.serde.MappingFileNameFormat; | ||
| 12 | import cuchaz.enigma.translation.mapping.serde.MappingParseException; | ||
| 13 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 14 | import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsReader; | ||
| 15 | import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Writer; | ||
| 16 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 17 | |||
| 18 | public class TestComments { | ||
| 19 | private static Path DIRECTORY; | ||
| 20 | |||
| 21 | static { | ||
| 22 | try { | ||
| 23 | DIRECTORY = Paths.get(TestTinyV2InnerClasses.class.getResource("/comments/").toURI()); | ||
| 24 | } catch (URISyntaxException e) { | ||
| 25 | throw new RuntimeException(e); | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | @Test | ||
| 30 | public void testParseAndWrite() throws IOException, MappingParseException { | ||
| 31 | ProgressListener progressListener = ProgressListener.none(); | ||
| 32 | MappingSaveParameters params = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF); | ||
| 33 | EntryTree<EntryMapping> mappings = EnigmaMappingsReader.DIRECTORY.read(DIRECTORY, progressListener, params); | ||
| 34 | |||
| 35 | new TinyV2Writer("intermediary", "named").write(mappings, DIRECTORY.resolve("convertedtiny.tiny"), progressListener, params); | ||
| 36 | } | ||
| 37 | } | ||
diff --git a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java index 25f11fbc..f665c36d 100644 --- a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java +++ b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java | |||
| @@ -104,11 +104,6 @@ public class TestReadWriteCycle { | |||
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | @Test | 106 | @Test |
| 107 | public void testEnigmaZip() throws IOException, MappingParseException { | ||
| 108 | testReadWriteCycle(MappingFormat.ENIGMA_ZIP, true, ".zip"); | ||
| 109 | } | ||
| 110 | |||
| 111 | @Test | ||
| 112 | public void testTinyFile() throws IOException, MappingParseException { | 107 | public void testTinyFile() throws IOException, MappingParseException { |
| 113 | testReadWriteCycle(MappingFormat.TINY_FILE, false, ".tiny"); | 108 | testReadWriteCycle(MappingFormat.TINY_FILE, false, ".tiny"); |
| 114 | } | 109 | } |
diff --git a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestTinyV2InnerClasses.java b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestTinyV2InnerClasses.java deleted file mode 100644 index 9164abe7..00000000 --- a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestTinyV2InnerClasses.java +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2015 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Lesser General Public | ||
| 5 | * License v3.0 which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/lgpl.html | ||
| 7 | * | ||
| 8 | * <p>Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | |||
| 12 | package cuchaz.enigma.translation.mapping; | ||
| 13 | |||
| 14 | import java.nio.file.Path; | ||
| 15 | import java.nio.file.Paths; | ||
| 16 | import java.util.List; | ||
| 17 | |||
| 18 | import cuchaz.enigma.Enigma; | ||
| 19 | import cuchaz.enigma.EnigmaProject; | ||
| 20 | import cuchaz.enigma.ProgressListener; | ||
| 21 | import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsReader; | ||
| 22 | |||
| 23 | public final class TestTinyV2InnerClasses { | ||
| 24 | private Path jar; | ||
| 25 | private Path mappings; | ||
| 26 | |||
| 27 | public TestTinyV2InnerClasses() throws Exception { | ||
| 28 | jar = Paths.get("build/test-obf/innerClasses.jar"); | ||
| 29 | mappings = Paths.get(TestTinyV2InnerClasses.class.getResource("/tinyV2InnerClasses/").toURI()); | ||
| 30 | } | ||
| 31 | |||
| 32 | // @Test | ||
| 33 | public void testMappings() throws Exception { | ||
| 34 | EnigmaProject project = Enigma.create().openJar(jar, List.of(), ProgressListener.none()); | ||
| 35 | project.setMappings(EnigmaMappingsReader.DIRECTORY.read(mappings, ProgressListener.none(), project.getEnigma().getProfile().getMappingSaveParameters())); | ||
| 36 | } | ||
| 37 | } | ||
diff --git a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestV2Main.java b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestV2Main.java deleted file mode 100644 index cc08b852..00000000 --- a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestV2Main.java +++ /dev/null | |||
| @@ -1,23 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping; | ||
| 2 | |||
| 3 | import java.nio.file.Path; | ||
| 4 | import java.nio.file.Paths; | ||
| 5 | |||
| 6 | import cuchaz.enigma.ProgressListener; | ||
| 7 | import cuchaz.enigma.translation.mapping.serde.MappingFileNameFormat; | ||
| 8 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 9 | import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsReader; | ||
| 10 | import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Writer; | ||
| 11 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 12 | |||
| 13 | public final class TestV2Main { | ||
| 14 | public static void main(String... args) throws Exception { | ||
| 15 | Path path = Paths.get(TestV2Main.class.getResource("/tinyV2InnerClasses/").toURI()); | ||
| 16 | |||
| 17 | MappingSaveParameters parameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF); | ||
| 18 | |||
| 19 | EntryTree<EntryMapping> tree = EnigmaMappingsReader.DIRECTORY.read(path, ProgressListener.none(), parameters); | ||
| 20 | |||
| 21 | new TinyV2Writer("obf", "deobf").write(tree, Paths.get("currentYarn.tiny"), ProgressListener.none(), parameters); | ||
| 22 | } | ||
| 23 | } | ||
diff --git a/enigma/src/test/java/cuchaz/enigma/translation/mapping/serde/recaf/TestRecaf.java b/enigma/src/test/java/cuchaz/enigma/translation/mapping/serde/recaf/TestRecaf.java deleted file mode 100644 index 5f3e47c0..00000000 --- a/enigma/src/test/java/cuchaz/enigma/translation/mapping/serde/recaf/TestRecaf.java +++ /dev/null | |||
| @@ -1,45 +0,0 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde.recaf; | ||
| 2 | |||
| 3 | import static org.junit.Assert.assertEquals; | ||
| 4 | |||
| 5 | import java.io.InputStream; | ||
| 6 | import java.nio.charset.StandardCharsets; | ||
| 7 | import java.nio.file.FileSystem; | ||
| 8 | import java.nio.file.Files; | ||
| 9 | import java.nio.file.Path; | ||
| 10 | import java.util.HashSet; | ||
| 11 | import java.util.Set; | ||
| 12 | |||
| 13 | import com.google.common.jimfs.Jimfs; | ||
| 14 | import org.junit.Test; | ||
| 15 | |||
| 16 | import cuchaz.enigma.ProgressListener; | ||
| 17 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 18 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 19 | |||
| 20 | public class TestRecaf { | ||
| 21 | @Test | ||
| 22 | public void testIntegrity() throws Exception { | ||
| 23 | Set<String> contents; | ||
| 24 | |||
| 25 | try (InputStream in = getClass().getResourceAsStream("/recaf.mappings")) { | ||
| 26 | contents = Set.of(new String(in.readAllBytes(), StandardCharsets.UTF_8).split("\\R")); | ||
| 27 | } | ||
| 28 | |||
| 29 | try (FileSystem fs = Jimfs.newFileSystem()) { | ||
| 30 | Path path = fs.getPath("recaf.mappings"); | ||
| 31 | Files.writeString(path, String.join("\n", contents)); | ||
| 32 | |||
| 33 | RecafMappingsWriter writer = RecafMappingsWriter.INSTANCE; | ||
| 34 | RecafMappingsReader reader = RecafMappingsReader.INSTANCE; | ||
| 35 | |||
| 36 | EntryTree<EntryMapping> mappings = reader.read(path, ProgressListener.none(), null); | ||
| 37 | writer.write(mappings, path, ProgressListener.none(), null); | ||
| 38 | |||
| 39 | reader.read(path, ProgressListener.none(), null); | ||
| 40 | Set<String> newContents = new HashSet<>(Files.readAllLines(path)); | ||
| 41 | |||
| 42 | assertEquals(contents, newContents); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | } | ||
diff --git a/enigma/src/test/resources/comments/test.mapping b/enigma/src/test/resources/comments/test.mapping deleted file mode 100644 index d1345583..00000000 --- a/enigma/src/test/resources/comments/test.mapping +++ /dev/null | |||
| @@ -1,18 +0,0 @@ | |||
| 1 | CLASS net/minecraft/class_1158 net/minecraft/util/math/Quaternion | ||
| 2 | COMMENT it circel | ||
| 3 | COMMENT next line | ||
| 4 | FIELD field_21493 IDENTITY Lnet/minecraft/class_1158; | ||
| 5 | COMMENT moar comment thing | ||
| 6 | COMMENT near field | ||
| 7 | METHOD foo bar (FFFF)V | ||
| 8 | COMMENT method comment | ||
| 9 | COMMENT second line | ||
| 10 | COMMENT third line | ||
| 11 | ARG 1 b | ||
| 12 | COMMENT arg comment | ||
| 13 | CLASS old new | ||
| 14 | COMMENT inner comment | ||
| 15 | FIELD field_19263 iterator Lnet/minecraft/class_3980; | ||
| 16 | METHOD tryAdvance (Ljava/util/function/Consumer;)Z | ||
| 17 | ARG 1 consumer | ||
| 18 | COMMENT very inner comment \ No newline at end of file | ||
diff --git a/enigma/src/test/resources/recaf.mappings b/enigma/src/test/resources/recaf.mappings deleted file mode 100644 index 479099ed..00000000 --- a/enigma/src/test/resources/recaf.mappings +++ /dev/null | |||
| @@ -1,10 +0,0 @@ | |||
| 1 | a testClass | ||
| 2 | a.a Z testField | ||
| 3 | a.a()V testMethod0 | ||
| 4 | a.a(Z)V testMethod1 | ||
| 5 | a.b()V testMethod2 | ||
| 6 | a/a testInnerClass | ||
| 7 | a/a.a Z testInnerField | ||
| 8 | a/a.a()V testInnerMethod0 | ||
| 9 | a/a.a(Z)V testInnerMethod1 | ||
| 10 | a/a.b()V testInnerMethod2 | ||
diff --git a/enigma/src/test/resources/tinyV2InnerClasses/c.mapping b/enigma/src/test/resources/tinyV2InnerClasses/c.mapping deleted file mode 100644 index f9b04428..00000000 --- a/enigma/src/test/resources/tinyV2InnerClasses/c.mapping +++ /dev/null | |||
| @@ -1,2 +0,0 @@ | |||
| 1 | CLASS c | ||
| 2 | CLASS a Kid | ||
diff --git a/enigma/src/test/resources/tinyV2InnerClasses/cuchaz/enigma/Dad.mapping b/enigma/src/test/resources/tinyV2InnerClasses/cuchaz/enigma/Dad.mapping deleted file mode 100644 index 8d43ba90..00000000 --- a/enigma/src/test/resources/tinyV2InnerClasses/cuchaz/enigma/Dad.mapping +++ /dev/null | |||
| @@ -1,5 +0,0 @@ | |||
| 1 | CLASS f cuchaz/enigma/Dad | ||
| 2 | CLASS a One | ||
| 3 | CLASS a Two | ||
| 4 | CLASS a | ||
| 5 | FIELD a value I | ||