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

Mon, 14 Nov 2011 15:11:10 -0800

author
ksrini
date
Mon, 14 Nov 2011 15:11:10 -0800
changeset 1138
7375d4979bd3
parent 581
f2fdd52e4e87
child 1280
5c0b3faeb0b0
permissions
-rw-r--r--

7106166: (javac) re-factor EndPos parser
Reviewed-by: jjg

jjg@73 1 /*
ksrini@1138 2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
jjg@73 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@73 4 *
jjg@73 5 * This code is free software; you can redistribute it and/or modify it
jjg@73 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
jjg@73 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
jjg@73 10 *
jjg@73 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@73 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@73 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@73 14 * version 2 for more details (a copy is included in the LICENSE file that
jjg@73 15 * accompanied this code).
jjg@73 16 *
jjg@73 17 * You should have received a copy of the GNU General Public License version
jjg@73 18 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@73 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@73 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
jjg@73 24 */
jjg@73 25
jjg@73 26 package com.sun.tools.javac.util;
jjg@73 27
jjg@73 28 import java.io.IOException;
jjg@73 29 import java.lang.ref.SoftReference;
jjg@73 30 import java.nio.CharBuffer;
jjg@73 31 import java.util.Map;
jjg@73 32 import javax.tools.JavaFileObject;
jjg@73 33
jjg@73 34 import com.sun.tools.javac.file.JavacFileManager;
ksrini@1138 35 import com.sun.tools.javac.parser.EndPosTable;
jjg@73 36 import com.sun.tools.javac.tree.JCTree;
jjg@73 37
jjg@73 38 import static com.sun.tools.javac.util.LayoutCharacters.*;
jjg@73 39
jjg@73 40 /**
jjg@73 41 * A simple abstraction of a source file, as needed for use in a diagnostic message.
jjg@73 42 * Provides access to the line and position in a line for any given character offset.
jjg@73 43 *
jjg@581 44 * <p><b>This is NOT part of any supported API.
jjg@581 45 * If you write code that depends on this, you do so at your own risk.
jjg@73 46 * This code and its internal interfaces are subject to change or
jjg@73 47 * deletion without notice.</b>
jjg@73 48 */
jjg@73 49 public class DiagnosticSource {
mcimadamore@303 50
mcimadamore@303 51 /* constant DiagnosticSource to be used when sourcefile is missing */
mcimadamore@303 52 public static final DiagnosticSource NO_SOURCE = new DiagnosticSource() {
mcimadamore@303 53 @Override
mcimadamore@303 54 protected boolean findLine(int pos) {
mcimadamore@303 55 return false;
mcimadamore@303 56 }
mcimadamore@303 57 };
mcimadamore@303 58
jjg@73 59 public DiagnosticSource(JavaFileObject fo, AbstractLog log) {
jjg@73 60 this.fileObject = fo;
jjg@73 61 this.log = log;
jjg@73 62 }
jjg@73 63
mcimadamore@303 64 private DiagnosticSource() {}
mcimadamore@303 65
jjg@73 66 /** Return the underlying file object handled by this
jjg@73 67 * DiagnosticSource object.
jjg@73 68 */
jjg@73 69 public JavaFileObject getFile() {
jjg@73 70 return fileObject;
jjg@73 71 }
jjg@73 72
jjg@73 73 /** Return the one-based line number associated with a given pos
jjg@73 74 * for the current source file. Zero is returned if no line exists
jjg@73 75 * for the given position.
jjg@73 76 */
jjg@73 77 public int getLineNumber(int pos) {
jjg@73 78 try {
jjg@73 79 if (findLine(pos)) {
jjg@73 80 return line;
jjg@73 81 }
jjg@73 82 return 0;
jjg@73 83 } finally {
jjg@73 84 buf = null;
jjg@73 85 }
jjg@73 86 }
jjg@73 87
jjg@73 88 /** Return the one-based column number associated with a given pos
jjg@73 89 * for the current source file. Zero is returned if no column exists
jjg@73 90 * for the given position.
jjg@73 91 */
mcimadamore@100 92 public int getColumnNumber(int pos, boolean expandTabs) {
jjg@73 93 try {
jjg@73 94 if (findLine(pos)) {
jjg@73 95 int column = 0;
jjg@73 96 for (int bp = lineStart; bp < pos; bp++) {
jjg@73 97 if (bp >= bufLen) {
jjg@73 98 return 0;
jjg@73 99 }
mcimadamore@100 100 if (buf[bp] == '\t' && expandTabs) {
jjg@73 101 column = (column / TabInc * TabInc) + TabInc;
jjg@73 102 } else {
jjg@73 103 column++;
jjg@73 104 }
jjg@73 105 }
jjg@73 106 return column + 1; // positions are one-based
jjg@73 107 }
jjg@73 108 return 0;
jjg@73 109 } finally {
jjg@73 110 buf = null;
jjg@73 111 }
jjg@73 112 }
jjg@73 113
jjg@73 114 /** Return the content of the line containing a given pos.
jjg@73 115 */
jjg@73 116 public String getLine(int pos) {
jjg@73 117 try {
jjg@73 118 if (!findLine(pos))
jjg@73 119 return null;
jjg@73 120
jjg@73 121 int lineEnd = lineStart;
jjg@73 122 while (lineEnd < bufLen && buf[lineEnd] != CR && buf[lineEnd] != LF)
jjg@73 123 lineEnd++;
jjg@73 124 if (lineEnd - lineStart == 0)
jjg@73 125 return null;
jjg@73 126 return new String(buf, lineStart, lineEnd - lineStart);
jjg@73 127 } finally {
jjg@73 128 buf = null;
jjg@73 129 }
jjg@73 130 }
jjg@73 131
ksrini@1138 132 public EndPosTable getEndPosTable() {
jjg@73 133 return endPosTable;
jjg@73 134 }
jjg@73 135
ksrini@1138 136 public void setEndPosTable(EndPosTable t) {
jjg@73 137 if (endPosTable != null && endPosTable != t)
jjg@73 138 throw new IllegalStateException("endPosTable already set");
jjg@73 139 endPosTable = t;
jjg@73 140 }
jjg@73 141
jjg@73 142 /** Find the line in the buffer that contains the current position
jjg@73 143 * @param pos Character offset into the buffer
jjg@73 144 */
mcimadamore@303 145 protected boolean findLine(int pos) {
jjg@73 146 if (pos == Position.NOPOS)
jjg@73 147 return false;
jjg@73 148
jjg@73 149 try {
jjg@73 150 // try and recover buffer from soft reference cache
jjg@73 151 if (buf == null && refBuf != null)
jjg@73 152 buf = refBuf.get();
jjg@73 153
jjg@73 154 if (buf == null) {
jjg@73 155 buf = initBuf(fileObject);
jjg@73 156 lineStart = 0;
jjg@73 157 line = 1;
jjg@73 158 } else if (lineStart > pos) { // messages don't come in order
jjg@73 159 lineStart = 0;
jjg@73 160 line = 1;
jjg@73 161 }
jjg@73 162
jjg@73 163 int bp = lineStart;
jjg@73 164 while (bp < bufLen && bp < pos) {
jjg@73 165 switch (buf[bp++]) {
jjg@73 166 case CR:
jjg@73 167 if (bp < bufLen && buf[bp] == LF) bp++;
jjg@73 168 line++;
jjg@73 169 lineStart = bp;
jjg@73 170 break;
jjg@73 171 case LF:
jjg@73 172 line++;
jjg@73 173 lineStart = bp;
jjg@73 174 break;
jjg@73 175 }
jjg@73 176 }
jjg@73 177 return bp <= bufLen;
jjg@73 178 } catch (IOException e) {
jjg@73 179 log.directError("source.unavailable");
jjg@73 180 buf = new char[0];
jjg@73 181 return false;
jjg@73 182 }
jjg@73 183 }
jjg@73 184
jjg@73 185 protected char[] initBuf(JavaFileObject fileObject) throws IOException {
jjg@73 186 char[] buf;
jjg@73 187 CharSequence cs = fileObject.getCharContent(true);
jjg@73 188 if (cs instanceof CharBuffer) {
jjg@73 189 CharBuffer cb = (CharBuffer) cs;
jjg@73 190 buf = JavacFileManager.toArray(cb);
jjg@73 191 bufLen = cb.limit();
jjg@73 192 } else {
jjg@73 193 buf = cs.toString().toCharArray();
jjg@73 194 bufLen = buf.length;
jjg@73 195 }
jjg@73 196 refBuf = new SoftReference<char[]>(buf);
jjg@73 197 return buf;
jjg@73 198 }
jjg@73 199
jjg@73 200 /** The underlying file object. */
jjg@73 201 protected JavaFileObject fileObject;
jjg@73 202
ksrini@1138 203 protected EndPosTable endPosTable;
jjg@73 204
jjg@73 205 /** A soft reference to the content of the file object. */
jjg@73 206 protected SoftReference<char[]> refBuf;
jjg@73 207
jjg@73 208 /** A temporary hard reference to the content of the file object. */
jjg@73 209 protected char[] buf;
jjg@73 210
jjg@73 211 /** The length of the content. */
jjg@73 212 protected int bufLen;
jjg@73 213
jjg@73 214 /** The start of a line found by findLine. */
jjg@73 215 protected int lineStart;
jjg@73 216
jjg@73 217 /** The line number of a line found by findLine. */
jjg@73 218 protected int line;
jjg@73 219
jjg@73 220 /** A log for reporting errors, such as errors accessing the content. */
jjg@73 221 protected AbstractLog log;
jjg@73 222 }

mercurial