Skip to content

Commit 3a9a00a

Browse files
author
Alexander Söderberg
committed
feature: move argument requirement out of CommandArgument
This moves `required` and `defaultValue` out of CommandArgument, into CommandComponent. This reduces the verbosity of the command arguments by no longer forcing multiple static methods to determine whether the argument is required. Whether an argument is required is now specified when adding the argument to the command. The previous `argument` methods on the command builder have been replaced by `required`/`optional` methods with many different overloads. We no longer have the ability to pass typed default values to the arguments as the command arguments no longer store the default values. We will have to think of a suitable replacement. To facilitate this movement of data we've had to replace many references to CommandArgument with CommandComponent. To make this easier the CommandTree.Node class has been made less generic and has also been renamed to CommandTree.CommandNode. Many deprecated methods have been removed as there is no real point in updating them as we'll want to drop them before releasing v2 anyway.
1 parent a63f517 commit 3a9a00a

122 files changed

Lines changed: 1178 additions & 3547 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cloud-annotations/src/main/java/cloud/commandframework/annotations/AnnotationParser.java

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import cloud.commandframework.ArgumentDescription;
2727
import cloud.commandframework.Command;
28+
import cloud.commandframework.CommandComponent;
2829
import cloud.commandframework.CommandManager;
2930
import cloud.commandframework.annotations.injection.ParameterInjectorRegistry;
3031
import cloud.commandframework.annotations.injection.RawArgs;
@@ -562,18 +563,16 @@ private <T> void parseParsers(final @NonNull T instance) {
562563
);
563564
final Collection<ArgumentParameterPair> arguments = this.argumentExtractor.apply(method);
564565
final Collection<CommandFlag<?>> flags = this.flagExtractor.apply(method);
565-
final Map<String, CommandArgument<C, ?>> commandArguments = new HashMap<>();
566-
final Map<CommandArgument<C, ?>, String> argumentDescriptions = new HashMap<>();
566+
final Map<String, CommandComponent<C>> commandComponents = new HashMap<>();
567567
/* Go through all annotated parameters and build up the argument tree */
568568
for (final ArgumentParameterPair argumentPair : arguments) {
569569
final String argumentName = this.processString(argumentPair.argumentName());
570-
final CommandArgument<C, ?> argument = this.buildArgument(
570+
final CommandComponent<C> component = this.buildComponent(
571571
method,
572572
this.findSyntaxFragment(tokens, argumentName),
573573
argumentPair
574574
);
575-
commandArguments.put(argument.getName(), argument);
576-
argumentDescriptions.put(argument, this.processString(argumentPair.getArgument().description()));
575+
commandComponents.put(component.argument().getName(), component);
577576
}
578577
boolean commandNameFound = false;
579578
/* Build the command tree */
@@ -585,16 +584,15 @@ private <T> void parseParsers(final @NonNull T instance) {
585584
if (token.getArgumentMode() == ArgumentMode.LITERAL) {
586585
builder = builder.literal(token.getMajor(), token.getMinor().toArray(new String[0]));
587586
} else {
588-
final CommandArgument<C, ?> argument = commandArguments.get(token.getMajor());
589-
if (argument == null) {
587+
final CommandComponent<C> component = commandComponents.get(token.getMajor());
588+
if (component == null) {
590589
throw new IllegalArgumentException(String.format(
591590
"Found no mapping for argument '%s' in method '%s'",
592591
token.getMajor(), method.getName()
593592
));
594593
}
595594

596-
final String description = argumentDescriptions.getOrDefault(argument, "");
597-
builder = builder.argument(argument, ArgumentDescription.of(description));
595+
builder = builder.argument(component);
598596
}
599597
}
600598
/* Try to find the command sender type */
@@ -623,7 +621,7 @@ private <T> void parseParsers(final @NonNull T instance) {
623621
final MethodCommandExecutionHandler.CommandMethodContext<C> context =
624622
new MethodCommandExecutionHandler.CommandMethodContext<>(
625623
instance,
626-
commandArguments,
624+
commandComponents,
627625
method,
628626
this /* annotationParser */
629627
);
@@ -701,7 +699,7 @@ private <T> void parseParsers(final @NonNull T instance) {
701699
}
702700

703701
@SuppressWarnings("unchecked")
704-
private @NonNull CommandArgument<C, ?> buildArgument(
702+
private @NonNull CommandComponent<C> buildComponent(
705703
final @NonNull Method method,
706704
final @Nullable SyntaxFragment syntaxFragment,
707705
final @NonNull ArgumentParameterPair argumentPair
@@ -747,16 +745,6 @@ private <T> void parseParsers(final @NonNull T instance) {
747745
parameter.getType(),
748746
argumentName
749747
);
750-
/* Set the argument requirement status */
751-
if (syntaxFragment.getArgumentMode() == ArgumentMode.OPTIONAL) {
752-
if (argument.defaultValue().isEmpty()) {
753-
argumentBuilder.asOptional();
754-
} else {
755-
argumentBuilder.asOptionalWithDefault(this.processString(argument.defaultValue()));
756-
}
757-
} else {
758-
argumentBuilder.asRequired();
759-
}
760748
/* Check for Completions annotation */
761749
final Completions completions = parameter.getDeclaredAnnotation(Completions.class);
762750
if (completions != null) {
@@ -789,8 +777,15 @@ private <T> void parseParsers(final @NonNull T instance) {
789777
builtArgument.addPreprocessor(preprocessor);
790778
}
791779
}
792-
/* Yay, we're done */
793-
return builtArgument;
780+
781+
final ArgumentDescription description = ArgumentDescription.of(this.processString(argumentPair.getArgument().description()));
782+
if (syntaxFragment.getArgumentMode() == ArgumentMode.REQUIRED) {
783+
return CommandComponent.required(builtArgument, description);
784+
} else if (argument.defaultValue().isEmpty()) {
785+
return CommandComponent.optional(builtArgument, description);
786+
} else {
787+
return CommandComponent.optional(builtArgument, description, this.processString(argument.defaultValue()));
788+
}
794789
}
795790

796791
@NonNull Map<@NonNull Class<@NonNull ? extends Annotation>,

cloud-annotations/src/main/java/cloud/commandframework/annotations/FlagExtractor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ final class FlagExtractor implements Function<@NonNull Method, Collection<@NonNu
122122
parameter.getType(),
123123
flagName
124124
);
125-
final CommandArgument.Builder argumentBuilder = argumentBuilder0.asRequired()
125+
final CommandArgument.Builder argumentBuilder = argumentBuilder0
126126
.manager(this.commandManager)
127127
.withParser(parser);
128128
final CommandArgument argument;

cloud-annotations/src/main/java/cloud/commandframework/annotations/MethodCommandExecutionHandler.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
//
2424
package cloud.commandframework.annotations;
2525

26+
import cloud.commandframework.CommandComponent;
2627
import cloud.commandframework.annotations.injection.ParameterInjectorRegistry;
27-
import cloud.commandframework.arguments.CommandArgument;
2828
import cloud.commandframework.arguments.flags.FlagContext;
2929
import cloud.commandframework.context.CommandContext;
3030
import cloud.commandframework.exceptions.CommandExecutionException;
@@ -116,8 +116,8 @@ protected final List<Object> createParameterValues(
116116
argumentName = this.annotationParser.processString(argument.value());
117117
}
118118

119-
final CommandArgument<C, ?> commandArgument = this.context.commandArguments.get(argumentName);
120-
if (commandArgument.isRequired()) {
119+
final CommandComponent<C> commandComponent = this.context.commandComponents.get(argumentName);
120+
if (commandComponent.required()) {
121121
arguments.add(commandContext.get(argumentName));
122122
} else {
123123
final Object optional = commandContext.getOptional(argumentName).orElse(null);
@@ -207,19 +207,19 @@ public final AnnotationAccessor annotationAccessor() {
207207
public static class CommandMethodContext<C> {
208208

209209
private final Object instance;
210-
private final Map<String, CommandArgument<C, ?>> commandArguments;
210+
private final Map<String, CommandComponent<C>> commandComponents;
211211
private final Method method;
212212
private final ParameterInjectorRegistry<C> injectorRegistry;
213213
private final AnnotationParser<C> annotationParser;
214214

215215
CommandMethodContext(
216216
final @NonNull Object instance,
217-
final @NonNull Map<@NonNull String, @NonNull CommandArgument<@NonNull C, @NonNull ?>> commandArguments,
217+
final @NonNull Map<@NonNull String, @NonNull CommandComponent<C>> commandComponents,
218218
final @NonNull Method method,
219219
final @NonNull AnnotationParser<C> annotationParser
220220
) {
221221
this.instance = instance;
222-
this.commandArguments = commandArguments;
222+
this.commandComponents = commandComponents;
223223
this.method = method;
224224
this.method.setAccessible(true);
225225
this.injectorRegistry = annotationParser.getParameterInjectorRegistry();
@@ -250,10 +250,10 @@ public static class CommandMethodContext<C> {
250250
* The compiled command arguments
251251
*
252252
* @return Compiled command arguments
253-
* @since 1.6.0
253+
* @since 2.0.0
254254
*/
255-
public final @NonNull Map<@NonNull String, @NonNull CommandArgument<C, ?>> commandArguments() {
256-
return this.commandArguments;
255+
public final @NonNull Map<@NonNull String, @NonNull CommandComponent<C>> commandComponents() {
256+
return this.commandComponents;
257257
}
258258

259259
/**

cloud-annotations/src/test/java/cloud/commandframework/annotations/AnnotationParserTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ void setup() {
8787
/* Register a builder modifier */
8888
annotationParser.registerBuilderModifier(
8989
IntegerArgumentInjector.class,
90-
(injector, builder) -> builder.argument(IntegerArgument.of(injector.value()))
90+
(injector, builder) -> builder.required(IntegerArgument.of(injector.value()))
9191
);
9292
/* Parse the class. Required for both testMethodConstruction() and testNamedSuggestionProvider() */
9393
commands = new ArrayList<>();
@@ -189,7 +189,7 @@ void testMultiAliasedCommands() {
189189

190190
// Find the root command that we are looking for.
191191
for (final Command<TestCommandSender> command : commands) {
192-
final StaticArgument<?> argument = (StaticArgument<?>) command.getArguments().get(0);
192+
final StaticArgument<?> argument = (StaticArgument<?>) command.components().get(0).argument();
193193

194194
if (argument.getAliases().contains("acommand")) {
195195
final Set<String> requiredAliases = new HashSet<>(Arrays.asList("acommand", "analias", "anotheralias"));

cloud-annotations/src/test/java/cloud/commandframework/annotations/feature/StringProcessingTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
package cloud.commandframework.annotations.feature;
2525

2626
import cloud.commandframework.Command;
27+
import cloud.commandframework.CommandComponent;
2728
import cloud.commandframework.annotations.AnnotationParser;
2829
import cloud.commandframework.annotations.Argument;
2930
import cloud.commandframework.annotations.CommandDescription;
@@ -105,10 +106,10 @@ void testStringProcessing() {
105106
assertThat(command.getCommandPermission().toString()).isEqualTo(testProperty);
106107
assertThat(command.getCommandMeta().get(CommandMeta.DESCRIPTION)).hasValue(testProperty);
107108

108-
final List<CommandArgument<TestCommandSender, ?>> arguments = command.getArguments();
109-
assertThat(arguments).hasSize(3);
109+
final List<CommandComponent<TestCommandSender>> components = command.components();
110+
assertThat(components).hasSize(3);
110111

111-
final FlagArgument<TestCommandSender> flagArgument = (FlagArgument<TestCommandSender>) arguments.get(2);
112+
final FlagArgument<TestCommandSender> flagArgument = (FlagArgument<TestCommandSender>) components.get(2).argument();
112113
assertThat(flagArgument).isNotNull();
113114

114115
final List<CommandFlag<?>> flags = new ArrayList<>(flagArgument.getFlags());

0 commit comments

Comments
 (0)