Bug 123671 - Method implementations act as they belong to the interface and not the enclosing class
Summary: Method implementations act as they belong to the interface and not the enclos...
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: Docs (show other bugs)
Version: 1.5.0RC2   Edit
Hardware: PC Windows XP
: P5 normal (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-01-12 16:29 EST by Jean-Sébastien Légaré CLA
Modified: 2007-10-23 12:01 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jean-Sébastien Légaré CLA 2006-01-12 16:29:45 EST
I would like to restrict the usage of a particular method annotation only to types that are marked with a specific annotation.

More specifically, I have the method annotations @Read and @Write, and one type annotation called @Access. I want it to be an error when @Read and @Write appear on a method inside a type that is not marked with @Access.

I encounter a problem when the methods marked with @Read or @Write are inside a type marked with @Access, but are declared inside an interface that is not marked with @Access.

Here is an example :

public aspect AccessRestrictedAspect {
	declare error : execution(@Read public * !@Access *.*(..)) :
	"Cannot have public @Read methods inside non @AccessClassified types."
}

public Interface TestInterface {
  public String getName();
}

@Access
public class Test1 {
   @Read
   public String getName() { return null; }     <--- ok
}

public class Test2 {
   @Read
   public String getName() { return null; }     <--- gives an error, and should
}

@Access
public class Test2 implements TestInterface { //Note the "implements"
   @Read
   public String getName() { return null; }     <-- gives an error,but shouldn't
}
Comment 1 Wes Isberg CLA 2006-02-17 14:07:31 EST
You might try

  declare error : !within(@Access *) && execution(@Read public * *(..)) 
    : "no read outside @Access types";

That works for your code below, and I think tracks your meaning better.  It does permit non-anonymous nested classes the privileges accorded to @Access types - not sure if that's what you meant.

Your code does look like a bug, but it's not a simple issue.

I suspect there are a number of semantics issues with annotations not being inherited and method signatures, and ambiguous or inherited method signatures (here from both TestInterface and Test2-3).  AspectJ matches execution against all the relevant method signatures (e.g., including supertype), but it's not clear to me that it should match the union of signatures or should match all signatures.  For example, if it looks like TestInterface.getName() matches but does not have @Access (on TestInterface), should it look to the Test3.getName() signature which does match?  If this is a negation (i.e., look for *executions* which don't match), then should a *signature* that doesn't match cause the error?  I don't think so, but then ....  So clearly I haven't thought this through enough to help.  

Anyway, I hope using within(..) works for you while we sort out this bug and any semantics issues.

Some working code:
-------------------------------
package stuff;

@interface Read {
}

@interface Write {
}

@interface Access {
}

class AccessRestrictedAspect {
     static aspect A {
         declare error : !within(@Access *) 
            && execution(@Read public * *(..)) 
            : "no read outside access";
      }

    public interface TestInterface {
        @Read public String getName();
    }

    @Access
    public class Test1 {
        @Read
        public String getName() {
            return null;
        } // <--- ok
        class T {
            @Read
            public String getName() {
                return null;
            } // <--- ok
            
        }
    }

    public class Test2 {
        @Read
        public String getName() {
            return null;
        } // <--- gives an error, and should
    }

    @Access
    public class Test3 implements TestInterface { // Note the "implements"
        @Read
        public String getName() {
            return null;
        } // no error - no bug here
    }
}
Comment 2 Wes Isberg CLA 2006-05-10 11:35:59 EDT
No response, so I presume my response was acceptable.  There are still semantics issues here to resolve or document, so I'm making this a doc bug.