🚚 Begin migrating from javax annotations to checker-qual

This commit is contained in:
Alexander Söderberg 2020-09-28 16:40:06 +02:00 committed by Alexander Söderberg
parent e914d04450
commit 9f0c846050
43 changed files with 273 additions and 549 deletions

View file

@ -25,9 +25,9 @@ package cloud.commandframework.services;
import cloud.commandframework.services.annotations.Order;
import cloud.commandframework.services.types.Service;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
@ -40,7 +40,8 @@ class AnnotatedMethodService<Context, Result> implements Service<Context, Result
private final Method method;
private final Object instance;
AnnotatedMethodService(@Nonnull final Object instance, @Nonnull final Method method)
AnnotatedMethodService(@NonNull final Object instance,
@NonNull final Method method)
throws Exception {
ExecutionOrder executionOrder = ExecutionOrder.SOON;
try {
@ -57,10 +58,9 @@ class AnnotatedMethodService<Context, Result> implements Service<Context, Result
this.method = method;
}
@Nullable
@Override
@SuppressWarnings("unchecked")
public Result handle(@Nonnull final Context context) {
public @Nullable Result handle(@NonNull final Context context) {
try {
return (Result) this.methodHandle.invoke(this.instance, context);
} catch (final Throwable throwable) {
@ -72,9 +72,8 @@ class AnnotatedMethodService<Context, Result> implements Service<Context, Result
return null;
}
@Nonnull
@Override
public ExecutionOrder order() {
public @NonNull ExecutionOrder order() {
return this.executionOrder;
}

View file

@ -26,8 +26,8 @@ package cloud.commandframework.services;
import io.leangen.geantyref.TypeToken;
import cloud.commandframework.services.annotations.ServiceImplementation;
import cloud.commandframework.services.types.Service;
import org.checkerframework.checker.nullness.qual.NonNull;
import javax.annotation.Nonnull;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@ -35,8 +35,8 @@ import java.util.Map;
enum AnnotatedMethodServiceFactory {
INSTANCE;
Map<? extends Service<?, ?>, TypeToken<? extends Service<?, ?>>> lookupServices(
@Nonnull final Object instance) throws Exception {
@NonNull Map<? extends Service<?, ?>, TypeToken<? extends Service<?, ?>>> lookupServices(
@NonNull final Object instance) throws Exception {
final Map<Service<?, ?>, TypeToken<? extends Service<?, ?>>> map = new HashMap<>();
final Class<?> clazz = instance.getClass();
for (final Method method : clazz.getDeclaredMethods()) {

View file

@ -23,7 +23,8 @@
//
package cloud.commandframework.services;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -38,18 +39,18 @@ import java.util.Map;
* @param <Context> Context/Request type
* @param <Result> Result type
*/
public abstract class ChunkedRequestContext<Context, Result> {
public abstract class ChunkedRequestContext<@NonNull Context, @NonNull Result> {
private final Object lock = new Object();
private final List<Context> requests;
private final Map<Context, Result> results;
private final List<@NonNull Context> requests;
private final Map<@NonNull Context, @NonNull Result> results;
/**
* Initialize a new request
*
* @param requests Request contexts
*/
protected ChunkedRequestContext(@Nonnull final Collection<Context> requests) {
protected ChunkedRequestContext(@NonNull final Collection<Context> requests) {
this.requests = new ArrayList<>(requests);
this.results = new HashMap<>(requests.size());
}
@ -59,8 +60,7 @@ public abstract class ChunkedRequestContext<Context, Result> {
*
* @return Unmodifiable map of results
*/
@Nonnull
public final Map<Context, Result> getAvailableResults() {
public final @NonNull Map<@NonNull Context, @NonNull Result> getAvailableResults() {
synchronized (this.lock) {
return Collections.unmodifiableMap(this.results);
}
@ -71,8 +71,7 @@ public abstract class ChunkedRequestContext<Context, Result> {
*
* @return Unmodifiable list of remaining requests
*/
@Nonnull
public final List<Context> getRemaining() {
public final @NonNull List<@NonNull Context> getRemaining() {
synchronized (this.lock) {
return Collections.unmodifiableList(this.requests);
}
@ -84,7 +83,7 @@ public abstract class ChunkedRequestContext<Context, Result> {
* @param context Context
* @param result Result
*/
public final void storeResult(@Nonnull final Context context, @Nonnull final Result result) {
public final void storeResult(@NonNull final Context context, @NonNull final Result result) {
synchronized (this.lock) {
this.results.put(context, result);
this.requests.remove(context);

View file

@ -23,7 +23,7 @@
//
package cloud.commandframework.services;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Wrapper for exceptions thrown during pipeline execution.
@ -37,7 +37,7 @@ public final class PipelineException extends RuntimeException {
*
* @param cause Cause of the exception
*/
public PipelineException(@Nonnull final Exception cause) {
public PipelineException(@NonNull final Exception cause) {
super(cause);
}
@ -47,7 +47,7 @@ public final class PipelineException extends RuntimeException {
* @param message Message explaining the exception
* @param cause Cause of the exception
*/
public PipelineException(@Nonnull final String message, @Nonnull final Exception cause) {
public PipelineException(@NonNull final String message, @NonNull final Exception cause) {
super(message, cause);
}

View file

@ -24,16 +24,16 @@
package cloud.commandframework.services;
import cloud.commandframework.services.types.Service;
import org.checkerframework.checker.nullness.qual.NonNull;
import javax.annotation.Nonnull;
import java.util.function.Predicate;
enum ServiceFilterHandler {
INSTANCE;
<Context> boolean passes(
@Nonnull final ServiceRepository<Context, ?>.ServiceWrapper<? extends Service<Context, ?>> service,
@Nonnull final Context context) {
@NonNull final ServiceRepository<Context, ?>.ServiceWrapper<? extends Service<Context, ?>> service,
@NonNull final Context context) {
if (!service.isDefaultImplementation()) {
for (final Predicate<Context> predicate : service.getFilters()) {
try {

View file

@ -25,8 +25,8 @@ package cloud.commandframework.services;
import io.leangen.geantyref.TypeToken;
import cloud.commandframework.services.types.Service;
import org.checkerframework.checker.nullness.qual.NonNull;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -45,7 +45,7 @@ public final class ServicePipeline {
private final Map<TypeToken<? extends Service<?, ?>>, ServiceRepository<?, ?>> repositories;
private final Executor executor;
ServicePipeline(@Nonnull final Executor executor) {
ServicePipeline(@NonNull final Executor executor) {
this.repositories = new HashMap<>();
this.executor = executor;
}
@ -55,8 +55,7 @@ public final class ServicePipeline {
*
* @return Builder instance
*/
@Nonnull
public static ServicePipelineBuilder builder() {
public static @NonNull ServicePipelineBuilder builder() {
return new ServicePipelineBuilder();
}
@ -71,9 +70,9 @@ public final class ServicePipeline {
* @param <Result> Service result type
* @return ServicePipeline The service pipeline instance
*/
public <Context, Result> ServicePipeline registerServiceType(
@Nonnull final TypeToken<? extends Service<Context, Result>> type,
@Nonnull final Service<Context, Result> defaultImplementation) {
public <Context, Result> @NonNull ServicePipeline registerServiceType(
@NonNull final TypeToken<? extends Service<@NonNull Context, @NonNull Result>> type,
@NonNull final Service<@NonNull Context, @NonNull Result> defaultImplementation) {
synchronized (this.lock) {
if (repositories.containsKey(type)) {
throw new IllegalArgumentException(String
@ -105,8 +104,8 @@ public final class ServicePipeline {
* @throws Exception Any exceptions thrown during the registration process
*/
@SuppressWarnings("unchecked")
public <T> ServicePipeline registerMethods(
@Nonnull final T instance) throws Exception {
public <T> @NonNull ServicePipeline registerMethods(
@NonNull final T instance) throws Exception {
synchronized (this.lock) {
final Map<? extends Service<?, ?>, TypeToken<? extends Service<?, ?>>> services =
AnnotatedMethodServiceFactory.INSTANCE.lookupServices(instance);
@ -139,9 +138,9 @@ public final class ServicePipeline {
* @return ServicePipeline The service pipeline instance
*/
public <Context, Result> ServicePipeline registerServiceImplementation(
@Nonnull final TypeToken<? extends Service<Context, Result>> type,
@Nonnull final Service<Context, Result> implementation,
@Nonnull final Collection<Predicate<Context>> filters) {
@NonNull final TypeToken<? extends Service<Context, Result>> type,
@NonNull final Service<Context, Result> implementation,
@NonNull final Collection<Predicate<Context>> filters) {
synchronized (this.lock) {
final ServiceRepository<Context, Result> repository = getRepository(type);
repository.registerImplementation(implementation, filters);
@ -163,9 +162,9 @@ public final class ServicePipeline {
* @return ServicePipeline The service pipeline instance
*/
public <Context, Result> ServicePipeline registerServiceImplementation(
@Nonnull final Class<? extends Service<Context, Result>> type,
@Nonnull final Service<Context, Result> implementation,
@Nonnull final Collection<Predicate<Context>> filters) {
@NonNull final Class<? extends Service<Context, Result>> type,
@NonNull final Service<Context, Result> implementation,
@NonNull final Collection<Predicate<Context>> filters) {
return registerServiceImplementation(TypeToken.get(type), implementation, filters);
}
@ -177,15 +176,15 @@ public final class ServicePipeline {
* @param <Context> Context type
* @return Service pumper instance
*/
@Nonnull
public <Context> ServicePump<Context> pump(@Nonnull final Context context) {
@NonNull
public <Context> ServicePump<Context> pump(@NonNull final Context context) {
return new ServicePump<>(this, context);
}
@SuppressWarnings("unchecked")
@Nonnull
@NonNull
<Context, Result> ServiceRepository<Context, Result> getRepository(
@Nonnull final TypeToken<? extends Service<Context, Result>> type) {
@NonNull final TypeToken<? extends Service<Context, Result>> type) {
final ServiceRepository<Context, Result> repository =
(ServiceRepository<Context, Result>) this.repositories.get(type);
if (repository == null) {
@ -200,7 +199,7 @@ public final class ServicePipeline {
*
* @return Returns an Immutable collection of the service types registered.
*/
@Nonnull
@NonNull
public Collection<TypeToken<? extends Service<?, ?>>> getRecognizedTypes() {
return Collections.unmodifiableCollection(this.repositories.keySet());
}
@ -215,10 +214,10 @@ public final class ServicePipeline {
* @return Returns an collection of the {@link TypeToken}s of the implementations for a given
* service. Iterator order matches the priority when pumping contexts through the pipeline
*/
@Nonnull
@NonNull
@SuppressWarnings("unchecked")
public <Context, Result, S extends Service<Context, Result>> Collection<TypeToken<? extends S>> getImplementations(
@Nonnull final TypeToken<S> type) {
@NonNull final TypeToken<S> type) {
ServiceRepository<Context, Result> repository = getRepository(type);
List<TypeToken<? extends S>> collection = new LinkedList<>();
final LinkedList<? extends ServiceRepository<Context, Result>.ServiceWrapper<? extends Service<Context, Result>>>
@ -232,7 +231,7 @@ public final class ServicePipeline {
return Collections.unmodifiableList(collection);
}
@Nonnull
@NonNull
Executor getExecutor() {
return this.executor;
}

View file

@ -23,7 +23,8 @@
//
package cloud.commandframework.services;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@ -44,8 +45,7 @@ public final class ServicePipelineBuilder {
*
* @return New service pipeline
*/
@Nonnull
public ServicePipeline build() {
public @NonNull ServicePipeline build() {
return new ServicePipeline(this.executor);
}
@ -56,8 +56,7 @@ public final class ServicePipelineBuilder {
* @param executor New executor
* @return Builder instance
*/
@Nonnull
public ServicePipelineBuilder withExecutor(@Nonnull final Executor executor) {
public @NonNull ServicePipelineBuilder withExecutor(@NonNull final Executor executor) {
this.executor = Objects.requireNonNull(executor, "Executor may not be null");
return this;
}

View file

@ -25,8 +25,7 @@ package cloud.commandframework.services;
import cloud.commandframework.services.types.Service;
import io.leangen.geantyref.TypeToken;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Class that forwards a context to a service type that consumes said context
@ -38,7 +37,8 @@ public final class ServicePump<Context> {
private final ServicePipeline servicePipeline;
private final Context context;
ServicePump(final ServicePipeline servicePipeline, final Context context) {
ServicePump(@NonNull final ServicePipeline servicePipeline,
@NonNull final Context context) {
this.servicePipeline = servicePipeline;
this.context = context;
}
@ -50,9 +50,8 @@ public final class ServicePump<Context> {
* @param <Result> Result type
* @return Service spigot instance
*/
@Nonnull
public <Result> ServiceSpigot<Context, Result> through(
@Nonnull final TypeToken<? extends Service<Context, Result>> type) {
public <Result> @NonNull ServiceSpigot<@NonNull Context, @NonNull Result> through(
@NonNull final TypeToken<? extends Service<@NonNull Context, @NonNull Result>> type) {
return new ServiceSpigot<>(this.servicePipeline, this.context, type);
}
@ -63,9 +62,8 @@ public final class ServicePump<Context> {
* @param <Result> Result type
* @return Service spigot instance
*/
@Nonnull
public <Result> ServiceSpigot<Context, Result> through(
@Nonnull final Class<? extends Service<Context, Result>> clazz) {
public <Result> @NonNull ServiceSpigot<@NonNull Context, @NonNull Result> through(
@NonNull final Class<? extends Service<@NonNull Context, @NonNull Result>> clazz) {
return this.through(TypeToken.get(clazz));
}

View file

@ -26,8 +26,8 @@ package cloud.commandframework.services;
import io.leangen.geantyref.TypeToken;
import cloud.commandframework.services.annotations.Order;
import cloud.commandframework.services.types.Service;
import org.checkerframework.checker.nullness.qual.NonNull;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@ -54,7 +54,7 @@ public final class ServiceRepository<Context, Response> {
*
* @param serviceType Service type
*/
ServiceRepository(@Nonnull final TypeToken<? extends Service<Context, Response>> serviceType) {
ServiceRepository(@NonNull final TypeToken<? extends Service<Context, Response>> serviceType) {
this.serviceType = serviceType;
this.implementations = new LinkedList<>();
}
@ -66,8 +66,8 @@ public final class ServiceRepository<Context, Response> {
* @param filters Filters that will be used to determine whether or not the service gets used
* @param <T> Type of the implementation
*/
<T extends Service<Context, Response>> void registerImplementation(@Nonnull final T service,
@Nonnull final Collection<Predicate<Context>> filters) {
<T extends Service<Context, Response>> void registerImplementation(@NonNull final T service,
@NonNull final Collection<Predicate<Context>> filters) {
synchronized (this.lock) {
this.implementations.add(new ServiceWrapper<>(service, filters));
}
@ -78,7 +78,7 @@ public final class ServiceRepository<Context, Response> {
*
* @return Queue containing all implementations
*/
@Nonnull
@NonNull
LinkedList<ServiceWrapper<? extends Service<Context, Response>>> getQueue() {
synchronized (this.lock) {
return new LinkedList<>(this.implementations);
@ -101,8 +101,8 @@ public final class ServiceRepository<Context, Response> {
private final int registrationOrder = ServiceRepository.this.registrationOrder++;
private final ExecutionOrder executionOrder;
private ServiceWrapper(@Nonnull final T implementation,
@Nonnull final Collection<Predicate<Context>> filters) {
private ServiceWrapper(@NonNull final T implementation,
@NonNull final Collection<Predicate<Context>> filters) {
this.defaultImplementation = implementations.isEmpty();
this.implementation = implementation;
this.filters = filters;
@ -118,12 +118,12 @@ public final class ServiceRepository<Context, Response> {
this.executionOrder = executionOrder;
}
@Nonnull
@NonNull
T getImplementation() {
return this.implementation;
}
@Nonnull
@NonNull
Collection<Predicate<Context>> getFilters() {
return Collections.unmodifiableCollection(this.filters);
}
@ -140,7 +140,7 @@ public final class ServiceRepository<Context, Response> {
}
@Override
public int compareTo(@Nonnull final ServiceWrapper<T> other) {
public int compareTo(@NonNull final ServiceWrapper<T> other) {
return Comparator.<ServiceWrapper<T>>comparingInt(
wrapper -> wrapper.isDefaultImplementation()
? Integer.MIN_VALUE

View file

@ -27,8 +27,8 @@ import io.leangen.geantyref.TypeToken;
import cloud.commandframework.services.types.ConsumerService;
import cloud.commandframework.services.types.Service;
import cloud.commandframework.services.types.SideEffectService;
import org.checkerframework.checker.nullness.qual.NonNull;
import javax.annotation.Nonnull;
import java.util.LinkedList;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
@ -45,8 +45,9 @@ public final class ServiceSpigot<Context, Result> {
private final ServicePipeline pipeline;
private final ServiceRepository<Context, Result> repository;
ServiceSpigot(@Nonnull final ServicePipeline pipeline, @Nonnull final Context context,
@Nonnull final TypeToken<? extends Service<Context, Result>> type) {
ServiceSpigot(@NonNull final ServicePipeline pipeline,
@NonNull final Context context,
@NonNull final TypeToken<? extends Service<@NonNull Context, @NonNull Result>> type) {
this.context = context;
this.pipeline = pipeline;
this.repository = pipeline.getRepository(type);
@ -72,11 +73,11 @@ public final class ServiceSpigot<Context, Result> {
* @see PipelineException PipelineException wraps exceptions thrown during filtering and result
* retrieval
*/
@Nonnull
@SuppressWarnings("unchecked")
public Result getResult()
public @NonNull Result getResult()
throws IllegalStateException, PipelineException {
final LinkedList<? extends ServiceRepository<Context, Result>.ServiceWrapper<? extends Service<Context, Result>>>
final LinkedList<? extends ServiceRepository<@NonNull Context, @NonNull Result>
.ServiceWrapper<? extends Service<@NonNull Context, @NonNull Result>>>
queue = this.repository.getQueue();
queue.sort(null); // Sort using the built in comparator method
ServiceRepository<Context, Result>.ServiceWrapper<? extends Service<Context, Result>>
@ -128,7 +129,7 @@ public final class ServiceSpigot<Context, Result> {
* default implementation
* @throws IllegalStateException If a {@link SideEffectService} returns {@code null}
*/
public void getResult(@Nonnull final BiConsumer<Result, Throwable> consumer) {
public void getResult(@NonNull final BiConsumer<Result, Throwable> consumer) {
try {
consumer.accept(getResult(), null);
} catch (final PipelineException pipelineException) {
@ -145,8 +146,7 @@ public final class ServiceSpigot<Context, Result> {
*
* @return Generated result
*/
@Nonnull
public CompletableFuture<Result> getResultAsynchronously() {
public @NonNull CompletableFuture<Result> getResultAsynchronously() {
return CompletableFuture.supplyAsync(this::getResult, this.pipeline.getExecutor());
}
@ -155,8 +155,7 @@ public final class ServiceSpigot<Context, Result> {
*
* @return New pump, for the result of this request
*/
@Nonnull
public ServicePump<Result> forward() {
public @NonNull ServicePump<Result> forward() {
return this.pipeline.pump(this.getResult());
}
@ -165,8 +164,7 @@ public final class ServiceSpigot<Context, Result> {
*
* @return New pump, for the result of this request
*/
@Nonnull
public CompletableFuture<ServicePump<Result>> forwardAsynchronously() {
public @NonNull CompletableFuture<ServicePump<Result>> forwardAsynchronously() {
return this.getResultAsynchronously().thenApply(pipeline::pump);
}

View file

@ -24,8 +24,8 @@
package cloud.commandframework.services.types;
import cloud.commandframework.services.State;
import org.checkerframework.checker.nullness.qual.NonNull;
import javax.annotation.Nonnull;
import java.util.function.Consumer;
/**
@ -49,9 +49,8 @@ public interface ConsumerService<Context>
throw new PipeBurst();
}
@Nonnull
@Override
default State handle(@Nonnull final Context context) {
default @NonNull State handle(@NonNull final Context context) {
try {
this.accept(context);
} catch (final PipeBurst burst) {
@ -67,7 +66,7 @@ public interface ConsumerService<Context>
* @param context Context to consume
*/
@Override
void accept(@Nonnull Context context);
void accept(@NonNull Context context);
class PipeBurst extends RuntimeException {

View file

@ -24,9 +24,9 @@
package cloud.commandframework.services.types;
import cloud.commandframework.services.ChunkedRequestContext;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
@ -38,11 +38,10 @@ import java.util.Map;
* @param <Chunked> Chunk request context
*/
public interface PartialResultService<Context, Result, Chunked extends ChunkedRequestContext<Context, Result>>
extends Service<Chunked, Map<Context, Result>> {
extends Service<Chunked, @Nullable Map<@NonNull Context, @NonNull Result>> {
@Override
@Nullable
default Map<Context, Result> handle(@Nonnull final Chunked context) {
default @Nullable Map<@NonNull Context, @NonNull Result> handle(@NonNull final Chunked context) {
if (!context.isCompleted()) {
this.handleRequests(context.getRemaining()).forEach(context::storeResult);
}
@ -59,7 +58,6 @@ public interface PartialResultService<Context, Result, Chunked extends ChunkedRe
* @param requests Requests
* @return Map of request-result pairs
*/
@Nonnull
Map<Context, Result> handleRequests(@Nonnull List<Context> requests);
@NonNull Map<@NonNull Context, @NonNull Result> handleRequests(@NonNull List<Context> requests);
}

View file

@ -25,9 +25,9 @@ package cloud.commandframework.services.types;
import cloud.commandframework.services.ExecutionOrder;
import cloud.commandframework.services.PipelineException;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.function.Function;
/**
@ -39,7 +39,7 @@ import java.util.function.Function;
* @param <Result> Response type, this is what is produced by the service ("provided")
*/
@FunctionalInterface
public interface Service<Context, Result> extends Function<Context, Result> {
public interface Service<Context, Result> extends Function<@NonNull Context, @Nullable Result> {
/**
* Provide a response for the given context. If the service implementation cannot provide a
@ -52,11 +52,10 @@ public interface Service<Context, Result> extends Function<Context, Result> {
* @throws Exception Any exception that occurs during the handling can be thrown, and will be
* wrapped by a {@link PipelineException}
*/
@Nullable
Result handle(@Nonnull Context context) throws Exception;
@Nullable Result handle(@NonNull Context context) throws Exception;
@Override
default Result apply(@Nonnull Context context) {
default @Nullable Result apply(@NonNull Context context) {
try {
return this.handle(context);
} catch (final Exception exception) {
@ -70,8 +69,7 @@ public interface Service<Context, Result> extends Function<Context, Result> {
*
* @return Execution order
*/
@Nullable
default ExecutionOrder order() {
default @Nullable ExecutionOrder order() {
return null;
}

View file

@ -24,8 +24,7 @@
package cloud.commandframework.services.types;
import cloud.commandframework.services.State;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Service implementation that alters the state of the owning application in some way. A
@ -49,7 +48,6 @@ public interface SideEffectService<Context> extends Service<Context, State> {
* wrapped by a {@link cloud.commandframework.services.PipelineException}
*/
@Override
@Nonnull
State handle(@Nonnull Context context) throws Exception;
@NonNull State handle(@NonNull Context context) throws Exception;
}