blob: e3cace3005951b8271f48155b876c3cfd2624a94 [file] [log] [blame]
nitindb12994e2005-05-26 17:34:10 +00001/*******************************************************************************
2 * Copyright (c) 2001, 2005 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *
11 *******************************************************************************/
12package org.eclipse.wst.html.ui.internal.text;
13
14// taken from package org.eclipse.jdt.ui.text;
15
16import java.io.IOException;
17
18import org.eclipse.jface.text.BadLocationException;
19import org.eclipse.jface.text.IDocument;
nitindf8e77632005-09-07 23:49:25 +000020import org.eclipse.wst.html.ui.internal.derived.SingleCharReader;
nitindb12994e2005-05-26 17:34:10 +000021
22/**
23 * Reads from a document either forwards or backwards. May be configured to
24 * skip comments and strings.
25 */
26class JavaCodeReader extends SingleCharReader {
27
28 /** The EOF character */
29 public static final int EOF = -1;
30
31 private boolean fSkipComments = false;
32 private boolean fSkipStrings = false;
33 private boolean fForward = false;
34
35 private IDocument fDocument;
36 private int fOffset;
37
38 private int fEnd = -1;
39 private int fCachedLineNumber = -1;
40 private int fCachedLineOffset = -1;
41
42
43 public JavaCodeReader() {
44 }
45
46 /**
47 * Returns the offset of the last read character. Should only be called
48 * after read has been called.
49 */
50 public int getOffset() {
51 return fForward ? fOffset - 1 : fOffset;
52 }
53
54 public void configureForwardReader(IDocument document, int offset, int length, boolean skipComments, boolean skipStrings) throws IOException {
55 fDocument = document;
56 fOffset = offset;
57 fSkipComments = skipComments;
58 fSkipStrings = skipStrings;
59
60 fForward = true;
61 fEnd = Math.min(fDocument.getLength(), fOffset + length);
62 }
63
64 public void configureBackwardReader(IDocument document, int offset, boolean skipComments, boolean skipStrings) throws IOException {
65 fDocument = document;
66 fOffset = offset;
67 fSkipComments = skipComments;
68 fSkipStrings = skipStrings;
69
70 fForward = false;
71 try {
72 fCachedLineNumber = fDocument.getLineOfOffset(fOffset);
73 }
74 catch (BadLocationException x) {
75 throw new IOException(x.getMessage());
76 }
77 }
78
79 /*
80 * @see Reader#close()
81 */
82 public void close() throws IOException {
83 fDocument = null;
84 }
85
86 /*
87 * @see SingleCharReader#read()
88 */
89 public int read() throws IOException {
90 try {
91 return fForward ? readForwards() : readBackwards();
92 }
93 catch (BadLocationException x) {
94 throw new IOException(x.getMessage());
95 }
96 }
97
98 private void gotoCommentEnd() throws BadLocationException {
99 while (fOffset < fEnd) {
100 char current = fDocument.getChar(fOffset++);
101 if (current == '*') {
102 if (fOffset < fEnd && fDocument.getChar(fOffset) == '/') {
103 ++fOffset;
104 return;
105 }
106 }
107 }
108 }
109
110 private void gotoStringEnd(char delimiter) throws BadLocationException {
111 while (fOffset < fEnd) {
112 char current = fDocument.getChar(fOffset++);
113 if (current == '\\') {
114 // ignore escaped characters
115 ++fOffset;
116 }
117 else if (current == delimiter) {
118 return;
119 }
120 }
121 }
122
123 private void gotoLineEnd() throws BadLocationException {
124 int line = fDocument.getLineOfOffset(fOffset);
125 fOffset = fDocument.getLineOffset(line + 1);
126 }
127
128 private int readForwards() throws BadLocationException {
129 while (fOffset < fEnd) {
130 char current = fDocument.getChar(fOffset++);
131
132 switch (current) {
133 case '/' :
134
135 if (fSkipComments && fOffset < fEnd) {
136 char next = fDocument.getChar(fOffset);
137 if (next == '*') {
138 // a comment starts, advance to the comment end
139 ++fOffset;
140 gotoCommentEnd();
141 continue;
142 }
143 else if (next == '/') {
144 // '//'-comment starts, advance to the line end
145 gotoLineEnd();
146 continue;
147 }
148 }
149
150 return current;
151
152 case '"' :
153 case '\'' :
154
155 if (fSkipStrings) {
156 gotoStringEnd(current);
157 continue;
158 }
159
160 return current;
161 }
162
163 return current;
164 }
165
166 return EOF;
167 }
168
169 private void handleSingleLineComment() throws BadLocationException {
170 int line = fDocument.getLineOfOffset(fOffset);
171 if (line < fCachedLineNumber) {
172 fCachedLineNumber = line;
173 fCachedLineOffset = fDocument.getLineOffset(line);
174 int offset = fOffset;
175 while (fCachedLineOffset < offset) {
176 char current = fDocument.getChar(offset--);
177 if (current == '/' && fCachedLineOffset <= offset && fDocument.getChar(offset) == '/') {
178 fOffset = offset;
179 return;
180 }
181 }
182 }
183 }
184
185 private void gotoCommentStart() throws BadLocationException {
186 while (0 < fOffset) {
187 char current = fDocument.getChar(fOffset--);
188 if (current == '*' && 0 <= fOffset && fDocument.getChar(fOffset) == '/')
189 return;
190 }
191 }
192
193 private void gotoStringStart(char delimiter) throws BadLocationException {
194 while (0 < fOffset) {
195 char current = fDocument.getChar(fOffset);
196 if (current == delimiter) {
197 if (!(0 <= fOffset && fDocument.getChar(fOffset - 1) == '\\'))
198 return;
199 }
200 --fOffset;
201 }
202 }
203
204 private int readBackwards() throws BadLocationException {
205
206 while (0 < fOffset) {
207 --fOffset;
208
209 handleSingleLineComment();
210
211 char current = fDocument.getChar(fOffset);
212 switch (current) {
213 case '/' :
214
215 if (fSkipComments && fOffset > 1) {
216 char next = fDocument.getChar(fOffset - 1);
217 if (next == '*') {
218 // a comment ends, advance to the comment start
219 fOffset -= 2;
220 gotoCommentStart();
221 continue;
222 }
223 }
224
225 return current;
226
227 case '"' :
228 case '\'' :
229
230 if (fSkipStrings) {
231 --fOffset;
232 gotoStringStart(current);
233 continue;
234 }
235
236 return current;
237 }
238
239 return current;
240 }
241
242 return EOF;
243 }
244}