🐛 Annotations API fix

Annotations API fix failure when a literal name matches an argument name (#143)
This commit is contained in:
Irmo van den Berge 2020-11-29 15:31:04 +01:00 committed by Alexander Söderberg
parent 013d2d61f4
commit 9e48a41eab
2 changed files with 26 additions and 15 deletions

View file

@ -55,7 +55,6 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -261,7 +260,7 @@ public final class AnnotationParser<C> {
for (final CommandMethodPair commandMethodPair : methodPairs) { for (final CommandMethodPair commandMethodPair : methodPairs) {
final CommandMethod commandMethod = commandMethodPair.getCommandMethod(); final CommandMethod commandMethod = commandMethodPair.getCommandMethod();
final Method method = commandMethodPair.getMethod(); final Method method = commandMethodPair.getMethod();
final LinkedHashMap<String, SyntaxFragment> tokens = this.syntaxParser.apply(commandMethod.value()); final List<SyntaxFragment> tokens = this.syntaxParser.apply(commandMethod.value());
/* Determine command name */ /* Determine command name */
final String commandToken = commandMethod.value().split(" ")[0].split("\\|")[0]; final String commandToken = commandMethod.value().split(" ")[0].split("\\|")[0];
@SuppressWarnings("rawtypes") final CommandManager manager = this.manager; @SuppressWarnings("rawtypes") final CommandManager manager = this.manager;
@ -274,7 +273,7 @@ public final class AnnotationParser<C> {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
Command.Builder builder = manager.commandBuilder( Command.Builder builder = manager.commandBuilder(
commandToken, commandToken,
tokens.get(commandToken).getMinor(), tokens.get(0).getMinor(),
metaBuilder.build() metaBuilder.build()
); );
final Collection<ArgumentParameterPair> arguments = this.argumentExtractor.apply(method); final Collection<ArgumentParameterPair> arguments = this.argumentExtractor.apply(method);
@ -285,7 +284,7 @@ public final class AnnotationParser<C> {
for (final ArgumentParameterPair argumentPair : arguments) { for (final ArgumentParameterPair argumentPair : arguments) {
final CommandArgument<C, ?> argument = this.buildArgument( final CommandArgument<C, ?> argument = this.buildArgument(
method, method,
tokens.get(argumentPair.getArgument().value()), this.findSyntaxFragment(tokens, argumentPair.getArgument().value()),
argumentPair argumentPair
); );
commandArguments.put(argument.getName(), argument); commandArguments.put(argument.getName(), argument);
@ -293,19 +292,19 @@ public final class AnnotationParser<C> {
} }
boolean commandNameFound = false; boolean commandNameFound = false;
/* Build the command tree */ /* Build the command tree */
for (final Map.Entry<String, SyntaxFragment> entry : tokens.entrySet()) { for (final SyntaxFragment token : tokens) {
if (!commandNameFound) { if (!commandNameFound) {
commandNameFound = true; commandNameFound = true;
continue; continue;
} }
if (entry.getValue().getArgumentMode() == ArgumentMode.LITERAL) { if (token.getArgumentMode() == ArgumentMode.LITERAL) {
builder = builder.literal(entry.getKey(), entry.getValue().getMinor().toArray(new String[0])); builder = builder.literal(token.getMajor(), token.getMinor().toArray(new String[0]));
} else { } else {
final CommandArgument<C, ?> argument = commandArguments.get(entry.getKey()); final CommandArgument<C, ?> argument = commandArguments.get(token.getMajor());
if (argument == null) { if (argument == null) {
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
"Found no mapping for argument '%s' in method '%s'", "Found no mapping for argument '%s' in method '%s'",
entry.getKey(), method.getName() token.getMajor(), method.getName()
)); ));
} }
@ -372,6 +371,19 @@ public final class AnnotationParser<C> {
return commands; return commands;
} }
private @NonNull SyntaxFragment findSyntaxFragment(
final @NonNull List<@NonNull SyntaxFragment> fragments,
final @NonNull String argumentName
) {
for (SyntaxFragment fragment : fragments) {
if (fragment.getArgumentMode() != ArgumentMode.LITERAL
&& fragment.getMajor().equals(argumentName)) {
return fragment;
}
}
throw new IllegalArgumentException("Argument is not declared in syntax: " + argumentName);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private @NonNull CommandArgument<C, ?> buildArgument( private @NonNull CommandArgument<C, ?> buildArgument(
final @NonNull Method method, final @NonNull Method method,

View file

@ -27,7 +27,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.function.Function; import java.util.function.Function;
@ -37,7 +36,7 @@ import java.util.regex.Pattern;
/** /**
* Parses command syntax into syntax fragments * Parses command syntax into syntax fragments
*/ */
final class SyntaxParser implements Function<@NonNull String, @NonNull LinkedHashMap<@NonNull String, @NonNull SyntaxFragment>> { final class SyntaxParser implements Function<@NonNull String, @NonNull List<@NonNull SyntaxFragment>> {
private static final Predicate<String> PATTERN_ARGUMENT_LITERAL = Pattern.compile("([A-Za-z0-9]+)(|([A-Za-z0-9]+))*") private static final Predicate<String> PATTERN_ARGUMENT_LITERAL = Pattern.compile("([A-Za-z0-9]+)(|([A-Za-z0-9]+))*")
.asPredicate(); .asPredicate();
@ -47,9 +46,9 @@ final class SyntaxParser implements Function<@NonNull String, @NonNull LinkedHas
.asPredicate(); .asPredicate();
@Override @Override
public @NonNull LinkedHashMap<@NonNull String, @NonNull SyntaxFragment> apply(final @NonNull String syntax) { public @NonNull List<@NonNull SyntaxFragment> apply(final @NonNull String syntax) {
final StringTokenizer stringTokenizer = new StringTokenizer(syntax, " "); final StringTokenizer stringTokenizer = new StringTokenizer(syntax, " ");
final LinkedHashMap<String, SyntaxFragment> map = new LinkedHashMap<>(); final List<SyntaxFragment> syntaxFragments = new ArrayList<>();
while (stringTokenizer.hasMoreTokens()) { while (stringTokenizer.hasMoreTokens()) {
final String token = stringTokenizer.nextToken(); final String token = stringTokenizer.nextToken();
String major; String major;
@ -70,9 +69,9 @@ final class SyntaxParser implements Function<@NonNull String, @NonNull LinkedHas
} else { } else {
throw new IllegalArgumentException(String.format("Unrecognizable syntax token '%s'", syntax)); throw new IllegalArgumentException(String.format("Unrecognizable syntax token '%s'", syntax));
} }
map.put(major, new SyntaxFragment(major, minor, mode)); syntaxFragments.add(new SyntaxFragment(major, minor, mode));
} }
return map; return syntaxFragments;
} }
} }