提交 bd1900ef 编写于 作者: J jjg

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
上级 9dc5a347
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -99,9 +99,6 @@ public class JavaCompiler extends com.sun.tools.javac.main.JavaCompiler { ...@@ -99,9 +99,6 @@ public class JavaCompiler extends com.sun.tools.javac.main.JavaCompiler {
private static Context preRegister(Context context) { private static Context preRegister(Context context) {
Bark.preRegister(context); Bark.preRegister(context);
// force the use of the scanner that captures Javadoc comments
DocCommentScanner.Factory.preRegister(context);
if (context.get(JavaFileManager.class) == null) if (context.get(JavaFileManager.class) == null)
JavacFileManager.preRegister(context); JavacFileManager.preRegister(context);
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -96,9 +96,6 @@ public class JavacTaskImpl extends JavacTask { ...@@ -96,9 +96,6 @@ public class JavacTaskImpl extends JavacTask {
args.getClass(); args.getClass();
context.getClass(); context.getClass();
fileObjects.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, JavacTaskImpl(JavacTool tool,
...@@ -337,9 +334,13 @@ public class JavacTaskImpl extends JavacTask { ...@@ -337,9 +334,13 @@ public class JavacTaskImpl extends JavacTask {
ListBuffer<TypeElement> elements = new ListBuffer<TypeElement>(); ListBuffer<TypeElement> elements = new ListBuffer<TypeElement>();
for (JCCompilationUnit unit : units) { for (JCCompilationUnit unit : units) {
for (JCTree node : unit.defs) for (JCTree node : unit.defs) {
if (node.getTag() == JCTree.CLASSDEF) if (node.getTag() == JCTree.CLASSDEF) {
elements.append(((JCTree.JCClassDecl) node).sym); JCClassDecl cdef = (JCClassDecl) node;
if (cdef.sym != null) // maybe null if errors in anno processing
elements.append(cdef.sym);
}
}
} }
return elements.toList(); return elements.toList();
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -62,9 +62,6 @@ import static javax.tools.StandardLocation.CLASS_OUTPUT; ...@@ -62,9 +62,6 @@ import static javax.tools.StandardLocation.CLASS_OUTPUT;
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
import static com.sun.tools.javac.util.ListBuffer.lb; 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.HashMap;
import java.util.Queue; import java.util.Queue;
import javax.lang.model.SourceVersion; import javax.lang.model.SourceVersion;
...@@ -964,11 +961,10 @@ public class JavaCompiler implements ClassReader.SourceCompleter { ...@@ -964,11 +961,10 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
processAnnotations = procEnvImpl.atLeastOneProcessor(); processAnnotations = procEnvImpl.atLeastOneProcessor();
if (processAnnotations) { if (processAnnotations) {
if (context.get(Scanner.Factory.scannerFactoryKey) == null)
DocCommentScanner.Factory.preRegister(context);
options.put("save-parameter-names", "save-parameter-names"); options.put("save-parameter-names", "save-parameter-names");
reader.saveParameterNames = true; reader.saveParameterNames = true;
keepComments = true; keepComments = true;
genEndPos = true;
if (taskListener != null) if (taskListener != null)
taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
log.deferDiagnostics = true; log.deferDiagnostics = true;
...@@ -1587,6 +1583,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { ...@@ -1587,6 +1583,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
} }
public void initRound(JavaCompiler prev) { public void initRound(JavaCompiler prev) {
genEndPos = prev.genEndPos;
keepComments = prev.keepComments; keepComments = prev.keepComments;
start_msec = prev.start_msec; start_msec = prev.start_msec;
hasBeenUsed = true; hasBeenUsed = true;
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -42,50 +42,17 @@ import static com.sun.tools.javac.util.LayoutCharacters.*; ...@@ -42,50 +42,17 @@ import static com.sun.tools.javac.util.LayoutCharacters.*;
*/ */
public class DocCommentScanner extends Scanner { 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 /** Create a scanner from the input buffer. buffer must implement
* array() and compact(), and remaining() must be less than limit(). * 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); super(fac, buffer);
} }
/** Create a scanner from the input array. The array must have at /** Create a scanner from the input array. The array must have at
* least a single character of extra space. * 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); super(fac, input, inputLength);
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -2473,6 +2473,11 @@ public class JavacParser implements Parser { ...@@ -2473,6 +2473,11 @@ public class JavacParser implements Parser {
defs.append(importDeclaration()); defs.append(importDeclaration());
} else { } else {
JCTree def = typeDeclaration(mods); 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) if (def instanceof JCExpressionStatement)
def = ((JCExpressionStatement)def).expr; def = ((JCExpressionStatement)def).expr;
defs.append(def); defs.append(def);
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -59,7 +59,7 @@ public class ParserFactory { ...@@ -59,7 +59,7 @@ public class ParserFactory {
final Source source; final Source source;
final Names names; final Names names;
final Options options; final Options options;
final Scanner.Factory scannerFactory; final ScannerFactory scannerFactory;
protected ParserFactory(Context context) { protected ParserFactory(Context context) {
super(); super();
...@@ -70,11 +70,11 @@ public class ParserFactory { ...@@ -70,11 +70,11 @@ public class ParserFactory {
this.keywords = Keywords.instance(context); this.keywords = Keywords.instance(context);
this.source = Source.instance(context); this.source = Source.instance(context);
this.options = Options.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) { public Parser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) {
Lexer lexer = scannerFactory.newScanner(input); Lexer lexer = scannerFactory.newScanner(input, keepDocComments);
if (keepEndPos) { if (keepEndPos) {
return new EndPosParser(this, lexer, keepDocComments, keepLineMap); return new EndPosParser(this, lexer, keepDocComments, keepLineMap);
} else { } else {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -47,48 +47,6 @@ public class Scanner implements Lexer { ...@@ -47,48 +47,6 @@ public class Scanner implements Lexer {
private static boolean scannerDebug = false; 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(): /* Output variables; set by nextToken():
*/ */
...@@ -177,7 +135,7 @@ public class Scanner implements Lexer { ...@@ -177,7 +135,7 @@ public class Scanner implements Lexer {
private final Keywords keywords; private final Keywords keywords;
/** Common code for constructors. */ /** Common code for constructors. */
private Scanner(Factory fac) { private Scanner(ScannerFactory fac) {
log = fac.log; log = fac.log;
names = fac.names; names = fac.names;
keywords = fac.keywords; keywords = fac.keywords;
...@@ -201,7 +159,7 @@ public class Scanner implements Lexer { ...@@ -201,7 +159,7 @@ public class Scanner implements Lexer {
/** Create a scanner from the input buffer. buffer must implement /** Create a scanner from the input buffer. buffer must implement
* array() and compact(), and remaining() must be less than limit(). * 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()); this(fac, JavacFileManager.toArray(buffer), buffer.limit());
} }
...@@ -216,7 +174,7 @@ public class Scanner implements Lexer { ...@@ -216,7 +174,7 @@ public class Scanner implements Lexer {
* @param inputLength the size of the input. * @param inputLength the size of the input.
* Must be positive and less than or equal to input.length. * 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); this(fac);
eofPos = inputLength; eofPos = inputLength;
if (inputLength == input.length) { if (inputLength == input.length) {
......
/*
* 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);
}
}
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -107,9 +107,6 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { ...@@ -107,9 +107,6 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
// force the use of Messager as a Log // force the use of Messager as a Log
messager = Messager.instance0(context); messager = Messager.instance0(context);
// force the use of the scanner that captures Javadoc comments
DocCommentScanner.Factory.preRegister(context);
return new JavadocTool(context); return new JavadocTool(context);
} catch (CompletionFailure ex) { } catch (CompletionFailure ex) {
messager.error(Position.NOPOS, ex.getMessage()); messager.error(Position.NOPOS, ex.getMessage());
......
/**
* This is a test that uses ISO 8859 encoding.
*/
class T6302184 { class T6302184 {
T6302184() { T6302184() {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -35,7 +35,6 @@ import javax.tools.SimpleJavaFileObject; ...@@ -35,7 +35,6 @@ import javax.tools.SimpleJavaFileObject;
import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.parser.Parser; import com.sun.tools.javac.parser.Parser;
import com.sun.tools.javac.parser.ParserFactory; 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.JCTree;
import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Context;
...@@ -60,7 +59,6 @@ public class TestLog ...@@ -60,7 +59,6 @@ public class TestLog
log.multipleErrors = true; log.multipleErrors = true;
JavacFileManager.preRegister(context); JavacFileManager.preRegister(context);
Scanner.Factory sfac = Scanner.Factory.instance(context);
ParserFactory pfac = ParserFactory.instance(context); ParserFactory pfac = ParserFactory.instance(context);
final String text = final String text =
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
*/ */
import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.parser.*; // XXX import com.sun.tools.javac.parser.*;
import com.sun.tools.javac.util.*; // XXX import com.sun.tools.javac.util.*;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.nio.*; import java.nio.*;
...@@ -65,7 +65,7 @@ public class TestJavacTaskScanner extends ToolTester { ...@@ -65,7 +65,7 @@ public class TestJavacTaskScanner extends ToolTester {
fm.getJavaFileObjects(new File[] {file}); fm.getJavaFileObjects(new File[] {file});
StandardJavaFileManager fm = getLocalFileManager(tool, null, null); StandardJavaFileManager fm = getLocalFileManager(tool, null, null);
task = (JavacTaskImpl)tool.getTask(null, fm, null, null, null, compilationUnits); 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)); new MyScanner.Factory(task.getContext(), this));
elements = task.getElements(); elements = task.getElements();
types = task.getTypes(); types = task.getTypes();
...@@ -170,34 +170,36 @@ public class TestJavacTaskScanner extends ToolTester { ...@@ -170,34 +170,36 @@ public class TestJavacTaskScanner extends ToolTester {
class MyScanner extends Scanner { class MyScanner extends Scanner {
public static class Factory extends Scanner.Factory { public static class Factory extends ScannerFactory {
public Factory(Context context, TestJavacTaskScanner test) { public Factory(Context context, TestJavacTaskScanner test) {
super(context); super(context);
this.test = test; this.test = test;
} }
@Override @Override
public Scanner newScanner(CharSequence input) { public Scanner newScanner(CharSequence input, boolean keepDocComments) {
assert !keepDocComments;
if (input instanceof CharBuffer) { if (input instanceof CharBuffer) {
return new MyScanner(this, (CharBuffer)input, test); return new MyScanner(this, (CharBuffer)input, test);
} else { } else {
char[] array = input.toString().toCharArray(); char[] array = input.toString().toCharArray();
return newScanner(array, array.length); return newScanner(array, array.length, keepDocComments);
} }
} }
@Override @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); return new MyScanner(this, input, inputLength, test);
} }
private TestJavacTaskScanner test; private TestJavacTaskScanner test;
} }
protected MyScanner(Factory fac, CharBuffer buffer, TestJavacTaskScanner test) { protected MyScanner(ScannerFactory fac, CharBuffer buffer, TestJavacTaskScanner test) {
super(fac, buffer); super(fac, buffer);
this.test = test; 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); super(fac, input, inputLength);
this.test = test; this.test = test;
} }
......
/*
* 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);
}
}
}
/*
* 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
}
}
/*
* 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 {
}
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
......
/*
* 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;
}
/**
* CLASS XprintDocComments
*/
class XPrintDocComments {
XPrintDocComments();
/**
* FIELD i;
*/
int i;
}
/*
* 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;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册