Bug 76374

Summary: Problem with declare parents when using non-public classes
Product: [Tools] AspectJ Reporter: Keven Ring <keven>
Component: CompilerAssignee: Adrian Colyer <adrian.colyer>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3    
Version: 1.2   
Target Milestone: 1.5.0 M4   
Hardware: All   
OS: All   
Whiteboard:

Description Keven Ring CLA 2004-10-15 13:23:09 EDT
Non-public classes, when explicitly named, do not get woven.

The test case below exhibits this problem when the package declaration is
uncommented.

If the package declaration is commented out, the class is woven correctly.
If the package declaration is uncommented, a compilation failure occurs with
AspectJ 1.2.  According to Andrew Clement, AspectJ 1.2.1 compiles, but does not
weave.
If the "MyInnerClass" is changed to be public [regardless of the package
declaration status], the class is woven correctly.

Also:
When the "MyInnerClass" is moved out of "MyClass", but kept in the MyClass.java
file, then the following behavior is exhibited:
If the package declaration is commented out, the class is woven correctly.
If the package declaration is uncommented out, a compilation failure occurs with
AspectJ 1.2.
Note, in this case, MyInnerClass cannot be declared as public.

It also appears that if the RunnableAspect is placed in the same package as
"MyClass", weaving occurs correctly, regardless of any class access modifiers

<MyClass.java>

// package mypackage;

public class MyClass {
 public MyClass() {
   MyInnerClass mic = new MyInnerClass();
   if (mic instanceof Runnable)
     mic.run();
 }

 class MyInnerClass {
   public void run() {
     System.out.println("In MyInnerClass.run()!!");
   }
 }

 public static void main(String args[]) {
   new MyClass();
 }
}

</MyClass.java>

<RunnableAspect.aj>

public aspect RunnableAspect {
 declare parents: MyClass$MyInnerClass implements Runnable;
 // declare parents: mypackage.MyClass$MyInnerClass implements Runnable;
}

</RunnableAspect.aj>
Comment 1 Andrew Clement CLA 2004-10-21 12:47:03 EDT
There is a bug here, but its not what I expected it to be.

When referring to inner classes in type patterns like this, you should use the
'.' notation rather than the $ notation.  So to refer to MyInnerClass, either:

// this works if you import mypackage.*
declare parents: MyClass.MyInnerClass implements Runnable;

// this just works
//declare parents: mypackage.MyClass.MyInnerClass implements Runnable;


What actually causes the confusion is that this works:

declare parents: MyClass$MyInnerClass implements Runnable;

when MyClass is not in a package.  It makes you think that:

declare parents: mypackage.MyClass$MyInnerClass implements Runnable;

should work when you put MyClass into a package.

Actually 'MyClass$MyInnerClass' doesn't refer to an inner class, it refers to a
class called 'MyClass$MyInnerClass' as $ is valid in a class name.  So the bug
is that we should have put out an error indicating no type match for:

declare parents: MyClass$MyInnerClass implements Runnable;

which would have led you to try MyClass.MyInnerClass which is correct.
Comment 2 Adrian Colyer CLA 2005-03-23 08:50:40 EST
scheduled for aj5m4
Comment 3 Adrian Colyer CLA 2005-09-21 12:50:48 EDT
Correctly produces xlint message "no type match for: blah blah" with the latest
compiler builds.