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