Bug 246393 - [plan] Cascading errors
Summary: [plan] Cascading errors
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: DEVELOPMENT   Edit
Hardware: All All
: P2 critical (vote)
Target Milestone: 1.6.4   Edit
Assignee: AJDT-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 263060
  Show dependency tree
 
Reported: 2008-09-05 11:35 EDT by Andrew Eisenberg CLA
Modified: 2009-01-30 11:42 EST (History)
1 user (show)

See Also:


Attachments
aspectj screensho (329.54 KB, application/octet-stream)
2008-09-05 11:43 EDT, Andrew Eisenberg CLA
no flags Details
Same file with same error, but now when project has a Java nature\ (320.23 KB, application/octet-stream)
2008-09-05 11:45 EDT, Andrew Eisenberg CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Eisenberg CLA 2008-09-05 11:35:06 EDT
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
Comment 1 Andrew Eisenberg CLA 2008-09-05 11:43:58 EDT
Created attachment 111833 [details]
aspectj screensho
Comment 2 Andrew Eisenberg CLA 2008-09-05 11:45:19 EDT
Created attachment 111834 [details]
Same file with same error, but now when project has a Java nature\
Comment 3 Andrew Clement CLA 2008-09-05 12:12:51 EDT
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?)
Comment 4 Andrew Eisenberg CLA 2008-09-05 13:28:41 EDT
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.
Comment 5 Andrew Clement CLA 2008-12-22 19:57:56 EST
believed to be AJ
Comment 6 Andrew Clement CLA 2009-01-06 19:09:36 EST
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.
Comment 7 Andrew Clement CLA 2009-01-20 20:36:10 EST
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()).
Comment 8 Andrew Clement CLA 2009-01-23 12:48:31 EST
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...
Comment 9 Andrew Clement CLA 2009-01-25 01:18:32 EST
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.
Comment 10 Andrew Clement CLA 2009-01-25 01:26:42 EST
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();
Comment 11 Andrew Clement CLA 2009-01-26 16:39:41 EST
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.
Comment 12 Andrew Clement CLA 2009-01-26 18:05:59 EST
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
Comment 13 Andrew Eisenberg CLA 2009-01-26 20:00:52 EST
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.
Comment 14 Andrew Clement CLA 2009-01-26 21:44:19 EST
new compiler committed into AspectJ HEAD, phew.
Comment 15 Andrew Eisenberg CLA 2009-01-27 00:39:09 EST
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.
Comment 16 Andrew Clement CLA 2009-01-27 11:54:51 EST
dont close it like that!  I did a bunch of work under it that I want to mark as done for 1.6.4.
Comment 17 Andrew Clement CLA 2009-01-27 12:24:37 EST
still some stuff to investigate on the AJDT side I think
Comment 18 Andrew Eisenberg CLA 2009-01-27 17:39:54 EST
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.
Comment 19 Andrew Eisenberg CLA 2009-01-27 18:03:09 EST
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.
Comment 20 Andrew Eisenberg CLA 2009-01-27 20:01:07 EST
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.
Comment 21 Andrew Eisenberg CLA 2009-01-28 01:00:27 EST
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.
Comment 22 Andrew Eisenberg CLA 2009-01-28 12:50:31 EST
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;
	}
}
Comment 23 Andrew Clement CLA 2009-01-30 02:07:38 EST
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
Comment 24 Andrew Eisenberg CLA 2009-01-30 11:17:06 EST
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.
Comment 25 Andrew Clement CLA 2009-01-30 11:42:26 EST
proposed fixes for 1.6.4 all in HEAD.