From bf21d102762d94035055e177bf82b4bfa17058b4 Mon Sep 17 00:00:00 2001 From: Paul King Date: Sat, 26 May 2018 17:10:55 +1000 Subject: [PATCH] GROOVY-8592: changes for groovysh and tidy up (closes #727) --- build.gradle | 1 - gradle/assemble.gradle | 12 +- gradle/docs.gradle | 3 + .../groovy/cli/GroovyPosixParser.java | 281 ------------------ src/test/org/codehaus/groovy/classgen/JO.java | 1 - .../groovy/cli/commons/CliBuilderTest.groovy | 25 +- subprojects/groovy-groovysh/build.gradle | 2 +- .../codehaus/groovy/tools/shell/Main.groovy | 16 +- .../tools/shell/util/HelpFormatter.groovy | 119 -------- 9 files changed, 24 insertions(+), 436 deletions(-) delete mode 100644 src/main/java/org/codehaus/groovy/cli/GroovyPosixParser.java delete mode 100644 subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/util/HelpFormatter.groovy diff --git a/build.gradle b/build.gradle index 107036ebe3d..b1f95ee98fb 100644 --- a/build.gradle +++ b/build.gradle @@ -181,7 +181,6 @@ dependencies { compile "org.ow2.asm:asm-tree:$asmVersion" compile "org.ow2.asm:asm-util:$asmVersion" - compile "commons-cli:commons-cli:$commonsCliVersion" compile "info.picocli:picocli:$picocliVersion" compile "org.apache.ant:ant:$antVersion" compile("com.thoughtworks.xstream:xstream:$xstreamVersion") { diff --git a/gradle/assemble.gradle b/gradle/assemble.gradle index bd67e480d01..2f83048f34b 100644 --- a/gradle/assemble.gradle +++ b/gradle/assemble.gradle @@ -198,8 +198,7 @@ allprojects { if (component instanceof ModuleComponentIdentifier) { return component.module in [ 'antlr', 'antlr-runtime', 'antlr4', 'antlr4-runtime', 'antlr4-annotations', - 'asm', 'asm-commons', 'asm-tree', 'asm-util', - 'commons-cli', 'picocli'] + 'asm', 'asm-commons', 'asm-tree', 'asm-util', 'picocli'] } return false } @@ -209,12 +208,6 @@ allprojects { } jarjarToolClasspath = rootProject.configurations.tools untouchedFiles = [ - 'org/codehaus/groovy/cli/GroovyPosixParser*.class', - 'groovy/util/CliBuilder*.class', - 'groovy/util/OptionAccessor*.class', - 'org/codehaus/groovy/tools/shell/util/HelpFormatter*.class', - 'groovy/cli/commons/CliBuilder*.class', - 'groovy/cli/commons/OptionAccessor*.class', 'groovy/cli/picocli/CliBuilder*.class', 'groovy/cli/picocli/OptionAccessor*.class' ] @@ -222,8 +215,7 @@ allprojects { 'antlr.**' : 'groovyjarjarantlr.@1', // antlr2 'org.antlr.**' : 'groovyjarjarantlr4.@1', // antlr4 'org.objectweb.**' : 'groovyjarjarasm.@1', - 'org.apache.commons.cli.**': 'groovyjarjarcommonscli.@1', - 'picocli.**': 'groovyjarjarpicocli.@1' + 'picocli.**' : 'groovyjarjarpicocli.@1' ] excludesPerLibrary = [ '*': ['META-INF/maven/**', 'META-INF/*', 'META-INF/services/javax.annotation.processing.Processor', 'module-info.class'] diff --git a/gradle/docs.gradle b/gradle/docs.gradle index 7b64132cbdd..0809388c413 100644 --- a/gradle/docs.gradle +++ b/gradle/docs.gradle @@ -59,8 +59,11 @@ def groovydocBaseSpec = { link 'http://docs.oracle.com/javase/8/docs/api/', 'java.', 'org.xml.', 'javax.', 'org.w3c.' link 'http://docs.groovy-lang.org/docs/ant/api/', 'org.apache.ant.', 'org.apache.tools.ant.' link 'http://junit.org/junit4/javadoc/latest/', 'org.junit.', 'junit.' + link 'http://junit.org/junit5/docs/current/api/', 'org.junit.jupiter.', 'org.junit.platform.' link 'http://www.antlr2.org/javadoc/', 'antlr.' + link 'http://www.antlr.org/api/Java/', 'org.antlr.v4.' link 'http://commons.apache.org/proper/commons-cli/javadocs/api-release/', 'org.apache.commons.cli.' + link 'http://picocli.info/apidocs/', 'picocli.' } def groovydocSpec = groovydocBaseSpec >> { diff --git a/src/main/java/org/codehaus/groovy/cli/GroovyPosixParser.java b/src/main/java/org/codehaus/groovy/cli/GroovyPosixParser.java deleted file mode 100644 index 4168fa68094..00000000000 --- a/src/main/java/org/codehaus/groovy/cli/GroovyPosixParser.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.codehaus.groovy.cli; - -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.Parser; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -/** - * This is a hacked version of Commons CLI 1.2 PosixParser with some bug fixes added. - * We aren't aware of any use cases where it isn't now preferable to use the - * Commons CLI 1.3 DefaultParser but this class is retained for the time being for - * backwards compatibility if someone is relying on this class's exact functionality. - * - * @author John Keyes (john at integralsource.com) - * @author Paul King (Groovy hacks/fixes) - * @deprecated use the DefaultParser from Commons CLI - */ -@Deprecated -public class GroovyPosixParser extends Parser -{ - /** holder for flattened tokens */ - private List tokens = new ArrayList(); - - /** specifies if bursting should continue */ - private boolean eatTheRest; - - /** holder for the current option */ - private Option currentOption; - - /** the command line Options */ - private Options options; - - /** - * Resets the members to their original state i.e. remove - * all of tokens entries and set eatTheRest - * to false. - */ - private void init() - { - eatTheRest = false; - tokens.clear(); - } - - /** - * An implementation of {@link Parser}'s abstract - * {@link Parser#flatten(Options,String[],boolean) flatten} method. - *

- * The following are the rules used by this flatten method. - *

    - *
  1. if stopAtNonOption is true then do not - * burst anymore of arguments entries, just add each - * successive entry without further processing. Otherwise, ignore - * stopAtNonOption.
  2. - *
  3. if the current arguments entry is "--" - * just add the entry to the list of processed tokens
  4. - *
  5. if the current arguments entry is "-" - * just add the entry to the list of processed tokens
  6. - *
  7. if the current arguments entry is two characters - * in length and the first character is "-" then check if this - * is a valid {@link Option} id. If it is a valid id, then add the - * entry to the list of processed tokens and set the current {@link Option} - * member. If it is not a valid id and stopAtNonOption - * is true, then the remaining entries are copied to the list of - * processed tokens. Otherwise, the current entry is ignored.
  8. - *
  9. if the current arguments entry is more than two - * characters in length and the first character is "-" then - * we need to burst the entry to determine its constituents. For more - * information on the bursting algorithm see - * {@link GroovyPosixParser#burstToken(String, boolean) burstToken}.
  10. - *
  11. if the current arguments entry is not handled - * by any of the previous rules, then the entry is added to the list - * of processed tokens.
  12. - *
- * - * @param options The command line {@link Options} - * @param arguments The command line arguments to be parsed - * @param stopAtNonOption Specifies whether to stop flattening when an non option is found. - * @return The flattened arguments String array. - */ - protected String[] flatten(Options options, String[] arguments, boolean stopAtNonOption) { - init(); - this.options = options; - - // an iterator for the command line tokens - Iterator iter = Arrays.asList(arguments).iterator(); - - // process each command line token - while (iter.hasNext()) - { - // get the next command line token - String token = (String) iter.next(); - - // handle long option --foo or --foo=bar - if (token.startsWith("--")) - { - int pos = token.indexOf('='); - String opt = pos == -1 ? token : token.substring(0, pos); // --foo - - if (!options.hasOption(opt)) - { - processNonOptionToken(token, stopAtNonOption); - } - else - { - tokens.add(opt); - if (pos != -1) - { - tokens.add(token.substring(pos + 1)); - } else { - currentOption = options.getOption(opt); - } - } - } - - // single hyphen - else if ("-".equals(token)) - { - tokens.add(token); - } - else if (token.startsWith("-")) - { - if (token.length() == 2 || options.hasOption(token)) - { - processOptionToken(token, stopAtNonOption); - } - // requires bursting - else - { - burstToken(token, stopAtNonOption); - } - } - else - { - processNonOptionToken(token, stopAtNonOption); - } - - gobble(iter); - } - - return (String[]) tokens.toArray(new String[0]); - } - - /** - * Adds the remaining tokens to the processed tokens list. - * - * @param iter An iterator over the remaining tokens - */ - private void gobble(Iterator iter) - { - if (eatTheRest) - { - while (iter.hasNext()) - { - tokens.add(iter.next()); - } - } - } - - /** - * Add the special token "--" and the current value - * to the processed tokens list. Then add all the remaining - * argument values to the processed tokens list. - * - * @param value The current token - */ - private void processNonOptionToken(String value, boolean stopAtNonOption) - { - if (stopAtNonOption && (currentOption == null || !currentOption.hasArg())) - { - eatTheRest = true; - tokens.add("--"); - } - - tokens.add(value); - currentOption = null; - } - - /** - * If an {@link Option} exists for token then - * add the token to the processed list. - *

- * If an {@link Option} does not exist and stopAtNonOption - * is set then add the remaining tokens to the processed tokens list - * directly. - * - * @param token The current option token - * @param stopAtNonOption Specifies whether flattening should halt at the first non option. - */ - private void processOptionToken(String token, boolean stopAtNonOption) { - if (stopAtNonOption && !options.hasOption(token)) - { - eatTheRest = true; - } - - if (options.hasOption(token)) { - currentOption = options.getOption(token); - } else { - currentOption = null; - } - - tokens.add(token); - } - - /** - * Breaks token into its constituent parts - * using the following algorithm. - * - *

- * - * @param token The current token to be burst - * @param stopAtNonOption Specifies whether to stop processing - * at the first non-Option encountered. - */ - protected void burstToken(String token, boolean stopAtNonOption) - { - for (int i = 1; i < token.length(); i++) - { - String ch = String.valueOf(token.charAt(i)); - - if (options.hasOption(ch)) - { - tokens.add("-" + ch); - currentOption = options.getOption(ch); - - if (currentOption.hasArg() && (token.length() != (i + 1))) - { - tokens.add(token.substring(i + 1)); - break; - } - } - else if (stopAtNonOption) - { - processNonOptionToken(token.substring(i), true); - break; - } - else - { - tokens.add(token); - break; - } - } - } -} diff --git a/src/test/org/codehaus/groovy/classgen/JO.java b/src/test/org/codehaus/groovy/classgen/JO.java index ae5414c39d0..206c9262b3c 100644 --- a/src/test/org/codehaus/groovy/classgen/JO.java +++ b/src/test/org/codehaus/groovy/classgen/JO.java @@ -38,7 +38,6 @@ MetaClass getStaticMetaClass (Object obj) { public static void main(String[] args) throws Exception { ASMifier.main(new String[]{"target/classes/groovy/swing/SwingBuilder.class"}); -// ASMifierClassVisitor.main(new String[]{"target/classes/org/codehaus/groovy/tools/shell/util/HelpFormatter.class"}); // ASMifierClassVisitor.main(new String[]{"target/classes/org/codehaus/groovy/runtime/callsite/PogoMetaMethodSite.class"}); // ASMifierClassVisitor.main(new String[]{"target/test-classes/spectralnorm.class"}); // ASMifierClassVisitor.main(new String[]{"target/test-classes/groovy/bugs/CustomMetaClassTest.class"}); diff --git a/subprojects/groovy-cli-commons/src/test/groovy/groovy/cli/commons/CliBuilderTest.groovy b/subprojects/groovy-cli-commons/src/test/groovy/groovy/cli/commons/CliBuilderTest.groovy index e9ff5a0b4b6..fd8928a1915 100644 --- a/subprojects/groovy-cli-commons/src/test/groovy/groovy/cli/commons/CliBuilderTest.groovy +++ b/subprojects/groovy-cli-commons/src/test/groovy/groovy/cli/commons/CliBuilderTest.groovy @@ -25,7 +25,6 @@ import groovy.transform.TypeChecked import org.apache.commons.cli.BasicParser import org.apache.commons.cli.DefaultParser import org.apache.commons.cli.GnuParser -import org.codehaus.groovy.cli.GroovyPosixParser import java.math.RoundingMode @@ -100,19 +99,19 @@ class CliBuilderTest extends GroovyTestCase { } void testSampleShort() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser -> + [new DefaultParser(), new GnuParser(), new BasicParser()].each { parser -> runSample(parser, ['-h', '-c', expectedParameter]) } } void testSampleLong() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser -> + [new DefaultParser(), new GnuParser(), new BasicParser()].each { parser -> runSample(parser, ['--help', '--encoding', expectedParameter]) } } void testSimpleArg() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser -> + [new DefaultParser(), new GnuParser(), new BasicParser()].each { parser -> def cli = new CliBuilder(parser: parser) cli.a([:], '') def options = cli.parse(['-a', '1', '2']) @@ -121,7 +120,7 @@ class CliBuilderTest extends GroovyTestCase { } void testMultipleArgs() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser -> + [new DefaultParser(), new GnuParser(), new BasicParser()].each { parser -> def cli = new CliBuilder(parser: parser) cli.a(longOpt: 'arg', args: 2, valueSeparator: ',' as char, 'arguments') def options = cli.parse(['-a', '1,2']) @@ -144,7 +143,7 @@ usage: groovy } void testLongOptsOnly_nonOptionShouldStopArgProcessing() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser()].each { parser -> + [new DefaultParser(), new GnuParser()].each { parser -> def cli = new CliBuilder(parser: parser) def anOption = builder().longOpt('anOption').hasArg().desc('An option.') .build() @@ -160,7 +159,7 @@ usage: groovy } void testLongAndShortOpts_allOptionsValid() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser -> + [new DefaultParser(), new GnuParser(), new BasicParser()].each { parser -> def cli = new CliBuilder(parser: parser) def anOption = builder().longOpt('anOption').hasArg().desc('An option.').build() cli.options.addOption(anOption) @@ -174,7 +173,7 @@ usage: groovy } void testUnrecognizedOptions() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser -> + [new DefaultParser(), new GnuParser(), new BasicParser()].each { parser -> def cli = new CliBuilder(parser: parser) cli.v(longOpt: 'verbose', 'verbose mode') def options = cli.parse(['-x', '-yyy', '--zzz', 'something']) @@ -183,7 +182,7 @@ usage: groovy } void testMultipleOccurrencesSeparateSeparate() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser -> + [new DefaultParser(), new GnuParser(), new BasicParser()].each { parser -> def cli = new CliBuilder(parser: parser) cli.a(longOpt: 'arg', args: UNLIMITED_VALUES, 'arguments') def options = cli.parse(['-a', '1', '-a', '2', '-a', '3']) @@ -196,7 +195,7 @@ usage: groovy } void testMultipleOccurrencesSeparateJuxtaposed() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser()].each { parser -> + [new DefaultParser(), new GnuParser()].each { parser -> def cli = new CliBuilder(parser: parser) //cli.a ( longOpt : 'arg' , args : UNLIMITED_VALUES , 'arguments' ) cli.a(longOpt: 'arg', args: 1, 'arguments') @@ -210,7 +209,7 @@ usage: groovy } void testMultipleOccurrencesTogetherSeparate() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser()].each { parser -> + [new DefaultParser(), new GnuParser()].each { parser -> def cli = new CliBuilder(parser: parser) cli.a(longOpt: 'arg', args: UNLIMITED_VALUES, valueSeparator: ',' as char, 'arguments') def options = cli.parse(['-a 1,2,3']) @@ -223,7 +222,7 @@ usage: groovy } void testMultipleOccurrencesTogetherJuxtaposed() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser()].each { parser -> + [new DefaultParser(), new GnuParser()].each { parser -> def cli1 = new CliBuilder(parser: parser) cli1.a(longOpt: 'arg', args: UNLIMITED_VALUES, valueSeparator: ',' as char, 'arguments') def options = cli1.parse(['-a1,2,3']) @@ -279,7 +278,7 @@ usage: groovy } void testMultiCharShortOpt() { - [new DefaultParser(), new GroovyPosixParser(), new GnuParser()].each { parser -> + [new DefaultParser(), new GnuParser()].each { parser -> def cli = new CliBuilder(writer: printWriter, parser: parser) cli.abc('abc option') cli.def(longOpt: 'defdef', 'def option') diff --git a/subprojects/groovy-groovysh/build.gradle b/subprojects/groovy-groovysh/build.gradle index e2347815601..6e5e1a0e95a 100644 --- a/subprojects/groovy-groovysh/build.gradle +++ b/subprojects/groovy-groovysh/build.gradle @@ -18,7 +18,7 @@ */ dependencies { compile rootProject - compile project(':groovy-cli-commons') + compile project(':groovy-cli-picocli') compile project(':groovy-console') testCompile project(':groovy-test') compile("jline:jline:$jlineVersion") { diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/Main.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/Main.groovy index 1b7a9a5c8d0..462dd358194 100644 --- a/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/Main.groovy +++ b/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/Main.groovy @@ -18,14 +18,13 @@ */ package org.codehaus.groovy.tools.shell -import groovy.cli.commons.CliBuilder -import groovy.cli.commons.OptionAccessor +import groovy.cli.picocli.CliBuilder +import groovy.cli.picocli.OptionAccessor import jline.TerminalFactory import jline.UnixTerminal import jline.UnsupportedTerminal import jline.WindowsTerminal import org.codehaus.groovy.control.CompilerConfiguration -import org.codehaus.groovy.tools.shell.util.HelpFormatter import org.codehaus.groovy.tools.shell.util.Logger import org.codehaus.groovy.tools.shell.util.MessageSource import org.codehaus.groovy.tools.shell.util.NoExitSecurityManager @@ -76,11 +75,10 @@ class Main { */ static void main(final String[] args) { MessageSource messages = new MessageSource(Main) - CliBuilder cli = new CliBuilder(usage: 'groovysh [options] [...]', formatter: new HelpFormatter(), stopAtNonOption: false, + CliBuilder cli = new CliBuilder(usage: 'groovysh [options] [...]', stopAtNonOption: false, header: messages['cli.option.header']) cli.with { - classpath(messages['cli.option.classpath.description']) - cp(longOpt: 'classpath', messages['cli.option.cp.description']) + _(names: ['-cp', '-classpath', '--classpath'], messages['cli.option.classpath.description']) h(longOpt: 'help', messages['cli.option.help.description']) V(longOpt: 'version', messages['cli.option.version.description']) v(longOpt: 'verbose', messages['cli.option.verbose.description']) @@ -88,7 +86,7 @@ class Main { d(longOpt: 'debug', messages['cli.option.debug.description']) e(longOpt: 'evaluate', args: 1, argName: 'CODE', optionalArg: false, messages['cli.option.evaluate.description']) C(longOpt: 'color', args: 1, argName: 'FLAG', optionalArg: true, messages['cli.option.color.description']) - D(longOpt: 'define', args: 2, argName: 'name=value', valueSeparator: '=', messages['cli.option.define.description']) + D(longOpt: 'define', type: Map, argName: 'name=value', messages['cli.option.define.description']) T(longOpt: 'terminal', args: 1, argName: 'TYPE', messages['cli.option.terminal.description']) pa(longOpt: 'parameters', messages['cli.option.parameters.description']) } @@ -134,9 +132,7 @@ class Main { IO io = new IO() if (options.hasOption('D')) { - options.getOptionProperties('D')?.each { k, v -> - System.setProperty(k, v) - } + options.Ds.each { k, v -> System.setProperty(k, v) } } if (options.v) { diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/util/HelpFormatter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/util/HelpFormatter.groovy deleted file mode 100644 index d4e14b97959..00000000000 --- a/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/util/HelpFormatter.groovy +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.codehaus.groovy.tools.shell.util - -import jline.Terminal -import org.apache.commons.cli.Option -import org.apache.commons.cli.Options - -// -// NOTE: Some code duplicated and augmented from commons-cli (1.0) sources to -// properly render options w/arguments. -// - - -/** - * Custom CLI help formatter to render things correctly. - * - * @author Jason Dillon - */ -class HelpFormatter - extends org.apache.commons.cli.HelpFormatter -{ - HelpFormatter() { - leftPadding = 2 - descPadding = 4 - } - - // Detect the terminal width late - int getDefaultWidth() { - return Terminal.terminal.terminalWidth - 1 - } - - @Override - protected StringBuffer renderOptions(final StringBuffer sb, final int width, final Options options, final int leftPad, final int descPad) { - assert sb != null - assert options - - List prefixes = [] - String lpad = ' ' * leftPad - - List