src/share/classes/com/sun/tools/javac/util/Position.java

Thu, 31 Aug 2017 15:17:03 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:17:03 +0800
changeset 2525
2eb010b6cb22
parent 1358
fc123bdeddb8
parent 0
959103a6100f
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.tools.javac.util;
aoqi@0 27
aoqi@0 28 import java.util.BitSet;
aoqi@0 29 import static com.sun.tools.javac.util.LayoutCharacters.*;
aoqi@0 30
aoqi@0 31 /** A class that defines source code positions as simple character
aoqi@0 32 * offsets from the beginning of the file. The first character
aoqi@0 33 * is at position 0.
aoqi@0 34 *
aoqi@0 35 * Support is also provided for (line,column) coordinates, but tab
aoqi@0 36 * expansion is optional and no Unicode excape translation is considered.
aoqi@0 37 * The first character is at location (1,1).
aoqi@0 38 *
aoqi@0 39 * <p><b>This is NOT part of any supported API.
aoqi@0 40 * If you write code that depends on this, you do so at your own risk.
aoqi@0 41 * This code and its internal interfaces are subject to change or
aoqi@0 42 * deletion without notice.</b>
aoqi@0 43 */
aoqi@0 44 public class Position {
aoqi@0 45 public static final int NOPOS = -1;
aoqi@0 46
aoqi@0 47 public static final int FIRSTPOS = 0;
aoqi@0 48 public static final int FIRSTLINE = 1;
aoqi@0 49 public static final int FIRSTCOLUMN = 1;
aoqi@0 50
aoqi@0 51 public static final int LINESHIFT = 10;
aoqi@0 52 public static final int MAXCOLUMN = (1<<LINESHIFT) - 1;
aoqi@0 53 public static final int MAXLINE = (1<<(Integer.SIZE-LINESHIFT)) - 1;
aoqi@0 54
aoqi@0 55 public static final int MAXPOS = Integer.MAX_VALUE;
aoqi@0 56
aoqi@0 57 /**
aoqi@0 58 * This is class is not supposed to be instantiated.
aoqi@0 59 */
aoqi@0 60 private Position() {}
aoqi@0 61
aoqi@0 62 /** A two-way map between line/column numbers and positions,
aoqi@0 63 * derived from a scan done at creation time. Tab expansion is
aoqi@0 64 * optionally supported via a character map. Text content
aoqi@0 65 * is not retained.
aoqi@0 66 *<p>
aoqi@0 67 * Notes: The first character position FIRSTPOS is at
aoqi@0 68 * (FIRSTLINE,FIRSTCOLUMN). No account is taken of Unicode escapes.
aoqi@0 69 *
aoqi@0 70 * @param src Source characters
aoqi@0 71 * @param max Number of characters to read
aoqi@0 72 * @param expandTabs If true, expand tabs when calculating columns
aoqi@0 73 */
aoqi@0 74 public static LineMap makeLineMap(char[] src, int max, boolean expandTabs) {
aoqi@0 75 LineMapImpl lineMap = expandTabs ?
aoqi@0 76 new LineTabMapImpl(max) : new LineMapImpl();
aoqi@0 77 lineMap.build(src, max);
aoqi@0 78 return lineMap;
aoqi@0 79 }
aoqi@0 80
aoqi@0 81 /** Encode line and column numbers in an integer as:
aoqi@0 82 * {@code line-number << LINESHIFT + column-number }.
aoqi@0 83 * {@link Position#NOPOS} represents an undefined position.
aoqi@0 84 *
aoqi@0 85 * @param line number of line (first is 1)
aoqi@0 86 * @param col number of character on line (first is 1)
aoqi@0 87 * @return an encoded position or {@link Position#NOPOS}
aoqi@0 88 * if the line or column number is too big to
aoqi@0 89 * represent in the encoded format
aoqi@0 90 * @throws IllegalArgumentException if line or col is less than 1
aoqi@0 91 */
aoqi@0 92 public static int encodePosition(int line, int col) {
aoqi@0 93 if (line < 1)
aoqi@0 94 throw new IllegalArgumentException("line must be greater than 0");
aoqi@0 95 if (col < 1)
aoqi@0 96 throw new IllegalArgumentException("column must be greater than 0");
aoqi@0 97
aoqi@0 98 if (line > MAXLINE || col > MAXCOLUMN) {
aoqi@0 99 return NOPOS;
aoqi@0 100 }
aoqi@0 101 return (line << LINESHIFT) + col;
aoqi@0 102 }
aoqi@0 103
aoqi@0 104 public static interface LineMap extends com.sun.source.tree.LineMap {
aoqi@0 105 /** Find the start position of a line.
aoqi@0 106 *
aoqi@0 107 * @param line number of line (first is 1)
aoqi@0 108 * @return position of first character in line
aoqi@0 109 * @throws ArrayIndexOutOfBoundsException
aoqi@0 110 * if {@code lineNumber < 1}
aoqi@0 111 * if {@code lineNumber > no. of lines}
aoqi@0 112 */
aoqi@0 113 int getStartPosition(int line);
aoqi@0 114
aoqi@0 115 /** Find the position corresponding to a (line,column).
aoqi@0 116 *
aoqi@0 117 * @param line number of line (first is 1)
aoqi@0 118 * @param column number of character on line (first is 1)
aoqi@0 119 *
aoqi@0 120 * @return position of character
aoqi@0 121 * @throws ArrayIndexOutOfBoundsException
aoqi@0 122 * if {@code line < 1}
aoqi@0 123 * if {@code line > no. of lines}
aoqi@0 124 */
aoqi@0 125 int getPosition(int line, int column);
aoqi@0 126
aoqi@0 127 /** Find the line containing a position; a line termination
aoqi@0 128 * character is on the line it terminates.
aoqi@0 129 *
aoqi@0 130 * @param pos character offset of the position
aoqi@0 131 * @return the line number on which pos occurs (first line is 1)
aoqi@0 132 */
aoqi@0 133 int getLineNumber(int pos);
aoqi@0 134
aoqi@0 135 /** Find the column for a character position.
aoqi@0 136 * Note: this method does not handle tab expansion.
aoqi@0 137 * If tab expansion is needed, use a LineTabMap instead.
aoqi@0 138 *
aoqi@0 139 * @param pos character offset of the position
aoqi@0 140 * @return the column number at which pos occurs
aoqi@0 141 */
aoqi@0 142 int getColumnNumber(int pos);
aoqi@0 143 }
aoqi@0 144
aoqi@0 145 static class LineMapImpl implements LineMap {
aoqi@0 146 protected int[] startPosition; // start position of each line
aoqi@0 147
aoqi@0 148 protected LineMapImpl() {}
aoqi@0 149
aoqi@0 150 protected void build(char[] src, int max) {
aoqi@0 151 int c = 0;
aoqi@0 152 int i = 0;
aoqi@0 153 int[] linebuf = new int[max];
aoqi@0 154 while (i < max) {
aoqi@0 155 linebuf[c++] = i;
aoqi@0 156 do {
aoqi@0 157 char ch = src[i];
aoqi@0 158 if (ch == '\r' || ch == '\n') {
aoqi@0 159 if (ch == '\r' && (i+1) < max && src[i+1] == '\n')
aoqi@0 160 i += 2;
aoqi@0 161 else
aoqi@0 162 ++i;
aoqi@0 163 break;
aoqi@0 164 }
aoqi@0 165 else if (ch == '\t')
aoqi@0 166 setTabPosition(i);
aoqi@0 167 } while (++i < max);
aoqi@0 168 }
aoqi@0 169 this.startPosition = new int[c];
aoqi@0 170 System.arraycopy(linebuf, 0, startPosition, 0, c);
aoqi@0 171 }
aoqi@0 172
aoqi@0 173 public int getStartPosition(int line) {
aoqi@0 174 return startPosition[line - FIRSTLINE];
aoqi@0 175 }
aoqi@0 176
aoqi@0 177 public long getStartPosition(long line) {
aoqi@0 178 return getStartPosition(longToInt(line));
aoqi@0 179 }
aoqi@0 180
aoqi@0 181 public int getPosition(int line, int column) {
aoqi@0 182 return startPosition[line - FIRSTLINE] + column - FIRSTCOLUMN;
aoqi@0 183 }
aoqi@0 184
aoqi@0 185 public long getPosition(long line, long column) {
aoqi@0 186 return getPosition(longToInt(line), longToInt(column));
aoqi@0 187 }
aoqi@0 188
aoqi@0 189 // Cache of last line number lookup
aoqi@0 190 private int lastPosition = Position.FIRSTPOS;
aoqi@0 191 private int lastLine = Position.FIRSTLINE;
aoqi@0 192
aoqi@0 193 public int getLineNumber(int pos) {
aoqi@0 194 if (pos == lastPosition) {
aoqi@0 195 return lastLine;
aoqi@0 196 }
aoqi@0 197 lastPosition = pos;
aoqi@0 198
aoqi@0 199 int low = 0;
aoqi@0 200 int high = startPosition.length-1;
aoqi@0 201 while (low <= high) {
aoqi@0 202 int mid = (low + high) >> 1;
aoqi@0 203 int midVal = startPosition[mid];
aoqi@0 204
aoqi@0 205 if (midVal < pos)
aoqi@0 206 low = mid + 1;
aoqi@0 207 else if (midVal > pos)
aoqi@0 208 high = mid - 1;
aoqi@0 209 else {
aoqi@0 210 lastLine = mid + 1; // pos is at beginning of this line
aoqi@0 211 return lastLine;
aoqi@0 212 }
aoqi@0 213 }
aoqi@0 214 lastLine = low;
aoqi@0 215 return lastLine; // pos is on this line
aoqi@0 216 }
aoqi@0 217
aoqi@0 218 public long getLineNumber(long pos) {
aoqi@0 219 return getLineNumber(longToInt(pos));
aoqi@0 220 }
aoqi@0 221
aoqi@0 222 public int getColumnNumber(int pos) {
aoqi@0 223 return pos - startPosition[getLineNumber(pos) - FIRSTLINE] + FIRSTCOLUMN;
aoqi@0 224 }
aoqi@0 225
aoqi@0 226 public long getColumnNumber(long pos) {
aoqi@0 227 return getColumnNumber(longToInt(pos));
aoqi@0 228 }
aoqi@0 229
aoqi@0 230 private static int longToInt(long longValue) {
aoqi@0 231 int intValue = (int)longValue;
aoqi@0 232 if (intValue != longValue)
aoqi@0 233 throw new IndexOutOfBoundsException();
aoqi@0 234 return intValue;
aoqi@0 235 }
aoqi@0 236
aoqi@0 237 protected void setTabPosition(int offset) {}
aoqi@0 238 }
aoqi@0 239
aoqi@0 240 /**
aoqi@0 241 * A LineMap that handles tab expansion correctly. The cost is
aoqi@0 242 * an additional bit per character in the source array.
aoqi@0 243 */
aoqi@0 244 public static class LineTabMapImpl extends LineMapImpl {
aoqi@0 245 private BitSet tabMap; // bits set for tab positions.
aoqi@0 246
aoqi@0 247 public LineTabMapImpl(int max) {
aoqi@0 248 super();
aoqi@0 249 tabMap = new BitSet(max);
aoqi@0 250 }
aoqi@0 251
aoqi@0 252 protected void setTabPosition(int offset) {
aoqi@0 253 tabMap.set(offset);
aoqi@0 254 }
aoqi@0 255
aoqi@0 256 public int getColumnNumber(int pos) {
aoqi@0 257 int lineStart = startPosition[getLineNumber(pos) - FIRSTLINE];
aoqi@0 258 int column = 0;
aoqi@0 259 for (int bp = lineStart; bp < pos; bp++) {
aoqi@0 260 if (tabMap.get(bp))
aoqi@0 261 column = (column / TabInc * TabInc) + TabInc;
aoqi@0 262 else
aoqi@0 263 column++;
aoqi@0 264 }
aoqi@0 265 return column + FIRSTCOLUMN;
aoqi@0 266 }
aoqi@0 267
aoqi@0 268 public int getPosition(int line, int column) {
aoqi@0 269 int pos = startPosition[line - FIRSTLINE];
aoqi@0 270 column -= FIRSTCOLUMN;
aoqi@0 271 int col = 0;
aoqi@0 272 while (col < column) {
aoqi@0 273 pos++;
aoqi@0 274 if (tabMap.get(pos))
aoqi@0 275 col = (col / TabInc * TabInc) + TabInc;
aoqi@0 276 else
aoqi@0 277 col++;
aoqi@0 278 }
aoqi@0 279 return pos;
aoqi@0 280 }
aoqi@0 281 }
aoqi@0 282 }

mercurial