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

Fri, 22 Aug 2008 11:46:29 +0100

author
mcimadamore
date
Fri, 22 Aug 2008 11:46:29 +0100
changeset 100
37551dc0f591
parent 73
1cf29847eb6e
child 303
8ec37cf2b37e
permissions
-rw-r--r--

6733837: Recent work on javac diagnostic affected javac output
Summary: Problems with diagnostic path and tab character in the source code
Reviewed-by: darcy, jjg

jjg@73 1 /*
jjg@73 2 * Copyright 1999-2008 Sun Microsystems, Inc. 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
jjg@73 7 * published by the Free Software Foundation. Sun designates this
jjg@73 8 * particular file as subject to the "Classpath" exception as provided
jjg@73 9 * by Sun 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 *
jjg@73 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
jjg@73 22 * CA 95054 USA or visit www.sun.com if you need additional information or
jjg@73 23 * have any 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;
jjg@73 35 import com.sun.tools.javac.tree.JCTree;
jjg@73 36
jjg@73 37 import static com.sun.tools.javac.util.LayoutCharacters.*;
jjg@73 38
jjg@73 39 /**
jjg@73 40 * A simple abstraction of a source file, as needed for use in a diagnostic message.
jjg@73 41 * Provides access to the line and position in a line for any given character offset.
jjg@73 42 *
jjg@73 43 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
jjg@73 44 * you write code that depends on this, you do so at your own risk.
jjg@73 45 * This code and its internal interfaces are subject to change or
jjg@73 46 * deletion without notice.</b>
jjg@73 47 */
jjg@73 48 public class DiagnosticSource {
jjg@73 49 public DiagnosticSource(JavaFileObject fo, AbstractLog log) {
jjg@73 50 this.fileObject = fo;
jjg@73 51 this.log = log;
jjg@73 52 }
jjg@73 53
jjg@73 54 /** Return the underlying file object handled by this
jjg@73 55 * DiagnosticSource object.
jjg@73 56 */
jjg@73 57 public JavaFileObject getFile() {
jjg@73 58 return fileObject;
jjg@73 59 }
jjg@73 60
jjg@73 61 public CharSequence getName() {
jjg@73 62 return JavacFileManager.getJavacBaseFileName(fileObject);
jjg@73 63 }
jjg@73 64
jjg@73 65 /** Return the one-based line number associated with a given pos
jjg@73 66 * for the current source file. Zero is returned if no line exists
jjg@73 67 * for the given position.
jjg@73 68 */
jjg@73 69 public int getLineNumber(int pos) {
jjg@73 70 try {
jjg@73 71 if (findLine(pos)) {
jjg@73 72 return line;
jjg@73 73 }
jjg@73 74 return 0;
jjg@73 75 } finally {
jjg@73 76 buf = null;
jjg@73 77 }
jjg@73 78 }
jjg@73 79
jjg@73 80 /** Return the one-based column number associated with a given pos
jjg@73 81 * for the current source file. Zero is returned if no column exists
jjg@73 82 * for the given position.
jjg@73 83 */
mcimadamore@100 84 public int getColumnNumber(int pos, boolean expandTabs) {
jjg@73 85 try {
jjg@73 86 if (findLine(pos)) {
jjg@73 87 int column = 0;
jjg@73 88 for (int bp = lineStart; bp < pos; bp++) {
jjg@73 89 if (bp >= bufLen) {
jjg@73 90 return 0;
jjg@73 91 }
mcimadamore@100 92 if (buf[bp] == '\t' && expandTabs) {
jjg@73 93 column = (column / TabInc * TabInc) + TabInc;
jjg@73 94 } else {
jjg@73 95 column++;
jjg@73 96 }
jjg@73 97 }
jjg@73 98 return column + 1; // positions are one-based
jjg@73 99 }
jjg@73 100 return 0;
jjg@73 101 } finally {
jjg@73 102 buf = null;
jjg@73 103 }
jjg@73 104 }
jjg@73 105
jjg@73 106 /** Return the content of the line containing a given pos.
jjg@73 107 */
jjg@73 108 public String getLine(int pos) {
jjg@73 109 try {
jjg@73 110 if (!findLine(pos))
jjg@73 111 return null;
jjg@73 112
jjg@73 113 int lineEnd = lineStart;
jjg@73 114 while (lineEnd < bufLen && buf[lineEnd] != CR && buf[lineEnd] != LF)
jjg@73 115 lineEnd++;
jjg@73 116 if (lineEnd - lineStart == 0)
jjg@73 117 return null;
jjg@73 118 return new String(buf, lineStart, lineEnd - lineStart);
jjg@73 119 } finally {
jjg@73 120 buf = null;
jjg@73 121 }
jjg@73 122 }
jjg@73 123
jjg@73 124 public Map<JCTree, Integer> getEndPosTable() {
jjg@73 125 return endPosTable;
jjg@73 126 }
jjg@73 127
jjg@73 128 public void setEndPosTable(Map<JCTree, Integer> t) {
jjg@73 129 if (endPosTable != null && endPosTable != t)
jjg@73 130 throw new IllegalStateException("endPosTable already set");
jjg@73 131 endPosTable = t;
jjg@73 132 }
jjg@73 133
jjg@73 134 /** Find the line in the buffer that contains the current position
jjg@73 135 * @param pos Character offset into the buffer
jjg@73 136 */
jjg@73 137 private boolean findLine(int pos) {
jjg@73 138 if (pos == Position.NOPOS)
jjg@73 139 return false;
jjg@73 140
jjg@73 141 try {
jjg@73 142 // try and recover buffer from soft reference cache
jjg@73 143 if (buf == null && refBuf != null)
jjg@73 144 buf = refBuf.get();
jjg@73 145
jjg@73 146 if (buf == null) {
jjg@73 147 buf = initBuf(fileObject);
jjg@73 148 lineStart = 0;
jjg@73 149 line = 1;
jjg@73 150 } else if (lineStart > pos) { // messages don't come in order
jjg@73 151 lineStart = 0;
jjg@73 152 line = 1;
jjg@73 153 }
jjg@73 154
jjg@73 155 int bp = lineStart;
jjg@73 156 while (bp < bufLen && bp < pos) {
jjg@73 157 switch (buf[bp++]) {
jjg@73 158 case CR:
jjg@73 159 if (bp < bufLen && buf[bp] == LF) bp++;
jjg@73 160 line++;
jjg@73 161 lineStart = bp;
jjg@73 162 break;
jjg@73 163 case LF:
jjg@73 164 line++;
jjg@73 165 lineStart = bp;
jjg@73 166 break;
jjg@73 167 }
jjg@73 168 }
jjg@73 169 return bp <= bufLen;
jjg@73 170 } catch (IOException e) {
jjg@73 171 log.directError("source.unavailable");
jjg@73 172 buf = new char[0];
jjg@73 173 return false;
jjg@73 174 }
jjg@73 175 }
jjg@73 176
jjg@73 177 protected char[] initBuf(JavaFileObject fileObject) throws IOException {
jjg@73 178 char[] buf;
jjg@73 179 CharSequence cs = fileObject.getCharContent(true);
jjg@73 180 if (cs instanceof CharBuffer) {
jjg@73 181 CharBuffer cb = (CharBuffer) cs;
jjg@73 182 buf = JavacFileManager.toArray(cb);
jjg@73 183 bufLen = cb.limit();
jjg@73 184 } else {
jjg@73 185 buf = cs.toString().toCharArray();
jjg@73 186 bufLen = buf.length;
jjg@73 187 }
jjg@73 188 refBuf = new SoftReference<char[]>(buf);
jjg@73 189 return buf;
jjg@73 190 }
jjg@73 191
jjg@73 192 /** The underlying file object. */
jjg@73 193 protected JavaFileObject fileObject;
jjg@73 194
jjg@73 195 protected Map<JCTree, Integer> endPosTable;
jjg@73 196
jjg@73 197 /** A soft reference to the content of the file object. */
jjg@73 198 protected SoftReference<char[]> refBuf;
jjg@73 199
jjg@73 200 /** A temporary hard reference to the content of the file object. */
jjg@73 201 protected char[] buf;
jjg@73 202
jjg@73 203 /** The length of the content. */
jjg@73 204 protected int bufLen;
jjg@73 205
jjg@73 206 /** The start of a line found by findLine. */
jjg@73 207 protected int lineStart;
jjg@73 208
jjg@73 209 /** The line number of a line found by findLine. */
jjg@73 210 protected int line;
jjg@73 211
jjg@73 212 /** A log for reporting errors, such as errors accessing the content. */
jjg@73 213 protected AbstractLog log;
jjg@73 214 }

mercurial