Skip to content

Commit

Permalink
[#2270] Custom type converter for primitive boolean options should …
Browse files Browse the repository at this point in the history
…not be ignored
  • Loading branch information
remkop committed May 6, 2024
1 parent fa33be1 commit c825d20
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 6 deletions.
4 changes: 2 additions & 2 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).
`PropertiesDefaultProvider` now tries to load properties from the classpath if the file cannot be found in the user.home directory.



## <a name="4.7.6-fixes"></a> Fixed issues

* [#2102][#2107] Enhancement: `PropertiesDefaultProvider` should try to load properties from classpath (last). Thanks to [Lumír Návrat](https://github.com/rimuln) for the pull request.
* [#2202] Enhancement: Change log level from WARN to INFO when bean not found in ApplicationContext. Thanks to [Desmond Kirrane](https://github.com/dkirrane) for raising this.
* [#2248] Enhancement: Don't show hidden commands in JLine3 command description. Thanks to [Reinhard Handler](https://github.com/rehand) for the pull request.
* [#2170] Enhancement: Use `...` vararg instead of array parameter to match overridden method signature. Thanks to [Michael Vorburger](https://github.com/vorburger) for the pull request.
* [#2058] Bugfix: `defaultValue` should not be applied in addition to user-specified value for options with a custom `IParameterConsumer`. Thanks to [Staffan Arvidsson McShane](https://github.com/StaffanArvidsson) for raising this.
* [#2148] Bugfix: Fix NPE in jline3 `Example.jar` as `ConfigurationPath` cannot be `null` anymore. Thanks to [llzen44](https://github.com/llzen44) for the pull request.
* [#2232] Bugfix: fix bug for `Optional<T>` arguments with initial value. Thanks to [hq6](https://github.com/hq6) for raising this.
* [#2149] Bugfix: `@Option`-annotated setter method not invoked with default value when used in mixin for both command and subcommand. Thanks to [Zhonghao Wang](https://github.com/JBWKZsf) for raising this.
* [#2170] Enhancement: Use `...` vararg instead of array parameter to match overridden method signature. Thanks to [Michael Vorburger](https://github.com/vorburger) for the pull request.
* [#2270] Bugfix: Custom type converter for primitive `boolean` options should not be ignored. Thanks to [Sven Kammerer](https://codeberg.org/sven.k) for raising this.
* [#2234] BUILD: fix errorprone `TruthSelfEquals` warnings
* [#2172] BUILD: Fix broken build. Thanks to [Michael Vorburger](https://github.com/vorburger) for the pull request.
* [#2174] BUILD: Fix .gitattributes related CR/LF problems. Thanks to [Michael Vorburger](https://github.com/vorburger) for the pull request.
Expand Down
5 changes: 2 additions & 3 deletions picocli-tests-java8/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ test {

dependencies {
api rootProject
testImplementation supportDependencies.junit5Api
testRuntimeOnly supportDependencies.junit5Engine
testImplementation supportDependencies.systemLambda
testImplementation supportDependencies.junit
testImplementation supportDependencies.hamcrestCore
}

jar {
Expand Down
78 changes: 78 additions & 0 deletions picocli-tests-java8/src/test/java/picocli/Issue2270.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package picocli;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import picocli.CommandLine.ITypeConverter;
import picocli.CommandLine.Option;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.*;

public class Issue2270 {
static class CmdObjectBoolean {
@Option(names = "--test-Boolean", defaultValue = "dHJ1ZQ==" /* base64-encoded 'true' */)
Boolean testBoolean;
}
static class CmdPrimitiveBoolean {
@Option(names = "--test-boolean", defaultValue = "dHJ1ZQ==" /* base64-encoded 'true' */)
boolean testboolean;
}

static class Base64BooleanTypeConverter implements ITypeConverter<Boolean> {

static List<String> invocations = new ArrayList<>();

public Boolean convert(String value) {
invocations.add(value);
System.out.printf("converter invocation %s: called with value %s%n",
invocations.size(), value);
if (Boolean.parseBoolean(value)) {
return true;
}
return Boolean.parseBoolean(new String(Base64.getDecoder().decode(value)));
}
}

@Before
public void beforeTests() {
CommandLine.tracer().setLevel(CommandLine.TraceLevel.DEBUG);
}

@After
public void afterTests() {
CommandLine.tracer().setLevel(CommandLine.TraceLevel.WARN);
}

@Test
public void testObjectBoolean() {
Base64BooleanTypeConverter.invocations.clear();
CmdObjectBoolean cmd = new CmdObjectBoolean();
new CommandLine(cmd)
.registerConverter(Boolean.class, new Base64BooleanTypeConverter())
.parseArgs();
assertThat(Base64BooleanTypeConverter.invocations.size(), greaterThanOrEqualTo(1));
assertEquals(Arrays.asList("dHJ1ZQ==", "true"), Base64BooleanTypeConverter.invocations);

assertTrue(cmd.testBoolean);
}

@Test
public void testPrimitiveBoolean() {
Base64BooleanTypeConverter.invocations.clear();
CmdPrimitiveBoolean cmd = new CmdPrimitiveBoolean();
new CommandLine(cmd)
.registerConverter(Boolean.TYPE, new Base64BooleanTypeConverter())
.parseArgs();
assertThat(Base64BooleanTypeConverter.invocations.size(), greaterThanOrEqualTo(1));
assertEquals(Arrays.asList("dHJ1ZQ==", "true"), Base64BooleanTypeConverter.invocations);

assertTrue(cmd.testboolean);
}
}
2 changes: 1 addition & 1 deletion src/main/java/picocli/CommandLine.java
Original file line number Diff line number Diff line change
Expand Up @@ -14910,7 +14910,7 @@ private boolean booleanValue(ArgSpec argSpec, Object value) {
}
String stringValue = String.valueOf(value);
if (empty(stringValue) || "null".equals(stringValue) || "Optional.empty".equals(value)) { return false; }
ITypeConverter<?> converter = getTypeConverter(new Class<?>[]{Boolean.class}, argSpec, 0);
ITypeConverter<?> converter = getTypeConverter(argSpec.auxiliaryTypes(), argSpec, 0);
return (Boolean) tryConvert(argSpec, -1, converter, stringValue, 0);
}

Expand Down

0 comments on commit c825d20

Please sign in to comment.