Community
Participate
Working Groups
HEAD Have this CU with syntax errors: package xy; public class Try { public static void main(String[] args) { synchronized new Thread() { public void run() { } }.start(); for (int i= 0; i < 10; i++) { System.out.println("batch " + i); for (int j= 0; j < 1000*1000*1000; j++) { new Integer(1); } } } } The ASTParser doesn't really like this: Error Tue Mar 22 18:19:44 CET 2011 Error in JDT Core during AST creation java.lang.ClassCastException: org.eclipse.jdt.core.dom.EnumDeclaration cannot be cast to org.eclipse.jdt.core.dom.TypeDeclaration at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:2430) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:532) at org.eclipse.jdt.core.dom.ASTConverter.buildBodyDeclarations(ASTConverter.java:183) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:2636) at org.eclipse.jdt.core.dom.ASTConverter.convert(ASTConverter.java:1218) at org.eclipse.jdt.core.dom.CompilationUnitResolver.convert(CompilationUnitResolver.java:289) at org.eclipse.jdt.core.dom.ASTParser.internalCreateAST(ASTParser.java:1201) at org.eclipse.jdt.core.dom.ASTParser.createAST(ASTParser.java:801) at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider$1.run(ASTProvider.java:544) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.createAST(ASTProvider.java:537) at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.getAST(ASTProvider.java:480) at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.getAST(ASTProvider.java:470) at org.eclipse.jdt.ui.SharedASTProvider.getAST(SharedASTProvider.java:127) at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$PartListenerGroup.calculateASTandInform(SelectionListenerWithASTManager.java:170) at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$PartListenerGroup$3.run(SelectionListenerWithASTManager.java:155) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
The synchronized leads to an empty enum type that looks like this: synchronized enum $missing$ { $missing$() { super(); } <clinit>() { } } So it blows up. I am investigating.
At this stage, the best we can do is to prevent the exception. The recovery is doing a poor job at getting a tree for the method body in this case. So we can tag some nodes as MALFORMED. The resulting tree is not really usable for refactoring as the only statement recovered in this method body is the synchronized keyword. Everything else is ignored after the syntax error. What AST would you expect in this case ?
Simplified example: public class Try { public static void main(String[] args) { synchronized new Object(); } } (In reply to comment #2) > What AST would you expect in this case ? Ideally one where just the bad keyword is removed or recovered (similar to when I use 'void' or 'synchronizedXXX' instead). If that's too much work, an empty body (MALFORMED Block with no statements) is also fine. Note that synchronized is not the only keyword causing trouble here. public protected private static final strictfp etc. have the same problem.
Ayushman, please try to see if there is a better way to recover from the synchronized modifier alone. If it possible to prevent the CCE, but we should see if there is a better way to recover first.
Created attachment 193087 [details] proposed fix This happens in the recovery because scope trial succeeds for the rule EnumHeaderName ::= Modifiersopt 'enum' Identifier (since 'synchronized', 'private', 'strictfp' etc are all modifiers), which is more permissive than it should be. Yet, there's no other option as well. The attached patch just makes sure that if the recovery, specifically the statements recovery finds a recovered enum declaration, it does not add it as a child to the recovered elements. The normal recovery will still find enums when they're declared in the usual correct manner. Olivier, what do you think about this approach? I'll add test cases if you approve.
I like the approach. I think it would even be better if this rule is not considered at all for the recovery as the suggestion for the syntax error is misleading. I am not sure if this is really doable.
(In reply to comment #6) > I like the approach. I think it would even be better if this rule is not > considered at all for the recovery as the suggestion for the syntax error is > misleading. I am not sure if this is really doable. I did try to think about that, but its not really doable. Recovery has 1:1 mapping to the grammar, and unless we can rewrite the rule EnumHeaderName ::= Modifiersopt 'enum' Identifier to make it more strict and allow only the valid modifiers, we can't achieve any change in the recovery. That, ofcourse, won't be a very clean way. I have not been able to find any explanation though, as to why EnumHeaderName is chosen over ClassHeaderName. Looks like a random choice to me. Anyway, with the above patch all tests.
Created attachment 193140 [details] proposed fix + tests Same patch with tests added.
+1
Released in HEAD for 3.7M7
Verified for 3.7 M7 using build I20110421-1800