Fix parsing of flag arguments that start with '-', i.e. a negative integer, add captions for flag argument

This commit is contained in:
jmp 2020-10-12 22:55:38 -07:00 committed by Alexander Söderberg
parent 2fbd90dfee
commit 5f466fcbc0
4 changed files with 151 additions and 12 deletions

View file

@ -27,7 +27,11 @@ import cloud.commandframework.arguments.CommandArgument;
import cloud.commandframework.arguments.flags.CommandFlag;
import cloud.commandframework.arguments.parser.ArgumentParseResult;
import cloud.commandframework.arguments.parser.ArgumentParser;
import cloud.commandframework.captions.Caption;
import cloud.commandframework.captions.CaptionVariable;
import cloud.commandframework.captions.StandardCaptionKeys;
import cloud.commandframework.context.CommandContext;
import cloud.commandframework.exceptions.parsing.ParserException;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Collection;
@ -106,11 +110,7 @@ public final class FlagArgument<C> extends CommandArgument<C, Object> {
CommandFlag<?> currentFlag = null;
for (final @NonNull String string : inputQueue) {
if (string.startsWith("-")) {
if (currentFlag != null && currentFlag.getCommandArgument() != null) {
return ArgumentParseResult.failure(
new IllegalArgumentException(String.format("Missing argument for '%s'", currentFlag.getName())));
}
if (string.startsWith("-") && currentFlag == null) {
if (string.startsWith("--")) {
final String flagName = string.substring(2);
for (final CommandFlag<?> flag : this.flags) {
@ -131,11 +131,17 @@ public final class FlagArgument<C> extends CommandArgument<C, Object> {
}
}
if (currentFlag == null) {
return ArgumentParseResult.failure(
new IllegalArgumentException(String.format("Unknown flag '%s'", string)));
return ArgumentParseResult.failure(new FlagParseException(
string,
FailureReason.UNKNOWN_FLAG,
commandContext
));
} else if (parsedFlags.contains(currentFlag)) {
return ArgumentParseResult.failure(
new IllegalArgumentException(String.format("Duplicate flag '%s'", string)));
return ArgumentParseResult.failure(new FlagParseException(
string,
FailureReason.DUPLICATE_FLAG,
commandContext
));
}
parsedFlags.add(currentFlag);
if (currentFlag.getCommandArgument() == null) {
@ -146,9 +152,11 @@ public final class FlagArgument<C> extends CommandArgument<C, Object> {
}
} else {
if (currentFlag == null) {
return ArgumentParseResult.failure(
new IllegalArgumentException(String.format("No flag started. Don't"
+ " know what to do with '%s'", string)));
return ArgumentParseResult.failure(new FlagParseException(
string,
FailureReason.NO_FLAG_STARTED,
commandContext
));
} else {
final ArgumentParseResult<?> result =
((CommandArgument) currentFlag.getCommandArgument())
@ -168,6 +176,13 @@ public final class FlagArgument<C> extends CommandArgument<C, Object> {
}
}
}
if (currentFlag != null) {
return ArgumentParseResult.failure(new FlagParseException(
currentFlag.getName(),
FailureReason.MISSING_ARGUMENT,
commandContext
));
}
/* We've consumed everything */
inputQueue.clear();
return ArgumentParseResult.success(FLAG_PARSE_RESULT_OBJECT);
@ -223,4 +238,71 @@ public final class FlagArgument<C> extends CommandArgument<C, Object> {
}
/**
* Flag parse exception
*/
public static final class FlagParseException extends ParserException {
private final String input;
/**
* Construct a new flag parse exception
*
* @param input Input
* @param failureReason The reason of failure
* @param context Command context
*/
public FlagParseException(
final @NonNull String input,
final @NonNull FailureReason failureReason,
final @NonNull CommandContext<?> context
) {
super(
FlagArgument.FlagArgumentParser.class,
context,
failureReason.getCaption(),
CaptionVariable.of("input", input),
CaptionVariable.of("flag", input)
);
this.input = input;
}
/**
* Get the supplied input
*
* @return String value
*/
public String getInput() {
return input;
}
}
/**
* Reasons for which flag parsing may fail
*/
public enum FailureReason {
UNKNOWN_FLAG(StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG),
DUPLICATE_FLAG(StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG),
NO_FLAG_STARTED(StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED),
MISSING_ARGUMENT(StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT);
private final Caption caption;
FailureReason(final @NonNull Caption caption) {
this.caption = caption;
}
/**
* Get the caption used for this failure reason
*
* @return The caption
*/
public @NonNull Caption getCaption() {
return this.caption;
}
}
}

View file

@ -60,6 +60,22 @@ public class SimpleCaptionRegistry<C> implements FactoryDelegatingCaptionRegistr
* Default caption for {@link StandardCaptionKeys#ARGUMENT_PARSE_FAILURE_UUID}
*/
public static final String ARGUMENT_PARSE_FAILURE_UUID = "'{input}' is not a valid UUID";
/**
* Default caption for {@link StandardCaptionKeys#ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG}
*/
public static final String ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG = "Unknown flag '{flag}'";
/**
* Default caption for {@link StandardCaptionKeys#ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG}
*/
public static final String ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG = "Duplicate flag '{flag}'";
/**
* Default caption for {@link StandardCaptionKeys#ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED}
*/
public static final String ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED = "No flag started. Don't know what to do with '{input}'";
/**
* Default caption for {@link StandardCaptionKeys#ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT}
*/
public static final String ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT = "Missing argument for '{flag}'";
private final Map<Caption, BiFunction<Caption, C, String>> messageFactories = new HashMap<>();
@ -88,6 +104,22 @@ public class SimpleCaptionRegistry<C> implements FactoryDelegatingCaptionRegistr
StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_UUID,
(caption, sender) -> ARGUMENT_PARSE_FAILURE_UUID
);
this.registerMessageFactory(
StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG,
(caption, sender) -> ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG
);
this.registerMessageFactory(
StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG,
(caption, sender) -> ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG
);
this.registerMessageFactory(
StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED,
(caption, sender) -> ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED
);
this.registerMessageFactory(
StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT,
(caption, sender) -> ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT
);
}
@Override

View file

@ -64,6 +64,22 @@ public final class StandardCaptionKeys {
* Variables: {input}, {pattern}
*/
public static final Caption ARGUMENT_PARSE_FAILURE_REGEX = of("argument.parse.failure.regex");
/**
* Variables: {flag}
*/
public static final Caption ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG = of("argument.parse.failure.flag.unknown");
/**
* Variables: {flag}
*/
public static final Caption ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG = of("argument.parse.failure.flag.duplicate_flag");
/**
* Variables: {input}
*/
public static final Caption ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED = of("argument.parse.failure.flag.no_flag_started");
/**
* Variables: {flag}
*/
public static final Caption ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT = of("argument.parse.failure.flag.missing_argument");
private StandardCaptionKeys() {
}

View file

@ -182,6 +182,15 @@ public final class MinecraftHelp<C> {
this.colors = colors;
}
/**
* Get the colors used for help messages.
*
* @return The active {@link HelpColors}
*/
public @NonNull HelpColors getHelpColors() {
return this.colors;
}
/**
* Set the length of the header/footer of help menus
* <p>