jjg@1539: /* jjg@1539: * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. jjg@1539: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@1539: * jjg@1539: * This code is free software; you can redistribute it and/or modify it jjg@1539: * under the terms of the GNU General Public License version 2 only, as jjg@1539: * published by the Free Software Foundation. jjg@1539: * jjg@1539: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@1539: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@1539: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@1539: * version 2 for more details (a copy is included in the LICENSE file that jjg@1539: * accompanied this code). jjg@1539: * jjg@1539: * You should have received a copy of the GNU General Public License version jjg@1539: * 2 along with this work; if not, write to the Free Software Foundation, jjg@1539: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@1539: * jjg@1539: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jjg@1539: * or visit www.oracle.com if you need additional information or have any jjg@1539: * questions. jjg@1539: */ jjg@1539: jjg@1539: /* jjg@1539: * @test jjg@1539: * @bug 8007344 jjg@1539: * @summary javac may not make tree end positions and/or doc comments jjg@1539: * available to processors and listeners jjg@1539: * @library /tools/javac/lib jjg@1539: * @build JavacTestingAbstractProcessor jjg@1539: * @run main Test jjg@1539: */ jjg@1539: jjg@1539: import java.io.File; jjg@1539: import java.io.PrintWriter; jjg@1539: import java.util.Arrays; jjg@1539: import java.util.Set; jjg@1539: jjg@1539: import javax.annotation.processing.RoundEnvironment; jjg@1539: import javax.lang.model.element.Element; jjg@1539: import javax.lang.model.element.TypeElement; jjg@1539: import javax.tools.JavaFileObject; jjg@1539: import javax.tools.StandardJavaFileManager; jjg@1549: import javax.tools.StandardLocation; jjg@1539: jjg@1539: import com.sun.source.doctree.DocCommentTree; jjg@1539: import com.sun.source.tree.*; jjg@1539: import com.sun.source.util.DocTrees; jjg@1539: import com.sun.source.util.JavacTask; jjg@1539: import com.sun.source.util.SourcePositions; jjg@1539: import com.sun.source.util.TaskEvent; jjg@1539: import com.sun.source.util.TaskListener; jjg@1539: import com.sun.source.util.TreePath; jjg@1539: import com.sun.source.util.TreePathScanner; jjg@1539: import com.sun.tools.javac.api.JavacTool; jjg@1539: import com.sun.tools.javac.tree.JCTree; jjg@1539: import com.sun.tools.javac.tree.Pretty; jjg@1539: import com.sun.tools.javac.util.Position; jjg@1539: jjg@1539: /** Doc comment: Test */ jjg@1539: public class Test { jjg@1539: public static final int EXPECT_DOC_COMMENTS = 3; jjg@1539: jjg@1539: /** Doc comment: main */ jjg@1539: public static void main(String... args) throws Exception { jjg@1539: PrintWriter out = new PrintWriter(System.err); jjg@1539: try { jjg@1539: new Test(out).run(); jjg@1539: } finally { jjg@1539: out.flush(); jjg@1539: } jjg@1539: } jjg@1539: jjg@1539: PrintWriter out; jjg@1539: int errors; jjg@1539: jjg@1539: Test(PrintWriter out) { jjg@1539: this.out = out; jjg@1539: } jjg@1539: jjg@1539: /** Doc comment: run */ jjg@1539: void run() throws Exception { jjg@1539: File testSrc = new File(System.getProperty("test.src")); jjg@1539: File thisFile = new File(testSrc, getClass().getName() + ".java"); jjg@1539: JavacTool javac = JavacTool.create(); jjg@1539: StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null); jjg@1549: fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File("."))); jjg@1539: Iterable fos = fm.getJavaFileObjects(thisFile); jjg@1539: testAnnoProcessor(javac, fm, fos, out, EXPECT_DOC_COMMENTS); jjg@1539: testTaskListener(javac, fm, fos, out, EXPECT_DOC_COMMENTS); jjg@1539: jjg@1539: if (errors > 0) jjg@1539: throw new Exception(errors + " errors occurred"); jjg@1539: } jjg@1539: jjg@1539: void testAnnoProcessor(JavacTool javac, StandardJavaFileManager fm, jjg@1539: Iterable files, PrintWriter out, jjg@1539: int expectedDocComments) { jjg@1539: out.println("Test annotation processor"); jjg@1539: JavacTask task = javac.getTask(out, fm, null, null, null, files); jjg@1539: AnnoProc ap = new AnnoProc(DocTrees.instance(task)); jjg@1539: task.setProcessors(Arrays.asList(ap)); jjg@1539: task.call(); jjg@1539: ap.checker.checkDocComments(expectedDocComments); jjg@1539: } jjg@1539: jjg@1539: void testTaskListener(JavacTool javac, StandardJavaFileManager fm, jjg@1539: Iterable files, PrintWriter out, jjg@1539: int expectedDocComments) { jjg@1539: out.println("Test task listener"); jjg@1539: JavacTask task = javac.getTask(out, fm, null, null, null, files); jjg@1539: TaskListnr tl = new TaskListnr(DocTrees.instance(task)); jjg@1539: task.addTaskListener(tl); jjg@1539: task.call(); jjg@1539: tl.checker.checkDocComments(expectedDocComments); jjg@1539: } jjg@1539: jjg@1539: void error(String msg) { jjg@1539: out.println("Error: " + msg); jjg@1539: errors++; jjg@1539: } jjg@1539: jjg@1539: class AnnoProc extends JavacTestingAbstractProcessor { jjg@1539: Checker checker; jjg@1539: jjg@1539: AnnoProc(DocTrees trees) { jjg@1539: checker = new Checker(trees); jjg@1539: } jjg@1539: jjg@1539: @Override jjg@1539: public boolean process(Set annotations, RoundEnvironment roundEnv) { jjg@1539: for (Element e : roundEnv.getRootElements()) { jjg@1539: checker.scan(checker.trees.getPath(e), null); jjg@1539: } jjg@1539: return true; jjg@1539: } jjg@1539: } jjg@1539: jjg@1539: class TaskListnr implements TaskListener { jjg@1539: Checker checker; jjg@1539: jjg@1539: TaskListnr(DocTrees trees) { jjg@1539: checker = new Checker(trees); jjg@1539: } jjg@1539: jjg@1539: public void started(TaskEvent e) { jjg@1539: if (e.getKind() == TaskEvent.Kind.ANALYZE) jjg@1539: checker.scan(new TreePath(e.getCompilationUnit()), null); jjg@1539: } jjg@1539: jjg@1539: public void finished(TaskEvent e) { jjg@1539: } jjg@1539: } jjg@1539: jjg@1539: class Checker extends TreePathScanner { jjg@1539: DocTrees trees; jjg@1539: SourcePositions srcPosns; jjg@1539: jjg@1539: int docComments = 0; jjg@1539: jjg@1539: Checker(DocTrees trees) { jjg@1539: this.trees = trees; jjg@1539: srcPosns = trees.getSourcePositions(); jjg@1539: } jjg@1539: jjg@1539: @Override jjg@1539: public Void scan(Tree tree, Void ignore) { jjg@1539: if (tree != null) { jjg@1539: switch (tree.getKind()) { jjg@1539: // HACK: Workaround 8007350 jjg@1539: // Some tree nodes do not have endpos set jjg@1539: case ASSIGNMENT: jjg@1539: case BLOCK: jjg@1539: case IDENTIFIER: jjg@1539: case METHOD_INVOCATION: jjg@1539: break; jjg@1539: jjg@1539: default: jjg@1539: checkEndPos(getCurrentPath().getCompilationUnit(), tree); jjg@1539: } jjg@1539: } jjg@1539: return super.scan(tree, ignore); jjg@1539: } jjg@1539: jjg@1539: @Override jjg@1539: public Void visitClass(ClassTree tree, Void ignore) { jjg@1539: checkComment(); jjg@1539: return super.visitClass(tree, ignore); jjg@1539: } jjg@1539: jjg@1539: @Override jjg@1539: public Void visitMethod(MethodTree tree, Void ignore) { jjg@1539: checkComment(); jjg@1539: return super.visitMethod(tree, ignore); jjg@1539: } jjg@1539: jjg@1539: @Override jjg@1539: public Void visitVariable(VariableTree tree, Void ignore) { jjg@1539: checkComment(); jjg@1539: return super.visitVariable(tree, ignore); jjg@1539: } jjg@1539: jjg@1539: void checkComment() { jjg@1539: DocCommentTree dc = trees.getDocCommentTree(getCurrentPath()); jjg@1539: if (dc != null) { jjg@1539: out.println("comment: " + dc.toString().replaceAll("\\s+", " ")); jjg@1539: docComments++; jjg@1539: } jjg@1539: } jjg@1539: jjg@1539: void checkEndPos(CompilationUnitTree unit, Tree tree) { jjg@1539: long sp = srcPosns.getStartPosition(unit, tree); jjg@1539: long ep = srcPosns.getEndPosition(unit, tree); jjg@1539: if (sp >= 0 && ep == Position.NOPOS) { jjg@1539: error("endpos not set for " + tree.getKind() jjg@1539: + " " + Pretty.toSimpleString(((JCTree) tree)) jjg@1539: +", start:" + sp); jjg@1539: } jjg@1539: } jjg@1539: jjg@1539: void checkDocComments(int expected) { jjg@1539: if (docComments != expected) { jjg@1539: error("Unexpected number of doc comments received: " jjg@1539: + docComments + ", expected: " + expected); jjg@1539: } jjg@1539: } jjg@1539: jjg@1539: } jjg@1539: }