changeset 2379:a5e2ad53792d

8034245: Refactor TopLevel tree node. Summary: Added JCPackageDecl to JCTree to store package-level information. Reviewed-by: jjg, jlahoda
author pgovereau
date Tue, 22 Apr 2014 17:07:54 -0400
parents 71a8aaacdc8a
children 773a179340fc
files src/share/classes/com/sun/source/tree/CompilationUnitTree.java src/share/classes/com/sun/source/tree/PackageTree.java src/share/classes/com/sun/source/tree/Tree.java src/share/classes/com/sun/source/tree/TreeVisitor.java src/share/classes/com/sun/source/util/SimpleTreeVisitor.java src/share/classes/com/sun/source/util/TreeScanner.java src/share/classes/com/sun/tools/doclint/Checker.java src/share/classes/com/sun/tools/doclint/DocLint.java src/share/classes/com/sun/tools/javac/comp/Enter.java src/share/classes/com/sun/tools/javac/comp/Flow.java src/share/classes/com/sun/tools/javac/comp/Lower.java src/share/classes/com/sun/tools/javac/comp/MemberEnter.java src/share/classes/com/sun/tools/javac/main/JavaCompiler.java src/share/classes/com/sun/tools/javac/model/JavacElements.java src/share/classes/com/sun/tools/javac/parser/JavacParser.java src/share/classes/com/sun/tools/javac/tree/JCTree.java src/share/classes/com/sun/tools/javac/tree/Pretty.java src/share/classes/com/sun/tools/javac/tree/TreeCopier.java src/share/classes/com/sun/tools/javac/tree/TreeInfo.java src/share/classes/com/sun/tools/javac/tree/TreeMaker.java src/share/classes/com/sun/tools/javac/tree/TreeScanner.java src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java src/share/classes/com/sun/tools/javadoc/DocEnv.java src/share/classes/com/sun/tools/javadoc/JavadocEnter.java test/tools/javac/tree/DocCommentToplevelTest.java
diffstat 25 files changed, 293 insertions(+), 145 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/source/tree/CompilationUnitTree.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/source/tree/CompilationUnitTree.java	Tue Apr 22 17:07:54 2014 -0400
@@ -41,6 +41,12 @@
 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();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/source/tree/PackageTree.java	Tue Apr 22 17:07:54 2014 -0400
@@ -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();
+}
--- a/src/share/classes/com/sun/source/tree/Tree.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/source/tree/Tree.java	Tue Apr 22 17:07:54 2014 -0400
@@ -208,6 +208,12 @@
         LAMBDA_EXPRESSION(LambdaExpressionTree.class),
 
         /**
+         * Used for instances of {@link PackageTree}.
+         * @since 1.9
+         */
+        PACKAGE(PackageTree.class),
+
+        /**
          * Used for instances of {@link ParenthesizedTree}.
          */
         PARENTHESIZED(ParenthesizedTree.class),
--- a/src/share/classes/com/sun/source/tree/TreeVisitor.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/source/tree/TreeVisitor.java	Tue Apr 22 17:07:54 2014 -0400
@@ -88,6 +88,7 @@
     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);
--- a/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Tue Apr 22 17:07:54 2014 -0400
@@ -65,6 +65,10 @@
         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);
     }
--- a/src/share/classes/com/sun/source/util/TreeScanner.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/source/util/TreeScanner.java	Tue Apr 22 17:07:54 2014 -0400
@@ -114,13 +114,18 @@
  ****************************************************************************/
 
     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);
     }
--- a/src/share/classes/com/sun/tools/doclint/Checker.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/doclint/Checker.java	Tue Apr 22 17:07:54 2014 -0400
@@ -75,6 +75,7 @@
 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 @@
 
         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.
--- a/src/share/classes/com/sun/tools/doclint/DocLint.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/doclint/DocLint.java	Tue Apr 22 17:07:54 2014 -0400
@@ -42,6 +42,7 @@
 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 @@
         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());
--- a/src/share/classes/com/sun/tools/javac/comp/Enter.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Enter.java	Tue Apr 22 17:07:54 2014 -0400
@@ -288,15 +288,16 @@
         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 @@
         }
         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 @@
         }
         classEnter(tree.defs, topEnv);
         if (addEnv) {
-            todo.append(topEnv);
+            todo.append(packageEnv);
         }
         log.useSource(prev);
         result = null;
--- a/src/share/classes/com/sun/tools/javac/comp/Flow.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java	Tue Apr 22 17:07:54 2014 -0400
@@ -388,6 +388,10 @@
                 super.scan(tree);
             }
         }
+
+        public void visitPackageDef(JCPackageDecl tree) {
+            // Do nothing for PackageDecl
+        }
     }
 
     /**
@@ -723,10 +727,6 @@
             }
         }
 
-        public void visitTopLevel(JCCompilationUnit tree) {
-            // Do nothing for TopLevel since each class is visited individually
-        }
-
     /**************************************************************************
      * main method
      *************************************************************************/
@@ -1289,10 +1289,6 @@
             }
         }
 
-        public void visitTopLevel(JCCompilationUnit tree) {
-            // Do nothing for TopLevel since each class is visited individually
-        }
-
     /**************************************************************************
      * main method
      *************************************************************************/
@@ -2357,10 +2353,6 @@
             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 void visitTopLevel(JCCompilationUnit tree) {
-            // Do nothing for TopLevel since each class is visited individually
-        }
-
     /**************************************************************************
      * main method
      *************************************************************************/
--- a/src/share/classes/com/sun/tools/javac/comp/Lower.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java	Tue Apr 22 17:07:54 2014 -0400
@@ -2408,39 +2408,39 @@
         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;
-
-            translated.append(packageAnnotationsClass);
-        }
+    public void visitPackageDef(JCPackageDecl tree) {
+        if (!needPackageInfoClass(tree))
+            return;
+
+        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;
--- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Tue Apr 22 17:07:54 2014 -0400
@@ -493,10 +493,26 @@
             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 @@
                 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.
--- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Tue Apr 22 17:07:54 2014 -0400
@@ -601,8 +601,7 @@
      */
     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 @@
                                       : 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 @@
                 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 @@
             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;
--- a/src/share/classes/com/sun/tools/javac/model/JavacElements.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/model/JavacElements.java	Tue Apr 22 17:07:54 2014 -0400
@@ -170,8 +170,8 @@
         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;
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Tue Apr 22 17:07:54 2014 -0400
@@ -3081,27 +3081,33 @@
      */
     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 @@
                 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())
--- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Tue Apr 22 17:07:54 2014 -0400
@@ -89,6 +89,10 @@
         */
         TOPLEVEL,
 
+        /** Package level definitions.
+         */
+        PACKAGEDEF,
+
         /** Import clauses, of type Import.
          */
         IMPORT,
@@ -478,9 +482,6 @@
      * 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 @@
         /* 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 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() {
-            return packageAnnotations;
+            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 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;
         }
@@ -557,6 +558,39 @@
     }
 
     /**
+     * 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.
      */
     public static class JCImport extends JCTree implements ImportTree {
@@ -2438,9 +2472,9 @@
     /** 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 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); }
--- a/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Tue Apr 22 17:07:54 2014 -0400
@@ -367,16 +367,13 @@
     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 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 ");
--- a/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Tue Apr 22 17:07:54 2014 -0400
@@ -346,10 +346,15 @@
 
     public JCTree visitCompilationUnit(CompilationUnitTree node, P p) {
         JCCompilationUnit t = (JCCompilationUnit) node;
-        List<JCAnnotation> packageAnnotations = copy(t.packageAnnotations, p);
+        List<JCTree> defs = copy(t.defs, p);
+        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);
-        List<JCTree> defs = copy(t.defs, p);
-        return M.at(t.pos).TopLevel(packageAnnotations, pid, defs);
+        return M.at(t.pos).PackageDecl(annotations, pid);
     }
 
     public JCTree visitTry(TryTree node, P p) {
--- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Tue Apr 22 17:07:54 2014 -0400
@@ -406,6 +406,11 @@
             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 @@
         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 static boolean isDeclaration(JCTree node) {
         node = skipParens(node);
         switch (node.getTag()) {
+        case PACKAGEDEF:
         case CLASSDEF:
         case METHODDEF:
         case VARDEF:
--- a/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Tue Apr 22 17:07:54 2014 -0400
@@ -116,22 +116,28 @@
 
     /**
      * 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;
     }
--- a/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Tue Apr 22 17:07:54 2014 -0400
@@ -63,9 +63,12 @@
  ****************************************************************************/
 
     public void visitTopLevel(JCCompilationUnit tree) {
-        scan(tree.packageAnnotations);
+        scan(tree.defs);
+    }
+
+    public void visitPackageDef(JCPackageDecl tree) {
+        scan(tree.annotations);
         scan(tree.pid);
-        scan(tree.defs);
     }
 
     public void visitImport(JCImport tree) {
--- a/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Tue Apr 22 17:07:54 2014 -0400
@@ -116,8 +116,13 @@
  ****************************************************************************/
 
     public void visitTopLevel(JCCompilationUnit tree) {
+        tree.defs = translate(tree.defs);
+        result = tree;
+    }
+
+    public void visitPackageDef(JCPackageDecl tree) {
+        tree.annotations = translate(tree.annotations);
         tree.pid = translate(tree.pid);
-        tree.defs = translate(tree.defs);
         result = tree;
     }
 
--- a/src/share/classes/com/sun/tools/javadoc/DocEnv.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javadoc/DocEnv.java	Tue Apr 22 17:07:54 2014 -0400
@@ -743,6 +743,13 @@
         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)
--- a/src/share/classes/com/sun/tools/javadoc/JavadocEnter.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/src/share/classes/com/sun/tools/javadoc/JavadocEnter.java	Tue Apr 22 17:07:54 2014 -0400
@@ -27,6 +27,7 @@
 
 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 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);
         }
     }
 
--- a/test/tools/javac/tree/DocCommentToplevelTest.java	Tue Apr 22 19:52:15 2014 +0100
+++ b/test/tools/javac/tree/DocCommentToplevelTest.java	Tue Apr 22 17:07:54 2014 -0400
@@ -144,7 +144,8 @@
             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");
@@ -153,6 +154,17 @@
             }
 
             @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 &&
                         pk == PackageKind.NO_PKG && ik == ImportKind.ZERO &&