Add support for suspending functions
This also changes CommandExecutionHandler to return futures instead. The old method is still supported, and the new future-returning method will delegate to the old non-returning method.
This commit is contained in:
parent
c16ee8049b
commit
7bb5e63dc7
12 changed files with 556 additions and 249 deletions
|
|
@ -48,6 +48,9 @@ import cloud.commandframework.extra.confirmation.CommandConfirmationManager;
|
||||||
import cloud.commandframework.meta.CommandMeta;
|
import cloud.commandframework.meta.CommandMeta;
|
||||||
import cloud.commandframework.meta.SimpleCommandMeta;
|
import cloud.commandframework.meta.SimpleCommandMeta;
|
||||||
import io.leangen.geantyref.TypeToken;
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
|
@ -85,6 +88,8 @@ public final class AnnotationParser<C> {
|
||||||
@NonNull Queue<@NonNull String>, @NonNull ArgumentParseResult<Boolean>>>> preprocessorMappers;
|
@NonNull Queue<@NonNull String>, @NonNull ArgumentParseResult<Boolean>>>> preprocessorMappers;
|
||||||
private final Map<Class<? extends Annotation>, BiFunction<? extends Annotation, Command.Builder<C>, Command.Builder<C>>>
|
private final Map<Class<? extends Annotation>, BiFunction<? extends Annotation, Command.Builder<C>, Command.Builder<C>>>
|
||||||
builderModifiers;
|
builderModifiers;
|
||||||
|
private final Map<Predicate<Method>, Function<MethodCommandExecutionHandler.CommandMethodContext<C>,
|
||||||
|
MethodCommandExecutionHandler<C>>> commandMethodFactories;
|
||||||
private final Class<C> commandSenderClass;
|
private final Class<C> commandSenderClass;
|
||||||
private final MetaFactory metaFactory;
|
private final MetaFactory metaFactory;
|
||||||
private final FlagExtractor flagExtractor;
|
private final FlagExtractor flagExtractor;
|
||||||
|
|
@ -110,6 +115,7 @@ public final class AnnotationParser<C> {
|
||||||
this.annotationMappers = new HashMap<>();
|
this.annotationMappers = new HashMap<>();
|
||||||
this.preprocessorMappers = new HashMap<>();
|
this.preprocessorMappers = new HashMap<>();
|
||||||
this.builderModifiers = new HashMap<>();
|
this.builderModifiers = new HashMap<>();
|
||||||
|
this.commandMethodFactories = new HashMap<>();
|
||||||
this.flagExtractor = new FlagExtractor(manager);
|
this.flagExtractor = new FlagExtractor(manager);
|
||||||
this.registerAnnotationMapper(CommandDescription.class, d ->
|
this.registerAnnotationMapper(CommandDescription.class, d ->
|
||||||
ParserParameters.single(StandardParameters.DESCRIPTION, d.value()));
|
ParserParameters.single(StandardParameters.DESCRIPTION, d.value()));
|
||||||
|
|
@ -180,6 +186,29 @@ public final class AnnotationParser<C> {
|
||||||
return getMethodOrClassAnnotation(method, clazz) != null;
|
return getMethodOrClassAnnotation(method, clazz) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the command manager that was used to create this parser
|
||||||
|
*
|
||||||
|
* @return Command manager
|
||||||
|
*/
|
||||||
|
public @NonNull CommandManager<C> manager() {
|
||||||
|
return this.manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new command execution method factory. This allows for the registration of
|
||||||
|
* custom command method execution strategies.
|
||||||
|
*
|
||||||
|
* @param predicate The predicate that decides whether or not to apply the custom execution handler to the given method
|
||||||
|
* @param function The function that produces the command execution handler
|
||||||
|
*/
|
||||||
|
public void registerCommandExecutionMethodFactory(
|
||||||
|
final @NonNull Predicate<@NonNull Method> predicate,
|
||||||
|
final @NonNull Function<MethodCommandExecutionHandler.CommandMethodContext<C>, MethodCommandExecutionHandler<C>> function
|
||||||
|
) {
|
||||||
|
this.commandMethodFactories.put(predicate, function);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a builder modifier for a specific annotation. The builder modifiers are
|
* Register a builder modifier for a specific annotation. The builder modifiers are
|
||||||
* allowed to act on a {@link Command.Builder} after all arguments have been added
|
* allowed to act on a {@link Command.Builder} after all arguments have been added
|
||||||
|
|
@ -265,12 +294,6 @@ public final class AnnotationParser<C> {
|
||||||
if (!method.isAccessible()) {
|
if (!method.isAccessible()) {
|
||||||
method.setAccessible(true);
|
method.setAccessible(true);
|
||||||
}
|
}
|
||||||
if (method.getReturnType() != Void.TYPE) {
|
|
||||||
throw new IllegalArgumentException(String.format(
|
|
||||||
"@CommandMethod annotated method '%s' has non-void return type",
|
|
||||||
method.getName()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if (Modifier.isStatic(method.getModifiers())) {
|
if (Modifier.isStatic(method.getModifiers())) {
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(String.format(
|
||||||
"@CommandMethod annotated method '%s' is static! @CommandMethod annotated methods should not be static.",
|
"@CommandMethod annotated method '%s' is static! @CommandMethod annotated methods should not be static.",
|
||||||
|
|
@ -460,13 +483,25 @@ public final class AnnotationParser<C> {
|
||||||
builder = builder.senderType(senderType);
|
builder = builder.senderType(senderType);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
/* Construct the handler */
|
final MethodCommandExecutionHandler.CommandMethodContext<C> context = new MethodCommandExecutionHandler.CommandMethodContext<>(
|
||||||
final CommandExecutionHandler<C> commandExecutionHandler = new MethodCommandExecutionHandler<>(
|
|
||||||
instance,
|
instance,
|
||||||
commandArguments,
|
commandArguments,
|
||||||
method,
|
method,
|
||||||
this.getParameterInjectorRegistry()
|
this.getParameterInjectorRegistry()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* Create the command execution handler */
|
||||||
|
CommandExecutionHandler<C> commandExecutionHandler = new MethodCommandExecutionHandler<>(context);
|
||||||
|
for (final Map.Entry<Predicate<Method>, Function<MethodCommandExecutionHandler.CommandMethodContext<C>, MethodCommandExecutionHandler<C>>> entry :
|
||||||
|
commandMethodFactories.entrySet()) {
|
||||||
|
if (entry.getKey().test(method)) {
|
||||||
|
commandExecutionHandler = entry.getValue().apply(context);
|
||||||
|
|
||||||
|
/* Once we have our custom handler, we stop */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
builder = builder.handler(commandExecutionHandler);
|
builder = builder.handler(commandExecutionHandler);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
throw new RuntimeException("Failed to construct command execution handler", e);
|
throw new RuntimeException("Failed to construct command execution handler", e);
|
||||||
|
|
|
||||||
|
|
@ -40,38 +40,61 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
class MethodCommandExecutionHandler<C> implements CommandExecutionHandler<C> {
|
/**
|
||||||
|
* A command execution handler that invokes a method.
|
||||||
|
*
|
||||||
|
* @param <C> Command sender type.
|
||||||
|
*/
|
||||||
|
public class MethodCommandExecutionHandler<C> implements CommandExecutionHandler<C> {
|
||||||
|
|
||||||
|
private final CommandMethodContext<C> context;
|
||||||
private final Parameter[] parameters;
|
private final Parameter[] parameters;
|
||||||
private final MethodHandle methodHandle;
|
private final MethodHandle methodHandle;
|
||||||
private final Map<String, CommandArgument<C, ?>> commandArguments;
|
|
||||||
private final ParameterInjectorRegistry<C> injectorRegistry;
|
|
||||||
private final AnnotationAccessor annotationAccessor;
|
private final AnnotationAccessor annotationAccessor;
|
||||||
|
|
||||||
MethodCommandExecutionHandler(
|
/**
|
||||||
final @NonNull Object instance,
|
* Constructs a new method command execution handler
|
||||||
final @NonNull Map<@NonNull String, @NonNull CommandArgument<@NonNull C, @NonNull ?>> commandArguments,
|
*
|
||||||
final @NonNull Method method,
|
* @param context The context
|
||||||
final @NonNull ParameterInjectorRegistry<C> injectorRegistry
|
*/
|
||||||
|
public MethodCommandExecutionHandler(
|
||||||
|
final @NonNull CommandMethodContext<C> context
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
this.commandArguments = commandArguments;
|
this.context = context;
|
||||||
method.setAccessible(true);
|
this.methodHandle = MethodHandles.lookup().unreflect(context.method).bindTo(context.instance);
|
||||||
this.methodHandle = MethodHandles.lookup().unreflect(method).bindTo(instance);
|
this.parameters = context.method.getParameters();
|
||||||
this.parameters = method.getParameters();
|
this.annotationAccessor = AnnotationAccessor.of(context.method);
|
||||||
this.injectorRegistry = injectorRegistry;
|
|
||||||
this.annotationAccessor = AnnotationAccessor.of(method);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void execute(final @NonNull CommandContext<C> commandContext) {
|
public void execute(final @NonNull CommandContext<C> commandContext) {
|
||||||
final List<Object> arguments = new ArrayList<>(this.parameters.length);
|
/* Invoke the command method */
|
||||||
final FlagContext flagContext = commandContext.flags();
|
try {
|
||||||
|
this.methodHandle.invokeWithArguments(createParameterValues(
|
||||||
|
commandContext,
|
||||||
|
commandContext.flags(),
|
||||||
|
true)
|
||||||
|
);
|
||||||
|
} catch (final Error e) {
|
||||||
|
throw e;
|
||||||
|
} catch (final Throwable throwable) {
|
||||||
|
throw new CommandExecutionException(throwable, commandContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Bind parameters to context */
|
protected List<Object> createParameterValues(
|
||||||
|
final CommandContext<C> commandContext,
|
||||||
|
final FlagContext flagContext,
|
||||||
|
final boolean throwOnMissing
|
||||||
|
) {
|
||||||
|
final List<Object> arguments = new ArrayList<>(this.parameters.length);
|
||||||
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.commandArguments.get(argument.value());
|
final CommandArgument<C, ?> commandArgument = this.context.commandArguments.get(argument.value());
|
||||||
if (commandArgument.isRequired()) {
|
if (commandArgument.isRequired()) {
|
||||||
arguments.add(commandContext.get(argument.value()));
|
arguments.add(commandContext.get(argument.value()));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -89,14 +112,14 @@ class MethodCommandExecutionHandler<C> implements CommandExecutionHandler<C> {
|
||||||
if (parameter.getType().isAssignableFrom(commandContext.getSender().getClass())) {
|
if (parameter.getType().isAssignableFrom(commandContext.getSender().getClass())) {
|
||||||
arguments.add(commandContext.getSender());
|
arguments.add(commandContext.getSender());
|
||||||
} else {
|
} else {
|
||||||
final Optional<?> value = this.injectorRegistry.getInjectable(
|
final Optional<?> value = this.context.injectorRegistry.getInjectable(
|
||||||
parameter.getType(),
|
parameter.getType(),
|
||||||
commandContext,
|
commandContext,
|
||||||
AnnotationAccessor.of(AnnotationAccessor.of(parameter), this.annotationAccessor)
|
AnnotationAccessor.of(AnnotationAccessor.of(parameter), this.annotationAccessor)
|
||||||
);
|
);
|
||||||
if (value.isPresent()) {
|
if (value.isPresent()) {
|
||||||
arguments.add(value.get());
|
arguments.add(value.get());
|
||||||
} else {
|
} else if (throwOnMissing) {
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(String.format(
|
||||||
"Unknown command parameter '%s' in method '%s'",
|
"Unknown command parameter '%s' in method '%s'",
|
||||||
parameter.getName(),
|
parameter.getName(),
|
||||||
|
|
@ -106,15 +129,106 @@ class MethodCommandExecutionHandler<C> implements CommandExecutionHandler<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return arguments;
|
||||||
/* Invoke the command method */
|
|
||||||
try {
|
|
||||||
this.methodHandle.invokeWithArguments(arguments);
|
|
||||||
} catch (final Error e) {
|
|
||||||
throw e;
|
|
||||||
} catch (final Throwable throwable) {
|
|
||||||
throw new CommandExecutionException(throwable, commandContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the command method context
|
||||||
|
*
|
||||||
|
* @return The context
|
||||||
|
*/
|
||||||
|
public @NonNull CommandMethodContext<C> context() {
|
||||||
|
return this.context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all parameters passed to the method
|
||||||
|
*
|
||||||
|
* @return The parameters
|
||||||
|
*/
|
||||||
|
public final @NonNull Parameter @NonNull [] parameters() {
|
||||||
|
return this.parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the compiled method handle for the command method.
|
||||||
|
*
|
||||||
|
* @return The method handle
|
||||||
|
*/
|
||||||
|
public final @NonNull MethodHandle methodHandle() {
|
||||||
|
return this.methodHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The annotation accessor for the command method
|
||||||
|
*
|
||||||
|
* @return Annotation accessor
|
||||||
|
*/
|
||||||
|
public final AnnotationAccessor annotationAccessor() {
|
||||||
|
return this.annotationAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context for command methods
|
||||||
|
*
|
||||||
|
* @param <C> Command sender type
|
||||||
|
*/
|
||||||
|
public static class CommandMethodContext<C> {
|
||||||
|
|
||||||
|
private final Object instance;
|
||||||
|
private final Map<String, CommandArgument<C, ?>> commandArguments;
|
||||||
|
private final Method method;
|
||||||
|
private final ParameterInjectorRegistry<C> injectorRegistry;
|
||||||
|
|
||||||
|
CommandMethodContext(
|
||||||
|
final @NonNull Object instance,
|
||||||
|
final @NonNull Map<@NonNull String, @NonNull CommandArgument<@NonNull C, @NonNull ?>> commandArguments,
|
||||||
|
final @NonNull Method method,
|
||||||
|
final @NonNull ParameterInjectorRegistry<C> injectorRegistry
|
||||||
|
) {
|
||||||
|
this.instance = instance;
|
||||||
|
this.commandArguments = commandArguments;
|
||||||
|
this.method = method;
|
||||||
|
this.method.setAccessible(true);
|
||||||
|
this.injectorRegistry = injectorRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instance that owns the command method
|
||||||
|
*
|
||||||
|
* @return The instance
|
||||||
|
*/
|
||||||
|
public @NonNull Object instance() {
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command method
|
||||||
|
*
|
||||||
|
* @return The method
|
||||||
|
*/
|
||||||
|
public final @NonNull Method method() {
|
||||||
|
return this.method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The compiled command arguments
|
||||||
|
*
|
||||||
|
* @return Compiled command arguments
|
||||||
|
*/
|
||||||
|
public final @NonNull Map<@NonNull String, @NonNull CommandArgument<C, ?>> commandArguments() {
|
||||||
|
return this.commandArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The injector registry
|
||||||
|
*
|
||||||
|
* @return Injector registry
|
||||||
|
*/
|
||||||
|
public final @NonNull ParameterInjectorRegistry<C> injectorRegistry() {
|
||||||
|
return this.injectorRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -910,6 +910,15 @@ public abstract class CommandManager<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the command execution coordinator used in this manager
|
||||||
|
*
|
||||||
|
* @return Command execution coordinator
|
||||||
|
*/
|
||||||
|
public @NonNull CommandExecutionCoordinator<C> commandExecutionCoordinator() {
|
||||||
|
return this.commandExecutionCoordinator;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transition from the {@code in} state to the {@code out} state, if the manager is not already in that state.
|
* Transition from the {@code in} state to the {@code out} state, if the manager is not already in that state.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -81,14 +81,16 @@ public final class AsynchronousCommandExecutionCoordinator<C> extends CommandExe
|
||||||
|
|
||||||
final Consumer<Command<C>> commandConsumer = command -> {
|
final Consumer<Command<C>> commandConsumer = command -> {
|
||||||
if (this.commandManager.postprocessContext(commandContext, command) == State.ACCEPTED) {
|
if (this.commandManager.postprocessContext(commandContext, command) == State.ACCEPTED) {
|
||||||
try {
|
command.getCommandExecutionHandler().executeFuture(commandContext).whenComplete((result, throwable) -> {
|
||||||
command.getCommandExecutionHandler().execute(commandContext);
|
if (throwable != null) {
|
||||||
} catch (final CommandExecutionException exception) {
|
if (throwable instanceof CommandExecutionException) {
|
||||||
resultFuture.completeExceptionally(exception);
|
resultFuture.completeExceptionally(throwable);
|
||||||
} catch (final Exception exception) {
|
} else {
|
||||||
resultFuture.completeExceptionally(new CommandExecutionException(exception, commandContext));
|
resultFuture.completeExceptionally(new CommandExecutionException(throwable, commandContext));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.synchronizeParsing) {
|
if (this.synchronizeParsing) {
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ public abstract class CommandExecutionCoordinator<C> {
|
||||||
final Command<C> command = Objects.requireNonNull(pair.getFirst());
|
final Command<C> command = Objects.requireNonNull(pair.getFirst());
|
||||||
if (this.getCommandTree().getCommandManager().postprocessContext(commandContext, command) == State.ACCEPTED) {
|
if (this.getCommandTree().getCommandManager().postprocessContext(commandContext, command) == State.ACCEPTED) {
|
||||||
try {
|
try {
|
||||||
command.getCommandExecutionHandler().execute(commandContext);
|
command.getCommandExecutionHandler().executeFuture(commandContext).get();
|
||||||
} catch (final CommandExecutionException exception) {
|
} catch (final CommandExecutionException exception) {
|
||||||
completableFuture.completeExceptionally(exception);
|
completableFuture.completeExceptionally(exception);
|
||||||
} catch (final Exception exception) {
|
} catch (final Exception exception) {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,11 @@ package cloud.commandframework.execution;
|
||||||
|
|
||||||
import cloud.commandframework.Command;
|
import cloud.commandframework.Command;
|
||||||
import cloud.commandframework.context.CommandContext;
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler that is invoked whenever a {@link Command} is executed
|
* Handler that is invoked whenever a {@link Command} is executed
|
||||||
|
|
@ -43,6 +47,23 @@ public interface CommandExecutionHandler<C> {
|
||||||
*/
|
*/
|
||||||
void execute(@NonNull CommandContext<C> commandContext);
|
void execute(@NonNull CommandContext<C> commandContext);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle command execution
|
||||||
|
*
|
||||||
|
* @param commandContext Command context
|
||||||
|
* @return future that completes when the command has finished execution
|
||||||
|
*/
|
||||||
|
default CompletableFuture<@Nullable Object> executeFuture(@NonNull CommandContext<C> commandContext) {
|
||||||
|
final CompletableFuture<Object> future = new CompletableFuture<>();
|
||||||
|
try {
|
||||||
|
execute(commandContext);
|
||||||
|
/* The command executed successfully */
|
||||||
|
future.complete(null);
|
||||||
|
} catch (final Throwable throwable) {
|
||||||
|
future.completeExceptionally(throwable);
|
||||||
|
}
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command execution handler that does nothing
|
* Command execution handler that does nothing
|
||||||
|
|
@ -57,4 +78,27 @@ public interface CommandExecutionHandler<C> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler that is invoked whenever a {@link Command} is executed
|
||||||
|
* by a command sender
|
||||||
|
*
|
||||||
|
* @param <C> Command sender type
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
interface FutureCommandExecutionHandler<C> extends CommandExecutionHandler<C> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("FunctionalInterfaceMethodChanged")
|
||||||
|
default void execute(
|
||||||
|
@NonNull CommandContext<C> commandContext
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
CompletableFuture<@Nullable Object> executeFuture(
|
||||||
|
@NonNull CommandContext<C> commandContext
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
package cloud.commandframework.extra.confirmation;
|
package cloud.commandframework.extra.confirmation;
|
||||||
|
|
||||||
import cloud.commandframework.CommandManager;
|
import cloud.commandframework.CommandManager;
|
||||||
|
import cloud.commandframework.context.CommandContext;
|
||||||
import cloud.commandframework.execution.CommandExecutionHandler;
|
import cloud.commandframework.execution.CommandExecutionHandler;
|
||||||
import cloud.commandframework.execution.postprocessor.CommandPostprocessingContext;
|
import cloud.commandframework.execution.postprocessor.CommandPostprocessingContext;
|
||||||
import cloud.commandframework.execution.postprocessor.CommandPostprocessor;
|
import cloud.commandframework.execution.postprocessor.CommandPostprocessor;
|
||||||
|
|
@ -31,6 +32,9 @@ import cloud.commandframework.meta.CommandMeta;
|
||||||
import cloud.commandframework.meta.SimpleCommandMeta;
|
import cloud.commandframework.meta.SimpleCommandMeta;
|
||||||
import cloud.commandframework.services.types.ConsumerService;
|
import cloud.commandframework.services.types.ConsumerService;
|
||||||
import cloud.commandframework.types.tuples.Pair;
|
import cloud.commandframework.types.tuples.Pair;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
|
@ -158,20 +162,20 @@ public class CommandConfirmationManager<C> {
|
||||||
* @return Handler for a confirmation command
|
* @return Handler for a confirmation command
|
||||||
*/
|
*/
|
||||||
public @NonNull CommandExecutionHandler<C> createConfirmationExecutionHandler() {
|
public @NonNull CommandExecutionHandler<C> createConfirmationExecutionHandler() {
|
||||||
return context -> {
|
return (CommandExecutionHandler.FutureCommandExecutionHandler<C>) context -> {
|
||||||
final Optional<CommandPostprocessingContext<C>> pending = this.getPending(context.getSender());
|
final Optional<CommandPostprocessingContext<C>> pending = this.getPending(context.getSender());
|
||||||
if (pending.isPresent()) {
|
if (pending.isPresent()) {
|
||||||
final CommandPostprocessingContext<C> postprocessingContext = pending.get();
|
final CommandPostprocessingContext<C> postprocessingContext = pending.get();
|
||||||
postprocessingContext.getCommand()
|
return postprocessingContext.getCommand()
|
||||||
.getCommandExecutionHandler()
|
.getCommandExecutionHandler()
|
||||||
.execute(postprocessingContext.getCommandContext());
|
.executeFuture(postprocessingContext.getCommandContext());
|
||||||
} else {
|
} else {
|
||||||
this.errorNotifier.accept(context.getSender());
|
this.errorNotifier.accept(context.getSender());
|
||||||
}
|
}
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private final class CommandConfirmationPostProcessor implements CommandPostprocessor<C> {
|
private final class CommandConfirmationPostProcessor implements CommandPostprocessor<C> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import java.net.URL
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.4.31"
|
kotlin("jvm") version "1.4.31"
|
||||||
id("org.jetbrains.dokka") version "1.4.20"
|
id("org.jetbrains.dokka") version "1.4.20"
|
||||||
|
id("com.ncorti.ktfmt.gradle") version "0.6.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.all {
|
configurations.all {
|
||||||
|
|
@ -13,7 +14,14 @@ configurations.all {
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":cloud-core"))
|
api(project(":cloud-core"))
|
||||||
implementation(kotlin("stdlib-jdk8"))
|
implementation(kotlin("stdlib-jdk8"))
|
||||||
|
|
||||||
|
implementation(project(":cloud-annotations"))
|
||||||
|
implementation("org.jetbrains.kotlin:kotlin-reflect:1.4.31")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.4.3")
|
||||||
|
|
||||||
testImplementation("org.jetbrains.kotlin", "kotlin-test-junit5")
|
testImplementation("org.jetbrains.kotlin", "kotlin-test-junit5")
|
||||||
|
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.4.3")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
|
|
@ -42,3 +50,7 @@ tasks {
|
||||||
kotlin {
|
kotlin {
|
||||||
explicitApi()
|
explicitApi()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ktfmt {
|
||||||
|
dropboxStyle()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -36,7 +36,8 @@ import cloud.commandframework.permission.CommandPermission
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mutable [Command.Builder] wrapper, providing functions to assist in creating commands using the Kotlin builder DSL style
|
* A mutable [Command.Builder] wrapper, providing functions to assist in creating commands using the
|
||||||
|
* Kotlin builder DSL style
|
||||||
*
|
*
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
|
|
@ -54,7 +55,9 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(message = "ArgumentDescription should be used over Description", level = DeprecationLevel.HIDDEN)
|
@Deprecated(
|
||||||
|
message = "ArgumentDescription should be used over Description",
|
||||||
|
level = DeprecationLevel.HIDDEN)
|
||||||
public constructor(
|
public constructor(
|
||||||
name: String,
|
name: String,
|
||||||
description: Description = Description.empty(),
|
description: Description = Description.empty(),
|
||||||
|
|
@ -95,7 +98,9 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(message = "ArgumentDescription should be used over Description", level = DeprecationLevel.HIDDEN)
|
@Deprecated(
|
||||||
|
message = "ArgumentDescription should be used over Description",
|
||||||
|
level = DeprecationLevel.HIDDEN)
|
||||||
public constructor(
|
public constructor(
|
||||||
name: String,
|
name: String,
|
||||||
description: Description = Description.empty(),
|
description: Description = Description.empty(),
|
||||||
|
|
@ -126,10 +131,7 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
lambda(this)
|
lambda(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private constructor(
|
private constructor(commandManager: CommandManager<C>, commandBuilder: Command.Builder<C>) {
|
||||||
commandManager: CommandManager<C>,
|
|
||||||
commandBuilder: Command.Builder<C>
|
|
||||||
) {
|
|
||||||
this.commandManager = commandManager
|
this.commandManager = commandManager
|
||||||
this.commandBuilder = commandBuilder
|
this.commandBuilder = commandBuilder
|
||||||
}
|
}
|
||||||
|
|
@ -140,19 +142,17 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return built command
|
* @return built command
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun build(): Command<C> =
|
public fun build(): Command<C> = this.commandBuilder.build()
|
||||||
this.commandBuilder.build()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke the provided receiver lambda on this builder, then build a [Command] from the resulting state
|
* Invoke the provided receiver lambda on this builder, then build a [Command] from the
|
||||||
|
* resulting state
|
||||||
*
|
*
|
||||||
* @param lambda receiver lambda which will be invoked on builder before building
|
* @param lambda receiver lambda which will be invoked on builder before building
|
||||||
* @return built command
|
* @return built command
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun build(
|
public fun build(lambda: MutableCommandBuilder<C>.() -> Unit): Command<C> {
|
||||||
lambda: MutableCommandBuilder<C>.() -> Unit
|
|
||||||
): Command<C> {
|
|
||||||
lambda(this)
|
lambda(this)
|
||||||
return this.commandBuilder.build()
|
return this.commandBuilder.build()
|
||||||
}
|
}
|
||||||
|
|
@ -171,9 +171,7 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onlyMutate(
|
private fun onlyMutate(mutator: (Command.Builder<C>) -> Command.Builder<C>): Unit {
|
||||||
mutator: (Command.Builder<C>) -> Command.Builder<C>
|
|
||||||
): Unit {
|
|
||||||
mutate(mutator)
|
mutate(mutator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,15 +191,12 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return a copy of this mutable builder
|
* @return a copy of this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun copy(
|
public fun copy(lambda: MutableCommandBuilder<C>.() -> Unit): MutableCommandBuilder<C> =
|
||||||
lambda: MutableCommandBuilder<C>.() -> Unit
|
copy().apply { lambda(this) }
|
||||||
): MutableCommandBuilder<C> =
|
|
||||||
copy().apply {
|
|
||||||
lambda(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a new copy of this [MutableCommandBuilder], append a literal, and invoke the provided receiver lambda on it
|
* Make a new copy of this [MutableCommandBuilder], append a literal, and invoke the provided
|
||||||
|
* receiver lambda on it
|
||||||
*
|
*
|
||||||
* @param literal name for the literal
|
* @param literal name for the literal
|
||||||
* @param description description for the literal
|
* @param description description for the literal
|
||||||
|
|
@ -210,7 +205,9 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(message = "ArgumentDescription should be used over Description", level = DeprecationLevel.HIDDEN)
|
@Deprecated(
|
||||||
|
message = "ArgumentDescription should be used over Description",
|
||||||
|
level = DeprecationLevel.HIDDEN)
|
||||||
public fun copy(
|
public fun copy(
|
||||||
literal: String,
|
literal: String,
|
||||||
description: Description,
|
description: Description,
|
||||||
|
|
@ -222,7 +219,8 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a new copy of this [MutableCommandBuilder], append a literal, and invoke the provided receiver lambda on it
|
* Make a new copy of this [MutableCommandBuilder], append a literal, and invoke the provided
|
||||||
|
* receiver lambda on it
|
||||||
*
|
*
|
||||||
* @param literal name for the literal
|
* @param literal name for the literal
|
||||||
* @param description description for the literal
|
* @param description description for the literal
|
||||||
|
|
@ -241,7 +239,8 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a new copy of this [MutableCommandBuilder], append a literal, and invoke the provided receiver lambda on it
|
* Make a new copy of this [MutableCommandBuilder], append a literal, and invoke the provided
|
||||||
|
* receiver lambda on it
|
||||||
*
|
*
|
||||||
* @param literal name for the literal
|
* @param literal name for the literal
|
||||||
* @param lambda receiver lambda which will be invoked on the new builder
|
* @param lambda receiver lambda which will be invoked on the new builder
|
||||||
|
|
@ -264,29 +263,23 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @see [CommandManager.command]
|
* @see [CommandManager.command]
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun register(): MutableCommandBuilder<C> =
|
public fun register(): MutableCommandBuilder<C> = apply { this.commandManager.command(this) }
|
||||||
apply {
|
|
||||||
this.commandManager.command(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new copy of this mutable builder, act on it with a receiver lambda, and then register it with the owning
|
* Create a new copy of this mutable builder, act on it with a receiver lambda, and then
|
||||||
* command manager
|
* register it with the owning command manager
|
||||||
*
|
*
|
||||||
* @param lambda receiver lambda which will be invoked on the new builder
|
* @param lambda receiver lambda which will be invoked on the new builder
|
||||||
* @return the new mutable builder
|
* @return the new mutable builder
|
||||||
* @see [CommandManager.command]
|
* @see [CommandManager.command]
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun registerCopy(
|
public fun registerCopy(lambda: MutableCommandBuilder<C>.() -> Unit): MutableCommandBuilder<C> =
|
||||||
lambda: MutableCommandBuilder<C>.() -> Unit
|
|
||||||
): MutableCommandBuilder<C> =
|
|
||||||
copy(lambda).register()
|
copy(lambda).register()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new copy of this mutable builder, append a literal, act on it with a receiver lambda, and then register it with
|
* Create a new copy of this mutable builder, append a literal, act on it with a receiver
|
||||||
* the owning
|
* lambda, and then register it with the owning command manager
|
||||||
* command manager
|
|
||||||
*
|
*
|
||||||
* @param literal name for the literal
|
* @param literal name for the literal
|
||||||
* @param lambda receiver lambda which will be invoked on the new builder
|
* @param lambda receiver lambda which will be invoked on the new builder
|
||||||
|
|
@ -297,13 +290,11 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
public fun registerCopy(
|
public fun registerCopy(
|
||||||
literal: String,
|
literal: String,
|
||||||
lambda: MutableCommandBuilder<C>.() -> Unit
|
lambda: MutableCommandBuilder<C>.() -> Unit
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = copy(literal, lambda).register()
|
||||||
copy(literal, lambda).register()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new copy of this mutable builder, append a literal, act on it with a receiver lambda, and then register it with
|
* Create a new copy of this mutable builder, append a literal, act on it with a receiver
|
||||||
* the owning
|
* lambda, and then register it with the owning command manager
|
||||||
* command manager
|
|
||||||
*
|
*
|
||||||
* @param literal name for the literal
|
* @param literal name for the literal
|
||||||
* @param description description for the literal
|
* @param description description for the literal
|
||||||
|
|
@ -313,18 +304,18 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(message = "ArgumentDescription should be used over Description", level = DeprecationLevel.HIDDEN)
|
@Deprecated(
|
||||||
|
message = "ArgumentDescription should be used over Description",
|
||||||
|
level = DeprecationLevel.HIDDEN)
|
||||||
public fun registerCopy(
|
public fun registerCopy(
|
||||||
literal: String,
|
literal: String,
|
||||||
description: Description,
|
description: Description,
|
||||||
lambda: MutableCommandBuilder<C>.() -> Unit
|
lambda: MutableCommandBuilder<C>.() -> Unit
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = copy(literal, description, lambda).register()
|
||||||
copy(literal, description, lambda).register()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new copy of this mutable builder, append a literal, act on it with a receiver lambda, and then register it with
|
* Create a new copy of this mutable builder, append a literal, act on it with a receiver
|
||||||
* the owning
|
* lambda, and then register it with the owning command manager
|
||||||
* command manager
|
|
||||||
*
|
*
|
||||||
* @param literal name for the literal
|
* @param literal name for the literal
|
||||||
* @param description description for the literal
|
* @param description description for the literal
|
||||||
|
|
@ -337,8 +328,7 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
literal: String,
|
literal: String,
|
||||||
description: ArgumentDescription,
|
description: ArgumentDescription,
|
||||||
lambda: MutableCommandBuilder<C>.() -> Unit
|
lambda: MutableCommandBuilder<C>.() -> Unit
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = copy(literal, description, lambda).register()
|
||||||
copy(literal, description, lambda).register()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the value for a certain [CommandMeta.Key] in the command meta storage for this builder
|
* Set the value for a certain [CommandMeta.Key] in the command meta storage for this builder
|
||||||
|
|
@ -349,11 +339,10 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return this mutable builder
|
* @return this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun <T : Any> meta(
|
public fun <T : Any> meta(key: CommandMeta.Key<T>, value: T): MutableCommandBuilder<C> =
|
||||||
key: CommandMeta.Key<T>,
|
mutate {
|
||||||
value: T
|
it.meta(key, value)
|
||||||
): MutableCommandBuilder<C> =
|
}
|
||||||
mutate { it.meta(key, value) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the value for a certain [CommandMeta.Key] in the command meta storage for this builder
|
* Set the value for a certain [CommandMeta.Key] in the command meta storage for this builder
|
||||||
|
|
@ -363,9 +352,7 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return this mutable builder
|
* @return this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public infix fun <T : Any> CommandMeta.Key<T>.to(
|
public infix fun <T : Any> CommandMeta.Key<T>.to(value: T): MutableCommandBuilder<C> =
|
||||||
value: T
|
|
||||||
): MutableCommandBuilder<C> =
|
|
||||||
meta(this, value)
|
meta(this, value)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -375,9 +362,7 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return this mutable builder
|
* @return this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun commandDescription(
|
public fun commandDescription(description: String): MutableCommandBuilder<C> =
|
||||||
description: String
|
|
||||||
): MutableCommandBuilder<C> =
|
|
||||||
meta(CommandMeta.DESCRIPTION, description)
|
meta(CommandMeta.DESCRIPTION, description)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -387,9 +372,7 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return this mutable builder
|
* @return this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun longCommandDescription(
|
public fun longCommandDescription(description: String): MutableCommandBuilder<C> =
|
||||||
description: String
|
|
||||||
): MutableCommandBuilder<C> =
|
|
||||||
meta(CommandMeta.LONG_DESCRIPTION, description)
|
meta(CommandMeta.LONG_DESCRIPTION, description)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -399,9 +382,7 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return this mutable builder
|
* @return this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun hidden(
|
public fun hidden(hidden: Boolean = true): MutableCommandBuilder<C> =
|
||||||
hidden: Boolean = true
|
|
||||||
): MutableCommandBuilder<C> =
|
|
||||||
meta(CommandMeta.HIDDEN, hidden)
|
meta(CommandMeta.HIDDEN, hidden)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -411,8 +392,9 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return this mutable builder
|
* @return this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : C> senderType(): MutableCommandBuilder<C> =
|
public inline fun <reified T : C> senderType(): MutableCommandBuilder<C> = mutate {
|
||||||
mutate { it.senderType(T::class) }
|
it.senderType(T::class)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a required sender type
|
* Specify a required sender type
|
||||||
|
|
@ -421,10 +403,9 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return this mutable builder
|
* @return this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun senderType(
|
public fun senderType(type: KClass<out C>): MutableCommandBuilder<C> = mutate {
|
||||||
type: KClass<out C>
|
it.senderType(type)
|
||||||
): MutableCommandBuilder<C> =
|
}
|
||||||
mutate { it.senderType(type) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Field to get and set the required sender type for this command builder
|
* Field to get and set the required sender type for this command builder
|
||||||
|
|
@ -445,10 +426,9 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return this mutable builder
|
* @return this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun senderType(
|
public fun senderType(type: Class<out C>): MutableCommandBuilder<C> = mutate {
|
||||||
type: Class<out C>
|
it.senderType(type)
|
||||||
): MutableCommandBuilder<C> =
|
}
|
||||||
mutate { it.senderType(type) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a permission required to execute this command
|
* Specify a permission required to execute this command
|
||||||
|
|
@ -457,10 +437,9 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return this mutable builder
|
* @return this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun permission(
|
public fun permission(permission: String): MutableCommandBuilder<C> = mutate {
|
||||||
permission: String
|
it.permission(permission)
|
||||||
): MutableCommandBuilder<C> =
|
}
|
||||||
mutate { it.permission(permission) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a permission required to execute this command
|
* Specify a permission required to execute this command
|
||||||
|
|
@ -469,10 +448,9 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return this mutable builder
|
* @return this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun permission(
|
public fun permission(permission: CommandPermission): MutableCommandBuilder<C> = mutate {
|
||||||
permission: CommandPermission
|
it.permission(permission)
|
||||||
): MutableCommandBuilder<C> =
|
}
|
||||||
mutate { it.permission(permission) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Field to get and set the required permission for this command builder
|
* Field to get and set the required permission for this command builder
|
||||||
|
|
@ -501,12 +479,13 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(message = "ArgumentDescription should be used over Description", level = DeprecationLevel.HIDDEN)
|
@Deprecated(
|
||||||
|
message = "ArgumentDescription should be used over Description",
|
||||||
|
level = DeprecationLevel.HIDDEN)
|
||||||
public fun argument(
|
public fun argument(
|
||||||
argument: CommandArgument<C, *>,
|
argument: CommandArgument<C, *>,
|
||||||
description: Description = Description.empty()
|
description: Description = Description.empty()
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = mutate { it.argument(argument, description) }
|
||||||
mutate { it.argument(argument, description) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new argument to this command
|
* Add a new argument to this command
|
||||||
|
|
@ -519,8 +498,7 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
public fun argument(
|
public fun argument(
|
||||||
argument: CommandArgument<C, *>,
|
argument: CommandArgument<C, *>,
|
||||||
description: ArgumentDescription = ArgumentDescription.empty()
|
description: ArgumentDescription = ArgumentDescription.empty()
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = mutate { it.argument(argument, description) }
|
||||||
mutate { it.argument(argument, description) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new argument to this command
|
* Add a new argument to this command
|
||||||
|
|
@ -531,12 +509,13 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(message = "ArgumentDescription should be used over Description", level = DeprecationLevel.HIDDEN)
|
@Deprecated(
|
||||||
|
message = "ArgumentDescription should be used over Description",
|
||||||
|
level = DeprecationLevel.HIDDEN)
|
||||||
public fun argument(
|
public fun argument(
|
||||||
argument: CommandArgument.Builder<C, *>,
|
argument: CommandArgument.Builder<C, *>,
|
||||||
description: Description = Description.empty()
|
description: Description = Description.empty()
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = mutate { it.argument(argument, description) }
|
||||||
mutate { it.argument(argument, description) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new argument to this command
|
* Add a new argument to this command
|
||||||
|
|
@ -549,8 +528,7 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
public fun argument(
|
public fun argument(
|
||||||
argument: CommandArgument.Builder<C, *>,
|
argument: CommandArgument.Builder<C, *>,
|
||||||
description: ArgumentDescription = ArgumentDescription.empty()
|
description: ArgumentDescription = ArgumentDescription.empty()
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = mutate { it.argument(argument, description) }
|
||||||
mutate { it.argument(argument, description) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new argument to this command
|
* Add a new argument to this command
|
||||||
|
|
@ -561,12 +539,13 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(message = "ArgumentDescription should be used over Description", level = DeprecationLevel.HIDDEN)
|
@Deprecated(
|
||||||
|
message = "ArgumentDescription should be used over Description",
|
||||||
|
level = DeprecationLevel.HIDDEN)
|
||||||
public fun argument(
|
public fun argument(
|
||||||
description: Description = Description.empty(),
|
description: Description = Description.empty(),
|
||||||
argumentSupplier: () -> CommandArgument<C, *>
|
argumentSupplier: () -> CommandArgument<C, *>
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = mutate { it.argument(argumentSupplier(), description) }
|
||||||
mutate { it.argument(argumentSupplier(), description) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new argument to this command
|
* Add a new argument to this command
|
||||||
|
|
@ -579,8 +558,7 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
public fun argument(
|
public fun argument(
|
||||||
description: ArgumentDescription = ArgumentDescription.empty(),
|
description: ArgumentDescription = ArgumentDescription.empty(),
|
||||||
argumentSupplier: () -> CommandArgument<C, *>
|
argumentSupplier: () -> CommandArgument<C, *>
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = mutate { it.argument(argumentSupplier(), description) }
|
||||||
mutate { it.argument(argumentSupplier(), description) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new literal argument to this command
|
* Add a new literal argument to this command
|
||||||
|
|
@ -592,13 +570,14 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(message = "ArgumentDescription should be used over Description", level = DeprecationLevel.HIDDEN)
|
@Deprecated(
|
||||||
|
message = "ArgumentDescription should be used over Description",
|
||||||
|
level = DeprecationLevel.HIDDEN)
|
||||||
public fun literal(
|
public fun literal(
|
||||||
name: String,
|
name: String,
|
||||||
description: Description = Description.empty(),
|
description: Description = Description.empty(),
|
||||||
vararg aliases: String
|
vararg aliases: String
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = mutate { it.literal(name, description, *aliases) }
|
||||||
mutate { it.literal(name, description, *aliases) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new literal argument to this command
|
* Add a new literal argument to this command
|
||||||
|
|
@ -613,8 +592,7 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
name: String,
|
name: String,
|
||||||
description: ArgumentDescription = ArgumentDescription.empty(),
|
description: ArgumentDescription = ArgumentDescription.empty(),
|
||||||
vararg aliases: String
|
vararg aliases: String
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = mutate { it.literal(name, description, *aliases) }
|
||||||
mutate { it.literal(name, description, *aliases) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the [CommandExecutionHandler] for this builder
|
* Set the [CommandExecutionHandler] for this builder
|
||||||
|
|
@ -623,10 +601,9 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
* @return this mutable builder
|
* @return this mutable builder
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public fun handler(
|
public fun handler(handler: CommandExecutionHandler<C>): MutableCommandBuilder<C> = mutate {
|
||||||
handler: CommandExecutionHandler<C>
|
it.handler(handler)
|
||||||
): MutableCommandBuilder<C> =
|
}
|
||||||
mutate { it.handler(handler) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new flag argument to this command
|
* Add a new flag argument to this command
|
||||||
|
|
@ -645,12 +622,12 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
argumentSupplier: () -> CommandArgument<C, *>
|
argumentSupplier: () -> CommandArgument<C, *>
|
||||||
): MutableCommandBuilder<C> = mutate {
|
): MutableCommandBuilder<C> = mutate {
|
||||||
it.flag(
|
it.flag(
|
||||||
this.commandManager.flagBuilder(name)
|
this.commandManager
|
||||||
|
.flagBuilder(name)
|
||||||
.withAliases(*aliases)
|
.withAliases(*aliases)
|
||||||
.withDescription(description)
|
.withDescription(description)
|
||||||
.withArgument(argumentSupplier())
|
.withArgument(argumentSupplier())
|
||||||
.build()
|
.build())
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -670,12 +647,12 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
argument: CommandArgument<C, *>
|
argument: CommandArgument<C, *>
|
||||||
): MutableCommandBuilder<C> = mutate {
|
): MutableCommandBuilder<C> = mutate {
|
||||||
it.flag(
|
it.flag(
|
||||||
this.commandManager.flagBuilder(name)
|
this.commandManager
|
||||||
|
.flagBuilder(name)
|
||||||
.withAliases(*aliases)
|
.withAliases(*aliases)
|
||||||
.withDescription(description)
|
.withDescription(description)
|
||||||
.withArgument(argument)
|
.withArgument(argument)
|
||||||
.build()
|
.build())
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -695,12 +672,12 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
argumentBuilder: CommandArgument.Builder<C, *>
|
argumentBuilder: CommandArgument.Builder<C, *>
|
||||||
): MutableCommandBuilder<C> = mutate {
|
): MutableCommandBuilder<C> = mutate {
|
||||||
it.flag(
|
it.flag(
|
||||||
this.commandManager.flagBuilder(name)
|
this.commandManager
|
||||||
|
.flagBuilder(name)
|
||||||
.withAliases(*aliases)
|
.withAliases(*aliases)
|
||||||
.withDescription(description)
|
.withDescription(description)
|
||||||
.withArgument(argumentBuilder)
|
.withArgument(argumentBuilder)
|
||||||
.build()
|
.build())
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -718,10 +695,10 @@ public class MutableCommandBuilder<C : Any> {
|
||||||
description: ArgumentDescription = ArgumentDescription.empty(),
|
description: ArgumentDescription = ArgumentDescription.empty(),
|
||||||
): MutableCommandBuilder<C> = mutate {
|
): MutableCommandBuilder<C> = mutate {
|
||||||
it.flag(
|
it.flag(
|
||||||
this.commandManager.flagBuilder(name)
|
this.commandManager
|
||||||
|
.flagBuilder(name)
|
||||||
.withAliases(*aliases)
|
.withAliases(*aliases)
|
||||||
.withDescription(description)
|
.withDescription(description)
|
||||||
.build()
|
.build())
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
package cloud.commandframework.kotlin.coroutines
|
||||||
|
|
||||||
|
import cloud.commandframework.annotations.AnnotationParser
|
||||||
|
import cloud.commandframework.annotations.MethodCommandExecutionHandler
|
||||||
|
import cloud.commandframework.context.CommandContext
|
||||||
|
import cloud.commandframework.execution.CommandExecutionCoordinator
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
import java.util.concurrent.CompletableFuture
|
||||||
|
import java.util.function.Predicate
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
import kotlin.reflect.full.callSuspend
|
||||||
|
import kotlin.reflect.jvm.kotlinFunction
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlinx.coroutines.future.asCompletableFuture
|
||||||
|
|
||||||
|
/** Adds coroutine support to the [AnnotationParser]. */
|
||||||
|
public fun <C> AnnotationParser<C>.installCoroutineSupport(
|
||||||
|
scope: CoroutineScope = GlobalScope,
|
||||||
|
context: CoroutineContext = EmptyCoroutineContext
|
||||||
|
) {
|
||||||
|
if (manager().commandExecutionCoordinator() is CommandExecutionCoordinator.SimpleCoordinator) {
|
||||||
|
RuntimeException(
|
||||||
|
"""You are highly advised to not use the simple command execution coordinator together
|
||||||
|
with coroutine support. Consider using the asynchronous command execution coordinator instead.""")
|
||||||
|
.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
val predicate = Predicate<Method> { it.kotlinFunction?.isSuspend == true }
|
||||||
|
registerCommandExecutionMethodFactory(predicate) {
|
||||||
|
KotlinMethodCommandExecutionHandler(scope, context, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class KotlinMethodCommandExecutionHandler<C>(
|
||||||
|
private val coroutineScope: CoroutineScope,
|
||||||
|
private val coroutineContext: CoroutineContext,
|
||||||
|
context: CommandMethodContext<C>
|
||||||
|
) : MethodCommandExecutionHandler<C>(context) {
|
||||||
|
|
||||||
|
override fun executeFuture(commandContext: CommandContext<C>): CompletableFuture<Any?> {
|
||||||
|
val instance = context().instance()
|
||||||
|
val params = createParameterValues(commandContext, commandContext.flags(), false)
|
||||||
|
// We need to propagate exceptions to the caller.
|
||||||
|
return coroutineScope
|
||||||
|
.async(this@KotlinMethodCommandExecutionHandler.coroutineContext) {
|
||||||
|
context().method().kotlinFunction?.callSuspend(instance, *params.toTypedArray())
|
||||||
|
}
|
||||||
|
.asCompletableFuture()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -40,14 +40,15 @@ import kotlin.reflect.KClass
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(message = "ArgumentDescription should be used over Description", level = DeprecationLevel.HIDDEN)
|
@Deprecated(
|
||||||
|
message = "ArgumentDescription should be used over Description",
|
||||||
|
level = DeprecationLevel.HIDDEN)
|
||||||
public fun <C : Any> CommandManager<C>.commandBuilder(
|
public fun <C : Any> CommandManager<C>.commandBuilder(
|
||||||
name: String,
|
name: String,
|
||||||
description: Description = Description.empty(),
|
description: Description = Description.empty(),
|
||||||
aliases: Array<String> = emptyArray(),
|
aliases: Array<String> = emptyArray(),
|
||||||
lambda: MutableCommandBuilder<C>.() -> Unit
|
lambda: MutableCommandBuilder<C>.() -> Unit
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = MutableCommandBuilder(name, description, aliases, this, lambda)
|
||||||
MutableCommandBuilder(name, description, aliases, this, lambda)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new [MutableCommandBuilder] and invoke the provided receiver lambda on it
|
* Create a new [MutableCommandBuilder] and invoke the provided receiver lambda on it
|
||||||
|
|
@ -63,12 +64,11 @@ public fun <C : Any> CommandManager<C>.commandBuilder(
|
||||||
description: ArgumentDescription = ArgumentDescription.empty(),
|
description: ArgumentDescription = ArgumentDescription.empty(),
|
||||||
aliases: Array<String> = emptyArray(),
|
aliases: Array<String> = emptyArray(),
|
||||||
lambda: MutableCommandBuilder<C>.() -> Unit
|
lambda: MutableCommandBuilder<C>.() -> Unit
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = MutableCommandBuilder(name, description, aliases, this, lambda)
|
||||||
MutableCommandBuilder(name, description, aliases, this, lambda)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new [MutableCommandBuilder] which will invoke the provided receiver lambda, and then register itself with the
|
* Create a new [MutableCommandBuilder] which will invoke the provided receiver lambda, and then
|
||||||
* owning [CommandManager]
|
* register itself with the owning [CommandManager]
|
||||||
*
|
*
|
||||||
* @param name name for the root command node
|
* @param name name for the root command node
|
||||||
* @param description description for the root command node
|
* @param description description for the root command node
|
||||||
|
|
@ -77,18 +77,19 @@ public fun <C : Any> CommandManager<C>.commandBuilder(
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(message = "ArgumentDescription should be used over Description", level = DeprecationLevel.HIDDEN)
|
@Deprecated(
|
||||||
|
message = "ArgumentDescription should be used over Description",
|
||||||
|
level = DeprecationLevel.HIDDEN)
|
||||||
public fun <C : Any> CommandManager<C>.buildAndRegister(
|
public fun <C : Any> CommandManager<C>.buildAndRegister(
|
||||||
name: String,
|
name: String,
|
||||||
description: Description = Description.empty(),
|
description: Description = Description.empty(),
|
||||||
aliases: Array<String> = emptyArray(),
|
aliases: Array<String> = emptyArray(),
|
||||||
lambda: MutableCommandBuilder<C>.() -> Unit
|
lambda: MutableCommandBuilder<C>.() -> Unit
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = commandBuilder(name, description, aliases, lambda).register()
|
||||||
commandBuilder(name, description, aliases, lambda).register()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new [MutableCommandBuilder] which will invoke the provided receiver lambda, and then register itself with the
|
* Create a new [MutableCommandBuilder] which will invoke the provided receiver lambda, and then
|
||||||
* owning [CommandManager]
|
* register itself with the owning [CommandManager]
|
||||||
*
|
*
|
||||||
* @param name name for the root command node
|
* @param name name for the root command node
|
||||||
* @param description description for the root command node
|
* @param description description for the root command node
|
||||||
|
|
@ -101,11 +102,11 @@ public fun <C : Any> CommandManager<C>.buildAndRegister(
|
||||||
description: ArgumentDescription = ArgumentDescription.empty(),
|
description: ArgumentDescription = ArgumentDescription.empty(),
|
||||||
aliases: Array<String> = emptyArray(),
|
aliases: Array<String> = emptyArray(),
|
||||||
lambda: MutableCommandBuilder<C>.() -> Unit
|
lambda: MutableCommandBuilder<C>.() -> Unit
|
||||||
): MutableCommandBuilder<C> =
|
): MutableCommandBuilder<C> = commandBuilder(name, description, aliases, lambda).register()
|
||||||
commandBuilder(name, description, aliases, lambda).register()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the provided [MutableCommandBuilder]s into [Command]s, and then register them with the command manager
|
* Build the provided [MutableCommandBuilder]s into [Command]s, and then register them with the
|
||||||
|
* command manager
|
||||||
*
|
*
|
||||||
* @param commands mutable command builder(s) to register
|
* @param commands mutable command builder(s) to register
|
||||||
* @return the command manager
|
* @return the command manager
|
||||||
|
|
@ -114,12 +115,7 @@ public fun <C : Any> CommandManager<C>.buildAndRegister(
|
||||||
*/
|
*/
|
||||||
public fun <C : Any> CommandManager<C>.command(
|
public fun <C : Any> CommandManager<C>.command(
|
||||||
vararg commands: MutableCommandBuilder<C>
|
vararg commands: MutableCommandBuilder<C>
|
||||||
): CommandManager<C> =
|
): CommandManager<C> = apply { commands.forEach { command -> this.command(command.build()) } }
|
||||||
apply {
|
|
||||||
commands.forEach { command ->
|
|
||||||
this.command(command.build())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a required sender type
|
* Specify a required sender type
|
||||||
|
|
@ -141,11 +137,8 @@ public fun <C : Any> Command.Builder<C>.senderType(type: KClass<out C>): Command
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
message = "Use interface variant that allows for rich text",
|
message = "Use interface variant that allows for rich text",
|
||||||
replaceWith = ReplaceWith("argumentDescription(description)")
|
replaceWith = ReplaceWith("argumentDescription(description)"))
|
||||||
)
|
public fun description(description: String = ""): Description =
|
||||||
public fun description(
|
|
||||||
description: String = ""
|
|
||||||
): Description =
|
|
||||||
if (description.isEmpty()) Description.empty() else Description.of(description)
|
if (description.isEmpty()) Description.empty() else Description.of(description)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -155,7 +148,5 @@ public fun description(
|
||||||
* @return the description
|
* @return the description
|
||||||
* @since 1.4.0
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
public fun argumentDescription(
|
public fun argumentDescription(description: String = ""): ArgumentDescription =
|
||||||
description: String = ""
|
|
||||||
): ArgumentDescription =
|
|
||||||
if (description.isEmpty()) ArgumentDescription.empty() else ArgumentDescription.of(description)
|
if (description.isEmpty()) ArgumentDescription.empty() else ArgumentDescription.of(description)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
package cloud.commandframework.kotlin.coroutines
|
||||||
|
|
||||||
|
import cloud.commandframework.CommandManager
|
||||||
|
import cloud.commandframework.annotations.AnnotationParser
|
||||||
|
import cloud.commandframework.annotations.CommandMethod
|
||||||
|
import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator
|
||||||
|
import cloud.commandframework.internal.CommandRegistrationHandler
|
||||||
|
import cloud.commandframework.meta.CommandMeta
|
||||||
|
import cloud.commandframework.meta.SimpleCommandMeta
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.future.await
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
class KotlinAnnotatedMethodsTest {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val executorService = Executors.newSingleThreadExecutor()
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var commandManager: CommandManager<TestCommandSender>
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setUp() {
|
||||||
|
commandManager = TestCommandManager()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun awaitCommands() {
|
||||||
|
executorService.shutdown()
|
||||||
|
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test suspending command methods`(): Unit = runBlocking {
|
||||||
|
AnnotationParser(commandManager, TestCommandSender::class.java) {
|
||||||
|
SimpleCommandMeta.empty()
|
||||||
|
}.also { it.installCoroutineSupport() }.parse(CommandMethods())
|
||||||
|
|
||||||
|
commandManager.executeCommand(TestCommandSender(), "test").await()
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestCommandSender {}
|
||||||
|
|
||||||
|
private class TestCommandManager : CommandManager<TestCommandSender>(
|
||||||
|
AsynchronousCommandExecutionCoordinator.newBuilder<TestCommandSender>().withExecutor(executorService).build(),
|
||||||
|
CommandRegistrationHandler.nullCommandRegistrationHandler()
|
||||||
|
) {
|
||||||
|
|
||||||
|
override fun hasPermission(sender: TestCommandSender, permission: String): Boolean = true
|
||||||
|
|
||||||
|
override fun createDefaultCommandMeta(): CommandMeta = SimpleCommandMeta.empty()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommandMethods {
|
||||||
|
|
||||||
|
@CommandMethod("test")
|
||||||
|
public suspend fun suspendingCommand(): Unit = withContext(Dispatchers.Default) {
|
||||||
|
println("called from thread: ${Thread.currentThread().name}")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue