Skip to content

Commit

Permalink
Issue checkstyle#6068: migrate to picocli command line parser from Co…
Browse files Browse the repository at this point in the history
…mmons CLI
  • Loading branch information
remkop committed Sep 21, 2018
1 parent 27512b0 commit 45b1649
Show file tree
Hide file tree
Showing 11 changed files with 582 additions and 614 deletions.
6 changes: 5 additions & 1 deletion README.md
Expand Up @@ -77,7 +77,7 @@ are in the file named "RIGHTS.antlr" in this directory.
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).

The software uses the Cli, Logging and Beanutils packages from the
The software uses the Logging and Beanutils packages from the
Apache Commons project (http://commons.apache.org/). The license terms
of these packages are in the file named "LICENSE.apache20" in this
directory.
Expand All @@ -87,6 +87,10 @@ The software uses the Google Guava Libraries
these packages are in the file named "LICENSE.apache20" in this
directory.

The software uses the Picocli Library
(https://github.com/remkop/picocli/). Its license terms
are in the file named "LICENSE.apache20" in this directory.

[travis]:https://travis-ci.org/checkstyle/checkstyle/builds
[travis img]:https://travis-ci.org/checkstyle/checkstyle.svg

Expand Down
2 changes: 1 addition & 1 deletion config/import-control.xml
Expand Up @@ -29,7 +29,7 @@
<allow class="java.security.NoSuchAlgorithmException" local-only="true"/>
<allow pkg="com.puppycrawl.tools.checkstyle.utils" local-only="true"/>
<allow pkg="com.puppycrawl.tools.checkstyle.grammar" local-only="true"/>
<allow pkg="org.apache.commons.cli" local-only="true"/>
<allow pkg="picocli" local-only="true"/>
<allow pkg="org.antlr.v4.runtime" local-only="true"/>
<allow class="com.puppycrawl.tools.checkstyle.JavadocDetailNodeParser.+"
local-only="true" regex="true"/>
Expand Down
16 changes: 14 additions & 2 deletions config/pmd.xml
Expand Up @@ -36,7 +36,9 @@
<rule ref="category/java/bestpractices.xml/SystemPrintln">
<properties>
<!-- it is ok to use println in CLI class. -->
<property name="violationSuppressXPath" value="//ClassOrInterfaceDeclaration[@Image='Main']"/>
<property name="violationSuppressXPath"
value="//ClassOrInterfaceDeclaration
[@Image='Main' or @Image='JavadocPropertiesGenerator']"/>
</properties>
</rule>

Expand Down Expand Up @@ -310,8 +312,18 @@
<rule ref="category/java/design.xml/TooManyFields">
<properties>
<!-- Unable to split fields out of the class. -->
<!-- Main has an annotated field for each command line option. This is by design. -->
<property name="violationSuppressXPath"
value="//ClassOrInterfaceDeclaration[@Image='Checker']
| //ClassOrInterfaceDeclaration[@Image='Main']"/>
</properties>
</rule>
<rule ref="category/java/design.xml/ImmutableField">
<properties>
<!-- Main has annotated fields whose value is injected by picocli.
These fields should not be marked final. -->
<property name="violationSuppressXPath"
value="//ClassOrInterfaceDeclaration[@Image='Checker']"/>
value="//ClassOrInterfaceDeclaration[@Image='Main']"/>
</properties>
</rule>
<rule ref="category/java/design.xml/TooManyMethods">
Expand Down
6 changes: 6 additions & 0 deletions config/spotbugs-exclude.xml
Expand Up @@ -107,6 +107,12 @@
<Method name="loadProperties"/>
<Bug pattern="NP_NULL_PARAM_DEREF"/>
</Match>
<Match>
<!-- false-positive. See details at https://github.com/checkstyle/checkstyle/pull/5403 -->
<Class name="com.puppycrawl.tools.checkstyle.Main"/>
<Method name="runCli"/>
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/>
</Match>
<Match>
<!-- false-positive. See details at https://github.com/checkstyle/checkstyle/pull/5403 -->
<Class name="com.puppycrawl.tools.checkstyle.PackageNamesLoader"/>
Expand Down
31 changes: 26 additions & 5 deletions pom.xml
Expand Up @@ -231,6 +231,11 @@
</pluginRepositories>

<dependencies>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<version>3.6.0</version>
</dependency>
<dependency>
<groupId>antlr</groupId>
<artifactId>antlr</artifactId>
Expand All @@ -246,11 +251,6 @@
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
Expand Down Expand Up @@ -826,6 +826,7 @@
<exclude>
com.puppycrawl.tools.checkstyle.grammar.javadoc.JavadocParser*
</exclude>
<exclude>com.puppycrawl.tools.checkstyle.Main</exclude>
<exclude>com.puppycrawl.tools.checkstyle.grammar.javadoc.JavadocLexer</exclude>
<exclude>
com.puppycrawl.tools.checkstyle.JavadocDetailNodeParser.JavadocParserErrorStrategy
Expand Down Expand Up @@ -956,6 +957,26 @@
</limit>
</limits>
</rule>
<rule>
<element>CLASS</element>
<includes>
<include>
com.puppycrawl.tools.checkstyle.Main
</include>
</includes>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.99</minimum>
</limit>
<limit>
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>0.99</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
Expand Down
Expand Up @@ -27,19 +27,18 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.DetailNode;
import com.puppycrawl.tools.checkstyle.api.JavadocTokenTypes;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.ParameterException;
import picocli.CommandLine.Parameters;
import picocli.CommandLine.ParseResult;

/**
* This class is used internally in the build process to write a property file
Expand All @@ -49,24 +48,33 @@
* a programmatic access to the first sentence of the TokenType constants,
* so they can use them in their configuration gui.
*/
@Command(name = "java com.puppycrawl.tools.checkstyle.JavadocPropertiesGenerator",
mixinStandardHelpOptions = true)
public final class JavadocPropertiesGenerator {

/**
* The command line option to specify the output file.
* This regexp is used to extract the first sentence from the text.
* The end of the sentence is determined by the symbol "period", "exclamation mark" or
* "question mark", followed by a space or the end of the text.
*/
private static final String OPTION_DEST_FILE = "destfile";
private static final Pattern END_OF_SENTENCE_PATTERN = Pattern.compile("(.*?[.?!])(\\s|$)");

/** Max width of the usage help message for this command. */
private static final int USAGE_HELP_WIDTH = 100;

/**
* The width of the CLI help option.
* The command line option to specify the output file.
*/
private static final int HELP_WIDTH = 100;
@SuppressWarnings("all")
@Option(names = "--destfile", required = true, description = "The output file.")
private File outputFile;

/**
* This regexp is used to extract the first sentence from the text.
* The end of the sentence is determined by the symbol "period", "exclamation mark" or
* "question mark", followed by a space or the end of the text.
* The command line positional parameter to specify the input file.
*/
private static final Pattern END_OF_SENTENCE_PATTERN = Pattern.compile("(.*?[.?!])(\\s|$)");
@SuppressWarnings("all")
@Parameters(index = "0", description = "The input file.")
private File inputFile;

/**
* Don't create instance of this class, use the {@link #main(String[])} method instead.
Expand All @@ -78,29 +86,27 @@ private JavadocPropertiesGenerator() {
* TokenTypes.properties generator entry point.
* @param args the command line arguments
* @throws CheckstyleException if parser or lexer failed or if there is an IO problem
* @throws ParseException if the command line can not be passed
**/
public static void main(String... args)
throws CheckstyleException, ParseException {
final CommandLine commandLine = parseCli(args);
if (commandLine.getArgList().size() == 1) {
final File inputFile = new File(commandLine.getArgList().get(0));
final File outputFile = new File(commandLine.getOptionValue(OPTION_DEST_FILE));
writePropertiesFile(inputFile, outputFile);
public static void main(String... args) throws CheckstyleException {
final JavadocPropertiesGenerator generator = new JavadocPropertiesGenerator();
final CommandLine cmd = new CommandLine(generator).setUsageHelpWidth(USAGE_HELP_WIDTH);
try {
final ParseResult parseResult = cmd.parseArgs(args);
if (!CommandLine.printHelpIfRequested(parseResult)) {
generator.writePropertiesFile();
}
}
else {
printUsage();
catch (ParameterException ex) {
System.err.println(ex.getMessage());
ex.getCommandLine().usage(System.err);
}
}

/**
* Creates the .properties file from a .java file.
* @param inputFile .java file
* @param outputFile .properties file
* @throws CheckstyleException if a javadoc comment can not be parsed
*/
private static void writePropertiesFile(File inputFile, File outputFile)
throws CheckstyleException {
private void writePropertiesFile() throws CheckstyleException {
try (PrintWriter writer = new PrintWriter(outputFile, StandardCharsets.UTF_8.name())) {
final DetailAST top = JavaParser.parseFile(inputFile, JavaParser.Options.WITH_COMMENTS);
final DetailAST objBlock = getClassBody(top);
Expand Down Expand Up @@ -302,37 +308,4 @@ private static void formatHtmlElement(StringBuilder builder, DetailNode node) {
break;
}
}

/**
* Prints the usage information.
*/
private static void printUsage() {
final HelpFormatter formatter = new HelpFormatter();
formatter.setWidth(HELP_WIDTH);
formatter.printHelp(String.format("java %s [options] <input file>.",
JavadocPropertiesGenerator.class.getName()), buildOptions());
}

/**
* Parses command line based on passed arguments.
* @param args command line arguments
* @return parsed information about passed arguments
* @throws ParseException when passed arguments are not valid
*/
private static CommandLine parseCli(String... args)
throws ParseException {
final CommandLineParser clp = new DefaultParser();
return clp.parse(buildOptions(), args);
}

/**
* Builds and returns the list of supported parameters.
* @return available options
*/
private static Options buildOptions() {
final Options options = new Options();
options.addRequiredOption(null, OPTION_DEST_FILE, true, "The output file.");
return options;
}

}

0 comments on commit 45b1649

Please sign in to comment.