Community
Participate
Working Groups
I've noticed for a long time that in AJDT that when there is a missing paren or bracket, many spurious errors appear throughout the editor. I am attaching two screenshots. The first is a missing paren when the project is an AspectJ project. And the second is the same error in the same project when it is a Java project. This is most likely a compiler and a factor of how the compiler parses syntactically incorrect files. Perhaps this should be filed under AspectJ
Created attachment 111833 [details] aspectj screensho
Created attachment 111834 [details] Same file with same error, but now when project has a Java nature\
I can believe it is an AspectJ problem. Parser recovery is done in two ways: extra grammar rules and hand crafted recovery. We are not so careful about correctly adding our changes into the reocovery grammar rules and have no hand crafted recovery logic of our own. Also remember that AspectJ1.6 is currently Eclipse 3.3.1 compiler based and so comparing (in eclipse 3.4) the parser recovery may be revealing something that is different in eclipse 3.4 JDT compiler that we haven't picked up yet. (Did you mean to raise this against AJDT 1.6.1?)
Meant to raise this against the most recent version of AJDT. I don't expect this is easy to fix, but just wanted to point it out and have a record of it.
believed to be AJ
my few mins spent trying to recreate this with a piece of simple code have failed - so i won't progress it for now. I've also tried the other situation of using 'try { {' but can't get anything unreasonable to occur. Note that getting it to behave identically to the java editor is a nice goal but for now I'll only be looking to fix unreasonable cascading errors. I consider the 3 in that screenshot to be unreasonable so would like to address them.
Seem to have a case here of rogue errors: --- import java.io.*; package snippet; public class AspectSampleMain { public static void main(String[] args)throws Exception { String test = "hello world askdjlasdkjaldkjasldkjalsdkjaslkdjalskjdslakjd dsjalkjd"; ByteArrayInputStream bais = new ByteArrayInputStream(test.getBytes("UTF-8")); InputStream is = bais; bar(is); } public static void bar(InputStream is) { String l = readContent(is); System.out.println(l); // l is blank this is wrong because is has been read. } public static String readContent(InputStream is) { try { byte[] bs = new byte[8192]; int amount = is.read(bs); return new String(bs,0,amount,"UTF-8"); } catch (IOException ioe) { ioe.printStackTrace(); return null; } } } aspect AspectSample { pointcut sample(java.io.InputStream is): execution(* AspectSampleMain.bar( .. )) && args(is); void around (java.io.InputStream is): sample(is) { String l = AspectSampleMain. readContent(is); ByteArrayInputStream bais = new ByteArrayInputStream(l.getBytes()); System.out.println(l); proceed(bais); } } --- the package statement is on the wrong line, but it also shows an error on line 24 (ioe.printStackTrace()).
I have converted a plain old java project to AJ, just to explore this problem as I just develop code. (no aspects in site). Probably the most awful thing is that the errors can cascade up the file, not always down - so you can't always fix it by addressing the first error in the file. Presumably this is because of recovery jumping too far back in the file. I will try and hone down a small testcase for this because diagnosing it and fixing it will be a complete nightmare. Could be the grammar, could be the recovery logic in the parser...
Interesting scenario, simple program: --- public class C { public static void main(String[] args) { if (true) { if (false) { } } public void m() { System.out.println(">"); } } --- It is broken. If the file is compiled in either a Java or AJ project, the problems view shows the same two errors: Syntax error, insert "}" to complete Statement Syntax error, insert "else Statement" to complete BlockStatements However - the editor shows different contents depending on whether it is a java or aj project ! Open the file whilst it is in a java project. There is one compiler error marker in the gutter on line 7. Convert it to an AJ project and now 3 error markers appear (7, 10, 13). Given that the contents of the problem view stay constant - it looks like it *might* be an AJDT problem is this case.
Reworking what is in comment 7, I'm down to this: --- import java.io.*; package snippet; public class D { public static String readContent(InputStream is) { try { } catch (IOException ioe) { ioe.printStackTrace(); } } } --- with a rogue error reported on ioe.printStackTrace() by ajc: F:\temp\D.java:2 [error] Syntax error on token "package", import expected package snippet; ^^^^^^ F:\temp\D.java:8 [error] Syntax error on tokens, valid member declaration expected instead ioe.printStackTrace();
With removal of a rogue recovery rule in the grammar, case in comment 10 is fixed. But we have now affected this program: public class pr78314 { pr78314 a1 = new pr78314(); pr78314 a2 = new pr78314(); a1.foo(); } It used to say this: F:\aspectj164-dev\pr78314.aj:6 [error] Syntax error, insert "body" to complete declaration a1.foo(); F:\aspectj164-dev\pr78314.aj:6 [error] Syntax error on tokens, valid member declaration expected instead a1.foo(); F:\aspectj164-dev\pr78314.aj:6 [error] Syntax error on tokens, valid member declaration expected instead a1.foo(); --- Now it says: Syntax error on token "foo", privileged expected after this token I don't like the inclusion of privileged in that message. javac says: pr78314.java:6: <identifier> expected a1.foo(); ^ The problem here is that we want it to say 'Identifier expected' rather than 'privileged expected' - but the DiagnoseParser recovery code is processing a list of symbols and all the AspectJ symbols and 'Identifier' score the same (in terms of whether they could be a candidate resolution to the problem). Because they all score the same, only the first one is used - and that is privileged. damn this is tough stuff.
ok, I've addressed that. So I have reworked the grammar, regenerated the parser, rebuilt the compiler, rebuilt an AspectJ distribution and put that into my AJDT... My rogue errors are now gone and as far as I can see, the problems view is just showing correct errors. However, the editor is showing all sorts of wierd problems that aren't really there... Here is an example program: --- import java.io.*; package snippet; import java.io.IOException; public class AspectSampleMain { public static void bar(InputStream is) { } public static String readContent(InputStream is) { try { try { try { } // byte[] bs = new byte[8192]; // int amount = is.read(bs); // return new String(bs,0,amount,"UTF-8"); } catch (IOException ioe) { ioe.printStackTrace(); // return null; } } } --- see the errors against the readContent() declaration. of course you can't see them until i put this into an AJDT, hmmmmm
What I am noticing on the AJDT side is that reconciling can happen through either of two paths: 1. when building structure (ie- the IJavaElement hierarchy) 2. when making consistent (ie- computing text deltas and creating an ast) The first version does not show the spurious errors of c9. The second version *does* show the errors. Not sure exactly why, though. They are using different parsers (AJSourceElementParser for #1 and CommentRecorderParser for #2), but seem to be otherwise the same. It is surprising to me that the AJSourceElementParser is working, but the other is not, since we wrote the former and it is a sub-class of the latter. Is there something about this configuration and options of these parsers that are making the difference? I'll have to check.
new compiler committed into AspectJ HEAD, phew.
Hmmmmm....seems like the problem might be stemming from a little bit that I put in to ensure that all inner classes are parsed. I explicitly set the parseThreshold to a high number (10) so that up to 10 working copy compilation units are parsed before going to a diet parse. If a unit is not parsed, then ITDs cannot be inserted into them. On the other hand, for some reason, changing this from 10 back to 0 introduces these wierd spurious problems on occasion. I don't know why.
dont close it like that! I did a bunch of work under it that I want to mark as done for 1.6.4.
still some stuff to investigate on the AJDT side I think
Here's what's happening: When there is a diet parse, fewer errors are reported because the entire file is not visited. This is the default way of finding problems on a reconcile (it is different when finding problems while doing structure building). Reconciling that inserts ITDs, however, requires a full parse in order to find all inner types. This is because diet parsing will not necessarily create the inner types. Diet parsing requires fewer resources than full parsing, so it would be nice to be able to find a way to create all inner types while doing the diet parse.
So, it *seems* like if I use a SourceElementParser parser with a dummy SourceElementRequestor, I can set a flag that says reportLocalDeclarations. I believe that even for diet parses, this will calculate inner classes (so it will be a kind of semi-diet parse). I'll try it out and see if it works.
Hmmmm...I can't get my tests to pass unless I do a full parse. The diet parse or any of its variants is not cutting it. At least now, I can be more explicit that I am forcing the full parse.
I found that I was swallowing an exception in the around advice that calls the reconciling for the Java code. After swallowing the exception, I was calling the standard JDT reconciler. This exception was an OperationCancelledException. Rather than swallowing it, I should have been rethrowing it, which is what I am doing now. I am now seeing much better behavior from the reconciler. It seems that the exception is being raised during a reconcile operation so that it can be pre-empted by another reconcile operation. When this operation cancelling is allowed to proceed normally (rather than being swallowed by the aspect), it seems that the results of the final reconciling do not show spurious errors. This is good news, and it means that diet parsing is not an issue that I need to worry about at this point. However, I don't fully understand why I am seeing better behavior, which doesn't lead me to be very confident that it will work in all real situations.
Here is a situation that is broken. After a save, the initial reconcile action creates 3 spurious errors on the declaration of x(). These are AJDT editor errors, not compilation errors. Then, after making a whitespace change to the file, the spurious errors go away. This is because two different kinds of reconciling are being triggered. The first one is to makeConsistent and the second one is to buildStructure. public class C2 { public static void main(String[] args) { int x = 7; if (true) { } else x--; } } private static Object x(Object project, boolean b) { return null; } }
Andrew - do you want a different bug against AJDT to track the work done there? I'm finished with the AspectJ side for now and would like to close this to mark what has been done for 1.6.4
just fixed and committed the changes for this bug in AJDT. You can close this bug I will open a new AJDT bug to track this.
proposed fixes for 1.6.4 all in HEAD.