7106166: (javac) re-factor EndPos parser
authorksrini
Mon, 14 Nov 2011 15:11:10 -0800
changeset 11055 ec1418effa77
parent 11054 c4224d65eb3e
child 11056 06641a7160e5
7106166: (javac) re-factor EndPos parser Reviewed-by: jjg
langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java
langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java
langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java
langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java
langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java
langtools/src/share/classes/com/sun/tools/javac/parser/EndPosTable.java
langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java
langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java
langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java
langtools/src/share/classes/com/sun/tools/javac/util/DiagnosticSource.java
langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java
langtools/src/share/classes/com/sun/tools/javac/util/Log.java
langtools/test/tools/javac/6304921/TestLog.java
langtools/test/tools/javac/failover/CheckAttributedTree.java
langtools/test/tools/javac/tree/TreePosTest.java
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Mon Nov 14 15:11:10 2011 -0800
@@ -59,6 +59,7 @@
 import com.sun.tools.javac.comp.MemberEnter;
 import com.sun.tools.javac.comp.Resolve;
 import com.sun.tools.javac.model.JavacElements;
+import com.sun.tools.javac.parser.EndPosTable;
 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.tree.JCTree;
@@ -140,8 +141,8 @@
                 }
 
                 public long getEndPosition(CompilationUnitTree file, Tree tree) {
-                    Map<JCTree,Integer> endPositions = ((JCCompilationUnit) file).endPositions;
-                    return TreeInfo.getEndPos((JCTree) tree, endPositions);
+                    EndPosTable endPosTable = ((JCCompilationUnit) file).endPositions;
+                    return TreeInfo.getEndPos((JCTree) tree, endPosTable);
                 }
             };
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Nov 14 15:11:10 2011 -0800
@@ -40,6 +40,7 @@
 import com.sun.tools.javac.code.Type.*;
 
 import com.sun.tools.javac.jvm.Target;
+import com.sun.tools.javac.parser.EndPosTable;
 
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Flags.BLOCK;
@@ -127,7 +128,7 @@
 
     /** A hash table mapping syntax trees to their ending source positions.
      */
-    Map<JCTree, Integer> endPositions;
+    EndPosTable endPosTable;
 
 /**************************************************************************
  * Global mappings
@@ -2195,9 +2196,8 @@
         } else {
             make_at(tree.pos());
             T result = super.translate(tree);
-            if (endPositions != null && result != tree) {
-                Integer endPos = endPositions.remove(tree);
-                if (endPos != null) endPositions.put(result, endPos);
+            if (endPosTable != null && result != tree) {
+                endPosTable.replaceTree(tree, result);
             }
             return result;
         }
@@ -3675,7 +3675,7 @@
         try {
             attrEnv = env;
             this.make = make;
-            endPositions = env.toplevel.endPositions;
+            endPosTable = env.toplevel.endPositions;
             currentClass = null;
             currentMethodDef = null;
             outermostClassDef = (cdef.hasTag(CLASSDEF)) ? (JCClassDecl)cdef : null;
@@ -3704,7 +3704,7 @@
             // note that recursive invocations of this method fail hard
             attrEnv = null;
             this.make = null;
-            endPositions = null;
+            endPosTable = null;
             currentClass = null;
             currentMethodDef = null;
             outermostClassDef = null;
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java	Mon Nov 14 15:11:10 2011 -0800
@@ -31,6 +31,7 @@
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.parser.EndPosTable;
 
 /** This class contains the CharacterRangeTable for some method
  *  and the hashtable for mapping trees or lists of trees to their
@@ -54,9 +55,9 @@
      */
     private Map<Object,SourceRange> positions = new HashMap<Object,SourceRange>();
 
-    /** The hashtable for ending positions stored in the parser.
+    /** The object for ending positions stored in the parser.
      */
-    private Map<JCTree, Integer> endPositions;
+    private EndPosTable endPosTable;
 
     /** The tree of the method this table is intended for.
      *  We should traverse this tree to get source ranges.
@@ -65,9 +66,9 @@
 
     /** Constructor
      */
-    public CRTable(JCTree.JCMethodDecl tree, Map<JCTree, Integer> endPositions) {
+    public CRTable(JCTree.JCMethodDecl tree, EndPosTable endPosTable) {
         this.methodTree = tree;
-        this.endPositions = endPositions;
+        this.endPosTable = endPosTable;
     }
 
     /** Create a new CRTEntry and add it to the entries.
@@ -534,10 +535,7 @@
             if (tree == null) return Position.NOPOS;
             if (tree.hasTag(JCTree.Tag.BLOCK))
                 return ((JCBlock) tree).endpos;
-            Integer endpos = endPositions.get(tree);
-            if (endpos != null)
-                return endpos.intValue();
-            return Position.NOPOS;
+            return endPosTable.getEndPos(tree);
         }
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Mon Nov 14 15:11:10 2011 -0800
@@ -26,8 +26,6 @@
 package com.sun.tools.javac.jvm;
 import java.util.*;
 
-import javax.lang.model.element.ElementKind;
-
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
@@ -39,6 +37,7 @@
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.jvm.Code.*;
 import com.sun.tools.javac.jvm.Items.*;
+import com.sun.tools.javac.parser.EndPosTable;
 import com.sun.tools.javac.tree.JCTree.*;
 
 import static com.sun.tools.javac.code.Flags.*;
@@ -197,9 +196,10 @@
      */
     private int nerrs = 0;
 
-    /** A hash table mapping syntax trees to their ending source positions.
+    /** An object containing mappings of syntax trees to their
+     *  ending source positions.
      */
-    private Map<JCTree, Integer> endPositions;
+    EndPosTable endPosTable;
 
     /** Generate code to load an integer constant.
      *  @param n     The integer to be loaded.
@@ -482,20 +482,14 @@
                         JCStatement init = make.at(vdef.pos()).
                             Assignment(sym, vdef.init);
                         initCode.append(init);
-                        if (endPositions != null) {
-                            Integer endPos = endPositions.remove(vdef);
-                            if (endPos != null) endPositions.put(init, endPos);
-                        }
+                        endPosTable.replaceTree(vdef, init);
                     } else if (sym.getConstValue() == null) {
                         // Initialize class (static) variables only if
                         // they are not compile-time constants.
                         JCStatement init = make.at(vdef.pos).
                             Assignment(sym, vdef.init);
                         clinitCode.append(init);
-                        if (endPositions != null) {
-                            Integer endPos = endPositions.remove(vdef);
-                            if (endPos != null) endPositions.put(init, endPos);
-                        }
+                        endPosTable.replaceTree(vdef, init);
                     } else {
                         checkStringConstant(vdef.init.pos(), sym.getConstValue());
                     }
@@ -2217,7 +2211,7 @@
             attrEnv = env;
             ClassSymbol c = cdef.sym;
             this.toplevel = env.toplevel;
-            this.endPositions = toplevel.endPositions;
+            this.endPosTable = toplevel.endPositions;
             // If this is a class definition requiring Miranda methods,
             // add them.
             if (generateIproxies &&
@@ -2253,7 +2247,7 @@
             attrEnv = null;
             this.env = null;
             toplevel = null;
-            endPositions = null;
+            endPosTable = null;
             nerrs = 0;
         }
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java	Mon Nov 14 08:09:47 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2005, 2008, 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.util.Map;
-import java.util.HashMap;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.TreeInfo;
-
-import static com.sun.tools.javac.tree.JCTree.*;
-
-/**
- * This class is similar to Parser except that it stores ending
- * positions for the tree nodes.
- *
- * <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></p>
- */
-public class EndPosParser extends JavacParser {
-
-    public EndPosParser(ParserFactory fac, Lexer S, boolean keepDocComments, boolean keepLineMap) {
-        super(fac, S, keepDocComments, keepLineMap);
-        this.S = S;
-        endPositions = new HashMap<JCTree,Integer>();
-    }
-
-    private Lexer S;
-
-    /** A hashtable to store ending positions
-     *  of source ranges indexed by the tree nodes.
-     *  Defined only if option flag genEndPos is set.
-     */
-    Map<JCTree, Integer> endPositions;
-
-    /** {@inheritDoc} */
-    @Override
-    protected void storeEnd(JCTree tree, int endpos) {
-        int errorEndPos = getErrorEndPos();
-        endPositions.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    protected <T extends JCTree> T to(T t) {
-        storeEnd(t, token.endPos);
-        return t;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    protected <T extends JCTree> T toP(T t) {
-        storeEnd(t, S.prevToken().endPos);
-        return t;
-    }
-
-    @Override
-    public JCCompilationUnit parseCompilationUnit() {
-        JCCompilationUnit t = super.parseCompilationUnit();
-        t.endPositions = endPositions;
-        return t;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    JCExpression parExpression() {
-        int pos = token.pos;
-        JCExpression t = super.parExpression();
-        return toP(F.at(pos).Parens(t));
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public int getEndPos(JCTree tree) {
-        return TreeInfo.getEndPos(tree, endPositions);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosTable.java	Mon Nov 14 15:11:10 2011 -0800
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, 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 com.sun.tools.javac.tree.JCTree;
+
+/**
+ * Specifies the methods to access a mappings of syntax trees to end positions.
+ * <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></p>
+ */
+public interface EndPosTable {
+
+    /**
+     * This method will return the end position of a given tree, otherwise a
+     * Positions.NOPOS will be returned.
+     * @param tree JCTree
+     * @return position of the source tree or Positions.NOPOS for non-existent mapping
+     */
+    public int getEndPos(JCTree tree);
+
+    /**
+     * Give an old tree and a new tree, the old tree will be replaced with
+     * the new tree, the position of the new tree will be that of the old
+     * tree.
+     * not exist.
+     * @param oldtree a JCTree to be replaced
+     * @param newtree a JCTree to be replaced with
+     * @return position of the old tree or Positions.NOPOS for non-existent mapping
+     */
+    public int replaceTree(JCTree oldtree, JCTree newtree);
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Nov 14 15:11:10 2011 -0800
@@ -83,12 +83,16 @@
     /** The name table. */
     private Names names;
 
+    /** End position mappings container */
+    private final AbstractEndPosTable endPosTable;
+
     /** Construct a parser from a given scanner, tree factory and log.
      */
     protected JavacParser(ParserFactory fac,
                      Lexer S,
                      boolean keepDocComments,
-                     boolean keepLineMap) {
+                     boolean keepLineMap,
+                     boolean keepEndPositions) {
         this.S = S;
         nextToken(); // prime the pump
         this.F = fac.F;
@@ -110,8 +114,14 @@
         docComments = keepDocComments ? new HashMap<JCTree,String>() : null;
         this.keepLineMap = keepLineMap;
         this.errorTree = F.Erroneous();
+        endPosTable = newEndPosTable(keepEndPositions);
     }
 
+    protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
+        return  keepEndPositions
+                ? new SimpleEndPosTable()
+                : new EmptyEndPosTable();
+    }
     /** Switch: Should generics be recognized?
      */
     boolean allowGenerics;
@@ -389,37 +399,21 @@
 
 /* -------- source positions ------- */
 
-    private int errorEndPos = -1;
-
     private void setErrorEndPos(int errPos) {
-        if (errPos > errorEndPos)
-            errorEndPos = errPos;
+        endPosTable.setErrorEndPos(errPos);
     }
 
-    protected int getErrorEndPos() {
-        return errorEndPos;
+    private void storeEnd(JCTree tree, int endpos) {
+        endPosTable.storeEnd(tree, endpos);
     }
 
-    /**
-     * Store ending position for a tree.
-     * @param tree   The tree.
-     * @param endpos The ending position to associate with the tree.
-     */
-    protected void storeEnd(JCTree tree, int endpos) {}
+    private <T extends JCTree> T to(T t) {
+        return endPosTable.to(t);
+    }
 
-    /**
-     * Store ending position for a tree.  The ending position should
-     * be the ending position of the current token.
-     * @param t The tree.
-     */
-    protected <T extends JCTree> T to(T t) { return t; }
-
-    /**
-     * Store ending position for a tree.  The ending position should
-     * be greater of the ending position of the previous token and errorEndPos.
-     * @param t The tree.
-     */
-    protected <T extends JCTree> T toP(T t) { return t; }
+    private <T extends JCTree> T toP(T t) {
+        return endPosTable.toP(t);
+    }
 
     /** Get the start position for a tree node.  The start position is
      * defined to be the position of the first character of the first
@@ -439,7 +433,7 @@
      * @param tree  The tree node
      */
     public int getEndPos(JCTree tree) {
-        return Position.NOPOS;
+        return endPosTable.getEndPos(tree);
     }
 
 
@@ -1362,7 +1356,7 @@
             int pos = token.pos;
             nextToken();
             accept(CLASS);
-            if (token.pos == errorEndPos) {
+            if (token.pos == endPosTable.errorEndPos) {
                 // error recovery
                 Name name = null;
                 if (token.kind == IDENTIFIER) {
@@ -1542,10 +1536,11 @@
     /** ParExpression = "(" Expression ")"
      */
     JCExpression parExpression() {
+        int pos = token.pos;
         accept(LPAREN);
         JCExpression t = parseExpression();
         accept(RPAREN);
-        return t;
+        return toP(F.at(pos).Parens(t));
     }
 
     /** Block = "{" BlockStatements "}"
@@ -1661,7 +1656,7 @@
             // error recovery
             if (token.pos == lastErrPos)
                 return stats.toList();
-            if (token.pos <= errorEndPos) {
+            if (token.pos <= endPosTable.errorEndPos) {
                 skip(false, true, true, true);
                 lastErrPos = token.pos;
             }
@@ -2270,7 +2265,7 @@
         boolean checkForImports = true;
         boolean firstTypeDecl = true;
         while (token.kind != EOF) {
-            if (token.pos <= errorEndPos) {
+            if (token.pos <= endPosTable.errorEndPos) {
                 // error recovery
                 skip(checkForImports, false, false, false);
                 if (token.kind == EOF)
@@ -2304,6 +2299,7 @@
             toplevel.docComments = docComments;
         if (keepLineMap)
             toplevel.lineMap = S.getLineMap();
+        toplevel.endPositions = this.endPosTable;
         return toplevel;
     }
 
@@ -2494,7 +2490,7 @@
             while (token.kind != RBRACE && token.kind != EOF) {
                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
                                                                 false));
-                if (token.pos <= errorEndPos) {
+                if (token.pos <= endPosTable.errorEndPos) {
                     // error recovery
                    skip(false, true, true, false);
                 }
@@ -2556,7 +2552,7 @@
      */
     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
         accept(LBRACE);
-        if (token.pos <= errorEndPos) {
+        if (token.pos <= endPosTable.errorEndPos) {
             // error recovery
             skip(false, true, false, false);
             if (token.kind == LBRACE)
@@ -2565,7 +2561,7 @@
         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
         while (token.kind != RBRACE && token.kind != EOF) {
             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
-            if (token.pos <= errorEndPos) {
+            if (token.pos <= endPosTable.errorEndPos) {
                // error recovery
                skip(false, true, true, false);
            }
@@ -2697,7 +2693,7 @@
                 defaultValue = null;
             }
             accept(SEMI);
-            if (token.pos <= errorEndPos) {
+            if (token.pos <= endPosTable.errorEndPos) {
                 // error recovery
                 skip(false, true, false, false);
                 if (token.kind == LBRACE) {
@@ -3028,4 +3024,112 @@
             allowTWR = true;
         }
     }
+
+    /*
+     * a functional source tree and end position mappings
+     */
+    protected class SimpleEndPosTable extends AbstractEndPosTable {
+
+        private final Map<JCTree, Integer> endPosMap;
+
+        SimpleEndPosTable() {
+            endPosMap = new HashMap<JCTree, Integer>();
+        }
+
+        protected void storeEnd(JCTree tree, int endpos) {
+            endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
+        }
+
+        protected <T extends JCTree> T to(T t) {
+            storeEnd(t, token.endPos);
+            return t;
+        }
+
+        protected <T extends JCTree> T toP(T t) {
+            storeEnd(t, S.prevToken().endPos);
+            return t;
+        }
+
+        public int getEndPos(JCTree tree) {
+            Integer value = endPosMap.get(tree);
+            return (value == null) ? Position.NOPOS : value;
+        }
+
+        public int replaceTree(JCTree oldTree, JCTree newTree) {
+            Integer pos = endPosMap.remove(oldTree);
+            if (pos != null) {
+                endPosMap.put(newTree, pos);
+                return pos;
+            }
+            return Position.NOPOS;
+        }
+    }
+
+    /*
+     * a default skeletal implementation without any mapping overhead.
+     */
+    protected class EmptyEndPosTable extends AbstractEndPosTable {
+
+        protected void storeEnd(JCTree tree, int endpos) { /* empty */ }
+
+        protected <T extends JCTree> T to(T t) {
+            return t;
+        }
+
+        protected <T extends JCTree> T toP(T t) {
+            return t;
+        }
+
+        public int getEndPos(JCTree tree) {
+            return Position.NOPOS;
+        }
+
+        public int replaceTree(JCTree oldTree, JCTree newTree) {
+            return Position.NOPOS;
+        }
+
+    }
+
+    protected abstract class AbstractEndPosTable implements EndPosTable {
+
+        /**
+         * Store the last error position.
+         */
+        protected int errorEndPos;
+
+        /**
+         * Store ending position for a tree, the value of which is the greater
+         * of last error position and the given ending position.
+         * @param tree   The tree.
+         * @param endpos The ending position to associate with the tree.
+         */
+        protected abstract void storeEnd(JCTree tree, int endpos);
+
+        /**
+         * Store current token's ending position for a tree, the value of which
+         * will be the greater of last error position and the ending position of
+         * the current token.
+         * @param t The tree.
+         */
+        protected abstract <T extends JCTree> T to(T t);
+
+        /**
+         * Store current token's ending position for a tree, the value of which
+         * will be the greater of last error position and the ending position of
+         * the previous token.
+         * @param t The tree.
+         */
+        protected abstract <T extends JCTree> T toP(T t);
+
+        /**
+         * Set the error position during the parsing phases, the value of which
+         * will be set only if it is greater than the last stored error position.
+         * @param errPos The error position
+         */
+        protected void setErrorEndPos(int errPos) {
+            if (errPos > errorEndPos) {
+                errorEndPos = errPos;
+            }
+        }
+    }
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java	Mon Nov 14 15:11:10 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, 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
@@ -75,10 +75,6 @@
 
     public Parser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) {
         Lexer lexer = scannerFactory.newScanner(input, keepDocComments);
-        if (keepEndPos) {
-            return new EndPosParser(this, lexer, keepDocComments, keepLineMap);
-        } else {
-            return new JavacParser(this, lexer, keepDocComments, keepLineMap);
-        }
+        return new JavacParser(this, lexer, keepDocComments, keepLineMap, keepEndPos);
     }
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Nov 14 15:11:10 2011 -0800
@@ -39,6 +39,7 @@
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Scope.*;
 import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.parser.EndPosTable;
 import com.sun.source.tree.*;
 
 import static com.sun.tools.javac.code.BoundKind.*;
@@ -450,7 +451,7 @@
     }
 
     // for default DiagnosticPosition
-    public int getEndPosition(Map<JCTree, Integer> endPosTable) {
+    public int getEndPosition(EndPosTable endPosTable) {
         return TreeInfo.getEndPos(this, endPosTable);
     }
 
@@ -467,7 +468,7 @@
      * @param docComments      A hashtable that stores all documentation comments
      *                         indexed by the tree nodes they refer to.
      *                         defined only if option -s is set.
-     * @param endPositions     A hashtable that stores ending positions of source
+     * @param endPositions     An object encapsulating ending positions of source
      *                         ranges indexed by the tree nodes they belong to.
      *                         Defined only if option -Xjcov is set.
      */
@@ -481,7 +482,7 @@
         public StarImportScope starImportScope;
         public Position.LineMap lineMap = null;
         public Map<JCTree, String> docComments = null;
-        public Map<JCTree, Integer> endPositions = null;
+        public EndPosTable endPositions = null;
         protected JCCompilationUnit(List<JCAnnotation> packageAnnotations,
                         JCExpression pid,
                         List<JCTree> defs,
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Nov 14 15:11:10 2011 -0800
@@ -28,10 +28,10 @@
 import com.sun.source.tree.Tree;
 import com.sun.tools.javac.comp.AttrContext;
 import com.sun.tools.javac.comp.Env;
-import java.util.Map;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.parser.EndPosTable;
 import com.sun.tools.javac.tree.JCTree.*;
 
 import static com.sun.tools.javac.code.Flags.*;
@@ -346,17 +346,17 @@
 
     /** The end position of given tree, given  a table of end positions generated by the parser
      */
-    public static int getEndPos(JCTree tree, Map<JCTree, Integer> endPositions) {
+    public static int getEndPos(JCTree tree, EndPosTable endPosTable) {
         if (tree == null)
             return Position.NOPOS;
 
-        if (endPositions == null) {
+        if (endPosTable == null) {
             // fall back on limited info in the tree
             return endPos(tree);
         }
 
-        Integer mapPos = endPositions.get(tree);
-        if (mapPos != null)
+        int mapPos = endPosTable.getEndPos(tree);
+        if (mapPos != Position.NOPOS)
             return mapPos;
 
         switch(tree.getTag()) {
@@ -364,7 +364,7 @@
             case SL_ASG: case SR_ASG: case USR_ASG:
             case PLUS_ASG: case MINUS_ASG: case MUL_ASG:
             case DIV_ASG: case MOD_ASG:
-                return getEndPos(((JCAssignOp) tree).rhs, endPositions);
+                return getEndPos(((JCAssignOp) tree).rhs, endPosTable);
             case OR: case AND: case BITOR:
             case BITXOR: case BITAND: case EQ:
             case NE: case LT: case GT:
@@ -372,62 +372,62 @@
             case SR: case USR: case PLUS:
             case MINUS: case MUL: case DIV:
             case MOD:
-                return getEndPos(((JCBinary) tree).rhs, endPositions);
+                return getEndPos(((JCBinary) tree).rhs, endPosTable);
             case CASE:
-                return getEndPos(((JCCase) tree).stats.last(), endPositions);
+                return getEndPos(((JCCase) tree).stats.last(), endPosTable);
             case CATCH:
-                return getEndPos(((JCCatch) tree).body, endPositions);
+                return getEndPos(((JCCatch) tree).body, endPosTable);
             case CONDEXPR:
-                return getEndPos(((JCConditional) tree).falsepart, endPositions);
+                return getEndPos(((JCConditional) tree).falsepart, endPosTable);
             case FORLOOP:
-                return getEndPos(((JCForLoop) tree).body, endPositions);
+                return getEndPos(((JCForLoop) tree).body, endPosTable);
             case FOREACHLOOP:
-                return getEndPos(((JCEnhancedForLoop) tree).body, endPositions);
+                return getEndPos(((JCEnhancedForLoop) tree).body, endPosTable);
             case IF: {
                 JCIf node = (JCIf)tree;
                 if (node.elsepart == null) {
-                    return getEndPos(node.thenpart, endPositions);
+                    return getEndPos(node.thenpart, endPosTable);
                 } else {
-                    return getEndPos(node.elsepart, endPositions);
+                    return getEndPos(node.elsepart, endPosTable);
                 }
             }
             case LABELLED:
-                return getEndPos(((JCLabeledStatement) tree).body, endPositions);
+                return getEndPos(((JCLabeledStatement) tree).body, endPosTable);
             case MODIFIERS:
-                return getEndPos(((JCModifiers) tree).annotations.last(), endPositions);
+                return getEndPos(((JCModifiers) tree).annotations.last(), endPosTable);
             case SYNCHRONIZED:
-                return getEndPos(((JCSynchronized) tree).body, endPositions);
+                return getEndPos(((JCSynchronized) tree).body, endPosTable);
             case TOPLEVEL:
-                return getEndPos(((JCCompilationUnit) tree).defs.last(), endPositions);
+                return getEndPos(((JCCompilationUnit) tree).defs.last(), endPosTable);
             case TRY: {
                 JCTry node = (JCTry)tree;
                 if (node.finalizer != null) {
-                    return getEndPos(node.finalizer, endPositions);
+                    return getEndPos(node.finalizer, endPosTable);
                 } else if (!node.catchers.isEmpty()) {
-                    return getEndPos(node.catchers.last(), endPositions);
+                    return getEndPos(node.catchers.last(), endPosTable);
                 } else {
-                    return getEndPos(node.body, endPositions);
+                    return getEndPos(node.body, endPosTable);
                 }
             }
             case WILDCARD:
-                return getEndPos(((JCWildcard) tree).inner, endPositions);
+                return getEndPos(((JCWildcard) tree).inner, endPosTable);
             case TYPECAST:
-                return getEndPos(((JCTypeCast) tree).expr, endPositions);
+                return getEndPos(((JCTypeCast) tree).expr, endPosTable);
             case TYPETEST:
-                return getEndPos(((JCInstanceOf) tree).clazz, endPositions);
+                return getEndPos(((JCInstanceOf) tree).clazz, endPosTable);
             case POS:
             case NEG:
             case NOT:
             case COMPL:
             case PREINC:
             case PREDEC:
-                return getEndPos(((JCUnary) tree).arg, endPositions);
+                return getEndPos(((JCUnary) tree).arg, endPosTable);
             case WHILELOOP:
-                return getEndPos(((JCWhileLoop) tree).body, endPositions);
+                return getEndPos(((JCWhileLoop) tree).body, endPosTable);
             case ERRONEOUS: {
                 JCErroneous node = (JCErroneous)tree;
                 if (node.errs != null && node.errs.nonEmpty())
-                    return getEndPos(node.errs.last(), endPositions);
+                    return getEndPos(node.errs.last(), endPosTable);
             }
         }
         return Position.NOPOS;
@@ -444,7 +444,7 @@
             public JCTree getTree() { return tree; }
             public int getStartPosition() { return TreeInfo.getStartPos(tree); }
             public int getPreferredPosition() { return endPos; }
-            public int getEndPosition(Map<JCTree, Integer> endPosTable) {
+            public int getEndPosition(EndPosTable endPosTable) {
                 return TreeInfo.getEndPos(tree, endPosTable);
             }
         };
--- a/langtools/src/share/classes/com/sun/tools/javac/util/DiagnosticSource.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/DiagnosticSource.java	Mon Nov 14 15:11:10 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, 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
@@ -32,6 +32,7 @@
 import javax.tools.JavaFileObject;
 
 import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.parser.EndPosTable;
 import com.sun.tools.javac.tree.JCTree;
 
 import static com.sun.tools.javac.util.LayoutCharacters.*;
@@ -128,11 +129,11 @@
         }
     }
 
-    public Map<JCTree, Integer> getEndPosTable() {
+    public EndPosTable getEndPosTable() {
         return endPosTable;
     }
 
-    public void setEndPosTable(Map<JCTree, Integer> t) {
+    public void setEndPosTable(EndPosTable t) {
         if (endPosTable != null && endPosTable != t)
             throw new IllegalStateException("endPosTable already set");
         endPosTable = t;
@@ -199,7 +200,7 @@
     /** The underlying file object. */
     protected JavaFileObject fileObject;
 
-    protected Map<JCTree, Integer> endPosTable;
+    protected EndPosTable endPosTable;
 
     /** A soft reference to the content of the file object. */
     protected SoftReference<char[]> refBuf;
--- a/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Mon Nov 14 15:11:10 2011 -0800
@@ -35,6 +35,7 @@
 
 import com.sun.tools.javac.api.DiagnosticFormatter;
 import com.sun.tools.javac.code.Lint.LintCategory;
+import com.sun.tools.javac.parser.EndPosTable;
 import com.sun.tools.javac.tree.JCTree;
 
 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
@@ -313,7 +314,7 @@
         /** If there is a tree node, and if endPositions are available, get
          *  the end position of the tree node. Otherwise, just returns the
          *  same as getPreferredPosition(). */
-        int getEndPosition(Map<JCTree, Integer> endPosTable);
+        int getEndPosition(EndPosTable endPosTable);
     }
 
     /**
@@ -337,7 +338,7 @@
             return pos;
         }
 
-        public int getEndPosition(Map<JCTree, Integer> endPosTable) {
+        public int getEndPosition(EndPosTable endPosTable) {
             return pos;
         }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java	Mon Nov 14 15:11:10 2011 -0800
@@ -38,6 +38,7 @@
 
 import com.sun.tools.javac.api.DiagnosticFormatter;
 import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.parser.EndPosTable;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
@@ -250,9 +251,9 @@
         return diagListener != null;
     }
 
-    public void setEndPosTable(JavaFileObject name, Map<JCTree, Integer> table) {
+    public void setEndPosTable(JavaFileObject name, EndPosTable endPosTable) {
         name.getClass(); // null check
-        getSource(name).setEndPosTable(table);
+        getSource(name).setEndPosTable(endPosTable);
     }
 
     /** Return current sourcefile.
--- a/langtools/test/tools/javac/6304921/TestLog.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/test/tools/javac/6304921/TestLog.java	Mon Nov 14 15:11:10 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -33,6 +33,7 @@
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
 import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.parser.EndPosTable;
 import com.sun.tools.javac.parser.Parser;
 import com.sun.tools.javac.parser.ParserFactory;
 import com.sun.tools.javac.tree.JCTree;
@@ -97,9 +98,9 @@
     }
 
     private static class LogTester extends TreeScanner {
-        LogTester(Log log, java.util.Map<JCTree, Integer> endPositions) {
+        LogTester(Log log, EndPosTable endPosTable) {
             this.log = log;
-            this.endPositions = endPositions;
+            this.endPosTable = endPosTable;
         }
 
         public void visitIf(JCTree.JCIf tree) {
@@ -117,7 +118,7 @@
         }
 
         private Log log;
-        private java.util.Map<JCTree, Integer> endPositions;
+        private EndPosTable endPosTable;
     }
 
     private static class StringJavaFileObject extends SimpleJavaFileObject {
--- a/langtools/test/tools/javac/failover/CheckAttributedTree.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/test/tools/javac/failover/CheckAttributedTree.java	Mon Nov 14 15:11:10 2011 -0800
@@ -55,12 +55,8 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.nio.charset.Charset;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import javax.tools.Diagnostic;
 import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileObject;
@@ -72,8 +68,8 @@
 import com.sun.tools.javac.api.JavacTool;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.parser.EndPosTable;
 import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCClassDecl;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
 import com.sun.tools.javac.tree.JCTree.JCImport;
 import com.sun.tools.javac.tree.TreeInfo;
@@ -421,7 +417,7 @@
         }
 
         JavaFileObject sourcefile;
-        Map<JCTree, Integer> endPosTable;
+        EndPosTable endPosTable;
         Info encl;
     }
 
@@ -437,7 +433,7 @@
             end = Integer.MAX_VALUE;
         }
 
-        Info(JCTree tree, Map<JCTree, Integer> endPosTable) {
+        Info(JCTree tree, EndPosTable endPosTable) {
             this.tree = tree;
             tag = tree.getTag();
             start = TreeInfo.getStartPos(tree);
--- a/langtools/test/tools/javac/tree/TreePosTest.java	Mon Nov 14 08:09:47 2011 -0800
+++ b/langtools/test/tools/javac/tree/TreePosTest.java	Mon Nov 14 15:11:10 2011 -0800
@@ -73,6 +73,7 @@
 import com.sun.source.util.JavacTask;
 import com.sun.tools.javac.api.JavacTool;
 import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.parser.EndPosTable;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
 import com.sun.tools.javac.tree.JCTree.JCNewClass;
@@ -435,7 +436,7 @@
         }
 
         JavaFileObject sourcefile;
-        Map<JCTree, Integer> endPosTable;
+        EndPosTable endPosTable;
         Info encl;
 
     }
@@ -452,7 +453,7 @@
             end = Integer.MAX_VALUE;
         }
 
-        Info(JCTree tree, Map<JCTree, Integer> endPosTable) {
+        Info(JCTree tree, EndPosTable endPosTable) {
             this.tree = tree;
             tag = tree.getTag();
             start = TreeInfo.getStartPos(tree);