|
1 |
| |
|
2 |
| |
|
3 |
| |
|
4 |
| |
|
5 |
| |
|
6 |
| |
|
7 |
| |
|
8 |
| |
|
9 |
| |
|
10 |
| |
|
11 |
| |
|
12 |
| |
|
13 |
| |
|
14 |
| |
|
15 |
| |
|
16 |
| |
|
17 |
| |
|
18 |
| |
|
19 |
| |
|
20 |
| |
|
21 |
| |
|
22 |
| |
|
23 |
| |
|
24 |
| |
|
25 |
| |
|
26 |
| |
|
27 |
| |
|
28 |
| |
|
29 |
| |
|
30 |
| |
|
31 |
| |
|
32 |
| |
|
33 |
| |
|
34 |
| |
|
35 |
| |
|
36 |
| |
|
37 |
| package edu.rice.cs.drjava.model.compiler; |
|
38 |
| |
|
39 |
| import java.io.File; |
|
40 |
| import java.io.IOException; |
|
41 |
| import javax.swing.text.*; |
|
42 |
| import java.util.Arrays; |
|
43 |
| import java.util.List; |
|
44 |
| import java.util.LinkedList; |
|
45 |
| import java.util.HashMap; |
|
46 |
| import java.util.HashSet; |
|
47 |
| |
|
48 |
| import edu.rice.cs.drjava.model.DJError; |
|
49 |
| import edu.rice.cs.drjava.model.DummyGlobalModel; |
|
50 |
| import edu.rice.cs.drjava.model.GlobalModel; |
|
51 |
| import edu.rice.cs.drjava.model.OpenDefinitionsDocument; |
|
52 |
| import edu.rice.cs.drjava.model.FileMovedException; |
|
53 |
| import edu.rice.cs.drjava.model.DrJavaFileUtils; |
|
54 |
| import edu.rice.cs.util.FileOps; |
|
55 |
| import edu.rice.cs.util.OperationCanceledException; |
|
56 |
| import edu.rice.cs.util.StringOps; |
|
57 |
| import edu.rice.cs.util.UnexpectedException; |
|
58 |
| import edu.rice.cs.util.swing.Utilities; |
|
59 |
| |
|
60 |
| |
|
61 |
| |
|
62 |
| |
|
63 |
| public class CompilerErrorModel { |
|
64 |
| private static final String newLine = StringOps.EOL; |
|
65 |
| |
|
66 |
| |
|
67 |
| |
|
68 |
| |
|
69 |
| |
|
70 |
| |
|
71 |
| |
|
72 |
| |
|
73 |
| |
|
74 |
| private final DJError[] _errors; |
|
75 |
| |
|
76 |
| |
|
77 |
| |
|
78 |
| |
|
79 |
| private final Position[] _positions; |
|
80 |
| |
|
81 |
| |
|
82 |
| private final int _numErrors; |
|
83 |
| |
|
84 |
| |
|
85 |
| private volatile int _numCompilerErrors; |
|
86 |
| |
|
87 |
| |
|
88 |
| private volatile int _numWarnings; |
|
89 |
| |
|
90 |
| |
|
91 |
| |
|
92 |
| |
|
93 |
| |
|
94 |
| |
|
95 |
| |
|
96 |
| private volatile int _onlyWarnings = -1; |
|
97 |
| |
|
98 |
| |
|
99 |
| |
|
100 |
| |
|
101 |
| private final HashMap<File, StartAndEndIndex> _filesToIndexes = new HashMap<File, StartAndEndIndex>(); |
|
102 |
| |
|
103 |
| |
|
104 |
| private final GlobalModel _model; |
|
105 |
| |
|
106 |
| |
|
107 |
| |
|
108 |
2676
| public CompilerErrorModel() {
|
|
109 |
2676
| _model = new DummyGlobalModel() {
|
|
110 |
0
| public OpenDefinitionsDocument getDocumentForFile(File file) {
|
|
111 |
0
| throw new IllegalStateException("No documents to get!");
|
|
112 |
| } |
|
113 |
0
| public boolean isAlreadyOpen(File file) { return false; }
|
|
114 |
0
| public List<OpenDefinitionsDocument> getOpenDefinitionsDocuments() {
|
|
115 |
0
| return new LinkedList<OpenDefinitionsDocument>();
|
|
116 |
| } |
|
117 |
0
| public boolean hasModifiedDocuments() { return false; }
|
|
118 |
0
| public boolean hasUntitledDocuments() { return false; }
|
|
119 |
| }; |
|
120 |
2676
| _errors = new DJError[0];
|
|
121 |
2676
| _numErrors = 0;
|
|
122 |
2676
| _numWarnings = 0;
|
|
123 |
2676
| _numCompilerErrors = 0;
|
|
124 |
2676
| _positions = new Position[0];
|
|
125 |
| } |
|
126 |
| |
|
127 |
| |
|
128 |
| |
|
129 |
| |
|
130 |
| |
|
131 |
| |
|
132 |
3255
| public CompilerErrorModel(DJError[] errors, GlobalModel model) {
|
|
133 |
| |
|
134 |
| |
|
135 |
3255
| _model = model;
|
|
136 |
| |
|
137 |
| |
|
138 |
| |
|
139 |
| |
|
140 |
| |
|
141 |
| |
|
142 |
| |
|
143 |
| |
|
144 |
3255
| if (model!=null) {
|
|
145 |
3236
| HashSet<File> odds = new HashSet<File>();
|
|
146 |
3236
| for(OpenDefinitionsDocument odd: model.getOpenDefinitionsDocuments()) {
|
|
147 |
3352
| odds.add(odd.getRawFile());
|
|
148 |
| } |
|
149 |
3236
| for(int i=0; i<errors.length; ++i) {
|
|
150 |
2952
| DJError e = errors[i];
|
|
151 |
2952
| if (e.fileName().endsWith(edu.rice.cs.drjava.config.OptionConstants.JAVA_FILE_EXTENSION)) {
|
|
152 |
| |
|
153 |
26
| File javaFile = e.file();
|
|
154 |
26
| if (!odds.contains(javaFile)) {
|
|
155 |
| |
|
156 |
1
| File dj2File = DrJavaFileUtils.getDJ2ForJavaFile(javaFile);
|
|
157 |
1
| if (odds.contains(dj2File)) {
|
|
158 |
| |
|
159 |
0
| errors[i] = new DJError(dj2File, e.lineNumber(), e.startColumn(), e.message(), e.isWarning());
|
|
160 |
| } |
|
161 |
| } |
|
162 |
| } |
|
163 |
| } |
|
164 |
| } |
|
165 |
| |
|
166 |
| |
|
167 |
| |
|
168 |
3255
| _errors = errors;
|
|
169 |
| |
|
170 |
3255
| _numErrors = errors.length;
|
|
171 |
3255
| _positions = new Position[errors.length];
|
|
172 |
| |
|
173 |
3255
| _numWarnings = 0;
|
|
174 |
3255
| _numCompilerErrors = 0;
|
|
175 |
3255
| for (int i =0; i < errors.length; i++) {
|
|
176 |
43
| if (errors[i].isWarning()) _numWarnings++;
|
|
177 |
2909
| else _numCompilerErrors++;
|
|
178 |
| } |
|
179 |
| |
|
180 |
| |
|
181 |
3255
| Arrays.sort(_errors);
|
|
182 |
| |
|
183 |
| |
|
184 |
3255
| Utilities.invokeLater(new Runnable() { public void run() { _calculatePositions(); } });
|
|
185 |
| } |
|
186 |
| |
|
187 |
| |
|
188 |
| |
|
189 |
| |
|
190 |
| |
|
191 |
| |
|
192 |
| |
|
193 |
62
| public DJError getError(int idx) { return _errors[idx]; }
|
|
194 |
| |
|
195 |
| |
|
196 |
9
| public Position getPosition(DJError error) {
|
|
197 |
9
| int spot = Arrays.binarySearch(_errors, error);
|
|
198 |
9
| return _positions[spot];
|
|
199 |
| } |
|
200 |
| |
|
201 |
| |
|
202 |
272
| public int getNumErrors() { return _numErrors; }
|
|
203 |
| |
|
204 |
| |
|
205 |
70
| public int getNumCompErrors() { return _numCompilerErrors; }
|
|
206 |
| |
|
207 |
| |
|
208 |
13
| public int getNumWarnings() { return _numWarnings; }
|
|
209 |
| |
|
210 |
| |
|
211 |
0
| public String toString() {
|
|
212 |
0
| final StringBuilder buf = new StringBuilder();
|
|
213 |
0
| buf.append(this.getClass().toString() + ":\n ");
|
|
214 |
0
| for (int i = 0; i < _numErrors; i++) {
|
|
215 |
0
| buf.append(_errors[i].toString());
|
|
216 |
0
| buf.append("\n ");
|
|
217 |
| } |
|
218 |
0
| return buf.toString();
|
|
219 |
| } |
|
220 |
| |
|
221 |
| |
|
222 |
| |
|
223 |
| |
|
224 |
| |
|
225 |
| |
|
226 |
10
| public DJError getErrorAtOffset(OpenDefinitionsDocument odd, int offset) {
|
|
227 |
10
| File file;
|
|
228 |
10
| try {
|
|
229 |
10
| file = odd.getFile();
|
|
230 |
0
| if (file == null) return null;
|
|
231 |
| } |
|
232 |
0
| catch (FileMovedException e) { file = e.getFile(); }
|
|
233 |
| |
|
234 |
| |
|
235 |
10
| try { file = file.getCanonicalFile(); }
|
|
236 |
| catch (IOException ioe) { |
|
237 |
| |
|
238 |
| } |
|
239 |
| |
|
240 |
10
| StartAndEndIndex saei = _filesToIndexes.get(file);
|
|
241 |
0
| if (saei == null) return null;
|
|
242 |
10
| int start = saei.getStartPos();
|
|
243 |
10
| int end = saei.getEndPos();
|
|
244 |
0
| if (start == end) return null;
|
|
245 |
| |
|
246 |
| |
|
247 |
| |
|
248 |
| |
|
249 |
10
| int errorAfter;
|
|
250 |
10
| for (errorAfter = start; errorAfter < end; errorAfter++) {
|
|
251 |
11
| if (_positions[errorAfter] == null) {
|
|
252 |
| |
|
253 |
0
| return null;
|
|
254 |
| } |
|
255 |
8
| if (_positions[errorAfter].getOffset() >=offset) break;
|
|
256 |
| } |
|
257 |
| |
|
258 |
| |
|
259 |
10
| int errorBefore = errorAfter - 1;
|
|
260 |
| |
|
261 |
| |
|
262 |
10
| int shouldSelect = -1;
|
|
263 |
| |
|
264 |
10
| if (errorBefore >= start) {
|
|
265 |
3
| int errPos = _positions[errorBefore].getOffset();
|
|
266 |
3
| try {
|
|
267 |
3
| String betweenDotAndErr = odd.getText(errPos, offset - errPos);
|
|
268 |
0
| if (betweenDotAndErr.indexOf('\n') == -1) shouldSelect = errorBefore;
|
|
269 |
| } |
|
270 |
| catch (BadLocationException e) { } |
|
271 |
| catch (StringIndexOutOfBoundsException e) { } |
|
272 |
| } |
|
273 |
| |
|
274 |
10
| if ((shouldSelect == -1) && (errorAfter < end)) {
|
|
275 |
| |
|
276 |
| |
|
277 |
| |
|
278 |
8
| int errPos = _positions[errorAfter].getOffset();
|
|
279 |
8
| try {
|
|
280 |
8
| String betweenDotAndErr = odd.getText(offset, errPos - offset);
|
|
281 |
6
| if (betweenDotAndErr.indexOf('\n') == -1) shouldSelect = errorAfter;
|
|
282 |
| } |
|
283 |
| catch (BadLocationException e) { } |
|
284 |
| catch (StringIndexOutOfBoundsException e) { } |
|
285 |
| } |
|
286 |
| |
|
287 |
4
| if (shouldSelect == -1) return null;
|
|
288 |
6
| return _errors[shouldSelect];
|
|
289 |
| } |
|
290 |
| |
|
291 |
| |
|
292 |
11
| public boolean hasErrorsWithPositions(OpenDefinitionsDocument odd) {
|
|
293 |
11
| File file = FileOps.NULL_FILE;
|
|
294 |
11
| try {
|
|
295 |
11
| file = odd.getFile();
|
|
296 |
0
| if (file == null || file == FileOps.NULL_FILE) return false;
|
|
297 |
| } |
|
298 |
0
| catch (FileMovedException fme) { file = fme.getFile(); }
|
|
299 |
| |
|
300 |
| |
|
301 |
11
| try { file = file.getCanonicalFile(); }
|
|
302 |
| catch (IOException ioe) { } |
|
303 |
| |
|
304 |
11
| StartAndEndIndex saei = _filesToIndexes.get(file);
|
|
305 |
3
| if (saei == null) return false;
|
|
306 |
0
| if (saei.getStartPos() == saei.getEndPos()) return false;
|
|
307 |
8
| return true;
|
|
308 |
| } |
|
309 |
| |
|
310 |
| |
|
311 |
| |
|
312 |
| |
|
313 |
| |
|
314 |
21
| public boolean hasOnlyWarnings() {
|
|
315 |
| |
|
316 |
3
| if (_onlyWarnings == 0) return false;
|
|
317 |
0
| if (_onlyWarnings == 1) return true;
|
|
318 |
| else { |
|
319 |
| |
|
320 |
18
| boolean clean = true;
|
|
321 |
18
| for (int i = 0; clean && (i < _numErrors); i++) {
|
|
322 |
18
| clean = _errors[i].isWarning();
|
|
323 |
| } |
|
324 |
| |
|
325 |
18
| _onlyWarnings = clean? 1: 0;
|
|
326 |
18
| return clean;
|
|
327 |
| } |
|
328 |
| } |
|
329 |
| |
|
330 |
| |
|
331 |
3255
| private void _calculatePositions() {
|
|
332 |
3255
| try {
|
|
333 |
3255
| int curError = 0;
|
|
334 |
| |
|
335 |
| |
|
336 |
3255
| while ((curError < _numErrors)) {
|
|
337 |
| |
|
338 |
2876
| curError = nextErrorWithLine(curError);
|
|
339 |
2830
| if (curError >= _numErrors) {break;}
|
|
340 |
| |
|
341 |
| |
|
342 |
46
| File file = _errors[curError].file();
|
|
343 |
46
| OpenDefinitionsDocument document;
|
|
344 |
46
| try { document = _model.getDocumentForFile(file); }
|
|
345 |
| catch (Exception e) { |
|
346 |
| |
|
347 |
| |
|
348 |
0
| if ((e instanceof IOException) || (e instanceof OperationCanceledException)) {
|
|
349 |
0
| document = null;
|
|
350 |
| } |
|
351 |
0
| else throw new UnexpectedException(e);
|
|
352 |
| } |
|
353 |
46
| if (document==null) {
|
|
354 |
1
| do { curError++;}
|
|
355 |
1
| while ((curError < _numErrors) && (_errors[curError].file().equals(file)));
|
|
356 |
| |
|
357 |
1
| continue;
|
|
358 |
| } |
|
359 |
0
| if (curError >= _numErrors) break;
|
|
360 |
| |
|
361 |
| |
|
362 |
45
| final int fileStartIndex = curError;
|
|
363 |
45
| final int defsLength = document.getLength();
|
|
364 |
45
| final String defsText = document.getText(0, defsLength);
|
|
365 |
45
| int curLine = 0;
|
|
366 |
45
| int offset = 0;
|
|
367 |
| |
|
368 |
| |
|
369 |
| |
|
370 |
45
| while ((curError < _numErrors) &&
|
|
371 |
| file.equals(_errors[curError].file()) && |
|
372 |
| (offset <= defsLength)) { |
|
373 |
| |
|
374 |
101
| boolean didNotAdvance = false;
|
|
375 |
101
| if (_errors[curError].lineNumber() != curLine) {
|
|
376 |
| |
|
377 |
| |
|
378 |
| |
|
379 |
| |
|
380 |
32
| didNotAdvance = true;
|
|
381 |
| } |
|
382 |
| else { |
|
383 |
69
| while ((curError < _numErrors) &&
|
|
384 |
| file.equals(_errors[curError].file()) && |
|
385 |
| (_errors[curError].lineNumber() == curLine)) { |
|
386 |
74
| _positions[curError] = document.createPosition(offset + _errors[curError].startColumn());
|
|
387 |
74
| curError++;
|
|
388 |
| } |
|
389 |
| } |
|
390 |
| |
|
391 |
| |
|
392 |
| |
|
393 |
| |
|
394 |
| |
|
395 |
101
| if (curError < _numErrors) {
|
|
396 |
76
| int curErrorLine = _errors[curError].lineNumber();
|
|
397 |
76
| int nextNewline = 0;
|
|
398 |
76
| while ((curLine != curErrorLine)
|
|
399 |
| && (nextNewline != -1) |
|
400 |
| && (file.equals(_errors[curError].file()))) { |
|
401 |
143
| nextNewline = defsText.indexOf(newLine, offset);
|
|
402 |
0
| if (nextNewline == -1) nextNewline = defsText.indexOf("\n", offset);
|
|
403 |
143
| if (nextNewline != -1) {
|
|
404 |
143
| curLine++;
|
|
405 |
143
| offset = nextNewline + 1;
|
|
406 |
| } |
|
407 |
| else { |
|
408 |
| |
|
409 |
0
| if (didNotAdvance) {
|
|
410 |
| |
|
411 |
| |
|
412 |
| |
|
413 |
| |
|
414 |
| |
|
415 |
| |
|
416 |
| |
|
417 |
0
| _positions[curError] = null;
|
|
418 |
0
| curError++;
|
|
419 |
| } |
|
420 |
| } |
|
421 |
| } |
|
422 |
| } |
|
423 |
| } |
|
424 |
| |
|
425 |
| |
|
426 |
45
| int fileEndIndex = curError;
|
|
427 |
45
| if (fileEndIndex != fileStartIndex) {
|
|
428 |
| |
|
429 |
45
| try { file = file.getCanonicalFile(); }
|
|
430 |
| catch (IOException ioe) { } |
|
431 |
45
| _filesToIndexes.put(file, new StartAndEndIndex(fileStartIndex, fileEndIndex));
|
|
432 |
| } |
|
433 |
| } |
|
434 |
| } |
|
435 |
0
| catch (BadLocationException ble) { throw new UnexpectedException(ble); }
|
|
436 |
0
| catch (StringIndexOutOfBoundsException e) { throw new UnexpectedException(e); }
|
|
437 |
| } |
|
438 |
| |
|
439 |
| |
|
440 |
| |
|
441 |
| |
|
442 |
| |
|
443 |
2876
| private int nextErrorWithLine(int idx) {
|
|
444 |
2877
| while (idx < _numErrors && (_errors[idx].hasNoLocation() || _errors[idx].file() == null)) idx++;
|
|
445 |
2876
| return idx;
|
|
446 |
| } |
|
447 |
| |
|
448 |
| |
|
449 |
| |
|
450 |
| |
|
451 |
| private static class StartAndEndIndex { |
|
452 |
| private int startPos; |
|
453 |
| private int endPos; |
|
454 |
| |
|
455 |
45
| public StartAndEndIndex(int startPos, int endPos) {
|
|
456 |
45
| this.startPos = startPos;
|
|
457 |
45
| this.endPos = endPos;
|
|
458 |
| } |
|
459 |
18
| public int getStartPos() { return startPos; }
|
|
460 |
18
| public int getEndPos() { return endPos; }
|
|
461 |
| } |
|
462 |
| } |