Bug 80916 - In some cases the structure model doesn't contain the "matches declare" relationship
Summary: In some cases the structure model doesn't contain the "matches declare" relat...
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Andrew Clement CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-12-14 06:01 EST by Helen Beeken CLA
Modified: 2005-01-05 06:01 EST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Helen Beeken CLA 2004-12-14 06:01:38 EST
With a project containing one class and one aspect:

public class HelloClass {

	public static void main(String[] args) {
		new HelloClass().sayHello();
	}
	
	public void sayHello() {
		System.out.println("Hello");
	}
	
}


public aspect A1 {

	pointcut test() : get(* System.out);
	
	declare warning : test() && !within(A1)
		 : "test warning";
	
	pointcut anotherTest() : 
		execution(void HelloClass.sayHello(..));
	
	after() returning : anotherTest() {
		System.out.println("returning....");
	}
		
}

The following is returned from the structure model:

asmRelMap entry: HelloClass.sayHello(), relationship: advised by, target: 
A1.afterReturning(): anotherTest..
asmRelMap entry: A1.afterReturning(): anotherTest.., relationship: uses 
pointcut, target: A1.anotherTest()
asmRelMap entry: A1.afterReturning(): anotherTest.., relationship: advises, 
target: HelloClass.sayHello()
asmRelMap entry: HelloClass.sayHello(), relationship: advised by, target: 
A1.afterReturning(): anotherTest..
asmRelMap entry: A1.anotherTest(), relationship: pointcut used by, target: 
A1.afterReturning(): anotherTest..
asmRelMap entry: A1.declare warning: "test warning", relationship: matched by, 
target: HelloClass.sayHello()

In other words, the model is saying that there are two entries the same:

asmRelMap entry: HelloClass.sayHello(), relationship: advised by, target: 
A1.afterReturning(): anotherTest..

whereas one of these should be the "matches declare" relationship relating to 
the declare warning.

Changing the aspect to be:


public aspect A1 {

	pointcut test() : get(* System.out);
	
	declare warning : test() && !within(A1)
		 : "test warning";
	
	pointcut anotherTest() : 
		execution(void HelloClass.sayHello(..));
	
	after() returning : anotherTest() {
		System.out.println("returning....");
	}
	
	after() returning : test() {
		System.out.println("returning again!");
	}
	
}

means that the IRelationshipMap does now contain the "matches declare" 
relationship.

This is all with AspectJ 5 M1.
Comment 1 Mik Kersten CLA 2004-12-14 10:14:17 EST
I'll take a look at fixing this when I do the "concretizes pointcut" additions.
Comment 2 Helen Beeken CLA 2004-12-14 10:22:03 EST
Just as a note, this may have something to do with the changes Andy put in 
recently - he added the capability to get at the offset aswell as the line 
number (we needed this for AJDT). Plus there's the changes which have gone in 
for AspectJ 5. Yesterday we didn't have declare soft in the model, and that 
was fixed - it might be something in the same area.

Thanks, Helen
Comment 3 Andrew Clement CLA 2004-12-17 04:29:34 EST
It could well be related to what I did as I'm not sure how many tests there are
in existence around my changes.  Helen, can you tell me what you call to get
your output: (Matt mentioned some API with annotation in the name the other day
but I can't remember what it was)


asmRelMap entry: HelloClass.sayHello(), relationship: advised by, target: 
A1.afterReturning(): anotherTest..
asmRelMap entry: A1.afterReturning(): anotherTest.., relationship: uses 
pointcut, target: A1.anotherTest()
asmRelMap entry: A1.afterReturning(): anotherTest.., relationship: advises, 
target: HelloClass.sayHello()
asmRelMap entry: HelloClass.sayHello(), relationship: advised by, target: 
A1.afterReturning(): anotherTest..
asmRelMap entry: A1.anotherTest(), relationship: pointcut used by, target: 
A1.afterReturning(): anotherTest..
asmRelMap entry: A1.declare warning: "test warning", relationship: matched by, 
target: HelloClass.sayHello()

I have other ways of looking at the structure model - I'm trying to work out if
the data structure is incorrect inside AJ or just processed incorrectly by the
method you are calling.
Comment 4 Helen Beeken CLA 2004-12-17 05:24:50 EST
The way we get the relationships map is using:

AsmManager.getDefault().getRelationshipMap();

We then iterate through the entries.
Comment 5 Andrew Clement CLA 2004-12-17 06:50:42 EST
This turns out to be a long standing bug.

The structure model relationships data is correct.
The structure model node tree structure is missing a node.

It should look like this:

HelloClass.java  [java source file] 
[C:\temp\ajcSandbox\ajcTest55158.tmp\HelloClass.java|1|0|0]
    import declarations  [import reference]
    HelloClass  [class]  
      main(String[])  [method]
      sayHello()  [method]  
        field-get(java.io.PrintStream java.lang.System.out) 

But the field-get node is missing at the moment.  Without that in there, the
processRelationships code isn't doing what you think it is:

String sourceOfRel = (String) iter.next();
IProgramElement sourcePE = AsmManager.getDefault().getHierarchy()
				.findElementForHandle(sourceOfRel);			
List relationships = asmRelMap.get(sourcePE);

In the case of the matched declare, the first call to iter.next() gets hold of
the handle of the place matching the declare (which is inside the sayHello()
method).  Then it calls findElementForHandle() which returns *the nearest
matching node* - so without the field-get node existing in the node structure,
it gives you back the sayHello() method node - and then asmRelMap.get()
retrieves the relationships for that node.  So twice you will be asking for the
relationships on the sayHello() method and getting back the advised_by information.

The rewritten aspect works because the 2nd piece of advice on the get(*
System.out) method causes the field-get node to be created.

I'm just testing the fix.

You should be careful looking for the IJavaElement for a code node that you get
back as the end of a relationship, like 'field-get(java.io.PrintStream
java.lang.System.out)' - i'm not sure how you are currently handling them.
Comment 6 Mik Kersten CLA 2004-12-17 12:16:59 EST
Looks like you got this one Andy.

This reminds me... we seem to be getting onto the golden path of transitioning 
from the ASM IHierarchy to the JavaModel.  I'll post a note about we might 
make our life easier with that to ajdt-dev.


Comment 7 Andrew Clement CLA 2004-12-20 09:47:28 EST
Fix checked in, waiting on build.
Comment 8 Andrew Clement CLA 2005-01-05 06:01:32 EST
fix available.