]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/text/JavaCodeReader.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui / org / eclipse / jdt / internal / ui / text / JavaCodeReader.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 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 package org.eclipse.jdt.internal.ui.text;
12
13
14 import java.io.IOException;
15
16 import org.eclipse.jface.internal.text.html.SingleCharReader;
17
18 import org.eclipse.jface.text.BadLocationException;
19 import org.eclipse.jface.text.IDocument;
20
21
22 /**
23  * Reads from a document either forwards or backwards. May be configured to
24  * skip comments and strings.
25  */
26 public class 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 after read has been called.
48          */
49         public int getOffset() {
50                 return fForward ? fOffset -1 : fOffset;
51         }
52
53         public void configureForwardReader(IDocument document, int offset, int length, boolean skipComments, boolean skipStrings) throws IOException {
54                 fDocument= document;
55                 fOffset= offset;
56                 fSkipComments= skipComments;
57                 fSkipStrings= skipStrings;
58
59                 fForward= true;
60                 fEnd= Math.min(fDocument.getLength(), fOffset + length);
61         }
62
63         public void configureBackwardReader(IDocument document, int offset, boolean skipComments, boolean skipStrings) throws IOException {
64                 fDocument= document;
65                 fOffset= offset;
66                 fSkipComments= skipComments;
67                 fSkipStrings= skipStrings;
68
69                 fForward= false;
70                 try {
71                         fCachedLineNumber= fDocument.getLineOfOffset(fOffset);
72                 } catch (BadLocationException x) {
73                         throw new IOException(x.getMessage());
74                 }
75         }
76
77         /*
78          * @see Reader#close()
79          */
80         @Override
81         public void close() throws IOException {
82                 fDocument= null;
83         }
84
85         /*
86          * @see SingleCharReader#read()
87          */
88         @Override
89         public int read() throws IOException {
90                 try {
91                         return fForward ? readForwards() : readBackwards();
92                 } catch (BadLocationException x) {
93                         throw new IOException(x.getMessage());
94                 }
95         }
96
97         private void gotoCommentEnd() throws BadLocationException {
98                 while (fOffset < fEnd) {
99                         char current= fDocument.getChar(fOffset++);
100                         if (current == '*') {
101                                 if (fOffset < fEnd && fDocument.getChar(fOffset) == '/') {
102                                         ++ fOffset;
103                                         return;
104                                 }
105                         }
106                 }
107         }
108
109         private void gotoStringEnd(char delimiter) throws BadLocationException {
110                 while (fOffset < fEnd) {
111                         char current= fDocument.getChar(fOffset++);
112                         if (current == '\\') {
113                                 // ignore escaped characters
114                                 ++ fOffset;
115                         } else if (current == delimiter) {
116                                 return;
117                         }
118                 }
119         }
120
121         private void gotoLineEnd() throws BadLocationException {
122                 int line= fDocument.getLineOfOffset(fOffset);
123                 fOffset= fDocument.getLineOffset(line + 1);
124         }
125
126         private int readForwards() throws BadLocationException {
127                 while (fOffset < fEnd) {
128                         char current= fDocument.getChar(fOffset++);
129
130                         switch (current) {
131                                 case '/':
132
133                                         if (fSkipComments && fOffset < fEnd) {
134                                                 char next= fDocument.getChar(fOffset);
135                                                 if (next == '*') {
136                                                         // a comment starts, advance to the comment end
137                                                         ++ fOffset;
138                                                         gotoCommentEnd();
139                                                         continue;
140                                                 } else if (next == '/') {
141                                                         // '//'-comment starts, advance to the line end
142                                                         gotoLineEnd();
143                                                         continue;
144                                                 }
145                                         }
146
147                                         return current;
148
149                                 case '"':
150                                 case '\'':
151
152                                         if (fSkipStrings) {
153                                                 gotoStringEnd(current);
154                                                 continue;
155                                         }
156
157                                         return current;
158                         }
159
160                         return current;
161                 }
162
163                 return EOF;
164         }
165
166         private void handleSingleLineComment() throws BadLocationException {
167                 int line= fDocument.getLineOfOffset(fOffset);
168                 if (line < fCachedLineNumber) {
169                         fCachedLineNumber= line;
170                         fCachedLineOffset= fDocument.getLineOffset(line);
171                         int offset= fOffset;
172                         while (fCachedLineOffset < offset) {
173                                 char current= fDocument.getChar(offset--);
174                                 if (current == '/' && fCachedLineOffset <= offset && fDocument.getChar(offset) == '/') {
175                                         fOffset= offset;
176                                         return;
177                                 }
178                         }
179                 }
180         }
181
182         private void gotoCommentStart() throws BadLocationException {
183                 while (0 < fOffset) {
184                         char current= fDocument.getChar(fOffset--);
185                         if (current == '*' && 0 <= fOffset && fDocument.getChar(fOffset) == '/')
186                                 return;
187                 }
188         }
189
190         private void gotoStringStart(char delimiter) throws BadLocationException {
191                 while (0 < fOffset) {
192                         char current= fDocument.getChar(fOffset);
193                         if (current == delimiter) {
194                                 if ( !(0 <= fOffset && fDocument.getChar(fOffset -1) == '\\'))
195                                         return;
196                         }
197                         -- fOffset;
198                 }
199         }
200
201         private int readBackwards() throws BadLocationException {
202
203                 while (0 < fOffset) {
204                         -- fOffset;
205
206                         handleSingleLineComment();
207
208                         char current= fDocument.getChar(fOffset);
209                         switch (current) {
210                                 case '/':
211
212                                         if (fSkipComments && fOffset > 1) {
213                                                 char next= fDocument.getChar(fOffset - 1);
214                                                 if (next == '*') {
215                                                         // a comment ends, advance to the comment start
216                                                         fOffset -= 2;
217                                                         gotoCommentStart();
218                                                         continue;
219                                                 }
220                                         }
221
222                                         return current;
223
224                                 case '"':
225                                 case '\'':
226
227                                         if (fSkipStrings) {
228                                                 -- fOffset;
229                                                 gotoStringStart(current);
230                                                 continue;
231                                         }
232
233                                         return current;
234                         }
235
236                         return current;
237                 }
238
239                 return EOF;
240         }
241 }
242