Bug 168761

Summary: Scanner uses excessive exceptions for control flow
Product: [Eclipse Project] JDT Reporter: David Biesack <David.Biesack>
Component: CoreAssignee: Olivier Thomann <Olivier_Thomann>
Status: VERIFIED DUPLICATE QA Contact:
Severity: normal    
Priority: P3 CC: daniel_megert, philippe_mulet
Version: 3.2.1   
Target Milestone: 3.3 M5   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description David Biesack CLA 2006-12-20 14:39:46 EST
Build ID: M20060921-0945

Steps To Reproduce:

1. Create a PDE project
2. Set an exception breakpoint on ArrayIndexOutOfBoundsException
3. Launch the plugin it in Debug mode
4. In the debug session workspace, open a Java project and open a Java source file
5. Modify/save the source, causing the JDT compiler to run.

The compiler halts in org.eclipse.jdt.internal.compiler.parser.Scanner. 

This same breakpoint is hit many times. The exception occurs over 24 times per keystroke or file save. It appears to occur less often in 3.3M4.


More information:
This makes it difficult to track down ArrayIndexOutOfBoundsException when developing a plugin,
because the scanner throws it so often. (I cannot filter on the exception being thrown in org.eclipse.jdt.internal.compiler.parser.Scanner because that package/class is not available when I try to add an exclusion filter to the exception breakpoint.)

Scanner.java does:

			do {
				unicodePtr = this.withoutUnicodePtr;
				offset = this.currentPosition;
				this.startPosition = this.currentPosition;
				try {
					checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
						&& (this.source[this.currentPosition] == 'u');
				} catch(IndexOutOfBoundsException e) {
					if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
						// reposition scanner in case we are interested by spaces as tokens
						this.currentPosition--;
						this.startPosition = whiteStart;
						return TokenNameWHITESPACE;
					}
					if (this.currentPosition > this.eofPosition)
						return TokenNameEOF;
				}
				if (this.currentPosition > this.eofPosition)
					return TokenNameEOF;


Before testing for a "\u" sequence or incrementing this.currentPosition, it should test bounds with:

  if (this.currentPosition > this.eofPosition)
    return TokenNameEOF;

After seeing a '\\', it should set currentCharacter but
also test that (currentPosition+1) < eofPosition again before autoincrementing currentPosition, to avoid the exception.

Here is a traceback

Thread [org.eclipse.jdt.internal.ui.text.JavaReconciler] (Suspended (exception ArrayIndexOutOfBoundsException))	
	CommentRecorderScanner(Scanner).getNextToken() line: 857	
	SourceElementParser(Parser).parse() line: 8801	
	SourceElementParser(Parser).parse(ICompilationUnit, CompilationResult, int, int) line: 9062	
	SourceElementParser(Parser).parse(ICompilationUnit, CompilationResult) line: 9019	
	SourceElementParser.parseCompilationUnit(ICompilationUnit, boolean) line: 1518	
	CompilationUnit.buildStructure(OpenableElementInfo, IProgressMonitor, Map, IResource) line: 134	
	CompilationUnit(Openable).generateInfos(Object, HashMap, IProgressMonitor) line: 229	
	CompilationUnit(JavaElement).openWhenClosed(Object, IProgressMonitor) line: 505	
	CompilationUnit.makeConsistent(int, boolean, boolean, HashMap, IProgressMonitor) line: 992	
	ReconcileWorkingCopyOperation.makeConsistent(CompilationUnit, IProblemRequestor) line: 132	
	ReconcileWorkingCopyOperation.executeOperation() line: 72	
	ReconcileWorkingCopyOperation(JavaModelOperation).run(IProgressMonitor) line: 720	
	ReconcileWorkingCopyOperation(JavaModelOperation).runOperation(IProgressMonitor) line: 779	
	CompilationUnit.reconcile(int, boolean, boolean, WorkingCopyOwner, IProgressMonitor) line: 1122	
	JavaReconcilingStrategy$1.run() line: 97	
	SafeRunner.run(ISafeRunnable) line: 37	
	JavaReconcilingStrategy.reconcile(boolean) line: 82	
	JavaReconcilingStrategy.reconcile(IRegion) line: 145	
	JavaCompositeReconcilingStrategy(CompositeReconcilingStrategy).reconcile(IRegion) line: 86	
	JavaCompositeReconcilingStrategy.reconcile(IRegion) line: 94	
	JavaReconciler(MonoReconciler).process(DirtyRegion) line: 75	
	JavaReconciler.process(DirtyRegion) line: 342	
	AbstractReconciler$BackgroundThread.run() line: 204
Comment 1 Philipe Mulet CLA 2006-12-21 04:14:33 EST
Olivier - did you backport the related change in scanner for 3.2 maintenance ? Is there still an issue in our layer ? My recollection is that all problems were due to some specific usecase where some clients were scanning a small range of source (exactly one token source range).
Comment 2 Olivier Thomann CLA 2006-12-22 15:27:21 EST
Fix for bug 161400 has not been backported to 3.2 maintenance stream.
This would also require fix for bug 163349 to be backported.
Closing as duplicate of bug 161400.
Philippe,
Let me know if you want this to be backported.

*** This bug has been marked as a duplicate of bug 161400 ***
Comment 3 Eric Jodet CLA 2007-02-05 12:30:21 EST
verified using build I20070201-0800
Comment 4 David Biesack CLA 2007-02-05 14:49:14 EST
I also ran I20070201-0800 and I still find several AIOOBE (typically, about 4) per character typed, or when saving a source file. It is much better than before, but still makes it extremely difficult to debug a plugin because it is simply not workable to set an exception breakpoint on AIOOBE - that makes it hard to track down these exceptions in plugins.

Ideally, I'd like to see the patch remove all occurrences of the exception.
Comment 5 Eric Jodet CLA 2007-02-06 00:52:35 EST
Verified for 3.3 M5 using build I20070205-0009