langtools/test/tools/javac/processing/model/util/elements/doccomments/TestDocComments.java
changeset 6716 71df48777dd1
child 6717 0103d76cfe48
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/model/util/elements/doccomments/TestDocComments.java	Mon Sep 27 14:20:39 2010 -0700
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6877202
+ * @summary Elements.getDocComment() is not getting JavaDocComments
+ */
+
+import com.sun.source.tree.*;
+import com.sun.source.util.*;
+import java.io.*;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.lang.model.util.*;
+import javax.tools.*;
+
+/*
+ * For a mixture of pre-existing and generated source files, ensure that we can
+ * get the doc comments.
+ * The test uses both a standard ElementScanner to find all the elements being
+ * processed, and a TreeScanner to find all the local and anonymous inner classes
+ * as well.
+ * And, because the relevant code paths in the compiler are different for
+ * command line and JSR 199 invocation, the test covers both ways of invoking the
+ * compiler.
+ */
+
+@SupportedOptions("scan")
+@SupportedAnnotationTypes("*")
+public class TestDocComments extends AbstractProcessor {
+    enum CompileKind { API, CMD };
+    enum ScanKind { TREE, ELEMENT };
+
+    // ----- Main test driver: invoke compiler for the various test cases ------
+
+    public static void main(String... args) throws Exception {
+        for (CompileKind ck: CompileKind.values()) {
+            for (ScanKind sk: ScanKind.values()) {
+                try {
+                    test(ck, sk);
+                } catch (IOException e) {
+                    error(e.toString());
+                }
+            }
+        }
+
+        if (errors > 0)
+            throw new Exception(errors + " errors occurred");
+    }
+
+    static void test(CompileKind ck, ScanKind sk) throws IOException {
+        String testClasses = System.getProperty("test.classes");
+        String testSrc = System.getProperty("test.src");
+        File testDir = new File("test." + ck + "." + sk);
+        testDir.mkdirs();
+        String[] opts = {
+            "-d", testDir.getPath(),
+            "-implicit:none",
+            "-processor", TestDocComments.class.getName(),
+            "-processorpath", testClasses,
+            //"-XprintRounds",
+            "-Ascan=" + sk
+        };
+        File[] files = {
+            new File(testSrc, "a/First.java")
+        };
+
+        if (ck == CompileKind.API)
+            test_javac_api(opts, files);
+        else
+            test_javac_cmd(opts, files);
+    }
+
+    static void test_javac_api(String[] opts, File[] files) throws IOException {
+        System.err.println("test javac api: " + Arrays.asList(opts) + " " + Arrays.asList(files));
+        DiagnosticListener<JavaFileObject> dl = new DiagnosticListener<JavaFileObject>() {
+            public void report(Diagnostic diagnostic) {
+                error(diagnostic.toString());
+            }
+        };
+        JavaCompiler c = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager fm = c.getStandardFileManager(null, null, null);
+        Iterable<? extends JavaFileObject> units = fm.getJavaFileObjects(files);
+        JavacTask t = (JavacTask) c.getTask(null, fm, dl, Arrays.asList(opts), null, units);
+        t.parse();
+        t.analyze();
+    }
+
+    static void test_javac_cmd(String[] opts, File[] files) {
+        System.err.println("test javac cmd: " + Arrays.asList(opts) + " " + Arrays.asList(files));
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        List<String> args = new ArrayList<String>(Arrays.asList(opts));
+        for (File f: files)
+            args.add(f.getPath());
+        int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw);
+        pw.close();
+        String out = sw.toString();
+        if (out.length() > 0)
+            System.err.println(out);
+        if (rc > 0)
+            error("Compilation failed: rc=" + rc);
+    }
+
+    static void error(String msg) {
+        System.err.println(msg);
+        errors++;
+        //throw new Error(msg);
+    }
+
+    static int errors;
+
+    // ----- Annotation processor: scan for elements and check doc comments ----
+
+    Map<String,String> options;
+    Filer filer;
+    Messager messager;
+    Elements elements;
+    ScanKind skind;
+
+    int round = 0;
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    @Override
+    public void init(ProcessingEnvironment pEnv) {
+        super.init(pEnv);
+        options = pEnv.getOptions();
+        filer = pEnv.getFiler();
+        messager = pEnv.getMessager();
+        elements = pEnv.getElementUtils();
+        skind = ScanKind.valueOf(options.get("scan"));
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        round++;
+
+        // Scan elements using an appropriate scanner, and for each element found,
+        // call check(Element e) to verify the doc comment on that element
+        for (Element e: roundEnv.getRootElements()) {
+            System.err.println("scan " + skind + " " + e.getKind() + " " + e.getSimpleName());
+            if (skind == ScanKind.TREE) {
+                Trees trees = Trees.instance(processingEnv); // cannot cache this across rounds
+                new TestTreeScanner().scan(trees.getPath(e), trees);
+            }  else
+                new TestElementScanner().scan(e);
+        }
+
+        // For a few rounds, generate new source files, so that we can check whether
+        // doc comments are correctly handled in subsequent processing rounds
+        final int MAX_ROUNDS = 3;
+        if (round <= MAX_ROUNDS) {
+            String pkg = "p";
+            String currClass = "Gen" + round;
+            String curr = pkg + "." + currClass;
+            String next = (round < MAX_ROUNDS) ? (pkg + ".Gen" + (round + 1)) : "z.Last";
+            StringBuilder text = new StringBuilder();
+            text.append("package ").append(pkg).append(";\n");
+            text.append("/** CLASS ").append(currClass).append(" */\n");
+            text.append("public class ").append(currClass).append(" {\n");
+            text.append("    /** CONSTRUCTOR <init> **/\n");
+            text.append("    ").append(currClass).append("() { }\n");
+            text.append("    /** FIELD x */\n");
+            text.append("    ").append(next).append(" x;\n");
+            text.append("    /** METHOD m */\n");
+            text.append("    void m() { }\n");
+            text.append("}\n");
+
+            try {
+                JavaFileObject fo = filer.createSourceFile(curr);
+                Writer out = fo.openWriter();
+                try {
+                    out.write(text.toString());
+                } finally {
+                    out.close();
+                }
+            } catch (IOException e) {
+                throw new Error(e);
+            }
+        }
+
+        return true;
+    }
+
+    /*
+     * Check that the doc comment on an element is as expected.
+     * This method is invoked for each element found by the scanners run by process.
+     */
+    void check(Element e) {
+        System.err.println("Checking " + e);
+
+        String dc = elements.getDocComment(e);
+        System.err.println("   found " + dc);
+
+        String expect = (e.getKind() + " " + e.getSimpleName()); // default
+
+        Name name = e.getSimpleName();
+        Element encl = e.getEnclosingElement();
+        Name enclName = encl.getSimpleName();
+        ElementKind enclKind = encl.getKind();
+        switch (e.getKind()) {
+            case PARAMETER:
+            case LOCAL_VARIABLE:
+                // doc comments not retained for these elements
+                expect = null;
+                break;
+
+            case CONSTRUCTOR:
+                if (enclName.length() == 0 || enclKind == ElementKind.ENUM) {
+                    // Enum constructor is synthetic
+                    expect = null;
+                }
+                break;
+
+            case METHOD:
+                if (enclKind == ElementKind.ENUM
+                        && (name.contentEquals("values") || name.contentEquals("valueOf"))) {
+                    // synthetic enum methods
+                    expect = null;
+                }
+                break;
+
+            case CLASS:
+                if (e.getSimpleName().length() == 0) {
+                    // anon inner class
+                    expect = null;
+                }
+                break;
+        }
+
+        System.err.println("  expect " + expect);
+
+        if (dc == null ? expect == null : dc.trim().equals(expect))
+            return;
+
+        if (dc == null)
+            messager.printMessage(Diagnostic.Kind.ERROR, "doc comment is null", e);
+        else {
+            messager.printMessage(Diagnostic.Kind.ERROR,
+                    "unexpected comment: \"" + dc + "\", expected \"" + expect + "\"", e);
+        }
+    }
+
+    // ----- Scanners to find elements -----------------------------------------
+
+    class TestElementScanner extends ElementScanner7<Void, Void> {
+        @Override
+        public Void visitExecutable(ExecutableElement e, Void _) {
+            check(e);
+            return super.visitExecutable(e, _);
+        }
+        @Override
+        public Void visitType(TypeElement e, Void _) {
+            check(e);
+            return super.visitType(e, _);
+        }
+        @Override
+        public Void visitVariable(VariableElement e, Void _) {
+            check(e);
+            return super.visitVariable(e, _);
+        }
+    }
+
+    class TestTreeScanner extends TreePathScanner<Void,Trees> {
+        @Override
+        public Void visitClass(ClassTree tree, Trees trees) {
+            check(trees.getElement(getCurrentPath()));
+            return super.visitClass(tree, trees);
+        }
+        @Override
+        public Void visitMethod(MethodTree tree, Trees trees) {
+            check(trees.getElement(getCurrentPath()));
+            return super.visitMethod(tree, trees);
+        }
+        @Override
+        public Void visitVariable(VariableTree tree, Trees trees) {
+            check(trees.getElement(getCurrentPath()));
+            return super.visitVariable(tree, trees);
+        }
+    }
+
+}