#305 Adjust behavior of label handling; cleanup

- Fix bugs in behavior (wrong labels being shown for help)
- Change order of labels and arguments in FoundCommandResult constructors
- Move FoundResultStatus enum to its own class
- Create test class for HelpProvider
This commit is contained in:
ljacqu
2015-12-18 22:19:26 +01:00
parent d871939793
commit 01a294a334
9 changed files with 231 additions and 51 deletions
@@ -12,9 +12,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.INCORRECT_ARGUMENTS;
import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.MISSING_BASE_COMMAND;
import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.UNKNOWN_LABEL;
import static fr.xephi.authme.command.FoundResultStatus.INCORRECT_ARGUMENTS;
import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND;
import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL;
/**
* The AuthMe command handler, responsible for mapping incoming commands to the correct {@link CommandDescription}
@@ -121,9 +121,8 @@ public class CommandHandler {
// Show a command suggestion if available and the difference isn't too big
if (result.getDifference() < SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) {
sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/"
+ result.getCommandDescription() + ChatColor.YELLOW + "?");
// FIXME: Define a proper string representation of command description
sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD
+ CommandUtils.constructCommandPath(result.getCommandDescription()) + ChatColor.YELLOW + "?");
}
sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + result.getLabels().get(0)
@@ -175,9 +174,9 @@ public class CommandHandler {
List<String> remainingParts = parts.subList(1, parts.size());
CommandDescription childCommand = getSuitableChild(base, remainingParts);
if (childCommand != null) {
return new FoundCommandResult(childCommand, parts.subList(2, parts.size()), parts.subList(0, 2));
return new FoundCommandResult(childCommand, parts.subList(0, 2), parts.subList(2, parts.size()));
} else if (hasSuitableArgumentCount(base, remainingParts.size())) {
return new FoundCommandResult(base, parts.subList(1, parts.size()), parts.subList(0, 1));
return new FoundCommandResult(base, parts.subList(0, 1), parts.subList(1, parts.size()));
}
return getCommandWithSmallestDifference(base, parts);
@@ -200,13 +199,15 @@ public class CommandHandler {
// base command may have no children or no child label was present
if (closestCommand == null) {
return new FoundCommandResult(null, null, parts, minDifference, UNKNOWN_LABEL);
return new FoundCommandResult(null, parts, null, minDifference, UNKNOWN_LABEL);
}
FoundCommandResult.ResultStatus status = (minDifference == 0.0) ? INCORRECT_ARGUMENTS : UNKNOWN_LABEL;
FoundResultStatus status = (minDifference == 0.0) ? INCORRECT_ARGUMENTS : UNKNOWN_LABEL;
final int partsSize = parts.size();
List<String> labels = parts.subList(0, Math.min(closestCommand.getParentCount() + 1, partsSize));
List<String> arguments = parts.subList(Math.min(partsSize - 1, labels.size()), partsSize);
List<String> arguments = (labels.size() == partsSize)
? new ArrayList<String>()
: parts.subList(labels.size(), partsSize);
return new FoundCommandResult(closestCommand, labels, arguments, minDifference, status);
}
@@ -1,7 +1,6 @@
package fr.xephi.authme.command;
import com.google.common.collect.Lists;
import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.StringUtils;
import java.util.ArrayList;
@@ -25,7 +24,7 @@ public final class CommandUtils {
/**
* Provide a textual representation of a list of labels to show it as a command. For example, a list containing
* the items ["authme", "register", "player"] it will return "authme register player".
* the items ["authme", "register", "player"] will return "authme register player".
*
* @param labels The labels to format
*
@@ -4,17 +4,17 @@ import java.util.List;
/**
* Result of a command mapping by {@link CommandHandler}. An object of this class represents a successful mapping
* as well as erroneous ones, as communicated with {@link ResultStatus}.
* as well as erroneous ones, as communicated with {@link FoundResultStatus}.
* <p />
* Fields other than {@link ResultStatus} are available depending, among other factors, on the status:
* Fields other than {@link FoundResultStatus} are available depending, among other factors, on the status:
* <ul>
* <li>{@link ResultStatus#SUCCESS} entails that mapping the input to a command was successful. Therefore,
* <li>{@link FoundResultStatus#SUCCESS} entails that mapping the input to a command was successful. Therefore,
* the command description, labels and arguments are set. The difference is 0.0.</li>
* <li>{@link ResultStatus#INCORRECT_ARGUMENTS}: The received parts could be mapped to a command but the argument
* <li>{@link FoundResultStatus#INCORRECT_ARGUMENTS}: The received parts could be mapped to a command but the argument
* count doesn't match. Guarantees that the command description field is not null; difference is 0.0</li>
* <li>{@link ResultStatus#UNKNOWN_LABEL}: The labels could not be mapped to a command. The command description may
* be set to the most similar command, or it may be null. Difference is above 0.0.</li>
* <li>{@link ResultStatus#MISSING_BASE_COMMAND} should never occur. All other fields may be null and any further
* <li>{@link FoundResultStatus#UNKNOWN_LABEL}: The labels could not be mapped to a command. The command description
* may be set to the most similar command, or it may be null. Difference is above 0.0.</li>
* <li>{@link FoundResultStatus#MISSING_BASE_COMMAND} should never occur. All other fields may be null and any further
* processing of the object should be aborted.</li>
* </ul>
*/
@@ -24,38 +24,38 @@ public class FoundCommandResult {
* The command description instance.
*/
private final CommandDescription commandDescription;
/**
* The command arguments.
*/
private final List<String> arguments;
/**
* The labels used to invoke the command. This may be different for the same {@link ExecutableCommand} instance
* if multiple labels have been defined, e.g. "/authme register" and "/authme reg".
*/
private final List<String> labels;
/**
* The command arguments.
*/
private final List<String> arguments;
private final double difference;
private final ResultStatus resultStatus;
private final FoundResultStatus resultStatus;
/**
* Constructor.
*
* @param commandDescription The command description.
* @param labels The labels used to access the command.
* @param arguments The command arguments.
* @param labels The original query reference.
*/
public FoundCommandResult(CommandDescription commandDescription, List<String> arguments, List<String> labels,
double difference, ResultStatus resultStatus) {
public FoundCommandResult(CommandDescription commandDescription, List<String> labels, List<String> arguments,
double difference, FoundResultStatus resultStatus) {
this.commandDescription = commandDescription;
this.arguments = arguments;
this.labels = labels;
this.arguments = arguments;
this.difference = difference;
this.resultStatus = resultStatus;
}
public FoundCommandResult(CommandDescription commandDescription, List<String> arguments, List<String> labels) {
this(commandDescription, arguments, labels, 0.0, ResultStatus.SUCCESS);
public FoundCommandResult(CommandDescription commandDescription, List<String> labels, List<String> arguments) {
this(commandDescription, labels, arguments, 0.0, FoundResultStatus.SUCCESS);
}
public CommandDescription getCommandDescription() {
@@ -74,18 +74,8 @@ public class FoundCommandResult {
return difference;
}
public ResultStatus getResultStatus() {
public FoundResultStatus getResultStatus() {
return resultStatus;
}
public enum ResultStatus {
SUCCESS,
INCORRECT_ARGUMENTS,
UNKNOWN_LABEL,
MISSING_BASE_COMMAND
}
}
@@ -0,0 +1,16 @@
package fr.xephi.authme.command;
/**
* Result status for mapping command parts. See {@link FoundCommandResult} for a detailed description of the states.
*/
public enum FoundResultStatus {
SUCCESS,
INCORRECT_ARGUMENTS,
UNKNOWN_LABEL,
MISSING_BASE_COMMAND
}
@@ -5,6 +5,7 @@ import fr.xephi.authme.command.CommandHandler;
import fr.xephi.authme.command.CommandUtils;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.command.FoundCommandResult;
import fr.xephi.authme.command.FoundResultStatus;
import fr.xephi.authme.command.help.HelpProvider;
import fr.xephi.authme.permission.PermissionsManager;
import org.bukkit.ChatColor;
@@ -12,7 +13,9 @@ import org.bukkit.command.CommandSender;
import java.util.List;
import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.*;
import static fr.xephi.authme.command.FoundResultStatus.INCORRECT_ARGUMENTS;
import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND;
import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL;
public class HelpCommand extends ExecutableCommand {
@@ -27,8 +30,9 @@ public class HelpCommand extends ExecutableCommand {
// TODO ljacqu 20151213: This is essentially the same logic as in CommandHandler and we'd like to have the same
// messages. Maybe we can have another method in CommandHandler where the end command isn't executed upon
// success.
FoundCommandResult.ResultStatus resultStatus = foundCommandResult.getResultStatus();
FoundResultStatus resultStatus = foundCommandResult.getResultStatus();
if (MISSING_BASE_COMMAND.equals(resultStatus)) {
// FIXME something wrong - this error appears
sender.sendMessage(ChatColor.DARK_RED + "Could not get base command");
return;
} else if (INCORRECT_ARGUMENTS.equals(resultStatus) || UNKNOWN_LABEL.equals(resultStatus)) {
@@ -1,5 +1,6 @@
package fr.xephi.authme.command.help;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import fr.xephi.authme.command.CommandArgumentDescription;
@@ -216,11 +217,12 @@ public final class HelpProvider {
return (flag & options) != 0;
}
private static List<String> filterCorrectLabels(CommandDescription command, List<String> labels) {
@VisibleForTesting
protected static List<String> filterCorrectLabels(CommandDescription command, List<String> labels) {
List<CommandDescription> commands = new ArrayList<>(command.getParentCount() + 1);
CommandDescription currentCommand = command;
while (currentCommand != null) {
commands.add(command);
commands.add(currentCommand);
currentCommand = currentCommand.getParent();
}
commands = Lists.reverse(commands);