Community
Participate
Working Groups
Build 2.1-M2 On the following method test case, to be defined on org.eclipse.jdt.internal.compiler.util.CharOperation, when running following snippet, it did not suspend on a breakpoint located on first statement line (identified below with '<*>'). public static final boolean pathMatch(char[] pattern, char[] path, boolean isCaseSensitive, char pathSeparator) { <*> if (path == null) return false; // null name cannot match if (pattern == null) return true; // null pattern is equivalent to '*' char[] patternSegment = null; int iPattern = 0, nextPatternSegmentEnd = indexOf(pathSeparator, pattern), patternLength = pattern.length; int iPath = 0, nextPathSegmentEnd = indexOf(pathSeparator, path), pathLength = path.length; int patternSegmentLength = nextPatternSegmentEnd < 0 ? patternLength - iPattern : nextPatternSegmentEnd - iPattern + 1; int pathSegmentLength = nextPathSegmentEnd < 0 ? pathLength - iPath : nextPathSegmentEnd - iPath + 1; // first segments while (iPattern < patternLength - 1 && !(patternSegmentLength == 2 && pattern[iPattern] == '*' && pattern[iPattern+1] == '*')) { if (iPath >= pathLength) return false; if (!match(patternSegment, iPattern, patternSegmentLength, path, iPath, pathSegmentLength, isCaseSensitive)) { return false; } // jump to next segment iPattern += patternSegmentLength+1; // skip separator iPath += pathSegmentLength+1; // skip separator nextPatternSegmentEnd = indexOf(pathSeparator, pattern, nextPatternSegmentEnd+1); // skip separator patternSegmentLength = nextPatternSegmentEnd < 0 ? patternLength - iPattern : nextPatternSegmentEnd - iPattern + 1; nextPathSegmentEnd = indexOf(pathSeparator, path, nextPathSegmentEnd+1); // skip separator pathSegmentLength = nextPathSegmentEnd < 0 ? pathLength - iPath : nextPathSegmentEnd - iPath + 1; } /* check sequence of doubleStar+segment */ int segmentStart; if (patternSegmentLength == 2 && pattern[iPattern] == '*' && pattern [iPattern+1] == '*'){ segmentStart = (iPattern += 3); // skip double star+separator } else { segmentStart = 0; // force iName check } int prefixStart = iPath; checkSegment: while (iPath < pathLength && iPattern < patternLength){ /* segment is ending */ if (patternSegmentLength == 2 && pattern[iPattern] == '*' && pattern[iPattern+1] == '*') { segmentStart = (iPattern += 3); // skip double star+separator prefixStart = iPath; continue checkSegment; } /* chech current path segment */ if (!match(patternSegment, iPattern, patternSegmentLength, path, iPath, pathSegmentLength, isCaseSensitive)) { iPattern = segmentStart; // mismatch - restart current segment iPath = ++prefixStart; continue checkSegment; } // jump to next segment iPattern += patternSegmentLength+1; // skip separator iPath += pathSegmentLength+1; // skip separator nextPatternSegmentEnd = indexOf(pathSeparator, pattern, nextPatternSegmentEnd+1); // skip separator patternSegmentLength = nextPatternSegmentEnd < 0 ? patternLength - iPattern : nextPatternSegmentEnd - iPattern + 1; nextPathSegmentEnd = indexOf(pathSeparator, path, nextPathSegmentEnd+1); // skip separator pathSegmentLength = nextPathSegmentEnd < 0 ? pathLength - iPath : nextPathSegmentEnd - iPath + 1; } return (segmentStart >= patternSegmentLength) || (iPath >= pathLength && iPattern >= patternLength) || (iPattern == patternLength - 2 && pattern[iPattern] == '*' && pattern[iPattern+1] == '*'); }
Code snippet was: char[] pattern = "*.java".toCharArray(); char[] name = "world/X.java".toCharArray(); boolean match = org.eclipse.jdt.internal.compiler.util.CharOperation.pathMatch (pattern, name, true, '/'); match
We are also missing the (new?) method =: "match(char[], int, int, char[], int, int, boolean)"
Created attachment 2250 [details] new version of CharOperation
The attachment is a little modified version, but still exposing the issue.Also note that if placing the breakpoint a couple lines below, it will cause the breakpoint to be hit, but it is off by 2 lines when highlighting the corresponding line (it highlights 2 line above what's being run).
Initial investigation shows that the line number attributes are off by 2. The first executable line in the method shows as "502" (in my modified version of the source with no package decl). The next line is 503, then 505... The line the breakpoint is on is 500. Need to check debug attributes with another tool...
Output from javap confirms that debug attributes are incorrect (moving to JDT CORE) Line numbers for method boolean pathMatch(char[], char[], boolean, char) line 502: 0 line 503: 6 line 505: 12 line 506: 19 line 507: 26 line 509: 35 line 510: 42 line 511: 49 line 514: 58 line 519: 61 line 520: 70 line 521: 87 line 525: 89 line 526: 103 line 528: 112 line 529: 126 line 514: 135 line 515: 144 line 516: 153 line 517: 162 line 534: 173 line 535: 182 line 536: 191 line 537: 202 line 538: 216 line 539: 225 line 540: 229 line 542: 236 line 543: 239 line 545: 243 line 546: 247 line 548: 250 line 549: 259 line 550: 268 line 551: 279 line 552: 293 line 553: 302 line 554: 306 line 555: 310 line 556: 314 line 559: 317 line 560: 334 line 561: 338 line 562: 342 line 563: 349 line 566: 352 line 567: 366 line 569: 375 line 570: 389 line 546: 398 line 573: 412 line 574: 419 line 575: 433 line 573: 462
The problem is due to the block comment in the method isWhitespace. If you replace its source with: public static boolean isWhitespace(char c) { switch(c) { case 10 : case 12 : case 13 : case 32 : case 9 : return true; default : return false; } } Then all line attributes are fine again. I will investigate.
Ok, the problem is due to the fact that the comments contain unicode for a line break. Therefore the lineEnds collection contains entries which are not real lines in the source. This is a small test case that exposes the problem. Put a breakpoint on the System.out.... line in the main and do a step into. [public class A { public static void main(String[] args) { System.out.println(isWhitespace((char) 12)); } public static boolean isWhitespace(char c) { switch (c) { case 10 : /* \u000a: LINE FEED */ case 12 : /* \u000c: FORM FEED */ case 13 : /* \u000d: CARRIAGE RETURN */ case 32 : /* \u0020: SPACE */ case 9 : /* \u0009: HORIZONTAL TABULATION */ return true; default : return false; } } }] If you remove all the \u..... characters, it fixes the problem. Javac 1.4.1 has exactly the same problem.
Olivier - do you suggest we should ignore unicode linebreaks inside comments ?
Actually, shouldn't it rather not count unicode linebreaks at all ?
I am suggesting we should never record a line break which is in unicode. In the "real" source it doesn't correspond to a new line.
Change milestone.
Two places need to be changed. 1) jumpOverMethodBodies 2) getNextToken. We don't want to record a line end for a unicode character \r or \n, because there is no corresponding new lines in the source code. I am running all the tests prior to release.
Fixed and released in 2.1 stream. Regression test added.
Verified.