Feature: Allow argument names to be inferred from parameter names

This commit is contained in:
Alexander Söderberg 2021-10-02 11:49:02 +02:00 committed by Jason
parent 83163c2a77
commit ad80933a20
5 changed files with 37 additions and 9 deletions

View file

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `executeFuture` to `CommandExecutionHandler` which is now used internally. By default, this delegates to the old - Added `executeFuture` to `CommandExecutionHandler` which is now used internally. By default, this delegates to the old
`execute` method `execute` method
- Annotations: Apply builder modifiers from class annotations ([#303](https://github.com/Incendo/cloud/pull/303)) - Annotations: Apply builder modifiers from class annotations ([#303](https://github.com/Incendo/cloud/pull/303))
- Annotations: Add default value to `@Argument`, which will force the parser to infer the argument name from the parameter name
### Fixed ### Fixed
- Bukkit: Permission checking and syntax string for Bukkit '/help' command - Bukkit: Permission checking and syntax string for Bukkit '/help' command

View file

@ -79,6 +79,11 @@ import java.util.function.Function;
*/ */
public final class AnnotationParser<C> { public final class AnnotationParser<C> {
/**
* The value of {@link Argument} that should be used to infer argument names from parameter names.
*/
public static final String INFERRED_ARGUMENT_NAME = "__INFERRED_ARGUMENT_NAME__";
private final SyntaxParser syntaxParser = new SyntaxParser(); private final SyntaxParser syntaxParser = new SyntaxParser();
private final ArgumentExtractor argumentExtractor = new ArgumentExtractor(); private final ArgumentExtractor argumentExtractor = new ArgumentExtractor();
@ -438,7 +443,7 @@ public final class AnnotationParser<C> {
for (final ArgumentParameterPair argumentPair : arguments) { for (final ArgumentParameterPair argumentPair : arguments) {
final CommandArgument<C, ?> argument = this.buildArgument( final CommandArgument<C, ?> argument = this.buildArgument(
method, method,
this.findSyntaxFragment(tokens, argumentPair.getArgument().value()), this.findSyntaxFragment(tokens, argumentPair.argumentName()),
argumentPair argumentPair
); );
commandArguments.put(argument.getName(), argument); commandArguments.put(argument.getName(), argument);
@ -606,13 +611,13 @@ public final class AnnotationParser<C> {
if (syntaxFragment == null || syntaxFragment.getArgumentMode() == ArgumentMode.LITERAL) { if (syntaxFragment == null || syntaxFragment.getArgumentMode() == ArgumentMode.LITERAL) {
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
"Invalid command argument '%s' in method '%s': " "Invalid command argument '%s' in method '%s': "
+ "Missing syntax mapping", argumentPair.getArgument().value(), method.getName())); + "Missing syntax mapping", argumentPair.argumentName(), method.getName()));
} }
final Argument argument = argumentPair.getArgument(); final Argument argument = argumentPair.getArgument();
/* Create the argument builder */ /* Create the argument builder */
@SuppressWarnings("rawtypes") final CommandArgument.Builder argumentBuilder = CommandArgument.ofType( @SuppressWarnings("rawtypes") final CommandArgument.Builder argumentBuilder = CommandArgument.ofType(
parameter.getType(), parameter.getType(),
argument.value() argumentPair.argumentName()
); );
/* Set the argument requirement status */ /* Set the argument requirement status */
if (syntaxFragment.getArgumentMode() == ArgumentMode.OPTIONAL) { if (syntaxFragment.getArgumentMode() == ArgumentMode.OPTIONAL) {

View file

@ -39,11 +39,17 @@ import java.util.function.BiFunction;
public @interface Argument { public @interface Argument {
/** /**
* Argument name * The name of the argument that this parameter is bound to.
* This value must be overridden unless you have explicitly enabled
* the preservation of parameter names in your compiler options.
*
* If the parameter names are preserved and the name of the bound
* argument is the same as the parameter name, the default value
* may be used.
* *
* @return Argument name * @return Argument name
*/ */
@NonNull String value(); @NonNull String value() default AnnotationParser.INFERRED_ARGUMENT_NAME;
/** /**
* Name of the argument parser * Name of the argument parser

View file

@ -48,4 +48,12 @@ final class ArgumentParameterPair {
return this.argument; return this.argument;
} }
@NonNull String argumentName() {
if (this.argument.value().equals(AnnotationParser.INFERRED_ARGUMENT_NAME)) {
return this.parameter.getName();
} else {
return this.argument.value();
}
}
} }

View file

@ -105,11 +105,19 @@ public class MethodCommandExecutionHandler<C> implements CommandExecutionHandler
for (final Parameter parameter : this.parameters) { for (final Parameter parameter : this.parameters) {
if (parameter.isAnnotationPresent(Argument.class)) { if (parameter.isAnnotationPresent(Argument.class)) {
final Argument argument = parameter.getAnnotation(Argument.class); final Argument argument = parameter.getAnnotation(Argument.class);
final CommandArgument<C, ?> commandArgument = this.context.commandArguments.get(argument.value());
if (commandArgument.isRequired()) { final String argumentName;
arguments.add(commandContext.get(argument.value())); if (argument.value().equals(AnnotationParser.INFERRED_ARGUMENT_NAME)) {
argumentName = parameter.getName();
} else { } else {
final Object optional = commandContext.getOptional(argument.value()).orElse(null); argumentName = argument.value();
}
final CommandArgument<C, ?> commandArgument = this.context.commandArguments.get(argumentName);
if (commandArgument.isRequired()) {
arguments.add(commandContext.get(argumentName));
} else {
final Object optional = commandContext.getOptional(argumentName).orElse(null);
arguments.add(optional); arguments.add(optional);
} }
} else if (parameter.isAnnotationPresent(Flag.class)) { } else if (parameter.isAnnotationPresent(Flag.class)) {