diff --git a/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java b/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java index 9726cf37..4bc314ee 100644 --- a/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java +++ b/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java @@ -52,7 +52,6 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Map.Entry; import java.util.ServiceLoader; import java.util.Set; @@ -152,76 +151,7 @@ public CompilerResult performCompile( CompilerConfiguration config ) // Set Eclipse-specific options // compiler-specific extra options override anything else in the config object... - Map extras = config.getCustomCompilerArgumentsAsMap(); - if ( extras.containsKey( "errorsAsWarnings" ) ) - { - extras.remove( "errorsAsWarnings" ); - this.errorsAsWarnings = true; - } - else if ( extras.containsKey( "-errorsAsWarnings" ) ) - { - extras.remove( "-errorsAsWarnings" ); - this.errorsAsWarnings = true; - } - - //-- check for existence of the properties file manually - String props = extras.get( "-properties" ); - if ( null != props ) - { - File propFile = new File( props ); - if ( !propFile.exists() || !propFile.isFile() ) - { - throw new IllegalArgumentException( - "Properties file specified by -properties " + propFile + " does not exist" ); - } - } - - for ( Entry entry : extras.entrySet() ) - { - /* - * The compiler mojo makes quite a mess of passing arguments, depending on exactly WHICH - * way is used to pass them. The method method using uses the tag names - * of its contents to denote option names, and so the compiler mojo happily adds a '-' to - * all of the names there and adds them to the "custom compiler arguments" map as a - * name, value pair where the name always contains a single '-'. The Eclipse compiler (and - * javac too, btw) has options with two dashes (like --add-modules for java 9). These cannot - * be passed using a tag. - * - * The other method is to use , where each SINGLE argument needs to be passed - * using an xxxx tag. In there the xxx is not manipulated by the compiler mojo, so - * if it starts with a dash or more dashes these are perfectly preserved. But of course these - * single entries are not a pair. So the compiler mojo adds them as pairs of (xxxx, null). - * - * We use that knowledge here: if a pair has a null value then do not mess up the key but - * render it as a single value. This should ensure that something like: - * - * --add-modules - * java.se.ee - * - * - * is actually added to the command like as such. - * - * (btw: the above example will still give an error when using ecj <= 4.8M6: - * invalid module name: java.se.ee - * but that seems to be a bug in ecj). - */ - String opt = entry.getKey(); - String optionValue = entry.getValue(); - if ( null == optionValue ) - { - //-- We have an option from compilerArgs: use the key as-is as a single option value - args.add( opt ); - } - else - { - if ( !opt.startsWith( "-" ) ) - { - opt = "-" + opt; - } - args.add( opt ); - args.add( optionValue ); - } - } + this.errorsAsWarnings = processCustomArguments(config, args); // Output path args.add( "-d" ); @@ -275,13 +205,6 @@ else if ( extras.containsKey( "-errorsAsWarnings" ) ) } } - //-- Write .class files even when error occur, but make sure methods with compile errors do abort when called - if ( extras.containsKey( "-proceedOnError" ) ) - { - // Generate a class file even with errors, but make methods with errors fail when called - args.add( "-proceedOnError:Fatal" ); - } - //-- classpath List classpathEntries = new ArrayList<>( config.getClasspathEntries() ); classpathEntries.add( config.getOutputLocation() ); @@ -528,6 +451,88 @@ public void worked( int i, int i1 ) } } + static boolean processCustomArguments( CompilerConfiguration config, List args ) + { + boolean result = false; + + for ( Entry entry : config.getCustomCompilerArgumentsEntries() ) + { + String opt = entry.getKey(); + String optionValue = entry.getValue(); + + // handle errorsAsWarnings options + if ( opt.equals("errorsAsWarnings") || opt.equals("-errorsAsWarnings") ) + { + result = true; + continue; + } + + if ( opt.equals( "-properties" ) ) + { + if ( null != optionValue ) + { + File propFile = new File( optionValue ); + if ( !propFile.exists() || !propFile.isFile() ) + { + throw new IllegalArgumentException( + "Properties file specified by -properties " + propFile + " does not exist" ); + } + } + } + + //-- Write .class files even when error occur, but make sure methods with compile errors do abort when called + if ( opt.equals( "-proceedOnError" ) ) + { + // Generate a class file even with errors, but make methods with errors fail when called + args.add( "-proceedOnError:Fatal" ); + continue; + } + + /* + * The compiler mojo makes quite a mess of passing arguments, depending on exactly WHICH + * way is used to pass them. The method method using uses the tag names + * of its contents to denote option names, and so the compiler mojo happily adds a '-' to + * all of the names there and adds them to the "custom compiler arguments" map as a + * name, value pair where the name always contains a single '-'. The Eclipse compiler (and + * javac too, btw) has options with two dashes (like --add-modules for java 9). These cannot + * be passed using a tag. + * + * The other method is to use , where each SINGLE argument needs to be passed + * using an xxxx tag. In there the xxx is not manipulated by the compiler mojo, so + * if it starts with a dash or more dashes these are perfectly preserved. But of course these + * single entries are not a pair. So the compiler mojo adds them as pairs of (xxxx, null). + * + * We use that knowledge here: if a pair has a null value then do not mess up the key but + * render it as a single value. This should ensure that something like: + * + * --add-modules + * java.se.ee + * + * + * is actually added to the command like as such. + * + * (btw: the above example will still give an error when using ecj <= 4.8M6: + * invalid module name: java.se.ee + * but that seems to be a bug in ecj). + */ + if ( null == optionValue ) + { + //-- We have an option from compilerArgs: use the key as-is as a single option value + args.add( opt ); + } + else + { + if ( !opt.startsWith( "-" ) ) + { + opt = "-" + opt; + } + args.add( opt ); + args.add( optionValue ); + } + } + return result; + } + private static boolean haveSourceOrReleaseArgument( List args ) { Iterator allArgs = args.iterator(); diff --git a/plexus-compilers/plexus-compiler-eclipse/src/test/java/org/codehaus/plexus/compiler/eclipse/EclipseCompilerConfigurationTest.java b/plexus-compilers/plexus-compiler-eclipse/src/test/java/org/codehaus/plexus/compiler/eclipse/EclipseCompilerConfigurationTest.java new file mode 100644 index 00000000..13c6333a --- /dev/null +++ b/plexus-compilers/plexus-compiler-eclipse/src/test/java/org/codehaus/plexus/compiler/eclipse/EclipseCompilerConfigurationTest.java @@ -0,0 +1,111 @@ +package org.codehaus.plexus.compiler.eclipse; + +/** + * The MIT License + * + * Copyright (c) 2005, The Codehaus + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import junit.framework.TestCase; +import org.codehaus.plexus.compiler.CompilerConfiguration; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class EclipseCompilerConfigurationTest + extends TestCase +{ + private static final String PROPERTIES_FILE_NAME = + "src/test/resources".replace( "/", File.separator ) + File.separator + + EclipseCompilerConfigurationTest.class.getName().replace( ".", File.separator ) + + "-test.properties"; + + private CompilerConfiguration configuration; + + @Override + protected void setUp() + { + configuration = new CompilerConfiguration(); + } + + public void testProcessCustomArgumentsWithMultipleAddExports() + { + configuration.addCompilerCustomArgument( "--add-exports", "FROM-MOD/package1=OTHER-MOD" ); + configuration.addCompilerCustomArgument( "--add-exports", "FROM-MOD/package2=OTHER-MOD" ); + List args = new ArrayList<>(); + EclipseJavaCompiler.processCustomArguments( configuration, args ); + assertEquals( 4, args.size() ); + assertEquals( "--add-exports", args.get( 0 ) ); + assertEquals( "FROM-MOD/package1=OTHER-MOD", args.get( 1 ) ); + assertEquals( "--add-exports", args.get( 2 ) ); + assertEquals( "FROM-MOD/package2=OTHER-MOD", args.get( 3 ) ); + } + + public void testProcessCustomArgumentsWithProceedOnError() + { + configuration.addCompilerCustomArgument( "-proceedOnError", null ); + List args = new ArrayList<>(); + EclipseJavaCompiler.processCustomArguments( configuration, args ); + assertEquals( 1, args.size() ); + assertEquals( "-proceedOnError:Fatal", args.get( 0 ) ); + } + + public void testProcessCustomArgumentsWithErrorsAsWarnings() + { + configuration.addCompilerCustomArgument( "errorsAsWarnings", null ); + List args = new ArrayList<>(); + final boolean errorsAsWarnings = EclipseJavaCompiler.processCustomArguments( configuration, args ); + assertTrue( errorsAsWarnings ); + } + + public void testProcessCustomArgumentsWithErrorsAsWarningsAndMinus() + { + configuration.addCompilerCustomArgument( "-errorsAsWarnings", null ); + List args = new ArrayList<>(); + final boolean errorsAsWarnings = EclipseJavaCompiler.processCustomArguments( configuration, args ); + assertTrue( errorsAsWarnings ); + } + + public void testProcessCustomArgumentsWithPropertiesAndNonExistingFile() + { + configuration.addCompilerCustomArgument( "-properties", "fooBar.txt" ); + try + { + EclipseJavaCompiler.processCustomArguments( configuration, Collections.emptyList() ); + fail( "IllegalArgumentException expected" ); + } catch ( IllegalArgumentException expected ) + { + assertEquals( "Properties file specified by -properties fooBar.txt does not exist", expected.getMessage() ); + } + } + + public void testProcessCustomArgumentsWithPropertiesAndValidFile() + { + configuration.addCompilerCustomArgument( "-properties", PROPERTIES_FILE_NAME ); + List args = new ArrayList<>(); + EclipseJavaCompiler.processCustomArguments( configuration, args ); + assertEquals( 2, args.size() ); + assertEquals( "-properties", args.get( 0 ) ); + assertEquals( PROPERTIES_FILE_NAME, args.get( 1 ) ); + } +} diff --git a/plexus-compilers/plexus-compiler-eclipse/src/test/resources/org/codehaus/plexus/compiler/eclipse/EclipseCompilerConfigurationTest-test.properties b/plexus-compilers/plexus-compiler-eclipse/src/test/resources/org/codehaus/plexus/compiler/eclipse/EclipseCompilerConfigurationTest-test.properties new file mode 100644 index 00000000..74d0a43f --- /dev/null +++ b/plexus-compilers/plexus-compiler-eclipse/src/test/resources/org/codehaus/plexus/compiler/eclipse/EclipseCompilerConfigurationTest-test.properties @@ -0,0 +1 @@ +foo=bar