Bug 25188 - Debugger won't stop on method first statement breakpoint
Summary: Debugger won't stop on method first statement breakpoint
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.0   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: 2.1 M3   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-10-22 09:58 EDT by Philipe Mulet CLA
Modified: 2002-11-13 06:27 EST (History)
0 users

See Also:


Attachments
new version of CharOperation (26.06 KB, text/plain)
2002-10-22 11:21 EDT, Philipe Mulet CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Philipe Mulet CLA 2002-10-22 09:58:36 EDT
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] == '*'); 
}
Comment 1 Philipe Mulet CLA 2002-10-22 09:59:11 EDT
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
Comment 2 Darin Wright CLA 2002-10-22 10:35:54 EDT
We are also missing the (new?) method =:

"match(char[], int, int, char[], int, int, boolean)"
Comment 3 Philipe Mulet CLA 2002-10-22 11:21:42 EDT
Created attachment 2250 [details]
new version of CharOperation
Comment 4 Philipe Mulet CLA 2002-10-22 11:23:57 EDT
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).
Comment 5 Darin Wright CLA 2002-10-22 12:06:17 EDT
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...
Comment 6 Darin Wright CLA 2002-10-22 12:13:42 EDT
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
Comment 7 Olivier Thomann CLA 2002-10-22 16:10:27 EDT
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.
Comment 8 Olivier Thomann CLA 2002-10-22 16:30:42 EDT
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.
Comment 9 Philipe Mulet CLA 2002-10-22 17:25:42 EDT
Olivier - do you suggest we should ignore unicode linebreaks inside comments ?
Comment 10 Philipe Mulet CLA 2002-10-23 04:24:52 EDT
Actually, shouldn't it rather not count unicode linebreaks at all ?
Comment 11 Olivier Thomann CLA 2002-10-23 09:58:04 EDT
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.
Comment 12 Olivier Thomann CLA 2002-10-23 10:55:10 EDT
Change milestone.
Comment 13 Olivier Thomann CLA 2002-10-23 11:07:35 EDT
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.
Comment 14 Olivier Thomann CLA 2002-10-23 15:29:28 EDT
Fixed and released in 2.1 stream.
Regression test added.
Comment 15 David Audel CLA 2002-11-13 06:27:31 EST
Verified.