New parameter for the command line tool: --no-apply that disables application of the fixes and prints 'errors' instead.
authorJan Lahoda <jlahoda@netbeans.org>
Wed, 22 Dec 2010 13:43:37 +0100
changeset 503597c27ada9e3
parent 502 24b040fb7f78
child 504 7f867d2e9c09
New parameter for the command line tool: --no-apply that disables application of the fixes and prints 'errors' instead.
cmdline/tool/nbproject/genfiles.properties
cmdline/tool/nbproject/project.xml
cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java
cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/CreateToolTest.java
cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/MainTest.java
     1.1 --- a/cmdline/tool/nbproject/genfiles.properties	Fri Dec 17 21:19:03 2010 +0100
     1.2 +++ b/cmdline/tool/nbproject/genfiles.properties	Wed Dec 22 13:43:37 2010 +0100
     1.3 @@ -3,6 +3,6 @@
     1.4  build.xml.stylesheet.CRC32=a56c6a5b@1.44
     1.5  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
     1.6  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
     1.7 -nbproject/build-impl.xml.data.CRC32=9f4c23ee
     1.8 +nbproject/build-impl.xml.data.CRC32=3872d859
     1.9  nbproject/build-impl.xml.script.CRC32=08f1fb11
    1.10  nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.44
     2.1 --- a/cmdline/tool/nbproject/project.xml	Fri Dec 17 21:19:03 2010 +0100
     2.2 +++ b/cmdline/tool/nbproject/project.xml	Wed Dec 22 13:43:37 2010 +0100
     2.3 @@ -148,6 +148,15 @@
     2.4                      </run-dependency>
     2.5                  </dependency>
     2.6                  <dependency>
     2.7 +                    <code-name-base>org.netbeans.spi.editor.hints</code-name-base>
     2.8 +                    <build-prerequisite/>
     2.9 +                    <compile-dependency/>
    2.10 +                    <run-dependency>
    2.11 +                        <release-version>0</release-version>
    2.12 +                        <specification-version>1.16.0.7.5</specification-version>
    2.13 +                    </run-dependency>
    2.14 +                </dependency>
    2.15 +                <dependency>
    2.16                      <code-name-base>org.openide.filesystems</code-name-base>
    2.17                      <build-prerequisite/>
    2.18                      <compile-dependency/>
    2.19 @@ -172,6 +181,14 @@
    2.20                      </run-dependency>
    2.21                  </dependency>
    2.22                  <dependency>
    2.23 +                    <code-name-base>org.openide.text</code-name-base>
    2.24 +                    <build-prerequisite/>
    2.25 +                    <compile-dependency/>
    2.26 +                    <run-dependency>
    2.27 +                        <specification-version>6.34</specification-version>
    2.28 +                    </run-dependency>
    2.29 +                </dependency>
    2.30 +                <dependency>
    2.31                      <code-name-base>org.openide.util</code-name-base>
    2.32                      <build-prerequisite/>
    2.33                      <compile-dependency/>
     3.1 --- a/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java	Fri Dec 17 21:19:03 2010 +0100
     3.2 +++ b/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java	Wed Dec 22 13:43:37 2010 +0100
     3.3 @@ -47,7 +47,6 @@
     3.4  import java.io.PrintStream;
     3.5  import java.net.URL;
     3.6  import java.util.ArrayList;
     3.7 -import java.util.Arrays;
     3.8  import java.util.Collection;
     3.9  import java.util.LinkedList;
    3.10  import java.util.List;
    3.11 @@ -64,13 +63,16 @@
    3.12  import joptsimple.OptionParser;
    3.13  import joptsimple.OptionSet;
    3.14  import org.netbeans.api.java.classpath.ClassPath;
    3.15 +import org.netbeans.api.java.source.CompilationController;
    3.16  import org.netbeans.api.java.source.ModificationResult;
    3.17  import org.netbeans.core.startup.MainLookup;
    3.18  import org.netbeans.modules.jackpot30.impl.MessageImpl;
    3.19  import org.netbeans.modules.jackpot30.impl.RulesManager;
    3.20  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch;
    3.21  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.BatchResult;
    3.22 +import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Resource;
    3.23  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Scope;
    3.24 +import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.VerifiedSpansCallBack;
    3.25  import org.netbeans.modules.jackpot30.impl.batch.BatchUtilities;
    3.26  import org.netbeans.modules.jackpot30.impl.batch.ProgressHandleWrapper;
    3.27  import org.netbeans.modules.jackpot30.impl.batch.ProgressHandleWrapper.ProgressHandleAbstraction;
    3.28 @@ -79,6 +81,7 @@
    3.29  import org.netbeans.modules.java.source.parsing.JavaPathRecognizer;
    3.30  import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
    3.31  import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater;
    3.32 +import org.netbeans.spi.editor.hints.ErrorDescription;
    3.33  import org.netbeans.spi.java.classpath.ClassPathProvider;
    3.34  import org.netbeans.spi.java.classpath.support.ClassPathSupport;
    3.35  import org.netbeans.spi.java.queries.SourceLevelQueryImplementation2;
    3.36 @@ -97,6 +100,8 @@
    3.37   */
    3.38  public class Main {
    3.39  
    3.40 +    private static final String OPTION_NO_APPLY = "no-apply";
    3.41 +    
    3.42      public static void main(String... args) throws IOException, ClassNotFoundException {
    3.43          System.exit(compile(args));
    3.44      }
    3.45 @@ -117,6 +122,7 @@
    3.46          parser.accepts("progress", "show progress");
    3.47          parser.accepts("debug", "enable debugging loggers");
    3.48          parser.accepts("help", "prints this help");
    3.49 +        parser.accepts(OPTION_NO_APPLY, "do not apply changes - only print locations were the hint would be applied");
    3.50  
    3.51          OptionSet parsed;
    3.52  
    3.53 @@ -207,7 +213,13 @@
    3.54                  
    3.55                  FileUtil.setMIMEType("java", "text/x-java");
    3.56  
    3.57 -                perform(hints, roots.toArray(new FileObject[0]), parsed.has("progress"), parsed.valueOf(out));
    3.58 +                ProgressHandleWrapper progress = parsed.has("progress") ? new ProgressHandleWrapper(new ConsoleProgressHandleAbstraction(), 1) : new ProgressHandleWrapper(1);
    3.59 +
    3.60 +                if (parsed.has(OPTION_NO_APPLY)) {
    3.61 +                    findOccurrences(hints, roots.toArray(new FileObject[0]), progress, parsed.valueOf(out));
    3.62 +                } else {
    3.63 +                    apply(hints, roots.toArray(new FileObject[0]), progress, parsed.valueOf(out));
    3.64 +                }
    3.65              } catch (Throwable e) {
    3.66                  e.printStackTrace();
    3.67              }
    3.68 @@ -243,8 +255,49 @@
    3.69          TOP_LOGGER.setLevel(Level.OFF);
    3.70      }
    3.71      
    3.72 -    private static void perform(Iterable<? extends HintDescription> descs, FileObject[] sourceRoot, boolean showProgress, File out) throws IOException {
    3.73 -        ProgressHandleWrapper w = showProgress ? new ProgressHandleWrapper(new ConsoleProgressHandleAbstraction(), 1, 1) : new ProgressHandleWrapper(1, 1);
    3.74 +    private static void findOccurrences(Iterable<? extends HintDescription> descs, FileObject[] sourceRoot, ProgressHandleWrapper progress, File out) throws IOException {
    3.75 +        ProgressHandleWrapper w = progress.startNextPartWithEmbedding(1, 1);
    3.76 +        BatchResult occurrences = BatchSearch.findOccurrences(descs, Scope.createGivenSourceRoots(sourceRoot), w);
    3.77 +
    3.78 +        List<MessageImpl> problems = new LinkedList<MessageImpl>();
    3.79 +        BatchSearch.getVerifiedSpans(occurrences, progress, new VerifiedSpansCallBack() {
    3.80 +            @Override public void groupStarted() {}
    3.81 +            @Override public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
    3.82 +                for (ErrorDescription ed : hints) {
    3.83 +                    print(ed);
    3.84 +                }
    3.85 +                return true;
    3.86 +            }
    3.87 +            @Override public void groupFinished() {}
    3.88 +            @Override public void cannotVerifySpan(Resource r) {
    3.89 +                //TODO: ignored - what to do?
    3.90 +            }
    3.91 +        }, problems);
    3.92 +    }
    3.93 +
    3.94 +    private static void print(ErrorDescription error) throws IOException {
    3.95 +        int lineNumber = error.getRange().getBegin().getLine();
    3.96 +        String line = error.getFile().asLines().get(lineNumber);
    3.97 +        int column = error.getRange().getBegin().getColumn();
    3.98 +        StringBuilder b = new StringBuilder();
    3.99 +
   3.100 +        for (int i = 0; i < column; i++) {
   3.101 +            if (Character.isWhitespace(line.charAt(i))) {
   3.102 +                b.append(line.charAt(i));
   3.103 +            } else {
   3.104 +                b.append(' ');
   3.105 +            }
   3.106 +        }
   3.107 +
   3.108 +        b.append('^');
   3.109 +
   3.110 +        System.out.println(FileUtil.getFileDisplayName(error.getFile()) + ":" + lineNumber + ":" + error.getDescription());
   3.111 +        System.out.println(line);
   3.112 +        System.out.println(b);
   3.113 +    }
   3.114 +
   3.115 +    private static void apply(Iterable<? extends HintDescription> descs, FileObject[] sourceRoot, ProgressHandleWrapper progress, File out) throws IOException {
   3.116 +        ProgressHandleWrapper w = progress.startNextPartWithEmbedding(1, 1);
   3.117          BatchResult occurrences = BatchSearch.findOccurrences(descs, Scope.createGivenSourceRoots(sourceRoot), w);
   3.118  
   3.119          List<MessageImpl> problems = new LinkedList<MessageImpl>();
     4.1 --- a/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/CreateToolTest.java	Fri Dec 17 21:19:03 2010 +0100
     4.2 +++ b/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/CreateToolTest.java	Wed Dec 22 13:43:37 2010 +0100
     4.3 @@ -39,6 +39,7 @@
     4.4  
     4.5  package org.netbeans.modules.jackpot30.cmdline;
     4.6  
     4.7 +import java.io.ByteArrayOutputStream;
     4.8  import java.io.File;
     4.9  import java.io.IOException;
    4.10  import java.io.InputStream;
    4.11 @@ -65,7 +66,7 @@
    4.12      private static File compiler;
    4.13  
    4.14      @Override
    4.15 -    protected void reallyRunCompiler(File workingDir, String... params) throws IOException, Exception {
    4.16 +    protected void reallyRunCompiler(File workingDir, String[] output, String... params) throws Exception {
    4.17          assertNotNull(compiler);
    4.18          List<String> ll = new LinkedList<String>();
    4.19          ll.add("java");
    4.20 @@ -78,11 +79,16 @@
    4.21          ll.addAll(Arrays.asList(params));
    4.22          try {
    4.23              Process p = Runtime.getRuntime().exec(ll.toArray(new String[0]), null, workingDir);
    4.24 +            CopyStream outCopy = new CopyStream(p.getInputStream(), output, 0);
    4.25 +            CopyStream errCopy = new CopyStream(p.getErrorStream(), output, 1);
    4.26  
    4.27 -            new CopyStream(p.getInputStream(), System.out).start();
    4.28 -            new CopyStream(p.getErrorStream(), System.err).start();
    4.29 +            outCopy.start();
    4.30 +            errCopy.start();
    4.31  
    4.32              assertEquals(0, p.waitFor());
    4.33 +
    4.34 +            outCopy.doJoin();
    4.35 +            errCopy.doJoin();
    4.36          } catch (Throwable t) {
    4.37              throw new IOException(t);
    4.38          }
    4.39 @@ -90,11 +96,15 @@
    4.40  
    4.41      private static final class CopyStream extends Thread {
    4.42          private final InputStream ins;
    4.43 -        private final OutputStream out;
    4.44 +        private final ByteArrayOutputStream out;
    4.45 +        private final String[] target;
    4.46 +        private final int targetIndex;
    4.47  
    4.48 -        public CopyStream(InputStream ins, OutputStream out) {
    4.49 +        public CopyStream(InputStream ins, String[] target, int targetIndex) {
    4.50              this.ins = ins;
    4.51 -            this.out = out;
    4.52 +            this.out = new ByteArrayOutputStream();
    4.53 +            this.target = target;
    4.54 +            this.targetIndex = targetIndex;
    4.55          }
    4.56  
    4.57          @Override
    4.58 @@ -112,6 +122,12 @@
    4.59              }
    4.60          }
    4.61  
    4.62 +        public void doJoin() throws InterruptedException, IOException {
    4.63 +            join(60000);
    4.64 +            out.close();
    4.65 +            target[targetIndex] = new String(out.toByteArray());
    4.66 +        }
    4.67 +
    4.68      }
    4.69  
    4.70      public static Test suite() {
     5.1 --- a/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/MainTest.java	Fri Dec 17 21:19:03 2010 +0100
     5.2 +++ b/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/MainTest.java	Wed Dec 22 13:43:37 2010 +0100
     5.3 @@ -39,11 +39,15 @@
     5.4  
     5.5  package org.netbeans.modules.jackpot30.cmdline;
     5.6  
     5.7 +import java.io.ByteArrayOutputStream;
     5.8  import java.io.File;
     5.9 +import java.io.PrintStream;
    5.10  import java.util.Arrays;
    5.11  import java.util.Collections;
    5.12  import java.util.LinkedList;
    5.13  import java.util.List;
    5.14 +import java.util.regex.Matcher;
    5.15 +import java.util.regex.Pattern;
    5.16  import org.netbeans.api.java.source.TestUtilities;
    5.17  import org.netbeans.junit.NbTestCase;
    5.18  
    5.19 @@ -66,19 +70,54 @@
    5.20              "    }\n" +
    5.21              "}\n";
    5.22  
    5.23 -        doRunCompiler(golden, "src/test/Test.java",
    5.24 -                              "package test;\n" +
    5.25 -                              "public class Test {\n" +
    5.26 -                              "    private void test(java.util.Collection c) {\n" +
    5.27 -                              "        boolean b = c.size() == 0;\n" +
    5.28 -                              "    }\n" +
    5.29 -                              "}\n",
    5.30 -                              null,
    5.31 -                              "--hint",
    5.32 -                              "Usage of .size() == 0");
    5.33 +        doRunCompiler(golden,
    5.34 +                      null,
    5.35 +                      null,
    5.36 +                      "src/test/Test.java",
    5.37 +                      "package test;\n" +
    5.38 +                      "public class Test {\n" +
    5.39 +                      "    private void test(java.util.Collection c) {\n" +
    5.40 +                      "        boolean b = c.size() == 0;\n" +
    5.41 +                      "    }\n" +
    5.42 +                      "}\n",
    5.43 +                      null,
    5.44 +                      "--hint",
    5.45 +                      "Usage of .size() == 0");
    5.46      }
    5.47  
    5.48 -    private void doRunCompiler(String golden, String... fileContentAndExtraOptions) throws Exception {
    5.49 +    public void testDoNotApply() throws Exception {
    5.50 +        String golden =
    5.51 +            "package test;\n" +
    5.52 +            "public class Test {\n" +
    5.53 +            "    private void test(java.util.Collection c) {\n" +
    5.54 +            "        boolean b1 = c.size() == 0;\n" +
    5.55 +            "\tboolean b2 = c.size() == 0;\n" +
    5.56 +            "    }\n" +
    5.57 +            "}\n";
    5.58 +
    5.59 +        doRunCompiler(golden,
    5.60 +                      "${workdir}/src/test/Test.java:3:Usage of .size() == 0 can be replaced with .isEmpty()\n" +
    5.61 +                      "        boolean b1 = c.size() == 0;\n" +
    5.62 +                      "                     ^\n" +
    5.63 +                      "${workdir}/src/test/Test.java:4:Usage of .size() == 0 can be replaced with .isEmpty()\n" +
    5.64 +                      "\tboolean b2 = c.size() == 0;\n" +
    5.65 +                      "\t             ^\n",
    5.66 +                      null,
    5.67 +                      "src/test/Test.java",
    5.68 +                      "package test;\n" +
    5.69 +                      "public class Test {\n" +
    5.70 +                      "    private void test(java.util.Collection c) {\n" +
    5.71 +                      "        boolean b1 = c.size() == 0;\n" +
    5.72 +                      "\tboolean b2 = c.size() == 0;\n" +
    5.73 +                      "    }\n" +
    5.74 +                      "}\n",
    5.75 +                      null,
    5.76 +                      "--hint",
    5.77 +                      "Usage of .size() == 0",
    5.78 +                      "--no-apply");
    5.79 +    }
    5.80 +
    5.81 +    private void doRunCompiler(String golden, String stdOut, String stdErr, String... fileContentAndExtraOptions) throws Exception {
    5.82          List<String> fileAndContent = new LinkedList<String>();
    5.83          List<String> extraOptions = new LinkedList<String>();
    5.84          List<String> fileContentAndExtraOptionsList = Arrays.asList(fileContentAndExtraOptions);
    5.85 @@ -114,20 +153,44 @@
    5.86          options.addAll(extraOptions);
    5.87          options.add(wd.getAbsolutePath());
    5.88  
    5.89 -        reallyRunCompiler(wd, options.toArray(new String[0]));
    5.90 +        String[] output = new String[2];
    5.91 +
    5.92 +        reallyRunCompiler(wd, output, options.toArray(new String[0]));
    5.93  
    5.94          assertEquals(golden, TestUtilities.copyFileToString(source));
    5.95 +
    5.96 +        if (stdOut != null) {
    5.97 +            assertEquals(stdOut, output[0].replaceAll(Pattern.quote(wd.getAbsolutePath()), Matcher.quoteReplacement("${workdir}")));
    5.98 +        }
    5.99 +
   5.100 +        if (stdErr != null) {
   5.101 +            assertEquals(stdErr, output[1].replaceAll(Pattern.quote(wd.getAbsolutePath()), Matcher.quoteReplacement("${workdir}")));
   5.102 +        }
   5.103      }
   5.104  
   5.105 -    protected void reallyRunCompiler(File workDir, String... params) throws Exception {
   5.106 +    protected void reallyRunCompiler(File workDir, String[] output, String... params) throws Exception {
   5.107          String oldUserDir = System.getProperty("user.dir");
   5.108  
   5.109          System.setProperty("user.dir", workDir.getAbsolutePath());
   5.110 +        
   5.111 +        PrintStream oldOut = System.out;
   5.112 +        ByteArrayOutputStream outData = new ByteArrayOutputStream();
   5.113 +        System.setOut(new PrintStream(outData, true, "UTF-8"));
   5.114 +
   5.115 +        PrintStream oldErr = System.err;
   5.116 +        ByteArrayOutputStream errData = new ByteArrayOutputStream();
   5.117 +        System.setErr(new PrintStream(errData, true, "UTF-8"));
   5.118  
   5.119          try {
   5.120              assertEquals(0, Main.compile(params));
   5.121          } finally {
   5.122              System.setProperty("user.dir", oldUserDir);
   5.123 +            System.out.close();
   5.124 +            output[0] = new String(outData.toByteArray(), "UTF-8");
   5.125 +            System.setOut(oldOut);
   5.126 +            System.err.close();
   5.127 +            output[1] = new String(errData.toByteArray(), "UTF-8");
   5.128 +            System.setErr(oldErr);
   5.129          }
   5.130      }
   5.131