Add Tree interface to unify CommandTree and Argument chaining · Issue #644 · CommandAPI/CommandAPI · GitHub
Skip to content

Add Tree interface to unify CommandTree and Argument chaining #644

Description

@sya-ri

Description

Currently, both CommandTree.argument and Argument<*>.argument are defined separately. This is due to the lack of a common interface between CommandTree and Argument<*>, even though both define a then method. As more argument types are added — such as thenNested — or when third-party developers introduce their own argument types, we are forced to implement support separately for each of CommandTree and Argument<*>.

Introducing a shared interface — such as Tree (or another appropriate name) — would reduce both maintenance and implementation costs. While this change may be considered breaking at runtime, it is not a breaking change at build time.

Expected code

🆕 commandapi-core/src/main/java/dev/jorel/commandapi/Tree.java

package dev.jorel.commandapi;

import dev.jorel.commandapi.arguments.AbstractArgument;

import java.util.Arrays;
import java.util.List;

/**
 * This is the base interface for commands, arguments
 * @param <Impl> The class extending this class, used as the return type for chain calls
 * @param <Argument> The implementation of AbstractArgument being used by this class
 * @param <CommandSender> The CommandSender class used by the class extending this class
 */
public interface Tree<Impl, Argument extends AbstractArgument<?, ?, Argument, CommandSender>, CommandSender> {
	/**
	 * Create a child branch on this node
	 *
	 * @param tree The child branch
	 * @return this tree node
	 */
	Impl then(final AbstractArgumentTree<?, Argument, CommandSender> tree);

	/**
	 * Creates a chain of child branches starting at this node
	 * <p>
	 * {@code thenNested(a, b, c)} is equivalent to {@link #then}{@code (a.then(b.then(c)))}.
	 *
	 * @param trees The child branches to add in a chain.
	 * @return this tree node
	 */
	Impl thenNested(List<AbstractArgumentTree<?, Argument, CommandSender>> trees);

	/**
	 * Creates a chain of child branches starting at this node
	 * <p>
	 * {@code thenNested(a, b, c)} is equivalent to {@link #then}{@code (a.then(b.then(c)))}.
	 *
	 * @param trees The child branches to add in a chain.
	 * @return this tree node
	 */
	default Impl thenNested(final AbstractArgumentTree<?, Argument, CommandSender>... trees) {
		return thenNested(Arrays.asList(trees));
	}
}

commandapi-core/src/main/java/dev/jorel/commandapi/AbstractArgumentTree.java

public abstract class AbstractArgumentTree<Impl
/// @cond DOX
extends AbstractArgumentTree<Impl, Argument, CommandSender>
/// @endcond
, Argument
/// @cond DOX
extends AbstractArgument<?, ?, Argument, CommandSender>
/// @endcond
, CommandSender> extends Executable<Impl, CommandSender>
	implements Tree<Impl, Argument, CommandSender> { // <- NEW

commandapi-core/src/main/java/dev/jorel/commandapi/AbstractCommandTree.java

public abstract class AbstractCommandTree<Impl
/// @cond DOX
extends AbstractCommandTree<Impl, Argument, CommandSender>
/// @endcond
, Argument
/// @cond DOX
extends AbstractArgument<?, ?, Argument, CommandSender>
/// @endcond
, CommandSender> extends ExecutableCommand<Impl, CommandSender>
	implements Tree<Impl, Argument, CommandSender> { // <- NEW

Extra details

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions