6877202: Elements.getDocComment() is not getting JavaDocComments
6861094: javac -Xprint <file> does not print comments
6985205: access to tree positions and doc comments may be lost across annotation processing rounds
Reviewed-by: darcy
--- a/langtools/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java Mon Sep 27 14:05:33 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java Mon Sep 27 14:20:39 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -99,9 +99,6 @@
private static Context preRegister(Context context) {
Bark.preRegister(context);
- // force the use of the scanner that captures Javadoc comments
- DocCommentScanner.Factory.preRegister(context);
-
if (context.get(JavaFileManager.class) == null)
JavacFileManager.preRegister(context);
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Mon Sep 27 14:05:33 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Mon Sep 27 14:20:39 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -96,9 +96,6 @@
args.getClass();
context.getClass();
fileObjects.getClass();
-
- // force the use of the scanner that captures Javadoc comments
- com.sun.tools.javac.parser.DocCommentScanner.Factory.preRegister(context);
}
JavacTaskImpl(JavacTool tool,
@@ -337,9 +334,13 @@
ListBuffer<TypeElement> elements = new ListBuffer<TypeElement>();
for (JCCompilationUnit unit : units) {
- for (JCTree node : unit.defs)
- if (node.getTag() == JCTree.CLASSDEF)
- elements.append(((JCTree.JCClassDecl) node).sym);
+ for (JCTree node : unit.defs) {
+ if (node.getTag() == JCTree.CLASSDEF) {
+ JCClassDecl cdef = (JCClassDecl) node;
+ if (cdef.sym != null) // maybe null if errors in anno processing
+ elements.append(cdef.sym);
+ }
+ }
}
return elements.toList();
}
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Mon Sep 27 14:05:33 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Mon Sep 27 14:20:39 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -62,9 +62,6 @@
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
import static com.sun.tools.javac.util.ListBuffer.lb;
-// TEMP, until we have a more efficient way to save doc comment info
-import com.sun.tools.javac.parser.DocCommentScanner;
-
import java.util.HashMap;
import java.util.Queue;
import javax.lang.model.SourceVersion;
@@ -964,11 +961,10 @@
processAnnotations = procEnvImpl.atLeastOneProcessor();
if (processAnnotations) {
- if (context.get(Scanner.Factory.scannerFactoryKey) == null)
- DocCommentScanner.Factory.preRegister(context);
options.put("save-parameter-names", "save-parameter-names");
reader.saveParameterNames = true;
keepComments = true;
+ genEndPos = true;
if (taskListener != null)
taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
log.deferDiagnostics = true;
@@ -1587,6 +1583,7 @@
}
public void initRound(JavaCompiler prev) {
+ genEndPos = prev.genEndPos;
keepComments = prev.keepComments;
start_msec = prev.start_msec;
hasBeenUsed = true;
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentScanner.java Mon Sep 27 14:05:33 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentScanner.java Mon Sep 27 14:20:39 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -42,50 +42,17 @@
*/
public class DocCommentScanner extends Scanner {
- /** A factory for creating scanners. */
- public static class Factory extends Scanner.Factory {
-
- public static void preRegister(final Context context) {
- context.put(scannerFactoryKey, new Context.Factory<Scanner.Factory>() {
- public Factory make() {
- return new Factory(context);
- }
- });
- }
-
- /** Create a new scanner factory. */
- protected Factory(Context context) {
- super(context);
- }
-
- @Override
- public Scanner newScanner(CharSequence input) {
- if (input instanceof CharBuffer) {
- return new DocCommentScanner(this, (CharBuffer)input);
- } else {
- char[] array = input.toString().toCharArray();
- return newScanner(array, array.length);
- }
- }
-
- @Override
- public Scanner newScanner(char[] input, int inputLength) {
- return new DocCommentScanner(this, input, inputLength);
- }
- }
-
-
/** Create a scanner from the input buffer. buffer must implement
* array() and compact(), and remaining() must be less than limit().
*/
- protected DocCommentScanner(Factory fac, CharBuffer buffer) {
+ protected DocCommentScanner(ScannerFactory fac, CharBuffer buffer) {
super(fac, buffer);
}
/** Create a scanner from the input array. The array must have at
* least a single character of extra space.
*/
- protected DocCommentScanner(Factory fac, char[] input, int inputLength) {
+ protected DocCommentScanner(ScannerFactory fac, char[] input, int inputLength) {
super(fac, input, inputLength);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Sep 27 14:05:33 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Sep 27 14:20:39 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -2473,6 +2473,11 @@
defs.append(importDeclaration());
} else {
JCTree def = typeDeclaration(mods);
+ if (keepDocComments && dc != null && docComments.get(def) == dc) {
+ // If the first type declaration has consumed the first doc
+ // comment, then don't use it for the top level comment as well.
+ dc = null;
+ }
if (def instanceof JCExpressionStatement)
def = ((JCExpressionStatement)def).expr;
defs.append(def);
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java Mon Sep 27 14:05:33 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java Mon Sep 27 14:20:39 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -59,7 +59,7 @@
final Source source;
final Names names;
final Options options;
- final Scanner.Factory scannerFactory;
+ final ScannerFactory scannerFactory;
protected ParserFactory(Context context) {
super();
@@ -70,11 +70,11 @@
this.keywords = Keywords.instance(context);
this.source = Source.instance(context);
this.options = Options.instance(context);
- this.scannerFactory = Scanner.Factory.instance(context);
+ this.scannerFactory = ScannerFactory.instance(context);
}
public Parser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) {
- Lexer lexer = scannerFactory.newScanner(input);
+ Lexer lexer = scannerFactory.newScanner(input, keepDocComments);
if (keepEndPos) {
return new EndPosParser(this, lexer, keepDocComments, keepLineMap);
} else {
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java Mon Sep 27 14:05:33 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java Mon Sep 27 14:20:39 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -47,48 +47,6 @@
private static boolean scannerDebug = false;
- /** A factory for creating scanners. */
- public static class Factory {
- /** The context key for the scanner factory. */
- public static final Context.Key<Scanner.Factory> scannerFactoryKey =
- new Context.Key<Scanner.Factory>();
-
- /** Get the Factory instance for this context. */
- public static Factory instance(Context context) {
- Factory instance = context.get(scannerFactoryKey);
- if (instance == null)
- instance = new Factory(context);
- return instance;
- }
-
- final Log log;
- final Names names;
- final Source source;
- final Keywords keywords;
-
- /** Create a new scanner factory. */
- protected Factory(Context context) {
- context.put(scannerFactoryKey, this);
- this.log = Log.instance(context);
- this.names = Names.instance(context);
- this.source = Source.instance(context);
- this.keywords = Keywords.instance(context);
- }
-
- public Scanner newScanner(CharSequence input) {
- if (input instanceof CharBuffer) {
- return new Scanner(this, (CharBuffer)input);
- } else {
- char[] array = input.toString().toCharArray();
- return newScanner(array, array.length);
- }
- }
-
- public Scanner newScanner(char[] input, int inputLength) {
- return new Scanner(this, input, inputLength);
- }
- }
-
/* Output variables; set by nextToken():
*/
@@ -177,7 +135,7 @@
private final Keywords keywords;
/** Common code for constructors. */
- private Scanner(Factory fac) {
+ private Scanner(ScannerFactory fac) {
log = fac.log;
names = fac.names;
keywords = fac.keywords;
@@ -201,7 +159,7 @@
/** Create a scanner from the input buffer. buffer must implement
* array() and compact(), and remaining() must be less than limit().
*/
- protected Scanner(Factory fac, CharBuffer buffer) {
+ protected Scanner(ScannerFactory fac, CharBuffer buffer) {
this(fac, JavacFileManager.toArray(buffer), buffer.limit());
}
@@ -216,7 +174,7 @@
* @param inputLength the size of the input.
* Must be positive and less than or equal to input.length.
*/
- protected Scanner(Factory fac, char[] input, int inputLength) {
+ protected Scanner(ScannerFactory fac, char[] input, int inputLength) {
this(fac);
eofPos = inputLength;
if (inputLength == input.length) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/ScannerFactory.java Mon Sep 27 14:20:39 2010 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1999, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.tools.javac.parser;
+
+import java.nio.CharBuffer;
+
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Names;
+
+
+/**
+ * A factory for creating scanners.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own
+ * risk. This code and its internal interfaces are subject to change
+ * or deletion without notice.</b>
+ */
+public class ScannerFactory {
+ /** The context key for the scanner factory. */
+ public static final Context.Key<ScannerFactory> scannerFactoryKey =
+ new Context.Key<ScannerFactory>();
+
+ /** Get the Factory instance for this context. */
+ public static ScannerFactory instance(Context context) {
+ ScannerFactory instance = context.get(scannerFactoryKey);
+ if (instance == null)
+ instance = new ScannerFactory(context);
+ return instance;
+ }
+
+ final Log log;
+ final Names names;
+ final Source source;
+ final Keywords keywords;
+
+ /** Create a new scanner factory. */
+ protected ScannerFactory(Context context) {
+ context.put(scannerFactoryKey, this);
+ this.log = Log.instance(context);
+ this.names = Names.instance(context);
+ this.source = Source.instance(context);
+ this.keywords = Keywords.instance(context);
+ }
+
+ public Scanner newScanner(CharSequence input, boolean keepDocComments) {
+ if (input instanceof CharBuffer) {
+ CharBuffer buf = (CharBuffer) input;
+ if (keepDocComments)
+ return new DocCommentScanner(this, buf);
+ else
+ return new Scanner(this, buf);
+ } else {
+ char[] array = input.toString().toCharArray();
+ return newScanner(array, array.length, keepDocComments);
+ }
+ }
+
+ public Scanner newScanner(char[] input, int inputLength, boolean keepDocComments) {
+ if (keepDocComments)
+ return new DocCommentScanner(this, input, inputLength);
+ else
+ return new Scanner(this, input, inputLength);
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java Mon Sep 27 14:05:33 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java Mon Sep 27 14:20:39 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -107,9 +107,6 @@
// force the use of Messager as a Log
messager = Messager.instance0(context);
- // force the use of the scanner that captures Javadoc comments
- DocCommentScanner.Factory.preRegister(context);
-
return new JavadocTool(context);
} catch (CompletionFailure ex) {
messager.error(Position.NOPOS, ex.getMessage());
--- a/langtools/test/tools/javac/6302184/T6302184.out Mon Sep 27 14:05:33 2010 -0700
+++ b/langtools/test/tools/javac/6302184/T6302184.out Mon Sep 27 14:20:39 2010 -0700
@@ -1,4 +1,7 @@
+/**
+ * This is a test that uses ISO 8859 encoding.
+ */
class T6302184 {
T6302184() {
--- a/langtools/test/tools/javac/6304921/TestLog.java Mon Sep 27 14:05:33 2010 -0700
+++ b/langtools/test/tools/javac/6304921/TestLog.java Mon Sep 27 14:20:39 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -35,7 +35,6 @@
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.parser.Parser;
import com.sun.tools.javac.parser.ParserFactory;
-import com.sun.tools.javac.parser.Scanner;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Context;
@@ -60,7 +59,6 @@
log.multipleErrors = true;
JavacFileManager.preRegister(context);
- Scanner.Factory sfac = Scanner.Factory.instance(context);
ParserFactory pfac = ParserFactory.instance(context);
final String text =
--- a/langtools/test/tools/javac/api/TestJavacTaskScanner.java Mon Sep 27 14:05:33 2010 -0700
+++ b/langtools/test/tools/javac/api/TestJavacTaskScanner.java Mon Sep 27 14:20:39 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -31,8 +31,8 @@
*/
import com.sun.tools.javac.api.JavacTaskImpl;
-import com.sun.tools.javac.parser.*; // XXX
-import com.sun.tools.javac.util.*; // XXX
+import com.sun.tools.javac.parser.*;
+import com.sun.tools.javac.util.*;
import java.io.*;
import java.net.*;
import java.nio.*;
@@ -65,7 +65,7 @@
fm.getJavaFileObjects(new File[] {file});
StandardJavaFileManager fm = getLocalFileManager(tool, null, null);
task = (JavacTaskImpl)tool.getTask(null, fm, null, null, null, compilationUnits);
- task.getContext().put(Scanner.Factory.scannerFactoryKey,
+ task.getContext().put(ScannerFactory.scannerFactoryKey,
new MyScanner.Factory(task.getContext(), this));
elements = task.getElements();
types = task.getTypes();
@@ -170,34 +170,36 @@
class MyScanner extends Scanner {
- public static class Factory extends Scanner.Factory {
+ public static class Factory extends ScannerFactory {
public Factory(Context context, TestJavacTaskScanner test) {
super(context);
this.test = test;
}
@Override
- public Scanner newScanner(CharSequence input) {
+ public Scanner newScanner(CharSequence input, boolean keepDocComments) {
+ assert !keepDocComments;
if (input instanceof CharBuffer) {
return new MyScanner(this, (CharBuffer)input, test);
} else {
char[] array = input.toString().toCharArray();
- return newScanner(array, array.length);
+ return newScanner(array, array.length, keepDocComments);
}
}
@Override
- public Scanner newScanner(char[] input, int inputLength) {
+ public Scanner newScanner(char[] input, int inputLength, boolean keepDocComments) {
+ assert !keepDocComments;
return new MyScanner(this, input, inputLength, test);
}
private TestJavacTaskScanner test;
}
- protected MyScanner(Factory fac, CharBuffer buffer, TestJavacTaskScanner test) {
+ protected MyScanner(ScannerFactory fac, CharBuffer buffer, TestJavacTaskScanner test) {
super(fac, buffer);
this.test = test;
}
- protected MyScanner(Factory fac, char[] input, int inputLength, TestJavacTaskScanner test) {
+ protected MyScanner(ScannerFactory fac, char[] input, int inputLength, TestJavacTaskScanner test) {
super(fac, input, inputLength);
this.test = test;
}
--- a/langtools/test/tools/javac/processing/Xprint.java Mon Sep 27 14:05:33 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2005, 2006, 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 6266828
- * @summary JSR 269: Java Language Model API
- * @author Peter von der Ah\u00e9
- */
-import javax.tools.JavaCompiler;
-import javax.tools.ToolProvider;
-
-public class Xprint {
- public static void main(String[] args) {
- JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
- javac.run(System.in, null, null,
- "-Xprint",
- "com.sun.tools.javac.code.Types",
- "com.sun.tools.javac.parser.Parser",
- "java.util.EnumSet");
- }
-}
--- /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);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/model/util/elements/doccomments/a/First.java Mon Sep 27 14:20:39 2010 -0700
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+package a;
+
+/** CLASS First */
+public class First {
+ /** CONSTRUCTOR <init> */
+ First() { }
+
+ /** FIELD x */
+ p.Gen1 x;
+
+ /** METHOD m **/
+ void m(int i) {
+ /** CLASS Local */
+ class Local {
+ /** CONSTRUCTOR <init> */
+ Local() { }
+ }
+
+ Runnable r = new Runnable() {
+ /** METHOD run **/
+ public void run() { }
+ };
+
+ }
+
+ /** ENUM E */
+ enum E {
+ /** ENUM_CONSTANT e1 */
+ e1
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/model/util/elements/doccomments/z/Last.java Mon Sep 27 14:20:39 2010 -0700
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+package z;
+
+// This class should be read last, implicitly. Therefore it should not
+// be subject to anno processing. If it is, the lack of doc comments should
+// be detected and will flag an error.
+public class Last {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/options/Xprint.java Mon Sep 27 14:20:39 2010 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2005, 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 6266828
+ * @summary JSR 269: Java Language Model API
+ * @author Peter von der Ah\u00e9
+ */
+import javax.tools.JavaCompiler;
+import javax.tools.ToolProvider;
+
+public class Xprint {
+ public static void main(String[] args) {
+ JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
+ javac.run(System.in, null, null,
+ "-Xprint",
+ "com.sun.tools.javac.code.Types",
+ "com.sun.tools.javac.parser.Parser",
+ "java.util.EnumSet");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/options/XprintDocComments.java Mon Sep 27 14:20:39 2010 -0700
@@ -0,0 +1,39 @@
+/*
+ * 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 6861094
+ * @summary javac -Xprint <file> does not print comments
+ * @compile/ref=XprintDocComments.out -Xprint XprintDocComments.java
+ */
+
+/**
+ * CLASS XprintDocComments
+ */
+class XPrintDocComments {
+ /**
+ * FIELD i;
+ */
+ int i;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/options/XprintDocComments.out Mon Sep 27 14:20:39 2010 -0700
@@ -0,0 +1,12 @@
+
+/**
+ * CLASS XprintDocComments
+ */
+class XPrintDocComments {
+
+ XPrintDocComments();
+ /**
+ * FIELD i;
+ */
+ int i;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/tree/TreePosRoundsTest.java Mon Sep 27 14:20:39 2010 -0700
@@ -0,0 +1,204 @@
+/*
+ * 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 6985205
+ * @summary access to tree positions and doc comments may be lost across annotation processing rounds
+ * @build TreePosRoundsTest
+ * @compile -proc:only -processor TreePosRoundsTest TreePosRoundsTest.java
+ * @run main TreePosRoundsTest
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.tools.*;
+
+import com.sun.source.tree.*;
+import com.sun.source.util.*;
+import javax.tools.JavaCompiler.CompilationTask;
+
+// This test is an annotation processor that performs multiple rounds of
+// processing, and on each round, it checks that source positions are
+// available and correct.
+//
+// The test can be run directly as a processor from the javac command line
+// or via JSR 199 by invoking the main program.
+
+@SupportedAnnotationTypes("*")
+public class TreePosRoundsTest extends AbstractProcessor {
+ public static void main(String... args) throws Exception {
+ String testSrc = System.getProperty("test.src");
+ String testClasses = System.getProperty("test.classes");
+ JavaCompiler c = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fm = c.getStandardFileManager(null, null, null);
+ String thisName = TreePosRoundsTest.class.getName();
+ File thisFile = new File(testSrc, thisName + ".java");
+ Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(thisFile);
+ List<String> options = Arrays.asList(
+ "-proc:only",
+ "-processor", thisName,
+ "-processorpath", testClasses);
+ CompilationTask t = c.getTask(null, fm, null, options, null, files);
+ boolean ok = t.call();
+ if (!ok)
+ throw new Exception("processing failed");
+ }
+
+ Filer filer;
+ Messager messager;
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ @Override
+ public void init(ProcessingEnvironment pEnv) {
+ super.init(pEnv);
+ filer = pEnv.getFiler();
+ messager = pEnv.getMessager();
+ }
+
+ int round = 0;
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ round++;
+
+ // Scan trees for elements, verifying source tree positions
+ for (Element e: roundEnv.getRootElements()) {
+ try {
+ Trees trees = Trees.instance(processingEnv); // cannot cache this across rounds
+ TreePath p = trees.getPath(e);
+ new TestTreeScanner(p.getCompilationUnit(), trees).scan(trees.getPath(e), null);
+ } catch (IOException ex) {
+ messager.printMessage(Diagnostic.Kind.ERROR,
+ "Cannot get source: " + ex, e);
+ }
+ }
+
+ final int MAXROUNDS = 3;
+ if (round < MAXROUNDS)
+ generateSource("Gen" + round);
+
+ return true;
+ }
+
+ void generateSource(String name) {
+ StringBuilder text = new StringBuilder();
+ text.append("class ").append(name).append("{\n");
+ text.append(" int one = 1;\n");
+ text.append(" int two = 2;\n");
+ text.append(" int three = one + two;\n");
+ text.append("}\n");
+
+ try {
+ JavaFileObject fo = filer.createSourceFile(name);
+ Writer out = fo.openWriter();
+ try {
+ out.write(text.toString());
+ } finally {
+ out.close();
+ }
+ } catch (IOException e) {
+ throw new Error(e);
+ }
+ }
+
+ class TestTreeScanner extends TreePathScanner<Void,Void> {
+ TestTreeScanner(CompilationUnitTree unit, Trees trees) throws IOException {
+ this.unit = unit;
+ JavaFileObject sf = unit.getSourceFile();
+ source = sf.getCharContent(true).toString();
+ sourcePositions = trees.getSourcePositions();
+ }
+
+ @Override
+ public Void visitVariable(VariableTree tree, Void _) {
+ check(getCurrentPath());
+ return super.visitVariable(tree, _);
+ }
+
+ void check(TreePath tp) {
+ Tree tree = tp.getLeaf();
+
+ String expect = tree.toString();
+ if (tree.getKind() == Tree.Kind.VARIABLE) {
+ // tree.toString() does not know enough context to add ";",
+ // so deal with that manually...
+ Tree.Kind enclKind = tp.getParentPath().getLeaf().getKind();
+ //System.err.println(" encl: " +enclKind);
+ if (enclKind == Tree.Kind.CLASS || enclKind == Tree.Kind.BLOCK)
+ expect += ";";
+ }
+ //System.err.println("expect: " + expect);
+
+ int start = (int)sourcePositions.getStartPosition(unit, tree);
+ if (start == Diagnostic.NOPOS) {
+ messager.printMessage(Diagnostic.Kind.ERROR, "start pos not set for " + trim(tree));
+ return;
+ }
+
+ int end = (int)sourcePositions.getEndPosition(unit, tree);
+ if (end == Diagnostic.NOPOS) {
+ messager.printMessage(Diagnostic.Kind.ERROR, "end pos not set for " + trim(tree));
+ return;
+ }
+
+ String found = source.substring(start, end);
+ //System.err.println(" found: " + found);
+
+ // allow for long lines, in which case just compare beginning and
+ // end of the strings
+ boolean equal;
+ if (found.contains("\n")) {
+ String head = found.substring(0, found.indexOf("\n"));
+ String tail = found.substring(found.lastIndexOf("\n")).trim();
+ equal = expect.startsWith(head) && expect.endsWith(tail);
+ } else {
+ equal = expect.equals(found);
+ }
+
+ if (!equal) {
+ messager.printMessage(Diagnostic.Kind.ERROR,
+ "unexpected value found: '" + found + "'; expected: '" + expect + "'");
+ }
+ }
+
+ String trim(Tree tree) {
+ final int MAXLEN = 32;
+ String s = tree.toString().replaceAll("\\s+", " ").trim();
+ return (s.length() < MAXLEN) ? s : s.substring(0, MAXLEN);
+
+ }
+
+ CompilationUnitTree unit;
+ SourcePositions sourcePositions;
+ String source;
+ }
+
+}