Community
Participate
Working Groups
From bug 142473 - someone found these exceptions in their log. !ENTRY org.eclipse.jdt.ui 4 2 2006-05-23 11:07:11.376 !MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.jdt.ui". !STACK 0 java.lang.IllegalArgumentException at org.eclipse.jdt.core.dom.ASTNode.setSourceRange(ASTNode.java:2599) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:891) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:2353) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:511) at org.eclipse.jdt.core.dom.ASTConverter.buildBodyDeclarations(ASTConverter.java:179) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:2637) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:1236) at org.eclipse.jdt.core.dom.AST.convertCompilationUnit(AST.java:270) at org.eclipse.jdt.internal.core.CompilationUnit.buildStructure(CompilationUnit.java:187) at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:229) at org.eclipse.jdt.internal.core.JavaElement.openWhenClosed(JavaElement.java:505) at org.eclipse.jdt.internal.core.CompilationUnit.makeConsistent(CompilationUnit.java:993) at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.makeConsistent(ReconcileWorkingCopyOperation.java:131) at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.executeOperation(ReconcileWorkingCopyOperation.java:71) at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:720) at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:779) at org.eclipse.jdt.internal.core.CompilationUnit.reconcile(CompilationUnit.java:1123) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy$1.run(JavaReconcilingStrategy.java:97) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:82) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:145) at org.eclipse.jdt.internal.ui.text.CompositeReconcilingStrategy.reconcile(CompositeReconcilingStrategy.java:86) at org.eclipse.jdt.internal.ui.text.JavaCompositeReconcilingStrategy.reconcile(JavaCompositeReconcilingStrategy.java:94) at org.eclipse.jface.text.reconciler.MonoReconciler.process(MonoReconciler.java:75) at org.eclipse.jdt.internal.ui.text.JavaReconciler.process(JavaReconciler.java:342) at org.eclipse.jface.text.reconciler.AbstractReconciler$BackgroundThread.run(AbstractReconciler.java:204) !ENTRY org.eclipse.jdt.ui 4 0 2006-05-23 11:07:11.376 !MESSAGE Error in JDT Core during reconcile !STACK 0 java.lang.IllegalArgumentException at org.eclipse.jdt.core.dom.ASTNode.setSourceRange(ASTNode.java:2599) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:891) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:2353) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:511) at org.eclipse.jdt.core.dom.ASTConverter.buildBodyDeclarations(ASTConverter.java:179) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:2637) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:1236) at org.eclipse.jdt.core.dom.AST.convertCompilationUnit(AST.java:270) at org.eclipse.jdt.internal.core.CompilationUnit.buildStructure(CompilationUnit.java:187) at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:229) at org.eclipse.jdt.internal.core.JavaElement.openWhenClosed(JavaElement.java:505) at org.eclipse.jdt.internal.core.CompilationUnit.makeConsistent(CompilationUnit.java:993) at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.makeConsistent(ReconcileWorkingCopyOperation.java:131) at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.executeOperation(ReconcileWorkingCopyOperation.java:71) at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:720) at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:779) at org.eclipse.jdt.internal.core.CompilationUnit.reconcile(CompilationUnit.java:1123) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy$1.run(JavaReconcilingStrategy.java:97) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:82) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:145) at org.eclipse.jdt.internal.ui.text.CompositeReconcilingStrategy.reconcile(CompositeReconcilingStrategy.java:86) at org.eclipse.jdt.internal.ui.text.JavaCompositeReconcilingStrategy.reconcile(JavaCompositeReconcilingStrategy.java:94) at org.eclipse.jface.text.reconciler.MonoReconciler.process(MonoReconciler.java:75) at org.eclipse.jdt.internal.ui.text.JavaReconciler.process(JavaReconciler.java:342) at org.eclipse.jface.text.reconciler.AbstractReconciler$BackgroundThread.run(AbstractReconciler.java:204)
Misja, Would it be possible to get a test case? Is the code syntactically correct when the error occurs?
I found a test case to reproduce the same exception public class X { void bar() { # assert 0 == 1 : a[0; // ] is missing } } But these following test cases don't cause the exception public class X { void bar() { # assert 0 == 1 : a[0]; } } public class X { void bar() { # assert 0 == 1 : a[0 ; // ] is missing and there is space after '0' } }
The problem is inside statements recovery. With 'assert 0 == 1 : a[0;' statement recovery add a fake token ']' just after '0'. The position of this fake token is the position of the end of the previous real token + 1. It is also the location of the real token ';'. When the ASTConverter convert the assert statement, it try to retreive the location of the ';' by starting just after the end of the expression. In this case it is also just after the ';', that's why the ';' isn't found and the end of the assert statement is wrongly considered as -1. Instead of set the position of the fake token just after the end of the previous real token there, in some case like this one we could set the position of the fake token at the same location of the end of the previous real token. Indeed the ']' belongs to the expression and not to the next or enclosing node. However do such change for 3.2 would be to risky because this could change slightly the general behavior of the statement recovery and add some new unknown instabilities. Thats why if we don't want to throw the exception in 3.2 it would be better to only add a workaround in the ASTConverter. I am going to write a patch with a workaround. I will attach it to this bug when it will be ready.
The same bug occurs with the following test case but our internal behavior is not exactly the same. public class X { void bar() { # assert 0 == 1 : foo(; // ) is missing } } The end of the ast node 'foo(' is the 'currentPosition-1' of the fake token ). The end of the ast node 'a[0' is the 'startPosition' of the fake token ]. Inserted fake tokens 'currentPosition' and 'startPosition' are equals.
Another test case with some differences public class X { void bar() { # assert 0 == 1 : ("aa"; // ) is missing } }
Created attachment 42377 [details] Proposed fix
Created attachment 42378 [details] Regression test
This fix is not only a workaround. The exception can occurs for two reasons: 1) The end position of the last expression of the assert statement contains the ';'.This end position is used to start the search of the ending semicolon so the semicolon is never found. eg: 'assert 0 == 0 : a[0;' 2) The last token of the last expression of the assert statement ends with a fake ) or ] or }. As semicolon is take into account only if the parenthesis count is 0, then the semicolon is never found. eg: 'assert 0 == 0 : foo(;' The case 2) is fixed by the proposed patch. This patch remove the parenthesis count and use the end of the last DOM expression node instead of the end of the last compiler expression node. That's because the DOM position are corrected and are always correct so we don't need to count parenthesis. The case 1) would require to change the end position of the last expresion as explain in comment 3. This change would be to risky, and the patch add a workaround instead. The workaround is to use directly the end of the last expression when we fail to retreive the semicolon location.
Olivier - the proposed patch isn't exactly the patch you send me. In the proposed fix 'retrieveSemiColonPosition()' initialize the scanner to 'int end = start + length' as it is in the current code instead of 'int end = start + length - 1'. If we do not use this location the start position if the sanner is inside the string literal with the following test case: assert 0 == 1 : ("aa";.
This problem isn't highly critical as it concerns only assert statements. Therefore it's probably too late to add this fix for 3.2 but this is a good candidate for 3.2.1.
Inlike i thought the problem with array access isn't a problem of recovery. The problem is caused by a bug in the Parser (see bug 147877). The diagnosis of case 2) is still correct.
Fix released and tests added ASTConverterRecoveryTest#test0015() -> test0017() Released for 3.3 M1.
Verified for 3.3 M1 using build I20060804-0010.