diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/Argument.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/Argument.java index f91274270..ea7ce33d3 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/Argument.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/Argument.java @@ -1,84 +1,3 @@ package org.quiltmc.enigma.command; -public enum Argument { - INPUT_JAR("", - """ - A path to the .jar file to use in executing the command.""" - ), - INPUT_MAPPINGS("", - """ - A path to the file or folder to read mappings from.""" - ), - LEFT_MAPPINGS("", - """ - A path to the left file or folder to read mappings from, used in commands which take two mapping inputs.""" - ), - RIGHT_MAPPINGS("", - """ - A path to the right file or folder to read mappings from, used in commands which take two mapping inputs.""" - ), - MAPPING_OUTPUT("", - """ - A path to the file or folder to write mappings to. Will be created if missing.""" - ), - KEEP_MODE("", - """ - Which mappings should overwrite the others when composing conflicting mappings. Allowed values are "left", "right", and "both".""" - ), - DECOMPILER("", - """ - The decompiler to use when producing output. Allowed values are (case-insensitive): - - VINEFLOWER - - CFR - - PROCYON - - BYTECODE""" - ), - OUTPUT_FOLDER("", - """ - A path to the file or folder to write output to.""" - ), - OUTPUT_JAR("", - """ - A path to the .jar file to write output to. Will be created if missing.""" - ), - FILL_ALL("", - """ - Whether to fill all possible mappings. Allowed values are "true" and "false".""" - ), - ENIGMA_PROFILE("", - """ - A path to an Enigma profile JSON file, used to apply things like plugins.""" - ), - OBFUSCATED_NAMESPACE("", - """ - The namespace to use for obfuscated names when writing mappings. Only used in certain mapping formats.""" - ), - DEOBFUSCATED_NAMESPACE("", - """ - The namespace to use for deobfuscated names when writing mappings. Only used in certain mapping formats.""" - ); - - private final String displayForm; - private final String explanation; - - Argument(String displayForm, String explanation) { - this.displayForm = displayForm; - this.explanation = explanation; - } - - public String getDisplayForm() { - return this.displayForm; - } - - public String getExplanation() { - return this.explanation; - } - - public ComposedArgument required() { - return new ComposedArgument(this, false); - } - - public ComposedArgument optional() { - return new ComposedArgument(this, true); - } -} +record Argument(String displayForm, String explanation) { } diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/CheckMappingsCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/CheckMappingsCommand.java index 652d55463..d71e15492 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/CheckMappingsCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/CheckMappingsCommand.java @@ -10,11 +10,11 @@ import java.util.Set; import java.util.stream.Collectors; -public class CheckMappingsCommand extends Command { - public CheckMappingsCommand() { - super(Argument.INPUT_JAR.required(), - Argument.INPUT_MAPPINGS.required() - ); +public final class CheckMappingsCommand extends Command { + public static final CheckMappingsCommand INSTANCE = new CheckMappingsCommand(); + + private CheckMappingsCommand() { + super(CommonArguments.INPUT_JAR, CommonArguments.INPUT_MAPPINGS); } @Override diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/Command.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/Command.java index 5785c5510..3fce82632 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/Command.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/Command.java @@ -1,5 +1,6 @@ package org.quiltmc.enigma.command; +import com.google.common.collect.ImmutableList; import org.quiltmc.enigma.api.Enigma; import org.quiltmc.enigma.api.EnigmaProfile; import org.quiltmc.enigma.api.EnigmaProject; @@ -25,32 +26,28 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.Path; -import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Locale; import javax.annotation.Nullable; -public abstract class Command { - protected final List requiredArguments = new ArrayList<>(); - protected final List optionalArguments = new ArrayList<>(); - protected final List allArguments; +public abstract sealed class Command permits + CheckMappingsCommand, ComposeMappingsCommand, ConvertMappingsCommand, DecompileCommand, DeobfuscateCommand, + DropInvalidMappingsCommand, FillClassMappingsCommand, HelpCommand, InsertProposedMappingsCommand, + InvertMappingsCommand, MapSpecializedMethodsCommand, PrintStatsCommand { + final ImmutableList requiredArguments; + final ImmutableList optionalArguments; - protected Command(ComposedArgument... arguments) { - this.allArguments = new ArrayList<>(); + final int totalArgumentCount; - for (ComposedArgument argument : arguments) { - if (argument.optional()) { - this.optionalArguments.add(argument.argument()); - this.allArguments.add(argument); - } else { - this.requiredArguments.add(argument.argument()); - this.allArguments.add(argument); + Command(Argument... requiredArguments) { + this(ImmutableList.copyOf(requiredArguments), ImmutableList.of()); + } - if (!this.optionalArguments.isEmpty()) { - throw new IllegalArgumentException("optional arguments should be grouped at the end of command arguments! (declaring arg " + argument + ")"); - } - } - } + Command(Collection requiredArguments, Collection optionalArguments) { + this.requiredArguments = ImmutableList.copyOf(requiredArguments); + this.optionalArguments = ImmutableList.copyOf(optionalArguments); + this.totalArgumentCount = this.requiredArguments.size() + this.optionalArguments.size(); } public String getUsage() { @@ -68,7 +65,7 @@ public String getUsage() { private static void appendArguments(StringBuilder builder, List arguments) { for (int i = 0; i < arguments.size(); i++) { - builder.append(arguments.get(i).getDisplayForm()); + builder.append(arguments.get(i).displayForm()); if (i < arguments.size() - 1) { builder.append(" "); } @@ -81,8 +78,7 @@ private static void appendArguments(StringBuilder builder, List argume * @return {@code true} if the argument count is valid, {@code false} otherwise */ public boolean checkArgumentCount(int length) { - // valid if length is equal to the amount of required arguments or between required argument count and total argument count - return length == this.requiredArguments.size() || length > this.requiredArguments.size() && length <= this.allArguments.size(); + return length >= this.requiredArguments.size() && length <= this.totalArgumentCount; } /** @@ -125,10 +121,15 @@ public static Enigma createEnigma() { * @return the argument, as a string */ protected String getArg(String[] args, int index) { - if (index < this.allArguments.size() && index >= 0) { - return getArg(args, index, this.allArguments.get(index)); + if (index < this.totalArgumentCount && index >= 0) { + final int requiredCount = this.requiredArguments.size(); + if (index < requiredCount) { + return getArg(args, index, this.requiredArguments.get(index), false); + } else { + return getArg(args, index, this.optionalArguments.get(index - requiredCount), true); + } } else { - throw new RuntimeException("arg index is outside of range of possible arguments! (index: " + index + ", allowed arg count: " + this.allArguments.size() + ")"); + throw new RuntimeException("arg index is outside of range of possible arguments! (index: " + index + ", allowed arg count: " + this.totalArgumentCount + ")"); } } @@ -244,16 +245,16 @@ protected static Path getWritablePath(String path) { return dir; } - private static String getArg(String[] args, int i, ComposedArgument argument) { - if (i >= args.length) { - if (!argument.optional()) { - throw new IllegalArgumentException(argument.argument().getDisplayForm() + " is required"); + private static String getArg(String[] args, int index, Argument argument, boolean optional) { + if (index >= args.length) { + if (!optional) { + throw new IllegalArgumentException(argument.displayForm() + " is required"); } else { return null; } } - return args[i]; + return args[index]; } protected static boolean shouldDebug(String name) { diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/CommandsUtil.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/CommandsUtil.java index b7c503940..5af861ed7 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/CommandsUtil.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/CommandsUtil.java @@ -8,6 +8,10 @@ import java.nio.file.Path; public class CommandsUtil { + private CommandsUtil() { + throw new UnsupportedOperationException(); + } + public static ReadWriteService getReadWriteService(Enigma enigma, Path file) { var service = enigma.getReadWriteService(file); if (service.isEmpty()) { diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/CommonArguments.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/CommonArguments.java new file mode 100644 index 000000000..38a82f393 --- /dev/null +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/CommonArguments.java @@ -0,0 +1,36 @@ +package org.quiltmc.enigma.command; + +final class CommonArguments { + private CommonArguments() { + throw new UnsupportedOperationException(); + } + + static final Argument INPUT_JAR = new Argument("", + """ + A path to the .jar file to use in executing the command.""" + ); + static final Argument INPUT_MAPPINGS = new Argument("", + """ + A path to the file or folder to read mappings from.""" + ); + static final Argument MAPPING_OUTPUT = new Argument("", + """ + A path to the file or folder to write mappings to. Will be created if missing.""" + ); + static final Argument OUTPUT_JAR = new Argument("", + """ + A path to the .jar file to write output to. Will be created if missing.""" + ); + static final Argument ENIGMA_PROFILE = new Argument("", + """ + A path to an Enigma profile JSON file, used to apply things like plugins.""" + ); + static final Argument OBFUSCATED_NAMESPACE = new Argument("", + """ + The namespace to use for obfuscated names when writing mappings. Only used in certain mapping formats.""" + ); + static final Argument DEOBFUSCATED_NAMESPACE = new Argument("", + """ + The namespace to use for deobfuscated names when writing mappings. Only used in certain mapping formats.""" + ); +} diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/ComposeMappingsCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/ComposeMappingsCommand.java index 263b485cb..cd74e1bba 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/ComposeMappingsCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/ComposeMappingsCommand.java @@ -16,13 +16,24 @@ import java.io.IOException; import java.nio.file.Path; -public class ComposeMappingsCommand extends Command { - public ComposeMappingsCommand() { - super(Argument.LEFT_MAPPINGS.required(), - Argument.RIGHT_MAPPINGS.required(), - Argument.MAPPING_OUTPUT.required(), - Argument.KEEP_MODE.required() - ); +public final class ComposeMappingsCommand extends Command { + private static final Argument LEFT_MAPPINGS = new Argument("", + """ + A path to the left file or folder to read mappings from, used in commands which take two mapping inputs.""" + ); + private static final Argument RIGHT_MAPPINGS = new Argument("", + """ + A path to the right file or folder to read mappings from, used in commands which take two mapping inputs.""" + ); + private static final Argument KEEP_MODE = new Argument("", + """ + Which mappings should overwrite the others when composing conflicting mappings. Allowed values are "left", "right", and "both".""" + ); + + public static final ComposeMappingsCommand INSTANCE = new ComposeMappingsCommand(); + + private ComposeMappingsCommand() { + super(LEFT_MAPPINGS, RIGHT_MAPPINGS, CommonArguments.MAPPING_OUTPUT, KEEP_MODE); } @Override diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/ComposedArgument.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/ComposedArgument.java deleted file mode 100644 index 61cac1962..000000000 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/ComposedArgument.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.quiltmc.enigma.command; - -public record ComposedArgument(Argument argument, boolean optional) { -} diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/ConvertMappingsCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/ConvertMappingsCommand.java index 2b2a7bc66..11a2012f8 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/ConvertMappingsCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/ConvertMappingsCommand.java @@ -15,12 +15,15 @@ import java.io.IOException; import java.nio.file.Path; -public class ConvertMappingsCommand extends Command { - public ConvertMappingsCommand() { - super(Argument.INPUT_MAPPINGS.required(), - Argument.MAPPING_OUTPUT.required(), - Argument.OBFUSCATED_NAMESPACE.required(), - Argument.DEOBFUSCATED_NAMESPACE.required() +public final class ConvertMappingsCommand extends Command { + public static final ConvertMappingsCommand INSTANCE = new ConvertMappingsCommand(); + + private ConvertMappingsCommand() { + super( + CommonArguments.INPUT_MAPPINGS, + CommonArguments.MAPPING_OUTPUT, + CommonArguments.OBFUSCATED_NAMESPACE, + CommonArguments.DEOBFUSCATED_NAMESPACE ); } diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/DecompileCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/DecompileCommand.java index 8e3c7446a..ce7881e1e 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/DecompileCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/DecompileCommand.java @@ -1,5 +1,6 @@ package org.quiltmc.enigma.command; +import com.google.common.collect.ImmutableList; import org.quiltmc.enigma.api.EnigmaProject; import org.quiltmc.enigma.api.ProgressListener; import org.quiltmc.enigma.api.EnigmaProject.DecompileErrorStrategy; @@ -11,12 +12,23 @@ import java.nio.file.Path; import java.util.Locale; -public class DecompileCommand extends Command { - public DecompileCommand() { - super(Argument.DECOMPILER.required(), - Argument.INPUT_JAR.required(), - Argument.OUTPUT_JAR.required(), - Argument.INPUT_MAPPINGS.optional()); +public final class DecompileCommand extends Command { + private static final Argument DECOMPILER = new Argument("", + """ + The decompiler to use when producing output. Allowed values are (case-insensitive): + - VINEFLOWER + - CFR + - PROCYON + - BYTECODE""" + ); + + public static final DecompileCommand INSTANCE = new DecompileCommand(); + + private DecompileCommand() { + super( + ImmutableList.of(DECOMPILER, CommonArguments.INPUT_JAR, CommonArguments.OUTPUT_JAR), + ImmutableList.of(CommonArguments.INPUT_MAPPINGS) + ); } @Override diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/DeobfuscateCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/DeobfuscateCommand.java index 5944f409a..b17e06883 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/DeobfuscateCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/DeobfuscateCommand.java @@ -1,15 +1,18 @@ package org.quiltmc.enigma.command; +import com.google.common.collect.ImmutableList; import org.quiltmc.enigma.api.EnigmaProject; import org.quiltmc.enigma.api.ProgressListener; import java.nio.file.Path; -public class DeobfuscateCommand extends Command { - public DeobfuscateCommand() { - super(Argument.INPUT_JAR.required(), - Argument.OUTPUT_JAR.required(), - Argument.INPUT_MAPPINGS.optional() +public final class DeobfuscateCommand extends Command { + public static final DeobfuscateCommand INSTANCE = new DeobfuscateCommand(); + + private DeobfuscateCommand() { + super( + ImmutableList.of(CommonArguments.INPUT_JAR, CommonArguments.OUTPUT_JAR), + ImmutableList.of(CommonArguments.INPUT_MAPPINGS) ); } diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/DropInvalidMappingsCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/DropInvalidMappingsCommand.java index fabe1b11d..d364b8a6b 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/DropInvalidMappingsCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/DropInvalidMappingsCommand.java @@ -1,5 +1,6 @@ package org.quiltmc.enigma.command; +import com.google.common.collect.ImmutableList; import org.quiltmc.enigma.api.EnigmaProject; import org.quiltmc.enigma.api.ProgressListener; import org.quiltmc.enigma.api.translation.mapping.serde.MappingSaveParameters; @@ -13,11 +14,14 @@ import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; -public class DropInvalidMappingsCommand extends Command { - public DropInvalidMappingsCommand() { - super(Argument.INPUT_JAR.required(), - Argument.INPUT_MAPPINGS.required(), - Argument.MAPPING_OUTPUT.optional()); +public final class DropInvalidMappingsCommand extends Command { + public static final DropInvalidMappingsCommand INSTANCE = new DropInvalidMappingsCommand(); + + private DropInvalidMappingsCommand() { + super( + ImmutableList.of(CommonArguments.INPUT_JAR, CommonArguments.INPUT_MAPPINGS), + ImmutableList.of(CommonArguments.MAPPING_OUTPUT) + ); } @Override diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/FillClassMappingsCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/FillClassMappingsCommand.java index e522c53a7..a23d272f0 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/FillClassMappingsCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/FillClassMappingsCommand.java @@ -1,5 +1,6 @@ package org.quiltmc.enigma.command; +import com.google.common.collect.ImmutableList; import org.quiltmc.enigma.api.Enigma; import org.quiltmc.enigma.api.ProgressListener; import org.quiltmc.enigma.api.analysis.index.jar.JarIndex; @@ -20,14 +21,22 @@ import java.nio.file.Path; import java.util.List; -public class FillClassMappingsCommand extends Command { - protected FillClassMappingsCommand() { - super(Argument.INPUT_JAR.required(), - Argument.INPUT_MAPPINGS.required(), - Argument.MAPPING_OUTPUT.required(), - Argument.FILL_ALL.optional(), - Argument.OBFUSCATED_NAMESPACE.optional(), - Argument.DEOBFUSCATED_NAMESPACE.optional() +public final class FillClassMappingsCommand extends Command { + private static final Argument FILL_ALL = new Argument("", + """ + Whether to fill all possible mappings. Allowed values are "true" and "false".""" + ); + + public static final FillClassMappingsCommand INSTANCE = new FillClassMappingsCommand(); + + private FillClassMappingsCommand() { + super( + ImmutableList.of( + CommonArguments.INPUT_JAR, + CommonArguments.INPUT_MAPPINGS, + CommonArguments.MAPPING_OUTPUT + ), + ImmutableList.of(FILL_ALL, CommonArguments.OBFUSCATED_NAMESPACE, CommonArguments.DEOBFUSCATED_NAMESPACE) ); } @@ -54,7 +63,7 @@ public String getDescription() { } public static void run(Path jar, Path source, Path result, boolean fillAll, @Nullable String obfuscatedNamespace, @Nullable String deobfuscatedNamespace) throws Exception { - boolean debug = shouldDebug(new FillClassMappingsCommand().getName()); + boolean debug = shouldDebug(INSTANCE.getName()); JarIndex jarIndex = loadJar(jar); Enigma enigma = createEnigma(); diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/HelpCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/HelpCommand.java index 3f34e1d12..31cf1e760 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/HelpCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/HelpCommand.java @@ -4,8 +4,10 @@ import java.util.Collection; -public class HelpCommand extends Command { - protected HelpCommand() { +public final class HelpCommand extends Command { + public static final HelpCommand INSTANCE = new HelpCommand(); + + private HelpCommand() { super(); } diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/InsertProposedMappingsCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/InsertProposedMappingsCommand.java index b0158ac82..d62334440 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/InsertProposedMappingsCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/InsertProposedMappingsCommand.java @@ -1,5 +1,6 @@ package org.quiltmc.enigma.command; +import com.google.common.collect.ImmutableList; import org.quiltmc.enigma.api.Enigma; import org.quiltmc.enigma.api.EnigmaProfile; import org.quiltmc.enigma.api.EnigmaProject; @@ -26,14 +27,21 @@ import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.Nullable; -public class InsertProposedMappingsCommand extends Command { - public InsertProposedMappingsCommand() { - super(Argument.INPUT_JAR.required(), - Argument.INPUT_MAPPINGS.required(), - Argument.MAPPING_OUTPUT.required(), - Argument.ENIGMA_PROFILE.optional(), - Argument.OBFUSCATED_NAMESPACE.optional(), - Argument.DEOBFUSCATED_NAMESPACE.optional() +public final class InsertProposedMappingsCommand extends Command { + public static final InsertProposedMappingsCommand INSTANCE = new InsertProposedMappingsCommand(); + + private InsertProposedMappingsCommand() { + super( + ImmutableList.of( + CommonArguments.INPUT_JAR, + CommonArguments.INPUT_MAPPINGS, + CommonArguments.MAPPING_OUTPUT + ), + ImmutableList.of( + CommonArguments.ENIGMA_PROFILE, + CommonArguments.OBFUSCATED_NAMESPACE, + CommonArguments.DEOBFUSCATED_NAMESPACE + ) ); } @@ -67,7 +75,7 @@ public static void run(Path inJar, Path source, Path output, @Nullable Path prof } public static void run(Path inJar, Path source, Path output, Enigma enigma, @Nullable String obfuscatedNamespace, @Nullable String deobfuscatedNamespace) throws Exception { - boolean debug = shouldDebug(new InsertProposedMappingsCommand().getName()); + boolean debug = shouldDebug(INSTANCE.getName()); int nameProposalServices = enigma.getServices().get(NameProposalService.TYPE).size(); if (nameProposalServices == 0) { Logger.error("No name proposal services found!"); diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/InvertMappingsCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/InvertMappingsCommand.java index ed5fe916c..e1fdb2d32 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/InvertMappingsCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/InvertMappingsCommand.java @@ -1,5 +1,6 @@ package org.quiltmc.enigma.command; +import com.google.common.collect.ImmutableList; import org.quiltmc.enigma.api.Enigma; import org.quiltmc.enigma.util.MappingOperations; import org.quiltmc.enigma.api.translation.mapping.serde.MappingParseException; @@ -13,12 +14,18 @@ import java.io.IOException; import java.nio.file.Path; -public class InvertMappingsCommand extends Command { - public InvertMappingsCommand() { - super(Argument.INPUT_MAPPINGS.required(), - Argument.OUTPUT_FOLDER.required(), - Argument.OBFUSCATED_NAMESPACE.optional(), - Argument.DEOBFUSCATED_NAMESPACE.optional() +public final class InvertMappingsCommand extends Command { + private static final Argument OUTPUT_FOLDER = new Argument("", + """ + A path to the file or folder to write output to.""" + ); + + public static final InvertMappingsCommand INSTANCE = new InvertMappingsCommand(); + + private InvertMappingsCommand() { + super( + ImmutableList.of(CommonArguments.INPUT_MAPPINGS, OUTPUT_FOLDER), + ImmutableList.of(CommonArguments.OBFUSCATED_NAMESPACE, CommonArguments.DEOBFUSCATED_NAMESPACE) ); } diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/Main.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/Main.java index 5014feb4e..d5f9fd0f6 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/Main.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/Main.java @@ -1,14 +1,32 @@ package org.quiltmc.enigma.command; +import com.google.common.collect.ImmutableMap; import org.quiltmc.enigma.api.Enigma; import org.tinylog.Logger; -import java.util.LinkedHashMap; import java.util.Locale; -import java.util.Map; +import java.util.function.Function; +import java.util.stream.Stream; + +import static com.google.common.collect.ImmutableMap.toImmutableMap; public class Main { - private static final Map COMMANDS = new LinkedHashMap<>(); + private static final ImmutableMap COMMANDS = Stream + .of( + DeobfuscateCommand.INSTANCE, + DecompileCommand.INSTANCE, + ConvertMappingsCommand.INSTANCE, + ComposeMappingsCommand.INSTANCE, + InvertMappingsCommand.INSTANCE, + CheckMappingsCommand.INSTANCE, + MapSpecializedMethodsCommand.INSTANCE, + InsertProposedMappingsCommand.INSTANCE, + DropInvalidMappingsCommand.INSTANCE, + FillClassMappingsCommand.INSTANCE, + HelpCommand.INSTANCE, + PrintStatsCommand.INSTANCE + ) + .collect(toImmutableMap(Command::getName, Function.identity())); public static void main(String... args) { try { @@ -51,7 +69,7 @@ public static void main(String... args) { } } - public static Map getCommands() { + public static ImmutableMap getCommands() { return COMMANDS; } @@ -93,36 +111,14 @@ private static void appendHelp(Command command, StringBuilder builder) { } private static void appendHelp(Argument argument, int index, StringBuilder builder) { - builder.append(String.format("Argument %s: %s", index, argument.getDisplayForm())).append("\n"); - builder.append(argument.getExplanation()).append("\n"); - } - - private static void register(Command command) { - Command old = COMMANDS.put(command.getName(), command); - if (old != null) { - Logger.warn("Command {} with name {} has been substituted by {}", old, command.getName(), command); - } + builder.append(String.format("Argument %s: %s", index, argument.displayForm())).append("\n"); + builder.append(argument.explanation()).append("\n"); } private static void logEnigmaInfo() { Logger.info("{} - {}", Enigma.NAME, Enigma.VERSION); } - static { - register(new DeobfuscateCommand()); - register(new DecompileCommand()); - register(new ConvertMappingsCommand()); - register(new ComposeMappingsCommand()); - register(new InvertMappingsCommand()); - register(new CheckMappingsCommand()); - register(new MapSpecializedMethodsCommand()); - register(new InsertProposedMappingsCommand()); - register(new DropInvalidMappingsCommand()); - register(new FillClassMappingsCommand()); - register(new HelpCommand()); - register(new PrintStatsCommand()); - } - private static final class CommandHelpException extends IllegalArgumentException { final Command command; diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/MapSpecializedMethodsCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/MapSpecializedMethodsCommand.java index 22aea0304..b03e21276 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/MapSpecializedMethodsCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/MapSpecializedMethodsCommand.java @@ -1,5 +1,6 @@ package org.quiltmc.enigma.command; +import com.google.common.collect.ImmutableList; import org.quiltmc.enigma.api.Enigma; import org.quiltmc.enigma.api.analysis.index.jar.BridgeMethodIndex; import org.quiltmc.enigma.api.analysis.index.jar.JarIndex; @@ -23,13 +24,13 @@ import java.nio.file.Path; import java.util.Map; -public class MapSpecializedMethodsCommand extends Command { - public MapSpecializedMethodsCommand() { - super(Argument.INPUT_JAR.required(), - Argument.INPUT_MAPPINGS.required(), - Argument.MAPPING_OUTPUT.required(), - Argument.OBFUSCATED_NAMESPACE.optional(), - Argument.DEOBFUSCATED_NAMESPACE.optional() +public final class MapSpecializedMethodsCommand extends Command { + public static final MapSpecializedMethodsCommand INSTANCE = new MapSpecializedMethodsCommand(); + + private MapSpecializedMethodsCommand() { + super( + ImmutableList.of(CommonArguments.INPUT_JAR, CommonArguments.INPUT_MAPPINGS, CommonArguments.MAPPING_OUTPUT), + ImmutableList.of(CommonArguments.OBFUSCATED_NAMESPACE, CommonArguments.DEOBFUSCATED_NAMESPACE) ); } @@ -55,7 +56,7 @@ public String getDescription() { } public static void run(Path jar, Path sourcePath, Path output, @Nullable String obfuscatedNamespace, @Nullable String deobfuscatedNamespace) throws IOException, MappingParseException { - boolean debug = shouldDebug(new MapSpecializedMethodsCommand().getName()); + boolean debug = shouldDebug(INSTANCE.getName()); JarIndex jarIndex = loadJar(jar); Enigma enigma = createEnigma(); diff --git a/enigma-cli/src/main/java/org/quiltmc/enigma/command/PrintStatsCommand.java b/enigma-cli/src/main/java/org/quiltmc/enigma/command/PrintStatsCommand.java index 47d8067c0..e140aa74b 100644 --- a/enigma-cli/src/main/java/org/quiltmc/enigma/command/PrintStatsCommand.java +++ b/enigma-cli/src/main/java/org/quiltmc/enigma/command/PrintStatsCommand.java @@ -1,5 +1,6 @@ package org.quiltmc.enigma.command; +import com.google.common.collect.ImmutableList; import org.quiltmc.enigma.api.Enigma; import org.quiltmc.enigma.api.EnigmaPlugin; import org.quiltmc.enigma.api.EnigmaProfile; @@ -12,11 +13,14 @@ import java.nio.file.Path; import java.util.Set; -public class PrintStatsCommand extends Command { - public PrintStatsCommand() { - super(Argument.INPUT_JAR.required(), - Argument.INPUT_MAPPINGS.required(), - Argument.ENIGMA_PROFILE.optional()); +public final class PrintStatsCommand extends Command { + public static final PrintStatsCommand INSTANCE = new PrintStatsCommand(); + + private PrintStatsCommand() { + super( + ImmutableList.of(CommonArguments.INPUT_JAR, CommonArguments.INPUT_MAPPINGS), + ImmutableList.of(CommonArguments.ENIGMA_PROFILE) + ); } @Override diff --git a/enigma-cli/src/test/java/org/quiltmc/enigma/command/DropInvalidMappingsTest.java b/enigma-cli/src/test/java/org/quiltmc/enigma/command/DropInvalidMappingsTest.java index 8a56b7c1d..a5c5669d2 100644 --- a/enigma-cli/src/test/java/org/quiltmc/enigma/command/DropInvalidMappingsTest.java +++ b/enigma-cli/src/test/java/org/quiltmc/enigma/command/DropInvalidMappingsTest.java @@ -7,6 +7,8 @@ import java.nio.file.Files; import java.nio.file.Path; +import static org.quiltmc.enigma.TestUtil.toNewLineEndings; + public class DropInvalidMappingsTest extends CommandTest { private static final Path LONE_JAR = TestUtil.obfJar("lone_class"); private static final Path INNER_JAR = TestUtil.obfJar("inner_classes"); @@ -31,8 +33,8 @@ public void testInvalidMappings() throws Exception { DropInvalidMappingsCommand.run(LONE_JAR, INVALID_MAPPINGS_INPUT, resultFile); - String expectedLines = Files.readString(INVALID_MAPPINGS_EXPECTED); - String actualLines = Files.readString(resultFile); + String expectedLines = toNewLineEndings(Files.readString(INVALID_MAPPINGS_EXPECTED)); + String actualLines = toNewLineEndings(Files.readString(resultFile)); Assertions.assertEquals(expectedLines, actualLines); } @@ -55,8 +57,8 @@ public void testMappingSave() throws Exception { DropInvalidMappingsCommand.run(INNER_JAR, MAPPING_SAVE_INPUT, resultFile); - String expectedLines = Files.readString(MAPPING_SAVE_EXPECTED); - String actualLines = Files.readString(resultFile); + String expectedLines = toNewLineEndings(Files.readString(MAPPING_SAVE_EXPECTED)); + String actualLines = toNewLineEndings(Files.readString(resultFile)); Assertions.assertEquals(expectedLines, actualLines); } @@ -67,8 +69,8 @@ public void testDiscardInnerClass() throws Exception { DropInvalidMappingsCommand.run(INNER_JAR, DISCARD_INNER_CLASS_INPUT, resultFile); - String expectedLines = Files.readString(DISCARD_INNER_CLASS_EXPECTED); - String actualLines = Files.readString(resultFile); + String expectedLines = toNewLineEndings(Files.readString(DISCARD_INNER_CLASS_EXPECTED)); + String actualLines = toNewLineEndings(Files.readString(resultFile)); Assertions.assertEquals(expectedLines, actualLines); } @@ -79,8 +81,8 @@ public void testEnums() throws Exception { DropInvalidMappingsCommand.run(ENUMS_JAR, ENUMS_INPUT, resultFile); - String expectedLines = Files.readString(ENUMS_EXPECTED); - String actualLines = Files.readString(resultFile); + String expectedLines = toNewLineEndings(Files.readString(ENUMS_EXPECTED)); + String actualLines = toNewLineEndings(Files.readString(resultFile)); Assertions.assertEquals(expectedLines, actualLines); } diff --git a/enigma-cli/src/test/java/org/quiltmc/enigma/command/HelpCommandTest.java b/enigma-cli/src/test/java/org/quiltmc/enigma/command/HelpCommandTest.java index 96b2f1beb..d3af37405 100644 --- a/enigma-cli/src/test/java/org/quiltmc/enigma/command/HelpCommandTest.java +++ b/enigma-cli/src/test/java/org/quiltmc/enigma/command/HelpCommandTest.java @@ -6,6 +6,6 @@ public class HelpCommandTest { @Test void test() throws Exception { // for manually verifying output - new HelpCommand().run(); + HelpCommand.INSTANCE.run(); } } diff --git a/enigma/src/testFixtures/java/org/quiltmc/enigma/TestUtil.java b/enigma/src/testFixtures/java/org/quiltmc/enigma/TestUtil.java index 71b526fed..99ee9367d 100644 --- a/enigma/src/testFixtures/java/org/quiltmc/enigma/TestUtil.java +++ b/enigma/src/testFixtures/java/org/quiltmc/enigma/TestUtil.java @@ -5,9 +5,17 @@ import java.net.URISyntaxException; import java.nio.file.Path; +import java.util.regex.Pattern; public final class TestUtil { private TestUtil() { + throw new UnsupportedOperationException(); + } + + private static final Pattern UNWANTED_LINE_ENDING = Pattern.compile("\\r\\n?"); + + public static String toNewLineEndings(String string) { + return UNWANTED_LINE_ENDING.matcher(string).replaceAll("\n"); } public static Path obfJar(String name) {