Skip to content

Commit

Permalink
[#1137] Fix ClassCastException in annotation processor when an option…
Browse files Browse the repository at this point in the history
… has completionCandidates

Closes #1137
  • Loading branch information
remkop committed Jul 29, 2020
1 parent 40e2a52 commit 6731959
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 11 deletions.
1 change: 1 addition & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Picocli follows [semantic versioning](http://semver.org/).
* [#1124] Enhancement: automatically generate a better summary in the `AutoComplete.GenerateCompletion` generated man page.
* [#1126] Enhancement: Make picocli trace levels case-insensitive.
* [#1128] Enhancement: `ParameterException` caused by `TypeConversionException` now have their cause exception set.
* [#1137] Bugfix: The `picocli-codegen` annotation processor causes the build to fail with a `ClassCastException` when an option has `completionCandidates` defined.
* [#1127] DOC: Custom ShortErrorMessageHandler manual example should use bold red for error message.
* [#1130] DOC: Clarify how to run picocli-based applications.
* [#1131] DOC: Add anchor links before section titles in user manual.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,15 +225,8 @@ private void printArg(ArgSpec arg, PrintWriter pw, String indent) {
}

private String iter(Iterable<String> iterable) {
if (iterable == null) { return "null"; }
StringBuilder sb = new StringBuilder();
sb.append("[");
String sep = "";
for (String str : iterable) {
sb.append(sep).append(str);
sep = ", ";
}
return sb.append("]").toString();
// cannot list actual completion candidates: class cannot be instantiated at compile time
return String.valueOf(iterable);
}

@Command(name = "CommandSpecYamlPrinter", mixinStandardHelpOptions = true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
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 javax.tools.StandardLocation;

import static com.google.testing.compile.CompilationSubject.assertThat;
import static com.google.testing.compile.Compiler.javac;
import static picocli.annotation.processing.tests.Resources.slurp;
import static picocli.annotation.processing.tests.YamlAssert.compareCommandYamlDump;

public class Issue1137Test {
@Test
public void testIssue1137() {
Processor processor = new AnnotatedCommandSourceGeneratorProcessor();
Compilation compilation =
javac()
.withProcessors(processor)
.compile(JavaFileObjects.forResource(
"picocli/issue1137/Issue1137.java"));

assertThat(compilation).succeeded();
}

@Test
public void testIssue1137Details() {

Compilation compilation = compareCommandYamlDump(slurp("/picocli/issue1137/Issue1137.yaml"),
JavaFileObjects.forResource("picocli/issue1137/Issue1137.java"));

assertOnlySourceVersionWarning(compilation);
}

private void assertOnlySourceVersionWarning(Compilation compilation) {
assertThat(compilation).hadWarningCount(0); // #826 version warnings are now suppressed
// assertThat(compilation).hadWarningContaining("Supported source version 'RELEASE_6' from annotation processor 'picocli.annotation.processing.tests");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package picocli.issue1137;

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

import java.util.Arrays;
import java.util.ArrayList;
import java.util.UUID;
import java.util.concurrent.Callable;

@Command(name = "top",
version = {"test 1.0"},
resourceBundle = "mybundle5")
public class Issue1137 implements Callable<Integer> {

@CommandLine.Option(names = "--level",
description = "Level.",
defaultValue = "OFF",
showDefaultValue = CommandLine.Help.Visibility.ALWAYS,
completionCandidates = LevelCompletion.class)
private String level;

@Spec
CommandSpec spec;

@Override
public Integer call() throws Exception {
return 0;
}

public static class LevelCompletion extends ArrayList<String> {
public LevelCompletion() {
super(Arrays.asList("OFF", "INFO", "WARN"));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
CommandSpec:
name: 'top'
aliases: []
userObject: picocli.issue1137.Issue1137
helpCommand: false
defaultValueProvider: null
versionProvider: null
version: [test 1.0]
ArgGroups: []
Options:
- names: [--level]
usageHelp: false
versionHelp: false
description: [Level.]
descriptionKey: ''
typeInfo: CompileTimeTypeInfo(java.lang.String, aux=[java.lang.String], collection=false, map=false)
arity: 1
splitRegex: ''
interactive: false
required: false
hidden: false
hideParamSyntax: false
defaultValue: 'OFF'
showDefaultValue: ALWAYS
hasInitialValue: false
initialValue: 'null'
paramLabel: '<level>'
converters: []
completionCandidates: CompletionCandidatesMetaData(picocli.issue1137.Issue1137.LevelCompletion)
getter: AnnotatedElementHolder(FIELD level in picocli.issue1137.Issue1137)
setter: AnnotatedElementHolder(FIELD level in picocli.issue1137.Issue1137)
PositionalParams: []
UnmatchedArgsBindings: []
Mixins: []
UsageMessageSpec:
width: 80
abbreviateSynopsis: false
hidden: false
showDefaultValues: false
sortOptions: true
requiredOptionMarker: ' '
headerHeading: ''
header: []
synopsisHeading: 'Usage: '
customSynopsis: []
descriptionHeading: ''
description: []
parameterListHeading: ''
optionListHeading: ''
commandListHeading: 'Commands:%n'
footerHeading: ''
footer: []
ParserSpec:
separator: '='
endOfOptionsDelimiter: '--'
expandAtFiles: true
atFileCommentChar: '#'
overwrittenOptionsAllowed: false
unmatchedArgumentsAllowed: false
unmatchedOptionsArePositionalParams: false
stopAtUnmatched: false
stopAtPositional: false
posixClusteredShortOptionsAllowed: true
aritySatisfiedByAttachedOptionParam: false
caseInsensitiveEnumValuesAllowed: false
collectErrors: false
limitSplit: false
toggleBooleanFlags: false
Subcommands: []
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static Iterable<String> extract(Element element) {
for (ExecutableElement attribute : elementValues.keySet()) {
if ("completionCandidates".equals(attribute.getSimpleName().toString())) {
AnnotationValue typeMirror = elementValues.get(attribute);
return new CompletionCandidatesMetaData((TypeMirror) typeMirror);
return new CompletionCandidatesMetaData((TypeMirror) typeMirror.getValue());
}
}
}
Expand Down Expand Up @@ -72,7 +72,7 @@ public TypeElement getTypeElement() {
/** Always returns {@code null}. */
@Override
public Iterator<String> iterator() {
return null;
throw new UnsupportedOperationException("Cannot instantiate " + typeMirror + " at compile time.");
}

/**
Expand Down

0 comments on commit 6731959

Please sign in to comment.