8004833: Integrate doclint support into javac

Wed, 19 Dec 2012 11:29:56 +0000

author
jjg
date
Wed, 19 Dec 2012 11:29:56 +0000
changeset 1463
67b01d295cd2
parent 1462
573b38691a74
child 1464
f72c9c5aeaef

8004833: Integrate doclint support into javac
Reviewed-by: mcimadamore

src/share/classes/com/sun/tools/javac/main/Main.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/main/Option.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/resources/javac.properties file | annotate | diff | comparison | revisions
test/tools/javac/doclint/DocLintTest.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/main/Main.java	Tue Dec 18 18:15:47 2012 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/main/Main.java	Wed Dec 19 11:29:56 2012 +0000
     1.3 @@ -44,6 +44,8 @@
     1.4  
     1.5  import com.sun.source.util.JavacTask;
     1.6  import com.sun.source.util.Plugin;
     1.7 +import com.sun.tools.doclint.DocLint;
     1.8 +import com.sun.tools.javac.api.BasicJavacTask;
     1.9  import com.sun.tools.javac.code.Source;
    1.10  import com.sun.tools.javac.file.CacheFSInfo;
    1.11  import com.sun.tools.javac.file.JavacFileManager;
    1.12 @@ -428,6 +430,7 @@
    1.13              if (batchMode)
    1.14                  CacheFSInfo.preRegister(context);
    1.15  
    1.16 +            // FIXME: this code will not be invoked if using JavacTask.parse/analyze/generate
    1.17              // invoke any available plugins
    1.18              String plugins = options.get(PLUGIN);
    1.19              if (plugins != null) {
    1.20 @@ -464,11 +467,32 @@
    1.21                  }
    1.22              }
    1.23  
    1.24 +            comp = JavaCompiler.instance(context);
    1.25 +
    1.26 +            // FIXME: this code will not be invoked if using JavacTask.parse/analyze/generate
    1.27 +            String xdoclint = options.get(XDOCLINT);
    1.28 +            String xdoclintCustom = options.get(XDOCLINT_CUSTOM);
    1.29 +            if (xdoclint != null || xdoclintCustom != null) {
    1.30 +                Set<String> doclintOpts = new LinkedHashSet<String>();
    1.31 +                if (xdoclint != null)
    1.32 +                    doclintOpts.add(DocLint.XMSGS_OPTION);
    1.33 +                if (xdoclintCustom != null) {
    1.34 +                    for (String s: xdoclintCustom.split("\\s+")) {
    1.35 +                        if (s.isEmpty())
    1.36 +                            continue;
    1.37 +                        doclintOpts.add(s.replace(XDOCLINT_CUSTOM.text, DocLint.XMSGS_CUSTOM_PREFIX));
    1.38 +                    }
    1.39 +                }
    1.40 +                if (!(doclintOpts.size() == 1
    1.41 +                        && doclintOpts.iterator().next().equals(DocLint.XMSGS_CUSTOM_PREFIX + "none"))) {
    1.42 +                    JavacTask t = BasicJavacTask.instance(context);
    1.43 +                    new DocLint().init(t, doclintOpts.toArray(new String[doclintOpts.size()]));
    1.44 +                    comp.keepComments = true;
    1.45 +                }
    1.46 +            }
    1.47 +
    1.48              fileManager = context.get(JavaFileManager.class);
    1.49  
    1.50 -            comp = JavaCompiler.instance(context);
    1.51 -            if (comp == null) return Result.SYSERR;
    1.52 -
    1.53              if (!files.isEmpty()) {
    1.54                  // add filenames to fileObjects
    1.55                  comp = JavaCompiler.instance(context);
     2.1 --- a/src/share/classes/com/sun/tools/javac/main/Option.java	Tue Dec 18 18:15:47 2012 -0800
     2.2 +++ b/src/share/classes/com/sun/tools/javac/main/Option.java	Wed Dec 19 11:29:56 2012 +0000
     2.3 @@ -25,28 +25,30 @@
     2.4  
     2.5  package com.sun.tools.javac.main;
     2.6  
     2.7 +import java.io.File;
     2.8 +import java.io.FileWriter;
     2.9 +import java.io.PrintWriter;
    2.10  import java.util.Collections;
    2.11 -import com.sun.tools.javac.util.Log.PrefixKind;
    2.12 -import com.sun.tools.javac.util.Log.WriterKind;
    2.13 -import com.sun.tools.javac.util.Log;
    2.14 +import java.util.EnumSet;
    2.15 +import java.util.LinkedHashMap;
    2.16 +import java.util.Map;
    2.17 +import java.util.Set;
    2.18 +
    2.19 +import javax.lang.model.SourceVersion;
    2.20 +
    2.21 +import com.sun.tools.doclint.DocLint;
    2.22  import com.sun.tools.javac.code.Lint;
    2.23  import com.sun.tools.javac.code.Source;
    2.24  import com.sun.tools.javac.code.Type;
    2.25  import com.sun.tools.javac.jvm.Target;
    2.26 +import com.sun.tools.javac.processing.JavacProcessingEnvironment;
    2.27 +import com.sun.tools.javac.util.Log;
    2.28 +import com.sun.tools.javac.util.Log.PrefixKind;
    2.29 +import com.sun.tools.javac.util.Log.WriterKind;
    2.30  import com.sun.tools.javac.util.Options;
    2.31 -import com.sun.tools.javac.processing.JavacProcessingEnvironment;
    2.32 -import java.io.File;
    2.33 -import java.io.FileWriter;
    2.34 -import java.io.PrintWriter;
    2.35 -import java.util.EnumSet;
    2.36 -import java.util.LinkedHashMap;
    2.37 -import java.util.Map;
    2.38 -import java.util.Set;
    2.39 -import javax.lang.model.SourceVersion;
    2.40 -
    2.41  import static com.sun.tools.javac.main.Option.ChoiceKind.*;
    2.42 +import static com.sun.tools.javac.main.Option.OptionGroup.*;
    2.43  import static com.sun.tools.javac.main.Option.OptionKind.*;
    2.44 -import static com.sun.tools.javac.main.Option.OptionGroup.*;
    2.45  
    2.46  /**
    2.47   * Options for javac. The specific Option to handle a command-line option
    2.48 @@ -79,6 +81,24 @@
    2.49      XLINT_CUSTOM("-Xlint:", "opt.Xlint.suboptlist",
    2.50              EXTENDED,   BASIC, ANYOF, getXLintChoices()),
    2.51  
    2.52 +    XDOCLINT("-Xdoclint", "opt.Xdoclint", EXTENDED, BASIC),
    2.53 +
    2.54 +    XDOCLINT_CUSTOM("-Xdoclint:", "opt.Xdoclint.subopts", "opt.Xdoclint.custom", EXTENDED, BASIC) {
    2.55 +        @Override
    2.56 +        public boolean matches(String option) {
    2.57 +            return DocLint.isValidOption(
    2.58 +                    option.replace(XDOCLINT_CUSTOM.text, DocLint.XMSGS_CUSTOM_PREFIX));
    2.59 +        }
    2.60 +
    2.61 +        @Override
    2.62 +        public boolean process(OptionHelper helper, String option) {
    2.63 +            String prev = helper.get(XDOCLINT_CUSTOM);
    2.64 +            String next = (prev == null) ? option : (prev + " " + option);
    2.65 +            helper.put(XDOCLINT_CUSTOM.text, next);
    2.66 +            return false;
    2.67 +        }
    2.68 +    },
    2.69 +
    2.70      // -nowarn is retained for command-line backward compatibility
    2.71      NOWARN("-nowarn", "opt.nowarn", STANDARD, BASIC) {
    2.72          @Override
     3.1 --- a/src/share/classes/com/sun/tools/javac/resources/javac.properties	Tue Dec 18 18:15:47 2012 -0800
     3.2 +++ b/src/share/classes/com/sun/tools/javac/resources/javac.properties	Wed Dec 19 11:29:56 2012 +0000
     3.3 @@ -138,6 +138,14 @@
     3.4      Enable recommended warnings
     3.5  javac.opt.Xlint.suboptlist=\
     3.6      Enable or disable specific warnings
     3.7 +javac.opt.Xdoclint=\
     3.8 +    Enable recommended checks for problems in javadoc comments
     3.9 +javac.opt.Xdoclint.subopts = \
    3.10 +    (all|[-]<group>)[/<access>]
    3.11 +javac.opt.Xdoclint.custom=\n\
    3.12 +\        Enable or disable specific checks for problems in javadoc comments,\n\
    3.13 +\        where <group> is one of accessibility, html, reference, or syntax,\n\
    3.14 +\        and <access> is one of public, protected, package, or private.
    3.15  javac.opt.Xstdout=\
    3.16      Redirect standard output
    3.17  javac.opt.X=\
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/tools/javac/doclint/DocLintTest.java	Wed Dec 19 11:29:56 2012 +0000
     4.3 @@ -0,0 +1,225 @@
     4.4 +/*
     4.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.
    4.11 + *
    4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.15 + * version 2 for more details (a copy is included in the LICENSE file that
    4.16 + * accompanied this code).
    4.17 + *
    4.18 + * You should have received a copy of the GNU General Public License version
    4.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.21 + *
    4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    4.23 + * or visit www.oracle.com if you need additional information or have any
    4.24 + * questions.
    4.25 + */
    4.26 +
    4.27 +/*
    4.28 + * @test
    4.29 + * @bug 8004833
    4.30 + * @summary Integrate doclint support into javac
    4.31 + */
    4.32 +
    4.33 +import java.io.File;
    4.34 +import java.io.PrintWriter;
    4.35 +import java.io.StringWriter;
    4.36 +import java.net.URI;
    4.37 +import java.util.Arrays;
    4.38 +import java.util.Collections;
    4.39 +import java.util.List;
    4.40 +
    4.41 +import javax.tools.Diagnostic;
    4.42 +import javax.tools.JavaCompiler;
    4.43 +import javax.tools.JavaFileObject;
    4.44 +import javax.tools.SimpleJavaFileObject;
    4.45 +import javax.tools.StandardJavaFileManager;
    4.46 +import javax.tools.StandardLocation;
    4.47 +import javax.tools.ToolProvider;
    4.48 +import static javax.tools.Diagnostic.Kind.*;
    4.49 +
    4.50 +import com.sun.source.util.JavacTask;
    4.51 +import com.sun.tools.javac.main.Main;
    4.52 +import java.util.EnumSet;
    4.53 +import java.util.Set;
    4.54 +import java.util.regex.Matcher;
    4.55 +import java.util.regex.Pattern;
    4.56 +
    4.57 +public class DocLintTest {
    4.58 +    public static void main(String... args) throws Exception {
    4.59 +        new DocLintTest().run();
    4.60 +    }
    4.61 +
    4.62 +    JavaCompiler javac;
    4.63 +    StandardJavaFileManager fm;
    4.64 +    JavaFileObject file;
    4.65 +
    4.66 +    final String code =
    4.67 +        /* 01 */    "/** Class comment. */\n" +
    4.68 +        /* 02 */    "public class Test {\n" +
    4.69 +        /* 03 */    "    /** Method comment. */\n" +
    4.70 +        /* 04 */    "    public void method() { }\n" +
    4.71 +        /* 05 */    "\n" +
    4.72 +        /* 06 */    "    /** Syntax < error. */\n" +
    4.73 +        /* 07 */    "    private void syntaxError() { }\n" +
    4.74 +        /* 08 */    "\n" +
    4.75 +        /* 09 */    "    /** @see DoesNotExist */\n" +
    4.76 +        /* 10 */    "    protected void referenceError() { }\n" +
    4.77 +        /* 08 */    "\n" +
    4.78 +        /* 09 */    "    /** @return */\n" +
    4.79 +        /* 10 */    "    public int emptyReturn() { return 0; }\n" +
    4.80 +        /* 11 */    "}\n";
    4.81 +
    4.82 +    final String rawDiags = "-XDrawDiagnostics";
    4.83 +    private enum Message {
    4.84 +        // doclint messages
    4.85 +        DL_ERR6(ERROR, "Test.java:6:16: compiler.err.proc.messager: malformed HTML"),
    4.86 +        DL_ERR9(ERROR, "Test.java:9:14: compiler.err.proc.messager: reference not found"),
    4.87 +        DL_WRN12(WARNING, "Test.java:12:9: compiler.warn.proc.messager: no description for @return"),
    4.88 +
    4.89 +        OPT_BADARG(ERROR, "invalid flag: -Xdoclint:badarg");
    4.90 +
    4.91 +        final Diagnostic.Kind kind;
    4.92 +        final String text;
    4.93 +
    4.94 +        static Message get(String text) {
    4.95 +            for (Message m: values()) {
    4.96 +                if (m.text.equals(text))
    4.97 +                    return m;
    4.98 +            }
    4.99 +            return null;
   4.100 +        }
   4.101 +
   4.102 +        Message(Diagnostic.Kind kind, String text) {
   4.103 +            this.kind = kind;
   4.104 +            this.text = text;
   4.105 +        }
   4.106 +
   4.107 +        @Override
   4.108 +        public String toString() {
   4.109 +            return "[" + kind + ",\"" + text + "\"]";
   4.110 +        }
   4.111 +    }
   4.112 +    void run() throws Exception {
   4.113 +        javac = ToolProvider.getSystemJavaCompiler();
   4.114 +        fm = javac.getStandardFileManager(null, null, null);
   4.115 +        fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(".")));
   4.116 +        file = new SimpleJavaFileObject(URI.create("Test.java"), JavaFileObject.Kind.SOURCE) {
   4.117 +            @Override
   4.118 +            public CharSequence getCharContent(boolean ignoreEncoding) {
   4.119 +                return code;
   4.120 +            }
   4.121 +        };
   4.122 +
   4.123 +        test(Collections.<String>emptyList(),
   4.124 +                Main.Result.OK,
   4.125 +                EnumSet.noneOf(Message.class));
   4.126 +
   4.127 +        test(Arrays.asList("-Xdoclint:none"),
   4.128 +                Main.Result.OK,
   4.129 +                EnumSet.noneOf(Message.class));
   4.130 +
   4.131 +        test(Arrays.asList(rawDiags, "-Xdoclint"),
   4.132 +                Main.Result.ERROR,
   4.133 +                EnumSet.of(Message.DL_ERR6, Message.DL_ERR9, Message.DL_WRN12));
   4.134 +
   4.135 +        test(Arrays.asList(rawDiags, "-Xdoclint:all/public"),
   4.136 +                Main.Result.OK,
   4.137 +                EnumSet.of(Message.DL_WRN12));
   4.138 +
   4.139 +        test(Arrays.asList(rawDiags, "-Xdoclint:syntax"),
   4.140 +                Main.Result.ERROR,
   4.141 +                EnumSet.of(Message.DL_ERR6, Message.DL_WRN12));
   4.142 +
   4.143 +        test(Arrays.asList(rawDiags, "-Xdoclint:reference"),
   4.144 +                Main.Result.ERROR,
   4.145 +                EnumSet.of(Message.DL_ERR9));
   4.146 +
   4.147 +        test(Arrays.asList(rawDiags, "-Xdoclint:badarg"),
   4.148 +                Main.Result.CMDERR,
   4.149 +                EnumSet.of(Message.OPT_BADARG));
   4.150 +
   4.151 +        if (errors > 0)
   4.152 +            throw new Exception(errors + " errors occurred");
   4.153 +    }
   4.154 +
   4.155 +    void test(List<String> opts, Main.Result expectResult, Set<Message> expectMessages) {
   4.156 +        System.err.println("test: " + opts);
   4.157 +        StringWriter sw = new StringWriter();
   4.158 +        PrintWriter pw = new PrintWriter(sw);
   4.159 +        List<JavaFileObject> files = Arrays.asList(file);
   4.160 +        try {
   4.161 +            JavacTask t = (JavacTask) javac.getTask(pw, fm, null, opts, null, files);
   4.162 +            boolean ok = t.call();
   4.163 +            pw.close();
   4.164 +            String out = sw.toString().replaceAll("[\r\n]+", "\n");
   4.165 +            if (!out.isEmpty())
   4.166 +                System.err.println(out);
   4.167 +            if (ok && expectResult != Main.Result.OK) {
   4.168 +                error("Compilation succeeded unexpectedly");
   4.169 +            } else if (!ok && expectResult != Main.Result.ERROR) {
   4.170 +                error("Compilation failed unexpectedly");
   4.171 +            } else
   4.172 +                check(out, expectMessages);
   4.173 +        } catch (IllegalArgumentException e) {
   4.174 +            System.err.println(e);
   4.175 +            String expectOut = expectMessages.iterator().next().text;
   4.176 +            if (expectResult != Main.Result.CMDERR)
   4.177 +                error("unexpected exception caught");
   4.178 +            else if (!e.getMessage().equals(expectOut)) {
   4.179 +                error("unexpected exception message: "
   4.180 +                        + e.getMessage()
   4.181 +                        + " expected: " + expectOut);
   4.182 +            }
   4.183 +        }
   4.184 +
   4.185 +//        if (errors > 0)
   4.186 +//            throw new Error("stop");
   4.187 +    }
   4.188 +
   4.189 +    private void check(String out, Set<Message> expect) {
   4.190 +        Pattern stats = Pattern.compile("^([1-9]+) (error|warning)(s?)");
   4.191 +        Set<Message> found = EnumSet.noneOf(Message.class);
   4.192 +        int e = 0, w = 0;
   4.193 +        if (!out.isEmpty()) {
   4.194 +            for (String line: out.split("[\r\n]+")) {
   4.195 +                Matcher s = stats.matcher(line);
   4.196 +                if (s.matches()) {
   4.197 +                    int i = Integer.valueOf(s.group(1));
   4.198 +                    if (s.group(2).equals("error"))
   4.199 +                        e++;
   4.200 +                    else
   4.201 +                        w++;
   4.202 +                    continue;
   4.203 +                }
   4.204 +
   4.205 +                Message m = Message.get(line);
   4.206 +                if (m == null)
   4.207 +                    error("Unexpected line: " + line);
   4.208 +                else
   4.209 +                    found.add(m);
   4.210 +            }
   4.211 +        }
   4.212 +        for (Message m: expect) {
   4.213 +            if (!found.contains(m))
   4.214 +                error("expected message not found: " + m.text);
   4.215 +        }
   4.216 +        for (Message m: found) {
   4.217 +            if (!expect.contains(m))
   4.218 +                error("unexpected message found: " + m.text);
   4.219 +        }
   4.220 +    }
   4.221 +
   4.222 +    void error(String msg) {
   4.223 +        System.err.println("Error: " + msg);
   4.224 +        errors++;
   4.225 +    }
   4.226 +
   4.227 +    int errors;
   4.228 +}

mercurial