8034245: Refactor TopLevel tree node

Added JCPackageDecl to JCTree to store package-level information.

Reviewed-by: jjg, jlahoda
This commit is contained in:
Paul Govereau 2014-04-22 17:07:54 -04:00
parent b349726850
commit 9783b65028
25 changed files with 293 additions and 145 deletions

View File

@ -41,6 +41,12 @@ import javax.tools.JavaFileObject;
public interface CompilationUnitTree extends Tree {
List<? extends AnnotationTree> getPackageAnnotations();
ExpressionTree getPackageName();
/**
* Return the PackageTree associated with this compilation unit.
* @since 1.9
*/
PackageTree getPackage();
List<? extends ImportTree> getImports();
List<? extends Tree> getTypeDecls();
JavaFileObject getSourceFile();

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2014, 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.source.tree;
import java.util.List;
/**
* Represents the package declaration.
*
* @jls sections 7.3, and 7.4
*
* @author Paul Govereau
* @since 1.9
*/
@jdk.Exported
public interface PackageTree extends Tree {
List<? extends AnnotationTree> getAnnotations();
ExpressionTree getPackageName();
}

View File

@ -207,6 +207,12 @@ public interface Tree {
*/
LAMBDA_EXPRESSION(LambdaExpressionTree.class),
/**
* Used for instances of {@link PackageTree}.
* @since 1.9
*/
PACKAGE(PackageTree.class),
/**
* Used for instances of {@link ParenthesizedTree}.
*/

View File

@ -88,6 +88,7 @@ public interface TreeVisitor<R,P> {
R visitNewArray(NewArrayTree node, P p);
R visitNewClass(NewClassTree node, P p);
R visitLambdaExpression(LambdaExpressionTree node, P p);
R visitPackage(PackageTree node, P p);
R visitParenthesized(ParenthesizedTree node, P p);
R visitReturn(ReturnTree node, P p);
R visitMemberSelect(MemberSelectTree node, P p);

View File

@ -65,6 +65,10 @@ public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> {
return defaultAction(node, p);
}
public R visitPackage(PackageTree node, P p) {
return defaultAction(node, p);
}
public R visitImport(ImportTree node, P p) {
return defaultAction(node, p);
}

View File

@ -114,13 +114,18 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
****************************************************************************/
public R visitCompilationUnit(CompilationUnitTree node, P p) {
R r = scan(node.getPackageAnnotations(), p);
r = scanAndReduce(node.getPackageName(), p, r);
R r = scan(node.getPackage(), p);
r = scanAndReduce(node.getImports(), p, r);
r = scanAndReduce(node.getTypeDecls(), p, r);
return r;
}
public R visitPackage(PackageTree node, P p) {
R r = scan(node.getAnnotations(), p);
r = scanAndReduce(node.getPackageName(), p, r);
return r;
}
public R visitImport(ImportTree node, P p) {
return scan(node.getQualifiedIdentifier(), p);
}

View File

@ -75,6 +75,7 @@ import com.sun.source.doctree.UnknownBlockTagTree;
import com.sun.source.doctree.UnknownInlineTagTree;
import com.sun.source.doctree.ValueTree;
import com.sun.source.doctree.VersionTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.DocTreePath;
import com.sun.source.util.DocTreePathScanner;
import com.sun.source.util.TreePath;
@ -145,8 +146,8 @@ public class Checker extends DocTreePathScanner<Void, Void> {
boolean isOverridingMethod = !env.currOverriddenMethods.isEmpty();
if (p.getLeaf() == p.getCompilationUnit()) {
// If p points to a compilation unit, the implied declaration is the
if (p.getLeaf().getKind() == Tree.Kind.PACKAGE) {
// If p points to a package, the implied declaration is the
// package declaration (if any) for the compilation unit.
// Handle this case specially, because doc comments are only
// expected in package-info files.

View File

@ -42,6 +42,7 @@ import javax.tools.StandardLocation;
import com.sun.source.doctree.DocCommentTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.PackageTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
@ -346,13 +347,10 @@ public class DocLint implements Plugin {
abstract void visitDecl(Tree tree, Name name);
@Override
public Void visitCompilationUnit(CompilationUnitTree tree, Void ignore) {
if (tree.getPackageName() != null) {
visitDecl(tree, null);
}
return super.visitCompilationUnit(tree, ignore);
public Void visitPackage(PackageTree tree, Void ignore) {
visitDecl(tree, null);
return super.visitPackage(tree, ignore);
}
@Override
public Void visitClass(ClassTree tree, Void ignore) {
visitDecl(tree, tree.getSimpleName());

View File

@ -288,15 +288,16 @@ public class Enter extends JCTree.Visitor {
boolean addEnv = false;
boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info",
JavaFileObject.Kind.SOURCE);
if (tree.pid != null) {
tree.packge = syms.enterPackage(TreeInfo.fullName(tree.pid));
if (tree.packageAnnotations.nonEmpty()
|| pkginfoOpt == PkgInfo.ALWAYS
|| tree.docComments != null) {
JCPackageDecl pd = tree.getPackage();
if (pd != null) {
tree.packge = pd.packge = syms.enterPackage(TreeInfo.fullName(pd.pid));
if ( pd.annotations.nonEmpty()
|| pkginfoOpt == PkgInfo.ALWAYS
|| tree.docComments != null) {
if (isPkgInfo) {
addEnv = true;
} else if (tree.packageAnnotations.nonEmpty()){
log.error(tree.packageAnnotations.head.pos(),
} else if (pd.annotations.nonEmpty()) {
log.error(pd.annotations.head.pos(),
"pkg.annotations.sb.in.package-info.java");
}
}
@ -305,26 +306,20 @@ public class Enter extends JCTree.Visitor {
}
tree.packge.complete(); // Find all classes in package.
Env<AttrContext> topEnv = topLevelEnv(tree);
Env<AttrContext> packageEnv = isPkgInfo ? topEnv.dup(pd) : null;
// Save environment of package-info.java file.
if (isPkgInfo) {
Env<AttrContext> env0 = typeEnvs.get(tree.packge);
if (env0 == null) {
typeEnvs.put(tree.packge, topEnv);
} else {
if (env0 != null) {
JCCompilationUnit tree0 = env0.toplevel;
if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
log.warning(tree.pid != null ? tree.pid.pos()
: null,
log.warning(pd != null ? pd.pid.pos() : null,
"pkg-info.already.seen",
tree.packge);
if (addEnv || (tree0.packageAnnotations.isEmpty() &&
tree.docComments != null &&
tree.docComments.hasComment(tree))) {
typeEnvs.put(tree.packge, topEnv);
}
}
}
typeEnvs.put(tree.packge, packageEnv);
for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner)
q.flags_field |= EXISTS;
@ -339,7 +334,7 @@ public class Enter extends JCTree.Visitor {
}
classEnter(tree.defs, topEnv);
if (addEnv) {
todo.append(topEnv);
todo.append(packageEnv);
}
log.useSource(prev);
result = null;

View File

@ -388,6 +388,10 @@ public class Flow {
super.scan(tree);
}
}
public void visitPackageDef(JCPackageDecl tree) {
// Do nothing for PackageDecl
}
}
/**
@ -723,10 +727,6 @@ public class Flow {
}
}
public void visitTopLevel(JCCompilationUnit tree) {
// Do nothing for TopLevel since each class is visited individually
}
/**************************************************************************
* main method
*************************************************************************/
@ -1289,10 +1289,6 @@ public class Flow {
}
}
public void visitTopLevel(JCCompilationUnit tree) {
// Do nothing for TopLevel since each class is visited individually
}
/**************************************************************************
* main method
*************************************************************************/
@ -2357,10 +2353,6 @@ public class Flow {
tree.underlyingType.accept(this);
}
public void visitTopLevel(JCCompilationUnit tree) {
// Do nothing for TopLevel since each class is visited individually
}
/**************************************************************************
* main method
*************************************************************************/
@ -2677,10 +2669,6 @@ public class Flow {
}
}
public void visitTopLevel(JCCompilationUnit tree) {
// Do nothing for TopLevel since each class is visited individually
}
/**************************************************************************
* main method
*************************************************************************/

View File

@ -2408,39 +2408,39 @@ public class Lower extends TreeTranslator {
return trees;
}
public void visitTopLevel(JCCompilationUnit tree) {
if (needPackageInfoClass(tree)) {
Name name = names.package_info;
long flags = Flags.ABSTRACT | Flags.INTERFACE;
if (target.isPackageInfoSynthetic())
// package-info is marked SYNTHETIC in JDK 1.6 and later releases
flags = flags | Flags.SYNTHETIC;
JCClassDecl packageAnnotationsClass
= make.ClassDef(make.Modifiers(flags,
tree.packageAnnotations),
name, List.<JCTypeParameter>nil(),
null, List.<JCExpression>nil(), List.<JCTree>nil());
ClassSymbol c = tree.packge.package_info;
c.flags_field |= flags;
c.setAttributes(tree.packge);
ClassType ctype = (ClassType) c.type;
ctype.supertype_field = syms.objectType;
ctype.interfaces_field = List.nil();
packageAnnotationsClass.sym = c;
public void visitPackageDef(JCPackageDecl tree) {
if (!needPackageInfoClass(tree))
return;
translated.append(packageAnnotationsClass);
}
Name name = names.package_info;
long flags = Flags.ABSTRACT | Flags.INTERFACE;
if (target.isPackageInfoSynthetic())
// package-info is marked SYNTHETIC in JDK 1.6 and later releases
flags = flags | Flags.SYNTHETIC;
JCClassDecl packageAnnotationsClass
= make.ClassDef(make.Modifiers(flags, tree.getAnnotations()),
name, List.<JCTypeParameter>nil(),
null, List.<JCExpression>nil(), List.<JCTree>nil());
ClassSymbol c = tree.packge.package_info;
c.flags_field |= flags;
c.setAttributes(tree.packge);
ClassType ctype = (ClassType) c.type;
ctype.supertype_field = syms.objectType;
ctype.interfaces_field = List.nil();
packageAnnotationsClass.sym = c;
translated.append(packageAnnotationsClass);
}
// where
private boolean needPackageInfoClass(JCCompilationUnit tree) {
private boolean needPackageInfoClass(JCPackageDecl pd) {
switch (pkginfoOpt) {
case ALWAYS:
return true;
case LEGACY:
return tree.packageAnnotations.nonEmpty();
return pd.getAnnotations().nonEmpty();
case NONEMPTY:
for (Attribute.Compound a :
tree.packge.getDeclarationAttributes()) {
pd.packge.getDeclarationAttributes()) {
Attribute.RetentionPolicy p = types.getRetention(a);
if (p != Attribute.RetentionPolicy.SOURCE)
return true;

View File

@ -493,10 +493,26 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
return;
}
DiagnosticPosition prevLintPos = deferredLintHandler.immediate();
Lint prevLint = chk.setLint(lint);
try {
// Import-on-demand java.lang.
importAll(tree.pos, syms.enterPackage(names.java_lang), env);
// Process the package def and all import clauses.
memberEnter(tree.defs, env);
} finally {
chk.setLint(prevLint);
deferredLintHandler.setPos(prevLintPos);
}
}
public void visitPackageDef(JCPackageDecl tree) {
// check that no class exists with same fully qualified name as
// toplevel package
if (checkClash && tree.pid != null) {
Symbol p = tree.packge;
Symbol p = env.toplevel.packge;
while (p.owner != syms.rootPackage) {
p.owner.complete(); // enter all class members of p
if (syms.classes.get(p.getQualifiedName()) != null) {
@ -507,23 +523,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
p = p.owner;
}
}
// process package annotations
annotate.annotateLater(tree.packageAnnotations, env, tree.packge, null);
DiagnosticPosition prevLintPos = deferredLintHandler.immediate();
Lint prevLint = chk.setLint(lint);
try {
// Import-on-demand java.lang.
importAll(tree.pos, syms.enterPackage(names.java_lang), env);
// Process all import clauses.
memberEnter(tree.defs, env);
} finally {
chk.setLint(prevLint);
deferredLintHandler.setPos(prevLintPos);
}
annotate.annotateLater(tree.annotations, env, env.toplevel.packge, null);
}
// process the non-static imports and the static imports of types.

View File

@ -601,8 +601,7 @@ public class JavaCompiler {
*/
protected JCCompilationUnit parse(JavaFileObject filename, CharSequence content) {
long msec = now();
JCCompilationUnit tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(),
null, List.<JCTree>nil());
JCCompilationUnit tree = make.TopLevel(List.<JCTree>nil());
if (content != null) {
if (verbose) {
log.printVerbose("parsing.started", filename);
@ -689,7 +688,7 @@ public class JavaCompiler {
: make.Select(tree, names.fromString(s));
}
JCCompilationUnit toplevel =
make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil());
make.TopLevel(List.<JCTree>nil());
toplevel.packge = syms.unnamedPackage;
return attr.attribIdent(tree, toplevel);
} finally {
@ -768,7 +767,7 @@ public class JavaCompiler {
tree = parse(filename, filename.getCharContent(false));
} catch (IOException e) {
log.error("error.reading.file", filename, JavacFileManager.getMessage(e));
tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil());
tree = make.TopLevel(List.<JCTree>nil());
} finally {
log.useSource(prev);
}
@ -1440,7 +1439,7 @@ public class JavaCompiler {
make.at(Position.FIRSTPOS);
TreeMaker localMake = make.forToplevel(env.toplevel);
if (env.tree instanceof JCCompilationUnit) {
if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF)) {
if (!(stubOutput || sourceOutput || printFlat)) {
if (shouldStop(CompileState.LOWER))
return;

View File

@ -170,8 +170,8 @@ public class JavacElements implements Elements {
Symbol sym = cast(Symbol.class, e);
class Vis extends JCTree.Visitor {
List<JCAnnotation> result = null;
public void visitTopLevel(JCCompilationUnit tree) {
result = tree.packageAnnotations;
public void visitPackageDef(JCPackageDecl tree) {
result = tree.annotations;
}
public void visitClassDef(JCClassDecl tree) {
result = tree.mods.annotations;

View File

@ -3081,27 +3081,33 @@ public class JavacParser implements Parser {
*/
public JCTree.JCCompilationUnit parseCompilationUnit() {
Token firstToken = token;
JCExpression pid = null;
JCModifiers mods = null;
boolean consumedToplevelDoc = false;
boolean seenImport = false;
boolean seenPackage = false;
List<JCAnnotation> packageAnnotations = List.nil();
ListBuffer<JCTree> defs = new ListBuffer<>();
if (token.kind == MONKEYS_AT)
mods = modifiersOpt();
if (token.kind == PACKAGE) {
int packagePos = token.pos;
List<JCAnnotation> annotations = List.nil();
seenPackage = true;
if (mods != null) {
checkNoMods(mods.flags);
packageAnnotations = mods.annotations;
annotations = mods.annotations;
mods = null;
}
nextToken();
pid = qualident(false);
JCExpression pid = qualident(false);
accept(SEMI);
JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid);
attach(pd, firstToken.comment(CommentStyle.JAVADOC));
consumedToplevelDoc = true;
storeEnd(pd, token.pos);
defs.append(pd);
}
ListBuffer<JCTree> defs = new ListBuffer<>();
boolean checkForImports = true;
boolean firstTypeDecl = true;
while (token.kind != EOF) {
@ -3130,7 +3136,7 @@ public class JavacParser implements Parser {
firstTypeDecl = false;
}
}
JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(defs.toList());
if (!consumedToplevelDoc)
attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
if (defs.isEmpty())

View File

@ -89,6 +89,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
*/
TOPLEVEL,
/** Package level definitions.
*/
PACKAGEDEF,
/** Import clauses, of type Import.
*/
IMPORT,
@ -478,9 +482,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
* Everything in one source file is kept in a {@linkplain JCCompilationUnit} structure.
*/
public static class JCCompilationUnit extends JCTree implements CompilationUnitTree {
public List<JCAnnotation> packageAnnotations;
/** The tree representing the package clause. */
public JCExpression pid;
/** All definitions in this file (ClassDef, Import, and Skip) */
public List<JCTree> defs;
/* The source file name. */
@ -499,39 +500,39 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/* An object encapsulating ending positions of source ranges indexed by
* the tree nodes they belong to. Defined only if option -Xjcov is set. */
public EndPosTable endPositions = null;
protected JCCompilationUnit(List<JCAnnotation> packageAnnotations,
JCExpression pid,
List<JCTree> defs,
JavaFileObject sourcefile,
PackageSymbol packge,
ImportScope namedImportScope,
StarImportScope starImportScope) {
this.packageAnnotations = packageAnnotations;
this.pid = pid;
protected JCCompilationUnit(List<JCTree> defs) {
this.defs = defs;
this.sourcefile = sourcefile;
this.packge = packge;
this.namedImportScope = namedImportScope;
this.starImportScope = starImportScope;
}
@Override
public void accept(Visitor v) { v.visitTopLevel(this); }
public Kind getKind() { return Kind.COMPILATION_UNIT; }
public List<JCAnnotation> getPackageAnnotations() {
return packageAnnotations;
public JCPackageDecl getPackage() {
// PackageDecl must be the first entry if it exists
if (!defs.isEmpty() && defs.head.hasTag(PACKAGEDEF))
return (JCPackageDecl)defs.head;
return null;
}
public List<JCAnnotation> getPackageAnnotations() {
JCPackageDecl pd = getPackage();
return pd != null ? pd.getAnnotations() : List.<JCAnnotation>nil();
}
public ExpressionTree getPackageName() {
JCPackageDecl pd = getPackage();
return pd != null ? pd.getPackageName() : null;
}
public List<JCImport> getImports() {
ListBuffer<JCImport> imports = new ListBuffer<>();
for (JCTree tree : defs) {
if (tree.hasTag(IMPORT))
imports.append((JCImport)tree);
else if (!tree.hasTag(SKIP))
else if (!tree.hasTag(PACKAGEDEF) && !tree.hasTag(SKIP))
break;
}
return imports.toList();
}
public JCExpression getPackageName() { return pid; }
public JavaFileObject getSourceFile() {
return sourcefile;
}
@ -541,7 +542,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public List<JCTree> getTypeDecls() {
List<JCTree> typeDefs;
for (typeDefs = defs; !typeDefs.isEmpty(); typeDefs = typeDefs.tail)
if (!typeDefs.head.hasTag(IMPORT))
if (!typeDefs.head.hasTag(PACKAGEDEF) && !typeDefs.head.hasTag(IMPORT))
break;
return typeDefs;
}
@ -556,6 +557,39 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
}
}
/**
* Package definition.
*/
public static class JCPackageDecl extends JCTree implements PackageTree {
public List<JCAnnotation> annotations;
/** The tree representing the package clause. */
public JCExpression pid;
public PackageSymbol packge;
public JCPackageDecl(List<JCAnnotation> annotations, JCExpression pid) {
this.annotations = annotations;
this.pid = pid;
}
@Override
public void accept(Visitor v) { v.visitPackageDef(this); }
public Kind getKind() {
return Kind.PACKAGE;
}
public List<JCAnnotation> getAnnotations() {
return annotations;
}
public JCExpression getPackageName() {
return pid;
}
@Override
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
return v.visitPackage(this, d);
}
@Override
public Tag getTag() {
return PACKAGEDEF;
}
}
/**
* An import clause.
*/
@ -2438,9 +2472,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/** An interface for tree factories
*/
public interface Factory {
JCCompilationUnit TopLevel(List<JCAnnotation> packageAnnotations,
JCExpression pid,
List<JCTree> defs);
JCCompilationUnit TopLevel(List<JCTree> defs);
JCPackageDecl PackageDecl(List<JCAnnotation> annotations,
JCExpression pid);
JCImport Import(JCTree qualid, boolean staticImport);
JCClassDecl ClassDef(JCModifiers mods,
Name name,
@ -2528,6 +2562,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
*/
public static abstract class Visitor {
public void visitTopLevel(JCCompilationUnit that) { visitTree(that); }
public void visitPackageDef(JCPackageDecl that) { visitTree(that); }
public void visitImport(JCImport that) { visitTree(that); }
public void visitClassDef(JCClassDecl that) { visitTree(that); }
public void visitMethodDef(JCMethodDecl that) { visitTree(that); }

View File

@ -367,16 +367,13 @@ public class Pretty extends JCTree.Visitor {
public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOException {
docComments = tree.docComments;
printDocComment(tree);
if (tree.pid != null) {
print("package ");
printExpr(tree.pid);
print(";");
println();
}
boolean firstImport = true;
for (List<JCTree> l = tree.defs;
l.nonEmpty() && (cdef == null || l.head.hasTag(IMPORT));
l = l.tail) {
l.nonEmpty() &&
(cdef == null ||
l.head.hasTag(IMPORT) || l.head.hasTag(PACKAGEDEF));
l = l.tail) {
if (l.head.hasTag(IMPORT)) {
JCImport imp = (JCImport)l.head;
Name name = TreeInfo.name(imp.qualid);
@ -426,6 +423,21 @@ public class Pretty extends JCTree.Visitor {
}
}
public void visitPackageDef(JCPackageDecl tree) {
try {
printDocComment(tree);
printAnnotations(tree.annotations);
if (tree.pid != null) {
print("package ");
printExpr(tree.pid);
print(";");
println();
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitImport(JCImport tree) {
try {
print("import ");

View File

@ -346,10 +346,15 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
public JCTree visitCompilationUnit(CompilationUnitTree node, P p) {
JCCompilationUnit t = (JCCompilationUnit) node;
List<JCAnnotation> packageAnnotations = copy(t.packageAnnotations, p);
JCExpression pid = copy(t.pid, p);
List<JCTree> defs = copy(t.defs, p);
return M.at(t.pos).TopLevel(packageAnnotations, pid, defs);
return M.at(t.pos).TopLevel(defs);
}
public JCTree visitPackage(PackageTree node, P p) {
JCPackageDecl t = (JCPackageDecl) node;
List<JCAnnotation> annotations = copy(t.annotations, p);
JCExpression pid = copy(t.pid, p);
return M.at(t.pos).PackageDecl(annotations, pid);
}
public JCTree visitTry(TryTree node, P p) {

View File

@ -406,6 +406,11 @@ public class TreeInfo {
return Position.NOPOS;
switch(tree.getTag()) {
case PACKAGEDEF: {
JCPackageDecl pd = (JCPackageDecl)tree;
return pd.annotations.isEmpty() ? pd.pos :
pd.annotations.head.pos;
}
case APPLY:
return getStartPos(((JCMethodInvocation) tree).meth);
case ASSIGN:
@ -788,6 +793,8 @@ public class TreeInfo {
switch (node.getTag()) {
case TOPLEVEL:
return ((JCCompilationUnit) node).packge;
case PACKAGEDEF:
return ((JCPackageDecl) node).packge;
case CLASSDEF:
return ((JCClassDecl) node).sym;
case METHODDEF:
@ -820,6 +827,7 @@ public class TreeInfo {
public static boolean isDeclaration(JCTree node) {
node = skipParens(node);
switch (node.getTag()) {
case PACKAGEDEF:
case CLASSDEF:
case METHODDEF:
case VARDEF:

View File

@ -116,22 +116,28 @@ public class TreeMaker implements JCTree.Factory {
/**
* Create given tree node at current position.
* @param defs a list of ClassDef, Import, and Skip
* @param defs a list of PackageDef, ClassDef, Import, and Skip
*/
public JCCompilationUnit TopLevel(List<JCAnnotation> packageAnnotations,
JCExpression pid,
List<JCTree> defs) {
Assert.checkNonNull(packageAnnotations);
public JCCompilationUnit TopLevel(List<JCTree> defs) {
for (JCTree node : defs)
Assert.check(node instanceof JCClassDecl
|| node instanceof JCPackageDecl
|| node instanceof JCImport
|| node instanceof JCSkip
|| node instanceof JCErroneous
|| (node instanceof JCExpressionStatement
&& ((JCExpressionStatement)node).expr instanceof JCErroneous),
node.getClass().getSimpleName());
JCCompilationUnit tree = new JCCompilationUnit(packageAnnotations, pid, defs,
null, null, null, null);
JCCompilationUnit tree = new JCCompilationUnit(defs);
tree.pos = pos;
return tree;
}
public JCPackageDecl PackageDecl(List<JCAnnotation> annotations,
JCExpression pid) {
Assert.checkNonNull(annotations);
Assert.checkNonNull(pid);
JCPackageDecl tree = new JCPackageDecl(annotations, pid);
tree.pos = pos;
return tree;
}

View File

@ -63,11 +63,14 @@ public class TreeScanner extends Visitor {
****************************************************************************/
public void visitTopLevel(JCCompilationUnit tree) {
scan(tree.packageAnnotations);
scan(tree.pid);
scan(tree.defs);
}
public void visitPackageDef(JCPackageDecl tree) {
scan(tree.annotations);
scan(tree.pid);
}
public void visitImport(JCImport tree) {
scan(tree.qualid);
}

View File

@ -116,11 +116,16 @@ public class TreeTranslator extends JCTree.Visitor {
****************************************************************************/
public void visitTopLevel(JCCompilationUnit tree) {
tree.pid = translate(tree.pid);
tree.defs = translate(tree.defs);
result = tree;
}
public void visitPackageDef(JCPackageDecl tree) {
tree.annotations = translate(tree.annotations);
tree.pid = translate(tree.pid);
result = tree;
}
public void visitImport(JCImport tree) {
tree.qualid = translate(tree.qualid);
result = tree;

View File

@ -743,6 +743,13 @@ public class DocEnv {
return p;
}
TreePath getTreePath(JCCompilationUnit toplevel, JCPackageDecl tree) {
TreePath p = treePaths.get(tree);
if (p == null)
treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree));
return p;
}
TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) {
TreePath p = treePaths.get(tree);
if (p == null)

View File

@ -27,6 +27,7 @@ package com.sun.tools.javadoc;
import javax.tools.JavaFileObject;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.Enter;
@ -84,7 +85,9 @@ public class JavadocEnter extends Enter {
public void visitTopLevel(JCCompilationUnit tree) {
super.visitTopLevel(tree);
if (tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE)) {
docenv.makePackageDoc(tree.packge, docenv.getTreePath(tree));
JCPackageDecl pd = tree.getPackage();
TreePath tp = pd == null ? docenv.getTreePath(tree) : docenv.getTreePath(tree, pd);
docenv.makePackageDoc(tree.packge, tp);
}
}

View File

@ -144,7 +144,8 @@ public class DocCommentToplevelTest {
public ClassTree visitCompilationUnit(CompilationUnitTree node, Void unused) {
docComments = ((JCTree.JCCompilationUnit)node).docComments;
boolean expectedComment = tdk == ToplevelDocKind.HAS_DOC &&
(pk != PackageKind.NO_PKG || ik != ImportKind.ZERO);
pk == PackageKind.NO_PKG &&
ik != ImportKind.ZERO;
boolean foundComment = docComments.hasComment((JCTree) node);
if (expectedComment != foundComment) {
error("Unexpected comment " + docComments.getComment((JCTree) node) + " on toplevel");
@ -152,6 +153,17 @@ public class DocCommentToplevelTest {
return super.visitCompilationUnit(node, null);
}
@Override
public ClassTree visitPackage(PackageTree node, Void unused) {
boolean expectedComment = tdk == ToplevelDocKind.HAS_DOC &&
pk != PackageKind.NO_PKG;
boolean foundComment = docComments.hasComment((JCTree) node);
if (expectedComment != foundComment) {
error("Unexpected comment " + docComments.getComment((JCTree) node) + " on toplevel");
}
return super.visitPackage(node, null);
}
@Override
public ClassTree visitClass(ClassTree node, Void unused) {
boolean expectedComment = tdk == ToplevelDocKind.HAS_DOC &&