Skip to content

Commit

Permalink
add options parseOrExitMethodAcceptsList and enableAtFileExpansion
Browse files Browse the repository at this point in the history
  • Loading branch information
h908714124 committed Apr 30, 2023
1 parent 7655e95 commit 4def472
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 31 deletions.
20 changes: 20 additions & 0 deletions compiler/src/main/java/net/jbock/processor/SourceElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@ boolean isSkipGeneratingParseOrExitMethod() {
SuperCommand::skipGeneratingParseOrExitMethod);
}

boolean isParseOrExitMethodAcceptsList() {
return command.fold(
Command::parseOrExitMethodAcceptsList,
SuperCommand::parseOrExitMethodAcceptsList);
}

boolean isEnableAtFileExpansion() {
return command.fold(
Command::enableAtFileExpansion,
SuperCommand::enableAtFileExpansion);
}

String[] getDescription() {
return command.fold(
Command::description,
Expand Down Expand Up @@ -150,4 +162,12 @@ public List<String> description() {
public boolean skipGeneratingParseOrExitMethod() {
return command.isSkipGeneratingParseOrExitMethod();
}

public boolean parseOrExitMethodAcceptsList() {
return command.isParseOrExitMethodAcceptsList();
}

public boolean enableAtFileExpansion() {
return command.isEnableAtFileExpansion();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,12 @@ final List<Mapping<?>> allMappings() {
final boolean isSuperCommand() {
return commandRepresentation.sourceElement().isSuperCommand();
}

final boolean parseOrExitMethodAcceptsList() {
return commandRepresentation.sourceElement().parseOrExitMethodAcceptsList();
}

final boolean enableAtFileExpansion() {
return commandRepresentation.sourceElement().enableAtFileExpansion();
}
}
45 changes: 33 additions & 12 deletions compiler/src/main/java/net/jbock/writing/ParseOrExitMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
import net.jbock.util.AtFileError;
import net.jbock.util.ParseRequest;

import java.util.List;

import static io.jbock.javapoet.MethodSpec.methodBuilder;
import static io.jbock.javapoet.ParameterSpec.builder;
import static net.jbock.common.Constants.LIST_OF_STRING;
import static net.jbock.common.Constants.STRING;

final class ParseOrExitMethod extends HasCommandRepresentation {
Expand All @@ -33,26 +36,44 @@ final class ParseOrExitMethod extends HasCommandRepresentation {

MethodSpec define() {

ParameterSpec args = builder(ArrayTypeName.of(STRING), "args").build();
ParameterSpec args = parseOrExitMethodAcceptsList() ?
builder(LIST_OF_STRING, "args").build() :
builder(ArrayTypeName.of(STRING), "args").build();
ParameterSpec notSuccess = builder(generatedTypes.parseResultType(), "failure").build();
ParameterSpec err = builder(AtFileError.class, "err").build();

CodeBlock.Builder code = CodeBlock.builder();
code.beginControlFlow("if ($1N.length > 0 && $2S.equals($1N[0]))", args, "--help")
.add("$T.builder().build()\n", StandardErrorHandler.class).indent()
if (parseOrExitMethodAcceptsList()) {
code.beginControlFlow("if (!$1N.isEmpty() && $2S.equals($1N.get(0)))", args, "--help");
} else {
code.beginControlFlow("if ($1N.length > 0 && $2S.equals($1N[0]))", args, "--help");
}
code.add("$T.builder().build()\n", StandardErrorHandler.class).indent()
.add(".printUsageDocumentation($N());\n", createModelMethod.get()).unindent()
.addStatement("$T.exit(0)", System.class)
.endControlFlow();

code.add("return $T.from($N).expand()\n", ParseRequest.class, args).indent()
.add(".mapLeft($1N -> $1N.addModel($2N()))\n", err, createModelMethod.get())
.add(".flatMap(this::$N)\n", parseMethod.get())
.add(".orElseThrow($N -> {\n", notSuccess).indent()
.addStatement("$T.builder().build().printErrorMessage($N)",
StandardErrorHandler.class, notSuccess)
.addStatement("$T.exit(1)", System.class)
.addStatement("return new $T()", RuntimeException.class).unindent()
.addStatement("})").unindent();
if (enableAtFileExpansion()) {
code.add("return $T.from($N).expand()\n", ParseRequest.class, args).indent()
.add(".mapLeft($1N -> $1N.addModel($2N()))\n", err, createModelMethod.get())
.add(".flatMap(this::$N)\n", parseMethod.get())
.add(".orElseThrow($N -> {\n", notSuccess).indent()
.addStatement("$T.builder().build().printErrorMessage($N)",
StandardErrorHandler.class, notSuccess)
.addStatement("$T.exit(1)", System.class)
.addStatement("return new $T()", RuntimeException.class).unindent()
.addStatement("})").unindent();
} else {
CodeBlock pArgs = parseOrExitMethodAcceptsList() ?
CodeBlock.of("$N", args) :
CodeBlock.of("$T.of($N)", List.class, args);
code.add("return parse($L).orElseThrow($N -> {\n", pArgs, notSuccess).indent()
.addStatement("$T.builder().build().printErrorMessage($N)",
StandardErrorHandler.class, notSuccess)
.addStatement("$T.exit(1)", System.class)
.addStatement("return new $T()", RuntimeException.class).unindent()
.addStatement("})");
}
return methodBuilder("parseOrExit").addParameter(args)
.addModifiers(sourceElement().accessModifiers())
.returns(generatedTypes.sourceElement().typeName())
Expand Down
28 changes: 10 additions & 18 deletions compiler/src/test/java/net/jbock/processor/ParseOrExitFullTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ void testBasicGenerated() {
"import net.jbock.parse.VarargsParameterParser;",
"import net.jbock.util.ExConvert;",
"import net.jbock.util.ExFailure;",
"import net.jbock.util.ParseRequest;",
"import net.jbock.util.ParsingFailed;",
"",
"@Generated(",
Expand All @@ -62,14 +61,11 @@ void testBasicGenerated() {
" .printUsageDocumentation(createModel());",
" System.exit(0);",
" }",
" return ParseRequest.from(args).expand()",
" .mapLeft(err -> err.addModel(createModel()))",
" .flatMap(this::parse)",
" .orElseThrow(failure -> {",
" StandardErrorHandler.builder().build().printErrorMessage(failure);",
" System.exit(1);",
" return new RuntimeException();",
" });",
" return parse(List.of(args)).orElseThrow(failure -> {",
" StandardErrorHandler.builder().build().printErrorMessage(failure);",
" System.exit(1);",
" return new RuntimeException();",
" });",
" }",
"",
" CommandModel createModel() {",
Expand Down Expand Up @@ -130,7 +126,6 @@ void testPublicParser() {
"import net.jbock.parse.VarargsParameterParser;",
"import net.jbock.util.ExConvert;",
"import net.jbock.util.ExFailure;",
"import net.jbock.util.ParseRequest;",
"import net.jbock.util.ParsingFailed;",
"",
"@Generated(",
Expand All @@ -154,14 +149,11 @@ void testPublicParser() {
" .printUsageDocumentation(createModel());",
" System.exit(0);",
" }",
" return ParseRequest.from(args).expand()",
" .mapLeft(err -> err.addModel(createModel()))",
" .flatMap(this::parse)",
" .orElseThrow(failure -> {",
" StandardErrorHandler.builder().build().printErrorMessage(failure);",
" System.exit(1);",
" return new RuntimeException();",
" });",
" return parse(List.of(args)).orElseThrow(failure -> {",
" StandardErrorHandler.builder().build().printErrorMessage(failure);",
" System.exit(1);",
" return new RuntimeException();",
" });",
" }",
"",
" public CommandModel createModel() {",
Expand Down
3 changes: 2 additions & 1 deletion examples/src/main/java/net/jbock/examples/GitCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ interface GitCommand {

@Command(
name = "git-add",
description = "Add file contents to the index")
description = "Add file contents to the index",
parseOrExitMethodAcceptsList = true)
interface AddCommand {
@VarargsParameter
List<String> pathspec();
Expand Down
11 changes: 11 additions & 0 deletions jbock/src/main/java/net/jbock/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@
*/
boolean skipGeneratingParseOrExitMethod() default false;

/**
* If {@code true}, the generated {@code parseOrExit} method
* will accept {@code List<String>} instead of {@code String[]}.
*/
boolean parseOrExitMethodAcceptsList() default false;

/**
* Set to {@code true} to enable at-file expansion.
*/
boolean enableAtFileExpansion() default false;

/**
* If {@code true}, the generated parser class will be
* {@code public}. Otherwise, it will be package-private.
Expand Down
11 changes: 11 additions & 0 deletions jbock/src/main/java/net/jbock/SuperCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@
*/
boolean skipGeneratingParseOrExitMethod() default false;

/**
* If {@code true}, the generated {@code parseOrExit} method
* will accept {@code List<String>} instead of {@code String[]}.
*/
boolean parseOrExitMethodAcceptsList() default false;

/**
* Set to {@code true} to enable at-file expansion.
*/
boolean enableAtFileExpansion() default false;

/**
* @return {@code true} if public parser should be generated
* @see Command#publicParser()
Expand Down
11 changes: 11 additions & 0 deletions jbock/src/main/java/net/jbock/util/ParseRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ public static ParseRequest from(String[] args) {
return new ParseRequestSimple(List.of(args));
}

public static ParseRequest from(List<String> args) {
if (args.size() >= 1
&& args.get(0).length() >= 2
&& args.get(0).startsWith("@")) {
String fileName = args.get(0).substring(1);
List<String> rest = args.subList(1, args.size());
return new ParseRequestExpand(Paths.get(fileName), rest);
}
return new ParseRequestSimple(args);
}

/**
* Returns a Right containing the result of {@code @-file} expansion.
* If an error occurs during {@code @-file} reading, returns a Left containing
Expand Down
25 changes: 25 additions & 0 deletions jbock/src/test/java/net/jbock/util/ParseRequestTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package net.jbock.util;

import org.junit.jupiter.api.Test;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class ParseRequestTest {

@Test
void testParseList() {
ParseRequest parseRequest = ParseRequest.from(List.of("a"));
assertTrue(parseRequest.expand().isRight());
assertEquals(parseRequest.expand().getRight().orElseThrow(), List.of("a"));
}

@Test
void testParseArray() {
ParseRequest parseRequest = ParseRequest.from(new String[]{"a"});
assertTrue(parseRequest.expand().isRight());
assertEquals(parseRequest.expand().getRight().orElseThrow(), List.of("a"));
}
}

0 comments on commit 4def472

Please sign in to comment.