diff --git a/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/ListHints.java b/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/ListHints.java new file mode 100644 index 0000000..ce2ee7f --- /dev/null +++ b/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/ListHints.java @@ -0,0 +1,44 @@ +/** + * 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.netbeans.modules.jackpot30.maven; + +import java.util.List; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.project.MavenProject; + +/** + * @goal list + */ +public class ListHints extends RunJackpot30 { + + /** + * @parameter property="project" + * @required + * @readonly + */ + private MavenProject project; + + public void execute() throws MojoExecutionException, MojoFailureException { + if (!project.isExecutionRoot()) return; + + runWithArguments(List.of("--list")); + } + +} diff --git a/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/RunJackpot30.java b/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/RunJackpot30.java index c86be4c..5bff11f 100644 --- a/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/RunJackpot30.java +++ b/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/RunJackpot30.java @@ -20,7 +20,6 @@ import java.io.File; import java.io.IOException; -import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -40,67 +39,82 @@ public abstract class RunJackpot30 extends AbstractMojo { protected final void doRun(MavenProject project, boolean apply) throws MojoExecutionException, MojoFailureException { - try { - String sourceLevel = "1.5"; - Xpp3Dom sourceLevelConfiguration = Utils.getPluginConfiguration(project, "org.apache.maven.plugins", "maven-compiler-plugin"); + String sourceLevel = "1.5"; + Xpp3Dom sourceLevelConfiguration = Utils.getPluginConfiguration(project, "org.apache.maven.plugins", "maven-compiler-plugin"); - if (sourceLevelConfiguration != null) { - Xpp3Dom source = sourceLevelConfiguration.getChild("source"); + if (sourceLevelConfiguration != null) { + Xpp3Dom source = sourceLevelConfiguration.getChild("source"); - if (source != null) { - sourceLevel = source.getValue(); - } + if (source != null) { + sourceLevel = source.getValue(); } + } - String configurationFile = Utils.getJackpotConfigurationFile(project); - boolean failOnWarnings = Utils.getJackpotFailOnWarnings(project); + String hint = Utils.getJackpotHint(project); + String configurationFile = Utils.getJackpotConfigurationFile(project); + boolean failOnWarnings = Utils.getJackpotFailOnWarnings(project); - List cmdLine = new ArrayList(); + List cmdLine = new ArrayList(); - if (apply) - cmdLine.add("--apply"); - else - cmdLine.add("--no-apply"); + if (apply) + cmdLine.add("--apply"); + else + cmdLine.add("--no-apply"); - cmdLine.addAll(sourceAndCompileClassPaths(Collections.singletonList(project))); - cmdLine.add("--source"); - cmdLine.add(sourceLevel); + cmdLine.addAll(sourceAndCompileClassPaths(Collections.singletonList(project))); + cmdLine.add("--source"); + cmdLine.add(sourceLevel); - if (configurationFile != null) { - cmdLine.add("--config-file"); - cmdLine.add(configurationFile); - } + if (hint != null) { + cmdLine.add("--hint"); + cmdLine.add(hint); + } - if (failOnWarnings) { - cmdLine.add("--fail-on-warnings"); - } + if (configurationFile != null) { + cmdLine.add("--config-file"); + cmdLine.add(configurationFile); + } - boolean hasSourceRoots = false; + if (failOnWarnings) { + cmdLine.add("--fail-on-warnings"); + } - for (String sr : (List) project.getCompileSourceRoots()) { - if (!hasSourceRoots && new File(sr).isDirectory()) { - hasSourceRoots = true; - } - cmdLine.add(sr); - } + boolean hasSourceRoots = false; - if (!hasSourceRoots) { - getLog().debug("jackpot30 analyze: Not source roots to operate on"); - return ; + for (String sr : (List) project.getCompileSourceRoots()) { + if (!hasSourceRoots && new File(sr).isDirectory()) { + hasSourceRoots = true; } + cmdLine.add(sr); + } + + if (!hasSourceRoots) { + getLog().debug("jackpot30 analyze: Not source roots to operate on"); + return ; + } + runWithArguments(cmdLine); + } + protected final void runWithArguments(List jackpotToolArguments) throws MojoExecutionException{ + try { Path bin = Paths.get(System.getProperty("java.home")) .resolve("bin"); Path launcher = bin.resolve("java"); + if (!Files.exists(launcher)) { launcher = bin.resolve("java.exe"); } + + List cmdLine = new ArrayList<>(); + cmdLine.addAll(0, Arrays.asList(launcher.toAbsolutePath().toString(), "-classpath", Main.class.getProtectionDomain().getCodeSource().getLocation().getPath(), "-XX:+IgnoreUnrecognizedVMOptions", "--add-opens=java.base/java.net=ALL-UNNAMED", "--add-opens=java.desktop/sun.awt=ALL-UNNAMED", Main.class.getCanonicalName())); + cmdLine.addAll(jackpotToolArguments); + if (new ProcessBuilder(cmdLine).inheritIO().start().waitFor() != 0) { throw new MojoExecutionException("jackpo30 failed."); } @@ -108,8 +122,6 @@ protected final void doRun(MavenProject project, boolean apply) throws MojoExecu throw new MojoExecutionException(ex.getMessage(), ex); } catch (InterruptedException ex) { throw new MojoExecutionException(ex.getMessage(), ex); - } catch (DependencyResolutionRequiredException ex) { - throw new MojoExecutionException(ex.getMessage(), ex); } } @@ -125,23 +137,27 @@ private static String toClassPathString(List entries) { } @SuppressWarnings("unchecked") - public static List sourceAndCompileClassPaths(Iterable projects) throws DependencyResolutionRequiredException { - List compileSourceRoots = new ArrayList(); - List compileClassPath = new ArrayList(); + public static List sourceAndCompileClassPaths(Iterable projects) throws MojoExecutionException { + try { + List compileSourceRoots = new ArrayList(); + List compileClassPath = new ArrayList(); + + for (MavenProject project : projects) { + compileSourceRoots.addAll((List) project.getCompileSourceRoots()); - for (MavenProject project : projects) { - compileSourceRoots.addAll((List) project.getCompileSourceRoots()); + for (Resource r : (List) project.getResources()) { + compileSourceRoots.add(r.getDirectory()); + } - for (Resource r : (List) project.getResources()) { - compileSourceRoots.add(r.getDirectory()); + compileClassPath.addAll((List) project.getCompileClasspathElements()); } - - compileClassPath.addAll((List) project.getCompileClasspathElements()); - } - return Arrays.asList("--sourcepath", - toClassPathString(compileSourceRoots), - "--classpath", - toClassPathString(compileClassPath)); + return Arrays.asList("--sourcepath", + toClassPathString(compileSourceRoots), + "--classpath", + toClassPathString(compileClassPath)); + } catch (DependencyResolutionRequiredException ex) { + throw new MojoExecutionException(ex.getMessage(), ex); + } } } diff --git a/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/ShowGuiJackpot30.java b/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/ShowGuiJackpot30.java index d96a1df..6a4aadc 100644 --- a/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/ShowGuiJackpot30.java +++ b/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/ShowGuiJackpot30.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -63,8 +62,6 @@ public void execute() throws MojoExecutionException, MojoFailureException { throw new MojoExecutionException(ex.getMessage(), ex); } catch (ClassNotFoundException ex) { throw new MojoExecutionException(ex.getMessage(), ex); - } catch (DependencyResolutionRequiredException ex) { - throw new MojoExecutionException(ex.getMessage(), ex); } } diff --git a/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/Utils.java b/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/Utils.java index 8310a22..5753573 100644 --- a/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/Utils.java +++ b/cmdline/maven/src/main/java/org/netbeans/modules/jackpot30/maven/Utils.java @@ -60,6 +60,20 @@ public static String getJackpotConfigurationFile(MavenProject project) { return null; } + public static String getJackpotHint(MavenProject project) { + Xpp3Dom configuration = getJackpotPluginConfiguration(project); + + if (configuration != null) { + Xpp3Dom configurationFileElement = configuration.getChild("hint"); + + if (configurationFileElement != null) { + return configurationFileElement.getValue(); + } + } + + return null; + } + public static boolean getJackpotFailOnWarnings(MavenProject project) { Xpp3Dom configuration = getJackpotPluginConfiguration(project); diff --git a/cmdline/maven/tests/hint-option/golden b/cmdline/maven/tests/hint-option/golden new file mode 100644 index 0000000..48fd794 --- /dev/null +++ b/cmdline/maven/tests/hint-option/golden @@ -0,0 +1,12 @@ +${basedir}/src/main/java/test/App.java:24: warning: [Usage_of_Collection_Map_size_equals_0] java.util.Arrays.asList(args).size() == 0 can be replaced with java.util.Arrays.asList(args).isEmpty() + boolean b = java.util.Arrays.asList(args).size() == 0; + ^ +[ERROR] Failed to execute goal org.apache.netbeans.modules.jackpot30:jackpot30-maven-plugin:20.0:analyze (default-cli) on project maven-test: jackpo30 failed. -> [Help 1] +[ERROR] +[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. +[ERROR] Re-run Maven using the -X switch to enable full debug logging. +[ERROR] +[ERROR] For more information about the errors and possible solutions, please read the following articles: +[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException + +result: 1 \ No newline at end of file diff --git a/cmdline/maven/tests/hint-option/pom.xml b/cmdline/maven/tests/hint-option/pom.xml new file mode 100644 index 0000000..c5cfe09 --- /dev/null +++ b/cmdline/maven/tests/hint-option/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + org.netbeans.modules.jackpot30 + maven-test + 1.0-SNAPSHOT + jar + + jackpot30-maven-plugin-test1 + http://maven.apache.org + + + UTF-8 + + + + + junit + junit + 3.8.1 + test + + + + + + org.apache.netbeans.modules.jackpot30 + jackpot30-maven-plugin + ${jackpot.plugin.version} + + SizeReplaceableByIsEmpty + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 17 + 17 + + + + + diff --git a/cmdline/maven/tests/hint-option/src/main/java/test/App.java b/cmdline/maven/tests/hint-option/src/main/java/test/App.java new file mode 100644 index 0000000..473678b --- /dev/null +++ b/cmdline/maven/tests/hint-option/src/main/java/test/App.java @@ -0,0 +1,26 @@ +/** + * 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 test; + +public class App { + + public static void main( String[] args ) { + boolean b = java.util.Arrays.asList(args).size() == 0; + } +} diff --git a/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java b/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java index 511ab15..9197e08 100644 --- a/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java +++ b/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java @@ -784,11 +784,27 @@ public GroupResult join(GroupResult other) { public abstract GroupResult join(GroupResult other); } - private static Iterable findHints(ClassPath sourceFrom, ClassPath binaryFrom, String name, HintsSettings toEnableIn) { + private static Iterable findHints(ClassPath sourceFrom, ClassPath binaryFrom, String hintSpecification, HintsSettings toEnableIn) { List descs = new LinkedList(); + Map> hints = listHints(sourceFrom, binaryFrom); - for (Entry> e : listHints(sourceFrom, binaryFrom).entrySet()) { - if (e.getKey().displayName.equals(name)) { + for (Entry> e : hints.entrySet()) { + if (e.getKey().displayName.equals(hintSpecification)) { + descs.addAll(e.getValue()); + toEnableIn.setEnabled(e.getKey(), true); + } + } + + if (!descs.isEmpty()) { + //found by hint display name, end: + return descs; + } + + //interpret "hintSpecification" as a comma-separated list of @SuppressWarnings keys: + Set keys = new HashSet<>(Arrays.asList(hintSpecification.split(", *"))); + + for (Entry> e : hints.entrySet()) { + if (!Collections.disjoint(e.getKey().suppressWarnings, keys)) { descs.addAll(e.getValue()); toEnableIn.setEnabled(e.getKey(), true); } @@ -916,7 +932,27 @@ private static void printHints(ClassPath sourceFrom, ClassPath binaryFrom) throw Set hints = new TreeSet(); for (Entry> e : listHints(sourceFrom, binaryFrom).entrySet()) { - hints.add(e.getKey().displayName); + StringBuilder printText = new StringBuilder(); + + printText.append(e.getKey().displayName); + + List preferredKeys = new ArrayList<>(); + + for (String key : e.getKey().suppressWarnings) { + if (key == null || "".equals(key)) { + //only print the preferred @SuppressWarnings keys: + break; + } + preferredKeys.add(key); + } + + if (preferredKeys.size() == 1) { + printText.append(", @SuppressWarnings key: ").append(preferredKeys.get(0)); + } else if (preferredKeys.size() > 1) { + printText.append(", @SuppressWarnings key: ").append(preferredKeys.stream().collect(Collectors.joining(", "))); + } + + hints.add(printText.toString()); } for (String h : hints) { diff --git a/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/MainTest.java b/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/MainTest.java index a709ae6..3f36ca8 100644 --- a/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/MainTest.java +++ b/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/MainTest.java @@ -1064,6 +1064,31 @@ public void testSource17() throws Exception { "--source", "17"); } + public void testRunBySuppressWarningsKeys() throws Exception { + String code = + "package test;\n" + + "public class Test {\n" + + " private void test(java.util.Collection c) {\n" + + " boolean b = c.size() == 0;\n" + + " assert b = true;\n" + + " }\n" + + "}\n"; + + doRunCompiler(code, + "${workdir}/src/test/Test.java:4: warning: [Usage_of_Collection_Map_size_equals_0] c.size() == 0 can be replaced with c.isEmpty()\n" + + " boolean b = c.size() == 0;\n" + + " ^\n" + + "${workdir}/src/test/Test.java:5: warning: [Assert_with_side_effects] Assert condition produces side effects\n" + + " assert b = true;\n" + + " ^\n", + "", + "src/test/Test.java", + code, + null, + "--hint", + "SizeReplaceableByIsEmpty, AssertWithSideEffects"); + } + private static final String DONT_APPEND_PATH = new String("DONT_APPEND_PATH"); private static final String IGNORE = new String("IGNORE");