Skip to content
Open
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,37 @@
package picocli.annotation.processing.tests;

import com.google.testing.compile.Compilation;
import com.google.testing.compile.JavaFileObjects;
import org.junit.Test;

import javax.annotation.processing.Processor;

import static com.google.testing.compile.CompilationSubject.assertThat;
import static com.google.testing.compile.Compiler.javac;

public class Issue2430Test
{
@Test
public void testSpecInArgGroupClassUsedViaMixin() {
Processor processor = new AnnotatedCommandSourceGeneratorProcessor();
Compilation compilation =
javac()
.withProcessors(processor)
.compile(JavaFileObjects.forResource(
"picocli/issue2430/Main.java"));

assertThat(compilation).succeeded();
}

@Test
public void testSpecInArgGroupClassUsedDirectlyInCommand() {
Processor processor = new AnnotatedCommandSourceGeneratorProcessor();
Compilation compilation =
javac()
.withProcessors(processor)
.compile(JavaFileObjects.forResource(
"picocli/issue2430/SpecInArgGroup.java"));

assertThat(compilation).succeeded();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package picocli.issue2430;

import picocli.CommandLine;
import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Command;
import picocli.CommandLine.Mixin;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Option;
import picocli.CommandLine.ParameterException;
import picocli.CommandLine.Spec;

import java.util.concurrent.Callable;

@Command(name = "main")
class Main implements Callable<Integer> {

static class Options {
@Spec
CommandSpec spec;

int option1 = 1;
int option2 = 2;

@Option(names = "-o1")
void setOption1(int value) {
if (value > 10) {
throw new ParameterException(spec.commandLine(), "option1 must be <= 10");
}
this.option1 = value;
}

@Option(names = "-o2")
void setOption2(int value) {
if (value > 10) {
throw new ParameterException(spec.commandLine(), "option2 must be <= 10");
}
this.option2 = value;
}
}

static class SharedOptions {

@ArgGroup(exclusive = false, heading = "Shared options%n")
Options options = new Options();
}

@Mixin
SharedOptions sharedOptions = new SharedOptions();

@Override
public Integer call() throws Exception {
System.out.printf("Hello world: o1 = %s, o2 = %s%n",
sharedOptions.options.option1,
sharedOptions.options.option2
);
return 0;
}

public static void main(String[] args) {
int exitCode = new CommandLine(new Main()).execute(args);
System.exit(exitCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package picocli.issue2430;

import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Command;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Option;
import picocli.CommandLine.Spec;

@Command(name = "spec-in-arggroup")
class SpecInArgGroup {

static class Options {
@Spec
CommandSpec spec;

@Option(names = "-x")
int x;
}

@ArgGroup(exclusive = false)
Options options = new Options();
}
Original file line number Diff line number Diff line change
Expand Up @@ -929,23 +929,9 @@ private void connectModel(AbstractCommandSpecProcessor proc) {
logger.fine("Adding " + entry + " to commandSpec " + commandSpec1);
commandSpec1.addSpecElement(entry.getValue());
} else {
Element enclosingElement = entry.getKey().getEnclosingElement();
if (enclosingElement.getKind() == ElementKind.CLASS || enclosingElement.getKind() == ENUM) {
TypeMirror typeMirror = enclosingElement.asType();
TypeElement typeElement = (TypeElement) ((DeclaredType) typeMirror).asElement();
List<? extends TypeMirror> interfaces = typeElement.getInterfaces();
boolean valid = false;
for (TypeMirror interf : interfaces) {
if (interf.toString().equals("picocli.CommandLine.IVersionProvider")) {
valid = true;
}
}
if (!valid) {
proc.error(entry.getKey(), "@Spec must be enclosed in a @Command, or in a class that implements IVersionProvider but was %s: %s", entry.getKey().getEnclosingElement(), entry.getKey().getEnclosingElement().getSimpleName());
}
} else {
proc.error(entry.getKey(), "@Spec must be enclosed in a @Command, but was %s: %s", entry.getKey().getEnclosingElement(), entry.getKey().getEnclosingElement().getSimpleName());
}
// #2430 @Spec is also valid outside a @Command, for example in ArgGroup classes
// or in IVersionProvider implementations; picocli injects the CommandSpec at runtime
logger.fine("Not adding " + entry + " to any commandSpec: enclosing element " + entry.getKey().getEnclosingElement() + " is not a @Command");
}
}
for (Map.Entry<Element, IAnnotatedElement> entry : parentCommandElements.entrySet()) {
Expand Down