Skip to content

Instantly share code, notes, and snippets.

@Revxrsal
Created August 6, 2024 21:24
Show Gist options
  • Save Revxrsal/6a6beffd750335b2cf00af128a6d9ab3 to your computer and use it in GitHub Desktop.
Save Revxrsal/6a6beffd750335b2cf00af128a6d9ab3 to your computer and use it in GitHub Desktop.
package revxrsal.commands.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import revxrsal.commands.annotation.AnnotationList;
import revxrsal.commands.Lamp;
import revxrsal.commands.command.CommandActor;
import revxrsal.commands.node.ExecutionContext;
import revxrsal.commands.node.MutableParameterNode;
import revxrsal.commands.parameters.PrioritySpec;
import revxrsal.commands.parameters.builtins.ClassParameterTypeFactory;
import revxrsal.commands.stream.MutableStringStream;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
public interface ParameterType<A extends CommandActor, T> extends ParameterResolver<A, T> {
/**
* Reads input from the given {@link MutableStringStream}, parses the object, or throws
* exceptions if needed.
*
* @param input The input stream. This argument type is free to consume as much as it needs
* @param context The command execution context, as well as arguments that have been resolved
* @return The parsed object. This should never be null.
*/
T parse(
@NotNull MutableStringStream input,
@NotNull ExecutionContext<A> context
);
/**
* Returns the default suggestions. These will be sent if the
* containing {@link MutableParameterNode} does not
* supply any custom suggestions.
*
* @return The default type suggestions
*/
default @Nullable List<String> defaultSuggestions() {
return Collections.emptyList();
}
/**
* The priority for an argument of this type over other candidate arguments.
* <p>
* An example of this, is when a command has the following signatures:
* <ul>
* <li>/foo [integer]</li>
* <li>/foo [string]</li>
* </ul>
* <p>
* Because an integer parameter can only accept a certain type of input (i.e. numbers),
* it will have higher priority over a string parameter, and as such, if the user
* inputs {@code /foo 10}, the integer will be tested first, before moving on to the
* string.
* <p>
* For more details on the priority API, see {@link PrioritySpec}
*
* @return the parse priority for this parameter
*/
default @NotNull PrioritySpec parsePriority() {
return PrioritySpec.defaultPriority();
}
@Override
default boolean consumesInput() {
return true;
}
/**
* Represents a factory that constructs {@link ParameterTypes} dynamically
*
* @param <A> The command actor type
*/
interface Factory<A extends CommandActor> extends ParameterFactory {
/**
* Dynamically creates a {@link ParameterType}
*
* @param <T> The parameter type
* @param parameterType The command parameter to create for
* @param annotations The parameter annotations
* @param lamp The Lamp instance (for referencing other parameter types)
* @return The newly created {@link ParameterType}, or {@code null} if this factory
* cannot deal with it.
*/
@Nullable
<T> ParameterType<A, T> create(@NotNull Type parameterType, @NotNull AnnotationList annotations, @NotNull Lamp<A> lamp);
/**
* Creates a new {@link Factory} that returns a {@link ParameterType} for all
* parameters that <em>exactly</em> have a certain class.
*
* @param type Parameter type to check against
* @param parameterType The parameter type to supply
* @param <A> The actor type
* @param <T> The parameter type
* @return The parameter type factory
*/
static <A extends CommandActor, T> @NotNull Factory<A> forType(@NotNull Class<T> type, @NotNull ParameterType<A, T> parameterType) {
return new ClassParameterTypeFactory<>(type, parameterType, false);
}
/**
* Creates a new {@link Factory} that returns a {@link ParameterType} for all
* parameters that are assignable from the given {@code type}.
* <p>
* Checking is done using {@link Class#isAssignableFrom(Class)}.
*
* @param type Parameter type to check against
* @param parameterType The parameter type to supply
* @param <A> The actor type
* @param <T> The parameter type
* @return The parameter type factory
*/
static <A extends CommandActor, T> @NotNull Factory<A> forTypeAndSubclasses(@NotNull Class<T> type, @NotNull ParameterType<A, T> parameterType) {
return new ClassParameterTypeFactory<>(type, parameterType, true);
}
/**
* Tests whether this factory consumes input or not.
*
* @return If the factory consumes input or not
*/
@Override
default boolean consumesInput() {
return true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment