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

Arguments and options are not passed in correct order to method subcommands #1774

Closed
Onedy opened this issue Aug 11, 2022 · 4 comments
Closed
Labels
status: duplicate 👨🏻‍🤝‍👨🏻 A duplicate of another issue theme: parser An issue or change related to the parser type: bug 🐛
Milestone

Comments

@Onedy
Copy link

Onedy commented Aug 11, 2022

I have a method subcommand in a class subcommand which is added to the main command by commandLine.addSubcommand().
This is my method:

    @Command(name = "subcommand")
    void start(@Option(names = "-r", arity = "0") boolean optionR,
               @Option(names = "-s", arity = "0") boolean optionS,
               @Parameters(arity = "1") String url) {
        System.out.println("Everything OK");
    }

and the command: "test", "subcommand", "-r", "-s", "URL"

The issue is that arguments are passed in wrong order: string, boolean, boolean

Minimal working example:
PicocliTest.zip
Just unzip and run with ./gradlew clean assemble :test --tests "test.MyTest" --info

And look at: java.lang.IllegalArgumentException: argument type mismatch
As you can see, the parsed args are passed in wrong order:
image

In the other hand, if I define the method as follows (with only one option):

    @Command(name = "subcommand")
    void start(@Option(names = "-r", arity = "0") boolean optionR,
               @Parameters(arity = "1") String url) {
        System.out.println("Everything OK");
    }

and I execute the command: "test", "subcommand", "-r", "URL"
the method is called with boolean, boolean instead of boolean, String

@Onedy
Copy link
Author

Onedy commented Aug 11, 2022

The first case may be related to #1741, but the second case may be not.

@Onedy
Copy link
Author

Onedy commented Aug 11, 2022

Also if I define the method as follows:

    @Command(name = "subcommand")
    void start(@Parameters(arity = "1") String url,
               @Option(names = "-r", arity = "0") boolean optionR,
               @Option(names = "-s", arity = "0") boolean optionS,) {
        System.out.println("Everything OK");
    }

and I execute the command: "test", "subcommand", "URL", "-r", "-s"
the method is called with:
image
instead of "URL", true, true

@remkop
Copy link
Owner

remkop commented Aug 12, 2022

@Onedy I assume this is all with picocli 4.6.3, but does this issue still occur with the latest picocli main branch? (since that has the fix for #1741)

I won't be able to look at this in detail today.

@remkop remkop added this to the 4.7 milestone Aug 12, 2022
@remkop remkop added type: bug 🐛 theme: parser An issue or change related to the parser labels Aug 18, 2022
remkop added a commit that referenced this issue Aug 21, 2022
@remkop
Copy link
Owner

remkop commented Aug 21, 2022

Thank you for the project to reproduce the problem.
I created an equivalent test that does not use Spring:

package test;

import org.junit.jupiter.api.Test;
import picocli.CommandLine;
import picocli.CommandLine.*;

import static org.junit.jupiter.api.Assertions.*;
import static picocli.CommandLine.ScopeType.INHERIT;

/**
 * https://github.com/remkop/picocli/issues/1774
 */
public class Issue1774 {
    public CommandLine getTestCommandLine(ParentTestCommand parentCommand, TestCommand testCommand, IFactory factory) {
        CommandLine commandLine = new CommandLine(parentCommand, factory);
        commandLine.addSubcommand(testCommand);
        return commandLine;
    }
    @Command(name = "parentTestCommand", mixinStandardHelpOptions = true, scope = INHERIT)
    static class ParentTestCommand {
    }

    @Command(name = "parentTestCommand", mixinStandardHelpOptions = true, scope = INHERIT,
            subcommands = TestCommand.class)
    static class ParentTestCommand2 {
    }

    @Command(name = "test")
    class TestCommand {
        @Command(name = "subcommand")
        void start(@Option(names = "-r", arity = "0") boolean optionR,
                   @Option(names = "-s", arity = "0") boolean optionS,
                   @Parameters(arity = "1") String url) {
            System.out.println("Everything OK");
        }
    }
    @Test
    void testIssue1774() {
        CommandLine commandLine = getTestCommandLine(new ParentTestCommand(), new TestCommand(), CommandLine.defaultFactory());
        assertEquals(0, commandLine.execute("test", "subcommand", "-r", "-s", "URL"));
    }
}

This test fails with picocli 4.6.3, as demonstrated when I add it to the PicocliTest.zip project you provided:

Issue1774 > testIssue1774() FAILED
    org.opentest4j.AssertionFailedError at Issue1774.java:40  <--- test fails with picocli 4.6.3

MyTest > testIssue1774() FAILED
    org.opentest4j.AssertionFailedError at PicocliTest.java:26

2 tests completed, 2 failed

> Task :test FAILED

FAILURE: Build failed with an exception.

However, the test succeeds when I run it with the latest main.
So, I believe that the fix for #1741 also fixes this issue.

@remkop remkop closed this as completed Aug 21, 2022
@remkop remkop added the status: duplicate 👨🏻‍🤝‍👨🏻 A duplicate of another issue label Aug 21, 2022
remkop added a commit that referenced this issue Aug 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: duplicate 👨🏻‍🤝‍👨🏻 A duplicate of another issue theme: parser An issue or change related to the parser type: bug 🐛
Projects
None yet
Development

No branches or pull requests

2 participants