aoqi@0: /* aoqi@0: * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.tools.javac.jvm; aoqi@0: aoqi@0: import java.util.*; aoqi@0: aoqi@0: import com.sun.tools.javac.tree.*; aoqi@0: import com.sun.tools.javac.util.*; aoqi@0: import com.sun.tools.javac.util.List; aoqi@0: import com.sun.tools.javac.tree.JCTree.*; aoqi@0: import com.sun.tools.javac.tree.EndPosTable; aoqi@0: aoqi@0: /** This class contains the CharacterRangeTable for some method aoqi@0: * and the hashtable for mapping trees or lists of trees to their aoqi@0: * ending positions. aoqi@0: * aoqi@0: *

This is NOT part of any supported API. aoqi@0: * If you write code that depends on this, you do so at your own risk. aoqi@0: * This code and its internal interfaces are subject to change or aoqi@0: * deletion without notice. aoqi@0: */ aoqi@0: public class CRTable aoqi@0: implements CRTFlags { aoqi@0: aoqi@0: private final boolean crtDebug = false; aoqi@0: aoqi@0: /** The list of CRTable entries. aoqi@0: */ aoqi@0: private ListBuffer entries = new ListBuffer(); aoqi@0: aoqi@0: /** The hashtable for source positions. aoqi@0: */ aoqi@0: private Map positions = new HashMap(); aoqi@0: aoqi@0: /** The object for ending positions stored in the parser. aoqi@0: */ aoqi@0: private EndPosTable endPosTable; aoqi@0: aoqi@0: /** The tree of the method this table is intended for. aoqi@0: * We should traverse this tree to get source ranges. aoqi@0: */ aoqi@0: JCTree.JCMethodDecl methodTree; aoqi@0: aoqi@0: /** Constructor aoqi@0: */ aoqi@0: public CRTable(JCTree.JCMethodDecl tree, EndPosTable endPosTable) { aoqi@0: this.methodTree = tree; aoqi@0: this.endPosTable = endPosTable; aoqi@0: } aoqi@0: aoqi@0: /** Create a new CRTEntry and add it to the entries. aoqi@0: * @param tree The tree or the list of trees for which aoqi@0: * we are storing the code pointers. aoqi@0: * @param flags The set of flags designating type of the entry. aoqi@0: * @param startPc The starting code position. aoqi@0: * @param endPc The ending code position. aoqi@0: */ aoqi@0: public void put(Object tree, int flags, int startPc, int endPc) { aoqi@0: entries.append(new CRTEntry(tree, flags, startPc, endPc)); aoqi@0: } aoqi@0: aoqi@0: /** Compute source positions and write CRT to the databuf. aoqi@0: * @param databuf The buffer to write bytecodes to. aoqi@0: */ aoqi@0: public int writeCRT(ByteBuffer databuf, Position.LineMap lineMap, Log log) { aoqi@0: aoqi@0: int crtEntries = 0; aoqi@0: aoqi@0: // compute source positions for the method aoqi@0: new SourceComputer().csp(methodTree); aoqi@0: aoqi@0: for (List l = entries.toList(); l.nonEmpty(); l = l.tail) { aoqi@0: aoqi@0: CRTEntry entry = l.head; aoqi@0: aoqi@0: // eliminate entries that do not produce bytecodes: aoqi@0: // for example, empty blocks and statements aoqi@0: if (entry.startPc == entry.endPc) aoqi@0: continue; aoqi@0: aoqi@0: SourceRange pos = positions.get(entry.tree); aoqi@0: Assert.checkNonNull(pos, "CRT: tree source positions are undefined"); aoqi@0: if ((pos.startPos == Position.NOPOS) || (pos.endPos == Position.NOPOS)) aoqi@0: continue; aoqi@0: aoqi@0: if (crtDebug) { aoqi@0: System.out.println("Tree: " + entry.tree + ", type:" + getTypes(entry.flags)); aoqi@0: System.out.print("Start: pos = " + pos.startPos + ", pc = " + entry.startPc); aoqi@0: } aoqi@0: aoqi@0: // encode startPos into line/column representation aoqi@0: int startPos = encodePosition(pos.startPos, lineMap, log); aoqi@0: if (startPos == Position.NOPOS) aoqi@0: continue; aoqi@0: aoqi@0: if (crtDebug) { aoqi@0: System.out.print("End: pos = " + pos.endPos + ", pc = " + (entry.endPc - 1)); aoqi@0: } aoqi@0: aoqi@0: // encode endPos into line/column representation aoqi@0: int endPos = encodePosition(pos.endPos, lineMap, log); aoqi@0: if (endPos == Position.NOPOS) aoqi@0: continue; aoqi@0: aoqi@0: // write attribute aoqi@0: databuf.appendChar(entry.startPc); aoqi@0: // 'endPc - 1' because endPc actually points to start of the next command aoqi@0: databuf.appendChar(entry.endPc - 1); aoqi@0: databuf.appendInt(startPos); aoqi@0: databuf.appendInt(endPos); aoqi@0: databuf.appendChar(entry.flags); aoqi@0: aoqi@0: crtEntries++; aoqi@0: } aoqi@0: aoqi@0: return crtEntries; aoqi@0: } aoqi@0: aoqi@0: /** Return the number of the entries. aoqi@0: */ aoqi@0: public int length() { aoqi@0: return entries.length(); aoqi@0: } aoqi@0: aoqi@0: /** Return string describing flags enabled. aoqi@0: */ aoqi@0: private String getTypes(int flags) { aoqi@0: String types = ""; aoqi@0: if ((flags & CRT_STATEMENT) != 0) types += " CRT_STATEMENT"; aoqi@0: if ((flags & CRT_BLOCK) != 0) types += " CRT_BLOCK"; aoqi@0: if ((flags & CRT_ASSIGNMENT) != 0) types += " CRT_ASSIGNMENT"; aoqi@0: if ((flags & CRT_FLOW_CONTROLLER) != 0) types += " CRT_FLOW_CONTROLLER"; aoqi@0: if ((flags & CRT_FLOW_TARGET) != 0) types += " CRT_FLOW_TARGET"; aoqi@0: if ((flags & CRT_INVOKE) != 0) types += " CRT_INVOKE"; aoqi@0: if ((flags & CRT_CREATE) != 0) types += " CRT_CREATE"; aoqi@0: if ((flags & CRT_BRANCH_TRUE) != 0) types += " CRT_BRANCH_TRUE"; aoqi@0: if ((flags & CRT_BRANCH_FALSE) != 0) types += " CRT_BRANCH_FALSE"; aoqi@0: return types; aoqi@0: } aoqi@0: aoqi@0: /** Source file positions in CRT are integers in the format: aoqi@0: * {@literal line-number << LINESHIFT + column-number } aoqi@0: */ aoqi@0: private int encodePosition(int pos, Position.LineMap lineMap, Log log) { aoqi@0: int line = lineMap.getLineNumber(pos); aoqi@0: int col = lineMap.getColumnNumber(pos); aoqi@0: int new_pos = Position.encodePosition(line, col); aoqi@0: if (crtDebug) { aoqi@0: System.out.println(", line = " + line + ", column = " + col + aoqi@0: ", new_pos = " + new_pos); aoqi@0: } aoqi@0: if (new_pos == Position.NOPOS) aoqi@0: log.warning(pos, "position.overflow", line); aoqi@0: aoqi@0: return new_pos; aoqi@0: } aoqi@0: aoqi@0: /* ************************************************************************ aoqi@0: * Traversal methods aoqi@0: *************************************************************************/ aoqi@0: aoqi@0: /** aoqi@0: * This class contains methods to compute source positions for trees. aoqi@0: * Extends Tree.Visitor to traverse the abstract syntax tree. aoqi@0: */ aoqi@0: class SourceComputer extends JCTree.Visitor { aoqi@0: aoqi@0: /** The result of the tree traversal methods. aoqi@0: */ aoqi@0: SourceRange result; aoqi@0: aoqi@0: /** Visitor method: compute source positions for a single node. aoqi@0: */ aoqi@0: public SourceRange csp(JCTree tree) { aoqi@0: if (tree == null) return null; aoqi@0: tree.accept(this); aoqi@0: if (result != null) { aoqi@0: positions.put(tree, result); aoqi@0: } aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: /** Visitor method: compute source positions for a list of nodes. aoqi@0: */ aoqi@0: public SourceRange csp(List trees) { aoqi@0: if ((trees == null) || !(trees.nonEmpty())) return null; aoqi@0: SourceRange list_sr = new SourceRange(); aoqi@0: for (List l = trees; l.nonEmpty(); l = l.tail) { aoqi@0: list_sr.mergeWith(csp(l.head)); aoqi@0: } aoqi@0: positions.put(trees, list_sr); aoqi@0: return list_sr; aoqi@0: } aoqi@0: aoqi@0: /** Visitor method: compute source positions for aoqi@0: * a list of case blocks of switch statements. aoqi@0: */ aoqi@0: public SourceRange cspCases(List trees) { aoqi@0: if ((trees == null) || !(trees.nonEmpty())) return null; aoqi@0: SourceRange list_sr = new SourceRange(); aoqi@0: for (List l = trees; l.nonEmpty(); l = l.tail) { aoqi@0: list_sr.mergeWith(csp(l.head)); aoqi@0: } aoqi@0: positions.put(trees, list_sr); aoqi@0: return list_sr; aoqi@0: } aoqi@0: aoqi@0: /** Visitor method: compute source positions for aoqi@0: * a list of catch clauses in try statements. aoqi@0: */ aoqi@0: public SourceRange cspCatchers(List trees) { aoqi@0: if ((trees == null) || !(trees.nonEmpty())) return null; aoqi@0: SourceRange list_sr = new SourceRange(); aoqi@0: for (List l = trees; l.nonEmpty(); l = l.tail) { aoqi@0: list_sr.mergeWith(csp(l.head)); aoqi@0: } aoqi@0: positions.put(trees, list_sr); aoqi@0: return list_sr; aoqi@0: } aoqi@0: aoqi@0: public void visitMethodDef(JCMethodDecl tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.body)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitVarDef(JCVariableDecl tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: csp(tree.vartype); aoqi@0: sr.mergeWith(csp(tree.init)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitSkip(JCSkip tree) { aoqi@0: // endPos is the same as startPos for the empty statement aoqi@0: SourceRange sr = new SourceRange(startPos(tree), startPos(tree)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitBlock(JCBlock tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: csp(tree.stats); // doesn't compare because block's ending position is defined aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitDoLoop(JCDoWhileLoop tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.body)); aoqi@0: sr.mergeWith(csp(tree.cond)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitWhileLoop(JCWhileLoop tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.cond)); aoqi@0: sr.mergeWith(csp(tree.body)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitForLoop(JCForLoop tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.init)); aoqi@0: sr.mergeWith(csp(tree.cond)); aoqi@0: sr.mergeWith(csp(tree.step)); aoqi@0: sr.mergeWith(csp(tree.body)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitForeachLoop(JCEnhancedForLoop tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.var)); aoqi@0: sr.mergeWith(csp(tree.expr)); aoqi@0: sr.mergeWith(csp(tree.body)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitLabelled(JCLabeledStatement tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.body)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitSwitch(JCSwitch tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.selector)); aoqi@0: sr.mergeWith(cspCases(tree.cases)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitCase(JCCase tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.pat)); aoqi@0: sr.mergeWith(csp(tree.stats)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitSynchronized(JCSynchronized tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.lock)); aoqi@0: sr.mergeWith(csp(tree.body)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitTry(JCTry tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.resources)); aoqi@0: sr.mergeWith(csp(tree.body)); aoqi@0: sr.mergeWith(cspCatchers(tree.catchers)); aoqi@0: sr.mergeWith(csp(tree.finalizer)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitCatch(JCCatch tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.param)); aoqi@0: sr.mergeWith(csp(tree.body)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitConditional(JCConditional tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.cond)); aoqi@0: sr.mergeWith(csp(tree.truepart)); aoqi@0: sr.mergeWith(csp(tree.falsepart)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitIf(JCIf tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.cond)); aoqi@0: sr.mergeWith(csp(tree.thenpart)); aoqi@0: sr.mergeWith(csp(tree.elsepart)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitExec(JCExpressionStatement tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.expr)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitBreak(JCBreak tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitContinue(JCContinue tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitReturn(JCReturn tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.expr)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitThrow(JCThrow tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.expr)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitAssert(JCAssert tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.cond)); aoqi@0: sr.mergeWith(csp(tree.detail)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitApply(JCMethodInvocation tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.meth)); aoqi@0: sr.mergeWith(csp(tree.args)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitNewClass(JCNewClass tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.encl)); aoqi@0: sr.mergeWith(csp(tree.clazz)); aoqi@0: sr.mergeWith(csp(tree.args)); aoqi@0: sr.mergeWith(csp(tree.def)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitNewArray(JCNewArray tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.elemtype)); aoqi@0: sr.mergeWith(csp(tree.dims)); aoqi@0: sr.mergeWith(csp(tree.elems)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitParens(JCParens tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.expr)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitAssign(JCAssign tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.lhs)); aoqi@0: sr.mergeWith(csp(tree.rhs)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitAssignop(JCAssignOp tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.lhs)); aoqi@0: sr.mergeWith(csp(tree.rhs)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitUnary(JCUnary tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.arg)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitBinary(JCBinary tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.lhs)); aoqi@0: sr.mergeWith(csp(tree.rhs)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitTypeCast(JCTypeCast tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.clazz)); aoqi@0: sr.mergeWith(csp(tree.expr)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitTypeTest(JCInstanceOf tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.expr)); aoqi@0: sr.mergeWith(csp(tree.clazz)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitIndexed(JCArrayAccess tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.indexed)); aoqi@0: sr.mergeWith(csp(tree.index)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitSelect(JCFieldAccess tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.selected)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitIdent(JCIdent tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitLiteral(JCLiteral tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitTypeIdent(JCPrimitiveTypeTree tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitTypeArray(JCArrayTypeTree tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.elemtype)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitTypeApply(JCTypeApply tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.clazz)); aoqi@0: sr.mergeWith(csp(tree.arguments)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void visitLetExpr(LetExpr tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.defs)); aoqi@0: sr.mergeWith(csp(tree.expr)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitTypeParameter(JCTypeParameter tree) { aoqi@0: SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); aoqi@0: sr.mergeWith(csp(tree.bounds)); aoqi@0: result = sr; aoqi@0: } aoqi@0: aoqi@0: public void visitWildcard(JCWildcard tree) { aoqi@0: result = null; aoqi@0: } aoqi@0: aoqi@0: public void visitErroneous(JCErroneous tree) { aoqi@0: result = null; aoqi@0: } aoqi@0: aoqi@0: public void visitTree(JCTree tree) { aoqi@0: Assert.error(); aoqi@0: } aoqi@0: aoqi@0: /** The start position of given tree. aoqi@0: */ aoqi@0: public int startPos(JCTree tree) { aoqi@0: if (tree == null) return Position.NOPOS; aoqi@0: return TreeInfo.getStartPos(tree); aoqi@0: } aoqi@0: aoqi@0: /** The end position of given tree, if it has aoqi@0: * defined endpos, NOPOS otherwise. aoqi@0: */ aoqi@0: public int endPos(JCTree tree) { aoqi@0: if (tree == null) return Position.NOPOS; aoqi@0: return TreeInfo.getEndPos(tree, endPosTable); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** This class contains a CharacterRangeTableEntry. aoqi@0: */ aoqi@0: static class CRTEntry { aoqi@0: aoqi@0: /** A tree or a list of trees to obtain source positions. aoqi@0: */ aoqi@0: Object tree; aoqi@0: aoqi@0: /** The flags described in the CharacterRangeTable spec. aoqi@0: */ aoqi@0: int flags; aoqi@0: aoqi@0: /** The starting code position of this entry. aoqi@0: */ aoqi@0: int startPc; aoqi@0: aoqi@0: /** The ending code position of this entry. aoqi@0: */ aoqi@0: int endPc; aoqi@0: aoqi@0: /** Constructor */ aoqi@0: CRTEntry(Object tree, int flags, int startPc, int endPc) { aoqi@0: this.tree = tree; aoqi@0: this.flags = flags; aoqi@0: this.startPc = startPc; aoqi@0: this.endPc = endPc; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** This class contains source positions aoqi@0: * for some tree or list of trees. aoqi@0: */ aoqi@0: static class SourceRange { aoqi@0: aoqi@0: /** The starting source position. aoqi@0: */ aoqi@0: int startPos; aoqi@0: aoqi@0: /** The ending source position. aoqi@0: */ aoqi@0: int endPos; aoqi@0: aoqi@0: /** Constructor */ aoqi@0: SourceRange() { aoqi@0: startPos = Position.NOPOS; aoqi@0: endPos = Position.NOPOS; aoqi@0: } aoqi@0: aoqi@0: /** Constructor */ aoqi@0: SourceRange(int startPos, int endPos) { aoqi@0: this.startPos = startPos; aoqi@0: this.endPos = endPos; aoqi@0: } aoqi@0: aoqi@0: /** Compare the starting and the ending positions aoqi@0: * of the source range and combines them assigning aoqi@0: * the widest range to this. aoqi@0: */ aoqi@0: SourceRange mergeWith(SourceRange sr) { aoqi@0: if (sr == null) return this; aoqi@0: if (startPos == Position.NOPOS) aoqi@0: startPos = sr.startPos; aoqi@0: else if (sr.startPos != Position.NOPOS) aoqi@0: startPos = (startPos < sr.startPos ? startPos : sr.startPos); aoqi@0: if (endPos == Position.NOPOS) aoqi@0: endPos = sr.endPos; aoqi@0: else if (sr.endPos != Position.NOPOS) aoqi@0: endPos = (endPos > sr.endPos ? endPos : sr.endPos); aoqi@0: return this; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: }