Class BaseCommandProcessor
java.lang.Object
javax.annotation.processing.AbstractProcessor
io.github.projectunified.craftcommand.processor.BaseCommandProcessor
- All Implemented Interfaces:
Processor
- Direct Known Subclasses:
BukkitCommandProcessor,PaperCommandProcessor,StandaloneCommandProcessor
Re-structured, highly readable base class for command annotation processors.
Supports custom validation annotations, parameter resolvers, deep subcommand nesting, and compiler extensions via SPI.
-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected ResolverLookupCompile-time resolver/suggest/field lookups.Fields inherited from class javax.annotation.processing.AbstractProcessor
processingEnv -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected voidanchorAdditionalFields(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model) Phase 2: Add additional fields after instance and manager.protected voidanchorAdditionalHelpers(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model) Phase 5: Add additional helper methods.protected voidanchorBuildEntryMethods(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model, TypeElement typeElement) Phase 4: Generate platform-specific entry methods (execute, tabComplete, getCommandNode, etc.).protected voidanchorConfigureType(com.palantir.javapoet.TypeSpec.Builder typeSpec) Phase 1: Configure the class declaration (superclass, interfaces).protected voidanchorConstructorBottom(com.palantir.javapoet.MethodSpec.Builder constructorBuilder, CommandModel model) Phase 3 (bottom): Add platform-specific constructor statements at the end.protected voidanchorConstructorTop(com.palantir.javapoet.MethodSpec.Builder constructorBuilder, CommandModel model) Phase 3 (top): Add platform-specific constructor statements at the beginning.protected voidanchorExtraMethods(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model) Phase 7: Add extra methods after CommandInfoExposer (Brigadier tree, etc.).protected voidbuildAdditionalHelpers(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model) Generates additional platform-independent helper methods (like suggestBoolean and sender casting helpers).protected com.palantir.javapoet.CodeBlockprotected voidbuildBuiltInParameter(com.palantir.javapoet.MethodSpec.Builder methodSpec, ParameterModel p, com.palantir.javapoet.TypeName pTypeName, String varName, String argsVar, String argIdxVar, String senderVarName, boolean hasDynamic, int i) protected voidbuildExecutionRouting(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel model, String argsVar, String instanceVar, CommandModel rootModel, String returnStatement) protected voidbuildLocalResolverParameter(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, ParameterModel p, com.palantir.javapoet.TypeName pTypeName, String varName, ExecutableElement localResolver, CommandModel rootModel, String senderVarName, String argsVar, String argIdxVar, boolean hasDynamic, int i) protected voidbuildMethodExecution(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, String instanceVar, CommandModel rootModel, ExecutionSource source) protected voidbuildMethodExecution(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, String argsVar, String instanceVar, CommandModel rootModel) protected com.palantir.javapoet.MethodSpecbuildParameterSuggestionHelper(CommandModel classModel, MethodModel method, ParameterModel p, int index, CommandModel rootModel) protected voidbuildParameterSuggestions(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model, CommandModel rootModel) protected com.palantir.javapoet.MethodSpecbuildResolverParamSuggestionHelper(CommandModel classModel, MethodModel method, ParameterModel rp, String helperName, CommandModel rootModel) voidbuildSenderResolution(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, CommandModel rootModel, String senderVarName, ParameterModel senderParam, com.palantir.javapoet.TypeName senderParamTypeName) protected voidbuildSubcommandSuggestionRouting(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, String argsVar) protected voidbuildSuggestionRouting(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel model, String argsVar, String instanceVar, CommandModel rootModel) protected voidbuildWrapperClass(CommandModel model, TypeElement typeElement) Generates the wrapper class using the template flow with anchor injection points.protected ExecutionSourcecreateExecutionSource(String argsVar, boolean hasDynamic, String argIdxVar) protected static <A extends Annotation>
AfindAnnotationUp(Element element, Class<A> annotationType) Walks up the enclosing element hierarchy to find the first annotation of the given type on the element or any of its enclosing elements.findLocalResolver(CommandModel classModel, ParameterModel p, CommandModel rootModel) findModelForClass(CommandModel current, TypeElement targetClass) protected SuggestionProviderfindSuggestionProvider(com.palantir.javapoet.TypeName typeName) Finds a global suggestion provider for the given type via SPI.protected ExecutableElementfindSuggestMethod(TypeElement typeElement, String name) booleanfirstParamIsSender(ExecutableElement method) booleanfirstParamIsSender(ExecutableElement resolverMethod, MethodModel commandMethod) Checks if the first parameter of a method is a sender parameter, considering the command method's sender type.protected voidgenerateAssignDefaultValue(com.palantir.javapoet.MethodSpec.Builder methodSpec, TypeMirror type, String varName, String defaultValue, String senderVarName) protected voidgenerateExecuteMethodBody(com.palantir.javapoet.MethodSpec.Builder executeSpec, CommandModel model, String returnStatement) protected voidgenerateFieldsAndConstructorStatements(CommandModel model, com.palantir.javapoet.TypeSpec.Builder typeSpec, com.palantir.javapoet.MethodSpec.Builder constructor, String parentFieldName) voidgenerateResolverInvocation(com.palantir.javapoet.MethodSpec.Builder methodSpec, ExecutableElement localResolver, CommandModel classModel, CommandModel rootModel, com.palantir.javapoet.TypeName pTypeName, String varName, String senderVarName, List<String> resolverArgVarNames, boolean includeSender) Generates the common local resolver invocation code: null-check resolver instance, build method call with pre-resolved parameter variables, and assign the result.voidgenerateResolverResolution(ExecutionSource executionSource, com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, CommandModel rootModel, MethodModel resolverModel, String varName, String senderVarName, ParameterModel parentParam, String rawSourceExpr) Unified resolver param resolution: resolves each non-sender param using the same code path, then invokes the resolver method.protected voidgenerateResolveSingleArgument(com.palantir.javapoet.MethodSpec.Builder methodSpec, TypeMirror type, String varName, String argStrVar, String senderVar, String argsVar) protected voidgenerateSubcommandClassExecutors(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model, CommandModel rootModel) protected voidgenerateUnknownSubcommandMessage(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel model) com.palantir.javapoet.CodeBlockgetAssignmentValueForType(com.palantir.javapoet.TypeName typeName, String defaultValue) protected intgetBuiltInWidth(com.palantir.javapoet.TypeName typeName) Gets the default literal value expression for a primitive (or wrapper) type.getInstanceVarExpression(CommandModel classModel, CommandModel rootModel) protected intgetLocalResolverMaxWidth(ExecutableElement resolverMethod, MethodModel commandMethod) protected intgetLocalResolverMinWidth(ExecutableElement resolverMethod, MethodModel commandMethod) protected abstract com.palantir.javapoet.TypeNameReturns the platform-specific command manager type.protected StringgetParameterSuggestionMethodName(CommandModel classModel, MethodModel method, int index) getResolverInstanceExpr(ExecutableElement resolver, CommandModel classModel, CommandModel rootModel) Returns the instance expression for calling a resolver method.protected StringgetResolverParamSuggestionMethodName(CommandModel classModel, MethodModel method, String resolverName, int index) getResolverSenderExpression(ExecutableElement localResolver, String rawSourceExpr, String castSenderVar, com.palantir.javapoet.TypeName commandSenderType) Returns the sender expression to pass to a resolver method.protected com.palantir.javapoet.CodeBlockgetSenderExpression(String senderVar) Returns the sender expression for instanceof checks and general usage.protected abstract com.palantir.javapoet.ClassNameReturns the platform-specific command sender type name.static StringgetSimpleName(com.palantir.javapoet.TypeName typeName) Utility method to get the simple name of a type.protected Stringprotected static StringgetSubcommandNames(CommandModel model) Utility method to format a list of all subcommand names defined in a command model.protected static StringgetUsage(MethodModel method, CommandModel classModel) Utility method to build the command usage syntax string for a command method, with support for flattening @Resolve resolver params.protected abstract StringReturns the wrapper class suffix specific to the platform.protected static StringExtracts the i18n key from a message.voidinit(ProcessingEnvironment processingEnv) booleanisBuiltInType(com.palantir.javapoet.TypeName typeName) protected booleanisField(TypeElement typeElement, String name) protected static booleanReturns true if the message uses thei18n:prefix for runtime lookup.protected booleanisPlatformBuiltInType(com.palantir.javapoet.TypeName typeName) booleanisSenderBaseType(com.palantir.javapoet.TypeName typeName) booleanisSenderParam(com.palantir.javapoet.TypeName typeName, MethodModel method) Checks if a type is any sender tier: command's sender type, base sender type, or platform sender type.booleanisSenderType(com.palantir.javapoet.TypeName typeName) Checks if the sender type is supportedprotected booleanisStringArray(TypeMirror type) Checks if a TypeMirror is String[].protected voidonBeforeExecute(com.palantir.javapoet.MethodSpec.Builder methodSpec, Element element, String returnStatement) booleanprocess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) /** Main entry point for the compiler annotation processing round.protected voidregisterTypes(TypeSupport types) Override this method to register platform-specific types intoTypeSupport.voidresolveParameterForType(com.palantir.javapoet.MethodSpec.Builder methodSpec, com.palantir.javapoet.TypeName typeName, String varName, String argStrVar) voidrunParameterAnnotationHandlers(VariableElement param, String varName, String instanceExpr, String senderVar, com.palantir.javapoet.MethodSpec.Builder methodSpec) Runs all SPI parameter annotation handlers on a VariableElement.protected SenderTypeRegistryMethods inherited from class javax.annotation.processing.AbstractProcessor
getCompletions, getSupportedAnnotationTypes, getSupportedOptions, getSupportedSourceVersion, isInitialized
-
Field Details
-
resolverLookup
Compile-time resolver/suggest/field lookups. Initialized ininit(javax.annotation.processing.ProcessingEnvironment).
-
-
Constructor Details
-
BaseCommandProcessor
public BaseCommandProcessor()
-
-
Method Details
-
getSimpleName
Utility method to get the simple name of a type.- Parameters:
typeName- the full type name- Returns:
- the simple type name
-
getSubcommandNames
Utility method to format a list of all subcommand names defined in a command model.- Parameters:
model- the command model- Returns:
- a formatted string of subcommand names
-
getUsage
Utility method to build the command usage syntax string for a command method, with support for flattening @Resolve resolver params.- Parameters:
method- the method modelclassModel- the command model (for resolver lookup), or null to skip flattening- Returns:
- the usage string
-
findAnnotationUp
protected static <A extends Annotation> A findAnnotationUp(Element element, Class<A> annotationType) Walks up the enclosing element hierarchy to find the first annotation of the given type on the element or any of its enclosing elements.- Parameters:
element- the starting elementannotationType- the annotation class to search for- Returns:
- the annotation instance, or null if not found
-
isI18nKey
Returns true if the message uses thei18n:prefix for runtime lookup. -
i18nKey
Extracts the i18n key from a message. AssumesisI18nKey(String)is true. -
getDefaultPrimitiveValue
Gets the default literal value expression for a primitive (or wrapper) type. Delegates toTypeSupport; returns"null"for non-primitives.- Parameters:
type- the type mirror- Returns:
- the default value literal string
-
init
- Specified by:
initin interfaceProcessor- Overrides:
initin classAbstractProcessor
-
registerTypes
Override this method to register platform-specific types intoTypeSupport. Called duringinit(javax.annotation.processing.ProcessingEnvironment)after SPI extensions are loaded.Example (Bukkit):
@Override protected void registerTypes(TypeSupport types) { types.register(TypeSupport.Entry.builder(playerClass, 1) .primitiveDefault("null") .literal(d -> CodeBlock.of("null")) .platformResolution((spec, p) -> spec.addStatement("$L = getPlayer($L)", p[0], p[1])) .platformSuggestions((spec, p) -> spec.addStatement("return suggestPlayers($L)", p[2])) .build()); }- Parameters:
types- the type support registry to populate
-
getWrapperClassSuffix
Returns the wrapper class suffix specific to the platform.- Returns:
- the class name suffix (e.g. "$BukkitCommand" or "$StandaloneCommand")
-
getSenderTypeName
protected abstract com.palantir.javapoet.ClassName getSenderTypeName()Returns the platform-specific command sender type name. -
getManagerType
protected abstract com.palantir.javapoet.TypeName getManagerType()Returns the platform-specific command manager type. -
anchorConfigureType
protected void anchorConfigureType(com.palantir.javapoet.TypeSpec.Builder typeSpec) Phase 1: Configure the class declaration (superclass, interfaces). -
anchorAdditionalFields
protected void anchorAdditionalFields(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model) Phase 2: Add additional fields after instance and manager. -
anchorConstructorTop
protected void anchorConstructorTop(com.palantir.javapoet.MethodSpec.Builder constructorBuilder, CommandModel model) Phase 3 (top): Add platform-specific constructor statements at the beginning. Called before this.instance/this.manager assignments. -
anchorConstructorBottom
protected void anchorConstructorBottom(com.palantir.javapoet.MethodSpec.Builder constructorBuilder, CommandModel model) Phase 3 (bottom): Add platform-specific constructor statements at the end. Called after nested subcommand instantiation. -
anchorBuildEntryMethods
protected void anchorBuildEntryMethods(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model, TypeElement typeElement) Phase 4: Generate platform-specific entry methods (execute, tabComplete, getCommandNode, etc.). -
anchorAdditionalHelpers
protected void anchorAdditionalHelpers(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model) Phase 5: Add additional helper methods. Default generates suggestBoolean and sender-cast helpers. -
anchorExtraMethods
protected void anchorExtraMethods(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model) Phase 7: Add extra methods after CommandInfoExposer (Brigadier tree, etc.). -
createExecutionSource
protected ExecutionSource createExecutionSource(String argsVar, boolean hasDynamic, String argIdxVar) -
onBeforeExecute
-
generateUnknownSubcommandMessage
protected void generateUnknownSubcommandMessage(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel model) -
isSenderType
public boolean isSenderType(com.palantir.javapoet.TypeName typeName) Checks if the sender type is supported -
isSenderBaseType
public boolean isSenderBaseType(com.palantir.javapoet.TypeName typeName) -
isSenderParam
Checks if a type is any sender tier: command's sender type, base sender type, or platform sender type. When method is null, skips the command's sender type check. -
senderTypeRegistry
- Returns:
- the sender type registry for platform processors to register sender types
-
process
/** Main entry point for the compiler annotation processing round. Searches for types annotated with@Command, parses their structure, and generates the wrappers.- Specified by:
processin interfaceProcessor- Specified by:
processin classAbstractProcessor
-
buildWrapperClass
Generates the wrapper class using the template flow with anchor injection points.- Throws:
IOException
-
generateFieldsAndConstructorStatements
protected void generateFieldsAndConstructorStatements(CommandModel model, com.palantir.javapoet.TypeSpec.Builder typeSpec, com.palantir.javapoet.MethodSpec.Builder constructor, String parentFieldName) -
buildAliasesExpression
-
generateExecuteMethodBody
protected void generateExecuteMethodBody(com.palantir.javapoet.MethodSpec.Builder executeSpec, CommandModel model, String returnStatement) -
getSubcommandFieldName
-
getInstanceVarExpression
-
getResolverInstanceExpr
public String getResolverInstanceExpr(ExecutableElement resolver, CommandModel classModel, CommandModel rootModel) Returns the instance expression for calling a resolver method. When the resolver is on an outer class (not in the command tree), returns null to indicate the resolver cannot be called from this wrapper. -
getParameterSuggestionMethodName
protected String getParameterSuggestionMethodName(CommandModel classModel, MethodModel method, int index) -
generateSubcommandClassExecutors
protected void generateSubcommandClassExecutors(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model, CommandModel rootModel) -
buildExecutionRouting
protected void buildExecutionRouting(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel model, String argsVar, String instanceVar, CommandModel rootModel, String returnStatement) -
getLocalResolverMinWidth
-
getLocalResolverMaxWidth
-
firstParamIsSender
-
firstParamIsSender
Checks if the first parameter of a method is a sender parameter, considering the command method's sender type. -
generateResolveSingleArgument
protected void generateResolveSingleArgument(com.palantir.javapoet.MethodSpec.Builder methodSpec, TypeMirror type, String varName, String argStrVar, String senderVar, String argsVar) -
generateAssignDefaultValue
protected void generateAssignDefaultValue(com.palantir.javapoet.MethodSpec.Builder methodSpec, TypeMirror type, String varName, String defaultValue, String senderVarName) -
getAssignmentValueForType
public com.palantir.javapoet.CodeBlock getAssignmentValueForType(com.palantir.javapoet.TypeName typeName, String defaultValue) -
buildMethodExecution
protected void buildMethodExecution(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, String argsVar, String instanceVar, CommandModel rootModel) -
buildMethodExecution
protected void buildMethodExecution(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, String instanceVar, CommandModel rootModel, ExecutionSource source) -
buildSenderResolution
public void buildSenderResolution(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, CommandModel rootModel, String senderVarName, ParameterModel senderParam, com.palantir.javapoet.TypeName senderParamTypeName) -
buildLocalResolverParameter
protected void buildLocalResolverParameter(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, ParameterModel p, com.palantir.javapoet.TypeName pTypeName, String varName, ExecutableElement localResolver, CommandModel rootModel, String senderVarName, String argsVar, String argIdxVar, boolean hasDynamic, int i) -
buildBuiltInParameter
protected void buildBuiltInParameter(com.palantir.javapoet.MethodSpec.Builder methodSpec, ParameterModel p, com.palantir.javapoet.TypeName pTypeName, String varName, String argsVar, String argIdxVar, String senderVarName, boolean hasDynamic, int i) -
buildSuggestionRouting
protected void buildSuggestionRouting(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel model, String argsVar, String instanceVar, CommandModel rootModel) -
buildSubcommandSuggestionRouting
protected void buildSubcommandSuggestionRouting(com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, String argsVar) -
buildParameterSuggestions
protected void buildParameterSuggestions(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model, CommandModel rootModel) -
getResolverParamSuggestionMethodName
protected String getResolverParamSuggestionMethodName(CommandModel classModel, MethodModel method, String resolverName, int index) -
buildResolverParamSuggestionHelper
protected com.palantir.javapoet.MethodSpec buildResolverParamSuggestionHelper(CommandModel classModel, MethodModel method, ParameterModel rp, String helperName, CommandModel rootModel) -
buildParameterSuggestionHelper
protected com.palantir.javapoet.MethodSpec buildParameterSuggestionHelper(CommandModel classModel, MethodModel method, ParameterModel p, int index, CommandModel rootModel) -
findLocalResolver
public ExecutableElement findLocalResolver(CommandModel classModel, ParameterModel p, CommandModel rootModel) -
generateResolverInvocation
public void generateResolverInvocation(com.palantir.javapoet.MethodSpec.Builder methodSpec, ExecutableElement localResolver, CommandModel classModel, CommandModel rootModel, com.palantir.javapoet.TypeName pTypeName, String varName, String senderVarName, List<String> resolverArgVarNames, boolean includeSender) Generates the common local resolver invocation code: null-check resolver instance, build method call with pre-resolved parameter variables, and assign the result.- Parameters:
methodSpec- the target method builderlocalResolver- the resolver method elementclassModel- the command class modelrootModel- the root command modelpTypeName- the target parameter typevarName- the variable name to assign the result tosenderVarName- the sender variable nameresolverArgVarNames- pre-resolved resolver parameter variable names
-
generateResolverResolution
public void generateResolverResolution(ExecutionSource executionSource, com.palantir.javapoet.MethodSpec.Builder methodSpec, CommandModel classModel, MethodModel method, CommandModel rootModel, MethodModel resolverModel, String varName, String senderVarName, ParameterModel parentParam, String rawSourceExpr) Unified resolver param resolution: resolves each non-sender param using the same code path, then invokes the resolver method. Supports @Default, @Greedy, @Name, @Suggest, @Resolve (nested), and validation annotations like @Min, @Max, @ValidateWith.- Parameters:
rawSourceExpr- the raw sender expression for the platform (e.g. "sender" or "ctx.getSource()")
-
runParameterAnnotationHandlers
public void runParameterAnnotationHandlers(VariableElement param, String varName, String instanceExpr, String senderVar, com.palantir.javapoet.MethodSpec.Builder methodSpec) Runs all SPI parameter annotation handlers on a VariableElement. Used for both command method parameters and resolver method parameters. -
findSuggestMethod
-
isField
-
findModelForClass
-
isBuiltInType
public boolean isBuiltInType(com.palantir.javapoet.TypeName typeName) -
findSuggestionProvider
Finds a global suggestion provider for the given type via SPI. -
getBuiltInWidth
protected int getBuiltInWidth(com.palantir.javapoet.TypeName typeName) -
isPlatformBuiltInType
protected boolean isPlatformBuiltInType(com.palantir.javapoet.TypeName typeName) -
resolveParameterForType
-
getSenderExpression
Returns the sender expression for instanceof checks and general usage. Paper: sender.getSender() (extracts CommandSender from CommandSourceStack). Base: sender (already the correct type). -
isStringArray
Checks if a TypeMirror is String[]. -
getResolverSenderExpression
public String getResolverSenderExpression(ExecutableElement localResolver, String rawSourceExpr, String castSenderVar, com.palantir.javapoet.TypeName commandSenderType) Returns the sender expression to pass to a resolver method. Command's sender type → castSenderVar, base type → rawSourceExpr, platform sender → cast helper, else → castSenderVar. -
buildAdditionalHelpers
protected void buildAdditionalHelpers(com.palantir.javapoet.TypeSpec.Builder typeSpec, CommandModel model) Generates additional platform-independent helper methods (like suggestBoolean and sender casting helpers).
-