Community
Participate
Working Groups
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.
I'll take a look at fixing this when I do the "concretizes pointcut" additions.
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
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.
The way we get the relationships map is using: AsmManager.getDefault().getRelationshipMap(); We then iterate through the entries.
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.
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.
Fix checked in, waiting on build.
fix available.