CommandAPI icon indicating copy to clipboard operation
CommandAPI copied to clipboard

Add Tree interface to unify CommandTree and Argument chaining

Open sya-ri opened this issue 8 months ago • 2 comments

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

:new: 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

sya-ri avatar Apr 29 '25 06:04 sya-ri

This came up in the CommandAPI Discord like 2 years ago, although it seems no one did anything about it :P. The code changes you described make sense to me.

willkroboth avatar Apr 29 '25 13:04 willkroboth

Yeah, I have nothing against this either but since I believe that such a change would be backwards incompatible (unless my knowledge about this stuff is failing me), it can't be introduced during the 10.x.x release cycle. We can definitely schedule this for 11.0.0 though 👍

DerEchtePilz avatar Apr 29 '25 19:04 DerEchtePilz