diff options
author | mkersten <mkersten> | 2004-10-14 21:45:07 +0000 |
---|---|---|
committer | mkersten <mkersten> | 2004-10-14 21:45:07 +0000 |
commit | 4a4d4b2612ab6bbd9c82dc03b08b13f696725bf3 (patch) | |
tree | 1655439b851c7caad506cf53b8500a1a929696fd | |
parent | 0a77939b3286d5ac033797234741436c57ad202f (diff) | |
download | aspectj-4a4d4b2612ab6bbd9c82dc03b08b13f696725bf3.tar.gz aspectj-4a4d4b2612ab6bbd9c82dc03b08b13f696725bf3.zip |
Added "uses pointcut" relation to the ASM.
6 files changed, 163 insertions, 50 deletions
diff --git a/ajde/testdata/examples/coverage/ModelCoverage.java b/ajde/testdata/examples/coverage/ModelCoverage.java index bbab87a2f..a853ec83d 100644 --- a/ajde/testdata/examples/coverage/ModelCoverage.java +++ b/ajde/testdata/examples/coverage/ModelCoverage.java @@ -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() { } +} + diff --git a/ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java b/ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java index 64b365276..f693571a5 100644 --- a/ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java +++ b/ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java @@ -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, diff --git a/asm/src/org/aspectj/asm/IRelationship.java b/asm/src/org/aspectj/asm/IRelationship.java index 53b118262..4a33d4fb0 100644 --- a/asm/src/org/aspectj/asm/IRelationship.java +++ b/asm/src/org/aspectj/asm/IRelationship.java @@ -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; diff --git a/asm/src/org/aspectj/asm/internal/ProgramElement.java b/asm/src/org/aspectj/asm/internal/ProgramElement.java index ef4b28507..3965c21d0 100644 --- a/asm/src/org/aspectj/asm/internal/ProgramElement.java +++ b/asm/src/org/aspectj/asm/internal/ProgramElement.java @@ -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; } diff --git a/asm/src/org/aspectj/asm/overview.html b/asm/src/org/aspectj/asm/overview.html index 6608bd24e..3c5f61411 100644 --- a/asm/src/org/aspectj/asm/overview.html +++ b/asm/src/org/aspectj/asm/overview.html @@ -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> diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java index d5bdc99f7..3517931a9 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java @@ -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); |