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

Wed, 24 Jun 2009 10:50:54 +0100

author
mcimadamore
date
Wed, 24 Jun 2009 10:50:54 +0100
changeset 303
8ec37cf2b37e
parent 100
37551dc0f591
child 415
49359d0e6a9c
permissions
-rw-r--r--

6852595: Accessing scope using JSR199 API on erroneous tree causes Illegal Argument Exception
Summary: Fixed problem with empty DiagnosticSource objects causing IAE in the JCDiagnostic constructor
Reviewed-by: 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 {
mcimadamore@303 49
mcimadamore@303 50 /* constant DiagnosticSource to be used when sourcefile is missing */
mcimadamore@303 51 public static final DiagnosticSource NO_SOURCE = new DiagnosticSource() {
mcimadamore@303 52 @Override
mcimadamore@303 53 protected boolean findLine(int pos) {
mcimadamore@303 54 return false;
mcimadamore@303 55 }
mcimadamore@303 56 };
mcimadamore@303 57
jjg@73 58 public DiagnosticSource(JavaFileObject fo, AbstractLog log) {
jjg@73 59 this.fileObject = fo;
jjg@73 60 this.log = log;
jjg@73 61 }
jjg@73 62
mcimadamore@303 63 private DiagnosticSource() {}
mcimadamore@303 64
jjg@73 65 /** Return the underlying file object handled by this
jjg@73 66 * DiagnosticSource object.
jjg@73 67 */
jjg@73 68 public JavaFileObject getFile() {
jjg@73 69 return fileObject;
jjg@73 70 }
jjg@73 71
jjg@73 72 public CharSequence getName() {
jjg@73 73 return JavacFileManager.getJavacBaseFileName(fileObject);
jjg@73 74 }
jjg@73 75
jjg@73 76 /** Return the one-based line number associated with a given pos
jjg@73 77 * for the current source file. Zero is returned if no line exists
jjg@73 78 * for the given position.
jjg@73 79 */
jjg@73 80 public int getLineNumber(int pos) {
jjg@73 81 try {
jjg@73 82 if (findLine(pos)) {
jjg@73 83 return line;
jjg@73 84 }
jjg@73 85 return 0;
jjg@73 86 } finally {
jjg@73 87 buf = null;
jjg@73 88 }
jjg@73 89 }
jjg@73 90
jjg@73 91 /** Return the one-based column number associated with a given pos
jjg@73 92 * for the current source file. Zero is returned if no column exists
jjg@73 93 * for the given position.
jjg@73 94 */
mcimadamore@100 95 public int getColumnNumber(int pos, boolean expandTabs) {
jjg@73 96 try {
jjg@73 97 if (findLine(pos)) {
jjg@73 98 int column = 0;
jjg@73 99 for (int bp = lineStart; bp < pos; bp++) {
jjg@73 100 if (bp >= bufLen) {
jjg@73 101 return 0;
jjg@73 102 }
mcimadamore@100 103 if (buf[bp] == '\t' && expandTabs) {
jjg@73 104 column = (column / TabInc * TabInc) + TabInc;
jjg@73 105 } else {
jjg@73 106 column++;
jjg@73 107 }
jjg@73 108 }
jjg@73 109 return column + 1; // positions are one-based
jjg@73 110 }
jjg@73 111 return 0;
jjg@73 112 } finally {
jjg@73 113 buf = null;
jjg@73 114 }
jjg@73 115 }
jjg@73 116
jjg@73 117 /** Return the content of the line containing a given pos.
jjg@73 118 */
jjg@73 119 public String getLine(int pos) {
jjg@73 120 try {
jjg@73 121 if (!findLine(pos))
jjg@73 122 return null;
jjg@73 123
jjg@73 124 int lineEnd = lineStart;
jjg@73 125 while (lineEnd < bufLen && buf[lineEnd] != CR && buf[lineEnd] != LF)
jjg@73 126 lineEnd++;
jjg@73 127 if (lineEnd - lineStart == 0)
jjg@73 128 return null;
jjg@73 129 return new String(buf, lineStart, lineEnd - lineStart);
jjg@73 130 } finally {
jjg@73 131 buf = null;
jjg@73 132 }
jjg@73 133 }
jjg@73 134
jjg@73 135 public Map<JCTree, Integer> getEndPosTable() {
jjg@73 136 return endPosTable;
jjg@73 137 }
jjg@73 138
jjg@73 139 public void setEndPosTable(Map<JCTree, Integer> t) {
jjg@73 140 if (endPosTable != null && endPosTable != t)
jjg@73 141 throw new IllegalStateException("endPosTable already set");
jjg@73 142 endPosTable = t;
jjg@73 143 }
jjg@73 144
jjg@73 145 /** Find the line in the buffer that contains the current position
jjg@73 146 * @param pos Character offset into the buffer
jjg@73 147 */
mcimadamore@303 148 protected boolean findLine(int pos) {
jjg@73 149 if (pos == Position.NOPOS)
jjg@73 150 return false;
jjg@73 151
jjg@73 152 try {
jjg@73 153 // try and recover buffer from soft reference cache
jjg@73 154 if (buf == null && refBuf != null)
jjg@73 155 buf = refBuf.get();
jjg@73 156
jjg@73 157 if (buf == null) {
jjg@73 158 buf = initBuf(fileObject);
jjg@73 159 lineStart = 0;
jjg@73 160 line = 1;
jjg@73 161 } else if (lineStart > pos) { // messages don't come in order
jjg@73 162 lineStart = 0;
jjg@73 163 line = 1;
jjg@73 164 }
jjg@73 165
jjg@73 166 int bp = lineStart;
jjg@73 167 while (bp < bufLen && bp < pos) {
jjg@73 168 switch (buf[bp++]) {
jjg@73 169 case CR:
jjg@73 170 if (bp < bufLen && buf[bp] == LF) bp++;
jjg@73 171 line++;
jjg@73 172 lineStart = bp;
jjg@73 173 break;
jjg@73 174 case LF:
jjg@73 175 line++;
jjg@73 176 lineStart = bp;
jjg@73 177 break;
jjg@73 178 }
jjg@73 179 }
jjg@73 180 return bp <= bufLen;
jjg@73 181 } catch (IOException e) {
jjg@73 182 log.directError("source.unavailable");
jjg@73 183 buf = new char[0];
jjg@73 184 return false;
jjg@73 185 }
jjg@73 186 }
jjg@73 187
jjg@73 188 protected char[] initBuf(JavaFileObject fileObject) throws IOException {
jjg@73 189 char[] buf;
jjg@73 190 CharSequence cs = fileObject.getCharContent(true);
jjg@73 191 if (cs instanceof CharBuffer) {
jjg@73 192 CharBuffer cb = (CharBuffer) cs;
jjg@73 193 buf = JavacFileManager.toArray(cb);
jjg@73 194 bufLen = cb.limit();
jjg@73 195 } else {
jjg@73 196 buf = cs.toString().toCharArray();
jjg@73 197 bufLen = buf.length;
jjg@73 198 }
jjg@73 199 refBuf = new SoftReference<char[]>(buf);
jjg@73 200 return buf;
jjg@73 201 }
jjg@73 202
jjg@73 203 /** The underlying file object. */
jjg@73 204 protected JavaFileObject fileObject;
jjg@73 205
jjg@73 206 protected Map<JCTree, Integer> endPosTable;
jjg@73 207
jjg@73 208 /** A soft reference to the content of the file object. */
jjg@73 209 protected SoftReference<char[]> refBuf;
jjg@73 210
jjg@73 211 /** A temporary hard reference to the content of the file object. */
jjg@73 212 protected char[] buf;
jjg@73 213
jjg@73 214 /** The length of the content. */
jjg@73 215 protected int bufLen;
jjg@73 216
jjg@73 217 /** The start of a line found by findLine. */
jjg@73 218 protected int lineStart;
jjg@73 219
jjg@73 220 /** The line number of a line found by findLine. */
jjg@73 221 protected int line;
jjg@73 222
jjg@73 223 /** A log for reporting errors, such as errors accessing the content. */
jjg@73 224 protected AbstractLog log;
jjg@73 225 }

mercurial