Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-363 Refactor and fix multiple suggestion resolving. #365

Merged
merged 1 commit into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package dev.rollczi.litecommands.annotations.argument.resolver;

import dev.rollczi.litecommands.annotations.LiteConfig;
import dev.rollczi.litecommands.annotations.LiteTestSpec;
import dev.rollczi.litecommands.annotations.argument.Arg;
import dev.rollczi.litecommands.annotations.command.Command;
import dev.rollczi.litecommands.annotations.execute.Execute;
import dev.rollczi.litecommands.argument.Argument;
import dev.rollczi.litecommands.argument.parser.ParseResult;
import dev.rollczi.litecommands.argument.resolver.MultipleArgumentResolver;
import dev.rollczi.litecommands.argument.resolver.standard.NumberArgumentResolver;
import dev.rollczi.litecommands.input.raw.RawInput;
import dev.rollczi.litecommands.invocation.Invocation;
import dev.rollczi.litecommands.range.Range;
import dev.rollczi.litecommands.suggestion.Suggestion;
import dev.rollczi.litecommands.suggestion.SuggestionContext;
import dev.rollczi.litecommands.suggestion.SuggestionResult;
import dev.rollczi.litecommands.unit.TestSender;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;

public class MultipleResolverSuggestionsTest extends LiteTestSpec {

static TestResolver<TestSender> resolver = new TestResolver<>();

static class TestResolver<SENDER> implements MultipleArgumentResolver<SENDER, String> {

private Suggestion lastSuggestion;

@Override
public ParseResult<String> parse(Invocation<SENDER> invocation, Argument<String> argument, RawInput rawInput) {
return ParseResult.success(rawInput.next() + " " + rawInput.next());
}

@Override
public Range getRange(Argument<String> stringArgument) {
return Range.range(1, 2);
}

@Override
public SuggestionResult suggest(Invocation<SENDER> invocation, Argument<String> argument, SuggestionContext context) {
lastSuggestion = context.getCurrent();
return SuggestionResult.empty();
}

}

static LiteConfig config = builder -> builder
.argument(String.class, resolver);

@Command(name = "test")
static class TestCommand {

@Execute
void test(@Arg String one, @Arg String two) {
}

@Execute(name = "int")
void test(@Arg int one, @Arg String two) {
}

@Execute(name = "int-reverse")
void test(@Arg String two, @Arg int one) {
}


}

@Test
@Order(0)
void testOneArgument() {
platform.suggest("test first second");
assertThat(resolver.lastSuggestion.multilevel()).isEqualTo("first second");
}

@Test
@Order(1)
void testTwoArguments() {
platform.suggest("test first second thrid fourth");
assertThat(resolver.lastSuggestion.multilevel()).isEqualTo("thrid fourth");
}

@Test
@Order(2)
void testMixedArguments() {
platform.suggest("test int 0 int-first int-second");
assertThat(resolver.lastSuggestion.multilevel()).isEqualTo("int-first int-second");

platform.suggest("test int-reverse first second ")
.assertAsSuggester(NumberArgumentResolver.ofInteger(), "");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ public class Context<SENDER, T> {

private final Parser<SENDER, RawInput, T> parser;
private final Argument<T> argument;
private final int argumentMinCount;
private final int argumentMaxCount;
private final int realArgumentMaxCount;
private final boolean potentialLastArgument;
private final int realArgumentMinCount;

public Context(
Invocation<SENDER> invocation,
Expand All @@ -83,15 +84,10 @@ public Context(
this.parser = parserSet.getValidParserOrThrow(RawInput.class, invocation, argument);
Range range = parser.getRange(argument);

this.argumentMaxCount = range.getMin() + pivotPosition;
this.realArgumentMaxCount = calculateMaxArguments(rawArguments, range, pivotPosition);
int potentialMax = range.getMax() + pivotPosition;

if (potentialMax < 0) { // because Integer.MAX_VALUE + x = Integer.MIN_VALUE (x > 0)
potentialMax = Integer.MAX_VALUE;
}

this.potentialLastArgument = this.realArgumentMaxCount < potentialMax;
this.argumentMinCount = range.getMin() + pivotPosition;
this.argumentMaxCount = calculateMaxCount(range);
this.realArgumentMinCount = Math.min(argumentMinCount, rawArguments.size());
this.realArgumentMaxCount = calculateRealMaxCount(rawArguments, range, pivotPosition);
}

public ParseResult<T> parseArgument(Invocation<SENDER> invocation) {
Expand All @@ -105,23 +101,23 @@ public ParseResult<T> parseArgument(Invocation<SENDER> invocation) {
}

public boolean isLastRawArgument() {
return pivotPosition == rawArguments.size() - 1 || argumentMaxCount == rawArguments.size();
return pivotPosition == rawArguments.size() - 1 || realArgumentMaxCount >= rawArguments.size();
}

public boolean isParsedLast() {
return pivotPosition == rawArguments.size();
public boolean isMissingFullArgument() {
return isNoMoreArguments() && isMissingPartOfArgument();
}

public boolean isMissingFullArgument() {
return !hasNextRoute() && argumentMaxCount > rawArguments.size();
public boolean isNoMoreArguments() {
return pivotPosition >= rawArguments.size();
}

public boolean isMissingPartOfArgument() {
return argumentMaxCount > rawArguments.size();
return argumentMinCount != realArgumentMinCount;
}

public boolean isPotentialLastArgument() {
return potentialLastArgument;
return this.realArgumentMaxCount < this.argumentMaxCount;
}

public List<String> getAllNotConsumedArguments() {
Expand All @@ -130,12 +126,20 @@ public List<String> getAllNotConsumedArguments() {

}

private static int calculateMaxArguments(List<String> rawArguments, Range range, int routePosition) {
private static int calculateRealMaxCount(List<String> rawArguments, Range range, int routePosition) {
int maxArguments = range.getMax() == Integer.MAX_VALUE
? rawArguments.size()
: routePosition + range.getMax();

return Math.min(maxArguments, rawArguments.size());
}

private int calculateMaxCount(Range range) {
if (range.getMax() == Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}

return range.getMax() + pivotPosition;
}

}