]> source.dussan.org Git - aspectj.git/commitdiff
Added "uses pointcut" relation to the ASM.
authormkersten <mkersten>
Thu, 14 Oct 2004 21:45:07 +0000 (21:45 +0000)
committermkersten <mkersten>
Thu, 14 Oct 2004 21:45:07 +0000 (21:45 +0000)
ajde/testdata/examples/coverage/ModelCoverage.java
ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java
asm/src/org/aspectj/asm/IRelationship.java
asm/src/org/aspectj/asm/internal/ProgramElement.java
asm/src/org/aspectj/asm/overview.html
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java

index bbab87a2f938851522d39c50c868ba80e4a07e38..a853ec83d0938b9c95af5f08ae4c1d4f1c0df20b 100644 (file)
@@ -142,6 +142,19 @@ abstract class ModifiersCoverage {
        abstract void abstractM();
 }
 
+aspect Pointcuts {
+    pointcut a(): call(Point.new(..));   
+}
+
+aspect PointcutUsage {
+   
+    pointcut usesA(): Pointcuts.a() && within(Point);
+    
+    pointcut usesUsesA(): usesA();
+    
+    after(): usesUsesA() { }
+}
+
 
 
 
index 64b36527681101dea647a488f3a5b41b072a2d61..f693571a57654e9b2ccf9b5568319a26974df73c 100644 (file)
@@ -18,7 +18,9 @@ import org.aspectj.asm.AsmManager;
 import org.aspectj.asm.IProgramElement;
 import org.aspectj.asm.IRelationship;
 
-// TODO: check for return types
+/**
+ * @author Mik Kersten
+ */
 public class AsmRelationshipsTest extends AjdeTestCase {
   
        private AsmManager manager = null;
@@ -28,10 +30,31 @@ public class AsmRelationshipsTest extends AjdeTestCase {
                super(name);
        }
 
+       public void testUsesPointcut() {
+           IProgramElement ptUsage = AsmManager.getDefault().getHierarchy().findElementForType(null, "PointcutUsage");
+           assertNotNull(ptUsage);
+           IProgramElement pts = AsmManager.getDefault().getHierarchy().findElementForType(null, "Pointcuts");
+           assertNotNull(pts);
+           
+               IProgramElement pUsesA = manager.getHierarchy().findElementForLabel(
+                       ptUsage, 
+                               IProgramElement.Kind.POINTCUT, 
+                               "usesA()"/*Point"*/);
+               assertNotNull(pUsesA);
+
+               IProgramElement ptsA = manager.getHierarchy().findElementForLabel(
+                       pts, 
+                               IProgramElement.Kind.POINTCUT, 
+                               "a()"/*Point"*/);
+               assertNotNull(ptsA);
+               
+               assertTrue(AsmManager.getDefault().getRelationshipMap().get(pUsesA).size()>0);
+               assertTrue(AsmManager.getDefault().getRelationshipMap().get(ptsA).size()>0);
+       }
+       
        public void testDeclareParents() {              
                IProgramElement aspect = AsmManager.getDefault().getHierarchy().findElementForType(null, "DeclareCoverage");
-//             System.err.println(aspect.getChildren());
-               
+
                IProgramElement dp = manager.getHierarchy().findElementForLabel(
                                aspect, 
                                IProgramElement.Kind.DECLARE_PARENTS, 
index 53b1182620b92c5156a7e9997606768b8fe29c7d..4a33d4fb0175a72cb3d6d78ed805e10b8dc12a6f 100644 (file)
@@ -48,11 +48,12 @@ public interface IRelationship extends Serializable {
                public static final Kind ADVICE                = new Kind("advice");
                public static final Kind DECLARE               = new Kind("declare");
                public static final Kind DECLARE_INTER_TYPE    = new Kind("inter-type declaration");
+               public static final Kind USES_POINTCUT                  = new Kind("uses pointcut");
                
                public static final Kind[] ALL = { 
                        DECLARE_WARNING, DECLARE_ERROR,
                        ADVICE_AROUND,ADVICE_AFTERRETURNING,ADVICE_AFTERTHROWING,ADVICE_AFTER,ADVICE_BEFORE,
-                       ADVICE, DECLARE, DECLARE_INTER_TYPE };
+                       ADVICE, DECLARE, DECLARE_INTER_TYPE, USES_POINTCUT };
                        
                private final String name;
                
index ef4b285070689829b8b484ffad4db96d9af73bad..3965c21d0d44481fb34e5647de36ec907e440de8 100644 (file)
@@ -459,21 +459,25 @@ public class ProgramElement implements IProgramElement {
 
        private String handle = null;
        public String getHandleIdentifier() {
-                   if (null == handle) {
-                               if (sourceLocation != null) {
-                                       StringBuffer sb = new StringBuffer();
-                                       sb.append(AsmManager.getDefault()
-                                                                               .getCanonicalFilePath(sourceLocation.getSourceFile()));
-                                       sb.append(ID_DELIM);
-                                       sb.append(sourceLocation.getLine());
-                                       sb.append(ID_DELIM);
-                                       sb.append(sourceLocation.getColumn());
-                                       handle = sb.toString();
-                               }
-                   }
-                   return handle;
+           if (null == handle) {
+                       if (sourceLocation != null) {
+                           return genHandleIdentifier(sourceLocation);
+                       }
+           }
+           return handle;
        }
 
+       public static String genHandleIdentifier(ISourceLocation sourceLocation) {
+               StringBuffer sb = new StringBuffer();
+               sb.append(AsmManager.getDefault()
+                                                       .getCanonicalFilePath(sourceLocation.getSourceFile()));
+               sb.append(ID_DELIM);
+               sb.append(sourceLocation.getLine());
+               sb.append(ID_DELIM);
+               sb.append(sourceLocation.getColumn());
+               return sb.toString();
+       }
+       
        public List getParameterNames() {
                return parameterNames;
        }
index 6608bd24e336936a2cf5bae7b3c95a69c9ebc9fb..3c5f6141194d7b0795087226caa4981259c12723 100644 (file)
@@ -1,9 +1,16 @@
-<p>The is a placeholder for a document describing the Abstract Structure Model (ASM).
+<p>
 </p>
-<p><b>Notes</b></p>
+<p><b>Notes on using the Abstract Structure Model (ASM)</b></p>
 <ul>
        <li>The ASM contains the declaration hierarchy up to the member signature 
        level of granularity. In the case that an sub-method element is advised 
        (e.g. a call site, field get/set, or exception handler) the advised element 
        will also be present as a child of that member.</li>
+       <li>The structure model is built during the compilation process, after advice planning is done and before bytecodes are produced.  Here are the method calls involved with compiling and getting the model.  The org.aspectj.asm package contains the structure model APIs.
+  Ajde.getDefault().getConfigurationManager().setActiveConfigFile("foo.lst");
+Ajde.getDefault().getBuildManager().build(); Ajde.getDefault().getStructureModelManager().getStructureModel(); 
+<li>
+For examples of how to walk the model take a look at StructureModelTest in the test sources of the org.aspectj.ajde package.
+<li>
+If you're interested in being notified of when the model has been updated (i.e. when the user completed a compile) you can register a new listener with by calling the StructureModelManager.addListener method in the org.aspectj.asm package.  The org.aspectj.ajde package also has an API for creating views of the model, and you can look to the any IDE plug-in to see how they are used.  
 </ul>
index d5bdc99f7747b7467cfafcb821c9f9f71488a7f5..3517931a9c0975c20ce4f4d776fb33eaad2e60e8 100644 (file)
@@ -8,56 +8,49 @@
  *  
  * Contributors: 
  *     PARC     initial implementation 
+ *     Mik Kersten     revisions, added additional relationships 
  * ******************************************************************/
 
-
 package org.aspectj.ajdt.internal.core.builder;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.ListIterator;
-import java.util.Stack;
+import java.util.*;
 
+import org.aspectj.ajdt.internal.compiler.ast.*;
 import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
 import org.aspectj.ajdt.internal.compiler.ast.InterTypeDeclaration;
+import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
 import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
+import org.aspectj.asm.*;
 import org.aspectj.asm.IHierarchy;
 import org.aspectj.asm.IProgramElement;
 import org.aspectj.asm.internal.ProgramElement;
+import org.aspectj.asm.internal.Relationship;
 import org.aspectj.bridge.ISourceLocation;
 import org.aspectj.bridge.SourceLocation;
-import org.aspectj.util.LangUtil;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.ResolvedMember;
 import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Initializer;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.*;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.*;
 import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
+import org.aspectj.util.LangUtil;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.patterns.*;
 
 /**
  * At each iteration of <CODE>processCompilationUnit</CODE> the declarations for a 
  * particular compilation unit are added to the hierarchy passed as a a parameter.
- * 
+ * <p>
  * Clients who extend this class need to ensure that they do not override any of the existing
  * behavior.  If they do, the structure model will not be built properly and tools such as IDE
  * structure views and ajdoc will fail.
+ * <p>
+ * <b>Note:</b> this class is not considered public API and the overridable 
+ * methods are subject to change.
  * 
  * @author Mik Kersten
  */
@@ -312,7 +305,7 @@ public class AsmHierarchyBuilder extends ASTVisitor {
                stack.pop();
        }
        
-       protected String genSourceSignature(TypeDeclaration typeDeclaration) {
+       private String genSourceSignature(TypeDeclaration typeDeclaration) {
                StringBuffer output = new StringBuffer();
                typeDeclaration.printHeader(0, output);
                return output.toString();
@@ -331,7 +324,6 @@ public class AsmHierarchyBuilder extends ASTVisitor {
        
        public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {                   
                IProgramElement peNode = null;
-               
                // For intertype decls, use the modifiers from the original signature, not the generated method
 
                if (methodDeclaration instanceof InterTypeDeclaration) {
@@ -346,7 +338,6 @@ public class AsmHierarchyBuilder extends ASTVisitor {
                                                new ArrayList());  
                
                } else {
-               
                        peNode = new ProgramElement(
                                "",
                                IProgramElement.Kind.ERROR,
@@ -357,7 +348,11 @@ public class AsmHierarchyBuilder extends ASTVisitor {
                }
                formatter.genLabelAndKind(methodDeclaration, peNode);
                genBytecodeInfo(methodDeclaration, peNode);
-
+               List namedPointcuts = genNamedPointcuts(methodDeclaration);
+//             System.err.println(">>>>>>>>>>>>>>>>> " + methodDeclaration.);
+               addUsesPointcutRelationsForNode(peNode, namedPointcuts, methodDeclaration);
+//             System.err.println("> named: " + namedPointcuts);
+               
                if (methodDeclaration.returnType!=null) {
                  peNode.setCorrespondingType(methodDeclaration.returnType.toString());
                } else {
@@ -379,7 +374,77 @@ public class AsmHierarchyBuilder extends ASTVisitor {
                return true;
        }
 
-       private String genSourceSignature(MethodDeclaration methodDeclaration) {
+    private void addUsesPointcutRelationsForNode(IProgramElement peNode, List namedPointcuts, MethodDeclaration declaration) {
+        for (Iterator it = namedPointcuts.iterator(); it.hasNext();) {
+            ReferencePointcut rp = (ReferencePointcut) it.next();
+            ResolvedMember member = getPointcutDeclaration(rp, declaration);
+            if (member != null) {
+                IRelationship foreward = AsmManager.getDefault().getRelationshipMap().get(peNode.getHandleIdentifier(), IRelationship.Kind.USES_POINTCUT, "uses pointcut", false, true);
+                foreward.addTarget(ProgramElement.genHandleIdentifier(member.getSourceLocation()));            
+                
+                IRelationship back = AsmManager.getDefault().getRelationshipMap().get(ProgramElement.genHandleIdentifier(member.getSourceLocation()), IRelationship.Kind.USES_POINTCUT, "pointcut used by", false, true);
+                back.addTarget(peNode.getHandleIdentifier());             
+            } 
+        }        
+    }
+    
+    private ResolvedMember getPointcutDeclaration(ReferencePointcut rp, MethodDeclaration declaration) {
+               World world = ((AjLookupEnvironment)declaration.scope.environment()).factory.getWorld();
+               TypeX onType = rp.onType;
+               if (onType == null) {
+                   Member member = EclipseFactory.makeResolvedMember(declaration.binding);
+                       onType = member.getDeclaringType();
+               }
+               ResolvedMember[] members = onType.getDeclaredPointcuts(world);
+               if (members != null) {
+                       for (int i = 0; i < members.length; i++) {
+                           if (members[i].getName().equals(rp.name)) {
+                               return members[i];
+                           }
+                       }
+               }
+               return null;
+    }
+
+    /**
+     * @param methodDeclaration 
+     * @return all of the named pointcuts referenced by the PCD of this declaration
+     */
+    private List genNamedPointcuts(MethodDeclaration methodDeclaration) {
+        List pointcuts = new ArrayList();
+        if (methodDeclaration instanceof AdviceDeclaration) {
+//            ((AdviceDeclaration)methodDeclaration).
+//            System.err.println(">>>>>>>> got advice: " + new String(methodDeclaration.selector));
+            if (((AdviceDeclaration)methodDeclaration).pointcutDesignator != null) 
+                addAllNamed(((AdviceDeclaration)methodDeclaration).pointcutDesignator.getPointcut(), pointcuts);
+               } else if (methodDeclaration instanceof PointcutDeclaration) { 
+                   if (((PointcutDeclaration)methodDeclaration).pointcutDesignator != null)
+                       addAllNamed(((PointcutDeclaration)methodDeclaration).pointcutDesignator.getPointcut(), pointcuts);      
+               } 
+               return pointcuts;
+    }
+
+    /**
+     * @param left
+     * @param pointcuts        accumulator for named pointcuts
+     */
+    private void addAllNamed(Pointcut pointcut, List pointcuts) {
+        if (pointcut == null) return;
+        if (pointcut instanceof ReferencePointcut) {
+                       ReferencePointcut rp = (ReferencePointcut)pointcut;
+                       pointcuts.add(rp);
+               } else if (pointcut instanceof AndPointcut) {
+                   AndPointcut ap = (AndPointcut)pointcut;
+                   addAllNamed(ap.getLeft(), pointcuts);
+                   addAllNamed(ap.getRight(), pointcuts);
+               } else if (pointcut instanceof OrPointcut) {
+                       OrPointcut op = (OrPointcut)pointcut;
+                       addAllNamed(op.getLeft(), pointcuts);
+                   addAllNamed(op.getRight(), pointcuts);
+               } 
+    }
+
+    private String genSourceSignature(MethodDeclaration methodDeclaration) {
                StringBuffer output = new StringBuffer();
                ASTNode.printModifiers(methodDeclaration.modifiers, output);
                methodDeclaration.printReturnType(0, output).append(methodDeclaration.selector).append('(');
@@ -515,7 +580,7 @@ public class AsmHierarchyBuilder extends ASTVisitor {
        /**
         * Doesn't print qualified allocation expressions.
         */
-       private String genSourceSignature(FieldDeclaration fieldDeclaration) {
+       protected String genSourceSignature(FieldDeclaration fieldDeclaration) {
                StringBuffer output = new StringBuffer();
                FieldDeclaration.printModifiers(fieldDeclaration.modifiers, output);
                fieldDeclaration.type.print(0, output).append(' ').append(fieldDeclaration.name);