Skip to content

Commit ac2b81c

Browse files
committed
Bugfix: caret error marks in compiler output too short
This very old bug in EclipseAdapterUtils calculated the '^' caret error marks incorrectly. The marks were too short like this: void m() { return vax[3]; } ^^^^^^^^^^^ Where the correct result would look like this: void m() { return vax[3]; } ^^^^^^^^^^^^^^ This was due to the rather complicated way in which first surrounding context code - here the leading 'void m() { ' and trailing ' }' - was first added and then possible leading white space was cut off again from the left. It is difficult to explain, the code is a nightmare, trying to work with char arrays, counting indexes, repeatedly using System.arraycopy and using lots of counters and offsets. I would have liked to simplify the code, converting char[] buffers to Strings, but decided to keep the basic structure for now, not sure what kind of memory or performance considerations led to this design. Signed-off-by: Alexander Kriegisch <[email protected]>
1 parent 953a831 commit ac2b81c

File tree

1 file changed

+70
-53
lines changed

1 file changed

+70
-53
lines changed

org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/core/builder/EclipseAdapterUtils.java

Lines changed: 70 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,17 @@ public class EclipseAdapterUtils {
2929

3030
// XXX some cut-and-paste from eclipse sources
3131
public static String makeLocationContext(ICompilationUnit compilationUnit, IProblem problem) {
32-
// extra from the source the innacurate token
33-
// and "highlight" it using some underneath ^^^^^
34-
// put some context around too.
32+
// Extract the erroneous token plus some context around it from the beginning of the first to the end of the last
33+
// problematic line. Usually, it will be a single line, but not necessarily. After extraction, highlight the
34+
// erroneous token, "underlining" it withthe appropriate number of carets ('^').
35+
//
36+
// This code assumes, that the console font is fixed size.
3537

36-
// this code assumes that the font used in the console is fixed size
37-
38-
// sanity .....
38+
// Sanity checks
3939
int startPosition = problem.getSourceStart();
4040
int endPosition = problem.getSourceEnd();
4141

42-
if ((startPosition > endPosition) || ((startPosition <= 0) && (endPosition <= 0)) || compilationUnit == null)
42+
if (startPosition > endPosition || startPosition <= 0 && endPosition <= 0 || compilationUnit == null)
4343
//return Util.bind("problem.noSourceInformation"); //$NON-NLS-1$
4444
return "(no source information available)";
4545

@@ -53,57 +53,74 @@ public static String makeLocationContext(ICompilationUnit compilationUnit, IProb
5353
// (the code still works but the display is not optimal !)
5454

5555
// compute the how-much-char we are displaying around the inaccurate token
56-
int begin = startPosition >= source.length ? source.length - 1 : startPosition;
57-
if (begin == -1)
58-
return "(no source information available)"; // Dont like this - why does it occur? pr152835
59-
int relativeStart = 0;
60-
int end = endPosition >= source.length ? source.length - 1 : endPosition;
61-
int relativeEnd = 0;
62-
label: for (relativeStart = 0;; relativeStart++) {
63-
if (begin == 0)
64-
break label;
65-
if ((source[begin - 1] == '\n') || (source[begin - 1] == '\r'))
66-
break label;
67-
begin--;
56+
int contextStart = startPosition >= source.length ? source.length - 1 : startPosition;
57+
if (contextStart == -1)
58+
return "(no source information available)"; // Don't like this - why does it occur? pr152835
59+
int contextEnd = endPosition >= source.length ? source.length - 1 : endPosition;
60+
int problemLength = contextEnd - contextStart + 1;
61+
int trimLeftIndex = 0;
62+
char c;
63+
while (
64+
trimLeftIndex <= problemLength &&
65+
((c = source[contextStart + trimLeftIndex]) == TAB || c == SPACE)
66+
) {
67+
trimLeftIndex++;
6868
}
69-
label: for (relativeEnd = 0;; relativeEnd++) {
70-
if ((end + 1) >= source.length)
71-
break label;
72-
if ((source[end + 1] == '\r') || (source[end + 1] == '\n')) {
73-
break label;
74-
}
75-
end++;
69+
contextStart += trimLeftIndex;
70+
problemLength -= trimLeftIndex;
71+
72+
// Find the beginning of the first line containing the problem (contextStart)
73+
// as well as the relative problem start offset (problemStartOffset) from there
74+
int problemStartOffset;
75+
for (problemStartOffset = 0; ; problemStartOffset++) {
76+
if (contextStart == 0)
77+
break;
78+
if ((c = source[contextStart - 1]) == '\n' || c == '\r')
79+
break;
80+
contextStart--;
7681
}
77-
// extract the message form the source
78-
char[] extract = new char[end - begin + 1];
79-
System.arraycopy(source, begin, extract, 0, extract.length);
80-
char c;
81-
// remove all SPACE and TAB that begin the error message...
82-
int trimLeftIndex = 0;
83-
while ((((c = extract[trimLeftIndex++]) == TAB) || (c == SPACE)) && trimLeftIndex < extract.length) {
82+
83+
// Find the end of the last line containing the problem (contextEnd)
84+
// as well as the relative problem end offset (problemEndOffset) from there
85+
int problemEndOffset;
86+
for (problemEndOffset = 0; ; problemEndOffset--) {
87+
if (contextEnd + 1 >= source.length)
88+
break;
89+
if ((c = source[contextEnd + 1]) == '\r' || c == '\n')
90+
break;
91+
contextEnd++;
92+
}
93+
94+
// Extract the problematic lines of code from the source
95+
char[] extract = new char[contextEnd - contextStart + 1];
96+
System.arraycopy(source, contextStart, extract, 0, extract.length);
97+
98+
// Dedent (left-trim) the first line, i.e. remove leading spaces and tabs
99+
trimLeftIndex = 0;
100+
while (
101+
trimLeftIndex < extract.length &&
102+
((c = extract[trimLeftIndex]) == TAB || c == SPACE)
103+
) {
104+
trimLeftIndex++;
84105
}
85106
if (trimLeftIndex >= extract.length)
86-
return new String(extract) + "\n";
87-
System.arraycopy(extract, trimLeftIndex - 1, extract = new char[extract.length - trimLeftIndex + 1], 0, extract.length);
88-
relativeStart -= trimLeftIndex;
89-
// buffer spaces and tabs in order to reach the error position
107+
return new String(extract) + "\n"; // TODO: Shouldn't it return "" or "\n"?
108+
System.arraycopy(extract, trimLeftIndex, extract = new char[extract.length - trimLeftIndex], 0, extract.length);
109+
problemStartOffset -= trimLeftIndex;
110+
111+
// Insert spaces to reach the error position
90112
int pos = 0;
91-
char[] underneath = new char[extract.length]; // can't be bigger
92-
for (int i = 0; i <= relativeStart; i++) {
93-
if (extract[i] == TAB) {
94-
underneath[pos++] = TAB;
95-
} else {
96-
underneath[pos++] = SPACE;
97-
}
98-
}
99-
// mark the error position
100-
for (int i = startPosition + trimLeftIndex; // AMC if we took stuff off the start, take it into account!
101-
i <= (endPosition >= source.length ? source.length - 1 : endPosition); i++)
102-
underneath[pos++] = MARK;
103-
// resize underneathto remove 'null' chars
104-
System.arraycopy(underneath, 0, underneath = new char[pos], 0, pos);
105-
106-
return new String(extract) + "\n" + new String(underneath); //$NON-NLS-2$ //$NON-NLS-1$
113+
char[] underline = new char[extract.length]; // can't be bigger
114+
for (int i = 0; i < problemStartOffset; i++)
115+
underline[pos++] = SPACE;
116+
// Underline the error position with a '^^^^^' character sequence
117+
for (int i = 0; i < problemLength; i++)
118+
underline[pos++] = MARK;
119+
120+
// Resize to remove trailing NUL characters
121+
System.arraycopy(underline, 0, underline = new char[problemStartOffset + problemLength], 0, pos);
122+
123+
return new String(extract) + "\n" + new String(underline); //$NON-NLS-2$ //$NON-NLS-1$
107124
}
108125

109126
/**

0 commit comments

Comments
 (0)