From: aclement Date: Mon, 20 Oct 2008 18:51:09 +0000 (+0000) Subject: 246125: moving structure model related stuff out of org.aspectj.weaver into org.aspec... X-Git-Tag: V1_6_3rc1~171 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=edc97a8a96aaf01f6fdc015bdde2c4c1d2bb5a96;p=aspectj.git 246125: moving structure model related stuff out of org.aspectj.weaver into org.aspectj.weaver.model --- diff --git a/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java b/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java deleted file mode 100644 index 52336bfb8..000000000 --- a/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java +++ /dev/null @@ -1,487 +0,0 @@ -/* ******************************************************************* - * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). - * All rights reserved. - * This program and the accompanying materials are made available - * under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * PARC initial implementation - * ******************************************************************/ - -package org.aspectj.weaver; - -import java.util.Iterator; - -import org.aspectj.asm.AsmManager; -import org.aspectj.asm.IHierarchy; -import org.aspectj.asm.IProgramElement; -import org.aspectj.asm.IRelationship; -import org.aspectj.asm.IRelationshipMap; -import org.aspectj.asm.internal.ProgramElement; -import org.aspectj.bridge.ISourceLocation; -import org.aspectj.bridge.SourceLocation; - -public class AsmRelationshipProvider { - - protected static AsmRelationshipProvider INSTANCE = new AsmRelationshipProvider(); - - public static final String ADVISES = "advises"; - public static final String ADVISED_BY = "advised by"; - public static final String DECLARES_ON = "declares on"; - public static final String DECLAREDY_BY = "declared by"; - public static final String SOFTENS = "softens"; - public static final String SOFTENED_BY = "softened by"; - public static final String MATCHED_BY = "matched by"; - public static final String MATCHES_DECLARE = "matches declare"; - public static final String INTER_TYPE_DECLARES = "declared on"; - public static final String INTER_TYPE_DECLARED_BY = "aspect declarations"; - - public static final String ANNOTATES = "annotates"; - public static final String ANNOTATED_BY = "annotated by"; - - public void checkerMunger(AsmManager asm, Shadow shadow, Checker checker) { - if (asm == null) // !AsmManager.isCreatingModel()) - return; - if (shadow.getSourceLocation() == null || checker.getSourceLocation() == null) - return; - - if (World.createInjarHierarchy) { - checker.createHierarchy(asm); - } - - // Ensure a node for the target exists - IProgramElement targetNode = getNode(asm, shadow); - if (targetNode == null) - return; - String targetHandle = asm.getHandleProvider().createHandleIdentifier(targetNode); - if (targetHandle == null) - return; - - IProgramElement sourceNode = asm.getHierarchy().findElementForSourceLine(checker.getSourceLocation()); - String sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); - if (sourceHandle == null) - return; - - IRelationshipMap mapper = asm.getRelationshipMap(); - IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE, MATCHED_BY, false, true); - foreward.addTarget(targetHandle); - - IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, MATCHES_DECLARE, false, true); - if (back != null && back.getTargets() != null) { - back.addTarget(sourceHandle); - } - if (sourceNode.getSourceLocation() != null) { - asm.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); - } - - } - - // For ITDs - public void addRelationship(AsmManager asm, ResolvedType onType, ResolvedTypeMunger munger, ResolvedType originatingAspect) { - - if (asm == null)// !AsmManager.isCreatingModel()) - return; - if (originatingAspect.getSourceLocation() != null) { - String sourceHandle = ""; - IProgramElement sourceNode = null; - if (munger.getSourceLocation() != null && munger.getSourceLocation().getOffset() != -1) { - sourceNode = asm.getHierarchy().findElementForSourceLine(munger.getSourceLocation()); - sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); - } else { - sourceNode = asm.getHierarchy().findElementForSourceLine(originatingAspect.getSourceLocation()); - sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); - } - if (sourceHandle == null) - return; - IProgramElement targetNode = asm.getHierarchy().findElementForSourceLine(onType.getSourceLocation()); - String targetHandle = asm.getHandleProvider().createHandleIdentifier(targetNode); - if (targetHandle == null) - return; - - IRelationshipMap mapper = asm.getRelationshipMap(); - IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES, false, - true); - foreward.addTarget(targetHandle); - - IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY, false, - true); - back.addTarget(sourceHandle); - asm.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); - } - } - - // public void addDeclareParentsRelationship(ISourceLocation decp, - // ResolvedType targetType, List newParents) { - // if (!AsmManager.isCreatingModel()) - // return; - // - // IProgramElement sourceNode = - // AsmManager.getDefault().getHierarchy().findElementForSourceLine(decp); - // String sourceHandle = - // AsmManager.getDefault().getHandleProvider().createHandleIdentifier - // (sourceNode); - // if (sourceHandle == null) - // return; - // - // IProgramElement targetNode = AsmManager.getDefault().getHierarchy() - // .findElementForSourceLine(targetType.getSourceLocation()); - // String targetHandle = - // AsmManager.getDefault().getHandleProvider().createHandleIdentifier - // (targetNode); - // if (targetHandle == null) - // return; - // - // IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap(); - // IRelationship foreward = mapper.get(sourceHandle, - // IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES, false, true); - // foreward.addTarget(targetHandle); - // - // IRelationship back = mapper.get(targetHandle, - // IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY, false, - // true); - // back.addTarget(sourceHandle); - // } - - /** - * Adds a declare annotation relationship, sometimes entities don't have source locs (methods/fields) so use other variants of - * this method if that is the case as they will look the entities up in the structure model. - */ - public void addDeclareAnnotationRelationship(AsmManager asm, ISourceLocation declareAnnotationLocation, - ISourceLocation annotatedLocation) { - if (asm == null) // !AsmManager.isCreatingModel()) - return; - - IProgramElement sourceNode = asm.getHierarchy().findElementForSourceLine(declareAnnotationLocation); - String sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); - if (sourceHandle == null) - return; - - IProgramElement targetNode = asm.getHierarchy().findElementForSourceLine(annotatedLocation); - String targetHandle = asm.getHandleProvider().createHandleIdentifier(targetNode); - if (targetHandle == null) - return; - - IRelationshipMap mapper = asm.getRelationshipMap(); - IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true); - foreward.addTarget(targetHandle); - - IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true); - back.addTarget(sourceHandle); - if (sourceNode.getSourceLocation() != null) { - asm.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); - } - } - - public void adviceMunger(AsmManager asm, Shadow shadow, ShadowMunger munger) { - if (asm == null) // !AsmManager.isCreatingModel()) - return; - if (munger instanceof Advice) { - Advice advice = (Advice) munger; - - if (advice.getKind().isPerEntry() || advice.getKind().isCflow()) { - // TODO: might want to show these in the future - return; - } - - if (World.createInjarHierarchy) { - munger.createHierarchy(asm); - } - - IRelationshipMap mapper = asm.getRelationshipMap(); - IProgramElement targetNode = getNode(asm, shadow); - if (targetNode == null) - return; - boolean runtimeTest = advice.hasDynamicTests(); - - // Work out extra info to inform interested UIs ! - IProgramElement.ExtraInformation ai = new IProgramElement.ExtraInformation(); - - String adviceHandle = advice.getHandle(asm); - if (adviceHandle == null) - return; - - // What kind of advice is it? - // TODO: Prob a better way to do this but I just want to - // get it into CVS !!! - AdviceKind ak = ((Advice) munger).getKind(); - ai.setExtraAdviceInformation(ak.getName()); - IProgramElement adviceElement = asm.getHierarchy().findElementForHandle(adviceHandle); - if (adviceElement != null) { - adviceElement.setExtraInfo(ai); - } - String targetHandle = targetNode.getHandleIdentifier(); - if (advice.getKind().equals(AdviceKind.Softener)) { - IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.DECLARE_SOFT, SOFTENS, runtimeTest, true); - if (foreward != null) - foreward.addTarget(targetHandle);// foreward.getTargets().add - // (targetHandle); - - IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, SOFTENED_BY, runtimeTest, true); - if (back != null) - back.addTarget(adviceHandle);// back.getTargets().add( - // adviceHandle); - } else { - IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.ADVICE, ADVISES, runtimeTest, true); - if (foreward != null) - foreward.addTarget(targetHandle);// foreward.getTargets().add - // (targetHandle); - - IRelationship back = mapper.get(targetHandle, IRelationship.Kind.ADVICE, ADVISED_BY, runtimeTest, true); - if (back != null) - back.addTarget(adviceHandle);// back.getTargets().add( - // adviceHandle); - } - if (adviceElement.getSourceLocation() != null) { - asm.addAspectInEffectThisBuild(adviceElement.getSourceLocation().getSourceFile()); - } - } - } - - protected IProgramElement getNode(AsmManager model, Shadow shadow) { - Member enclosingMember = shadow.getEnclosingCodeSignature(); - - IProgramElement enclosingNode = lookupMember(model.getHierarchy(), enclosingMember); - if (enclosingNode == null) { - Lint.Kind err = shadow.getIWorld().getLint().shadowNotInStructure; - if (err.isEnabled()) { - err.signal(shadow.toString(), shadow.getSourceLocation()); - } - return null; - } - - Member shadowSig = shadow.getSignature(); - // pr235204 - if (shadow.getKind() == Shadow.MethodCall || !shadowSig.equals(enclosingMember)) { - IProgramElement bodyNode = findOrCreateCodeNode(model, enclosingNode, shadowSig, shadow); - return bodyNode; - } else { - return enclosingNode; - } - } - - private boolean sourceLinesMatch(ISourceLocation loc1, ISourceLocation loc2) { - if (loc1.getLine() != loc2.getLine()) - return false; - return true; - } - - /** - * Finds or creates a code IProgramElement for the given shadow. - * - * The byteCodeName of the created node is set to 'shadowSig.getName() + "!" + counter', eg "println!3". The counter is the - * occurence count of children within the enclosingNode which have the same name. So, for example, if a method contains two - * System.out.println statements, the first one will have byteCodeName 'println!1' and the second will have byteCodeName - * 'println!2'. This is to ensure the two nodes have unique handles when the handles do not depend on sourcelocations. - * - * Currently the shadows are examined in the sequence they appear in the source file. This means that the counters are - * consistent over incremental builds. All aspects are compiled up front and any new aspect created will force a full build. - * Moreover, if the body of the enclosingShadow is changed, then the model for this is rebuilt from scratch. - */ - private IProgramElement findOrCreateCodeNode(AsmManager asm, IProgramElement enclosingNode, Member shadowSig, Shadow shadow) { - for (Iterator it = enclosingNode.getChildren().iterator(); it.hasNext();) { - IProgramElement node = (IProgramElement) it.next(); - int excl = node.getBytecodeName().lastIndexOf('!'); - if (((excl != -1 && shadowSig.getName().equals(node.getBytecodeName().substring(0, excl))) || shadowSig.getName() - .equals(node.getBytecodeName())) - && shadowSig.getSignature().equals(node.getBytecodeSignature()) - && sourceLinesMatch(node.getSourceLocation(), shadow.getSourceLocation())) { - return node; - } - } - - ISourceLocation sl = shadow.getSourceLocation(); - - // XXX why not use shadow file? new SourceLocation(sl.getSourceFile(), - // sl.getLine()), - SourceLocation peLoc = new SourceLocation(enclosingNode.getSourceLocation().getSourceFile(), sl.getLine()); - peLoc.setOffset(sl.getOffset()); - IProgramElement peNode = new ProgramElement(asm, shadow.toString(), IProgramElement.Kind.CODE, peLoc, 0, null, null); - - // check to see if the enclosing shadow already has children with the - // same name. If so we want to add a counter to the byteCodeName - // otherwise - // we wont get unique handles - int numberOfChildrenWithThisName = 0; - for (Iterator it = enclosingNode.getChildren().iterator(); it.hasNext();) { - IProgramElement child = (IProgramElement) it.next(); - if (child.getName().equals(shadow.toString())) { - numberOfChildrenWithThisName++; - } - } - peNode.setBytecodeName(shadowSig.getName() + "!" + String.valueOf(numberOfChildrenWithThisName + 1)); - peNode.setBytecodeSignature(shadowSig.getSignature()); - enclosingNode.addChild(peNode); - return peNode; - } - - protected IProgramElement lookupMember(IHierarchy model, Member member) { - UnresolvedType declaringType = member.getDeclaringType(); - IProgramElement classNode = model.findElementForType(declaringType.getPackageName(), declaringType.getClassName()); - return findMemberInClass(classNode, member); - } - - protected IProgramElement findMemberInClass(IProgramElement classNode, Member member) { - if (classNode == null) - return null; // XXX remove this check - for (Iterator it = classNode.getChildren().iterator(); it.hasNext();) { - IProgramElement node = (IProgramElement) it.next(); - if (member.getName().equals(node.getBytecodeName()) && member.getSignature().equals(node.getBytecodeSignature())) { - return node; - } - } - // if we can't find the member, we'll just put it in the class - return classNode; - } - - // private static IProgramElement.Kind genShadowKind(Shadow shadow) { - // IProgramElement.Kind shadowKind; - // if (shadow.getKind() == Shadow.MethodCall - // || shadow.getKind() == Shadow.ConstructorCall - // || shadow.getKind() == Shadow.FieldGet - // || shadow.getKind() == Shadow.FieldSet - // || shadow.getKind() == Shadow.ExceptionHandler) { - // return IProgramElement.Kind.CODE; - // - // } else if (shadow.getKind() == Shadow.MethodExecution) { - // return IProgramElement.Kind.METHOD; - // - // } else if (shadow.getKind() == Shadow.ConstructorExecution) { - // return IProgramElement.Kind.CONSTRUCTOR; - // - // } else if (shadow.getKind() == Shadow.PreInitialization - // || shadow.getKind() == Shadow.Initialization) { - // return IProgramElement.Kind.CLASS; - // - // } else if (shadow.getKind() == Shadow.AdviceExecution) { - // return IProgramElement.Kind.ADVICE; - // - // } else { - // return IProgramElement.Kind.ERROR; - // } - // } - - public static AsmRelationshipProvider getDefault() { - return INSTANCE; - } - - /** - * Add a relationship to the known set for a declare @method/@constructor construct. Locating the method is a messy (for messy - * read 'fragile') bit of code that could break at any moment but it's working for my simple testcase. Currently just fails - * silently if any of the lookup code doesn't find anything... - * - * @param hierarchy - */ - public void addDeclareAnnotationMethodRelationship(ISourceLocation sourceLocation, String typename, ResolvedMember method, - AsmManager structureModel) { - if (structureModel == null) // !AsmManager.isCreatingModel()) - return; - - String pkg = null; - String type = typename; - int packageSeparator = typename.lastIndexOf("."); - if (packageSeparator != -1) { - pkg = typename.substring(0, packageSeparator); - type = typename.substring(packageSeparator + 1); - } - - IHierarchy hierarchy = structureModel.getHierarchy(); - - IProgramElement typeElem = hierarchy.findElementForType(pkg, type); - if (typeElem == null) - return; - - StringBuffer parmString = new StringBuffer("("); - UnresolvedType[] args = method.getParameterTypes(); - // Type[] args = method.getArgumentTypes(); - for (int i = 0; i < args.length; i++) { - String s = args[i].getName();// Utility.signatureToString(args[i]. - // getName()getSignature(), false); - parmString.append(s); - if ((i + 1) < args.length) - parmString.append(","); - } - parmString.append(")"); - IProgramElement methodElem = null; - - if (method.getName().startsWith("")) { - // its a ctor - methodElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.CONSTRUCTOR, type + parmString); - if (methodElem == null && args.length == 0) - methodElem = typeElem; // assume default ctor - } else { - // its a method - methodElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.METHOD, method.getName() + parmString); - } - - if (methodElem == null) - return; - - try { - String targetHandle = methodElem.getHandleIdentifier(); - if (targetHandle == null) - return; - - IProgramElement sourceNode = hierarchy.findElementForSourceLine(sourceLocation); - String sourceHandle = structureModel.getHandleProvider().createHandleIdentifier(sourceNode); - if (sourceHandle == null) - return; - - IRelationshipMap mapper = structureModel.getRelationshipMap(); - IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true); - foreward.addTarget(targetHandle); - - IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true); - back.addTarget(sourceHandle); - } catch (Throwable t) { // I'm worried about that code above, this will - // make sure we don't explode if it plays up - t.printStackTrace(); // I know I know .. but I don't want to lose - // it! - } - } - - /** - * Add a relationship to the known set for a declare @field construct. Locating the field is trickier than it might seem since - * we have no line number info for it, we have to dig through the structure model under the fields' type in order to locate it. - * Currently just fails silently if any of the lookup code doesn't find anything... - */ - public void addDeclareAnnotationFieldRelationship(AsmManager asm, ISourceLocation sourceLocation, String typename, - ResolvedMember field) { - if (asm == null) // !AsmManager.isCreatingModel()) - return; - - String pkg = null; - String type = typename; - int packageSeparator = typename.lastIndexOf("."); - if (packageSeparator != -1) { - pkg = typename.substring(0, packageSeparator); - type = typename.substring(packageSeparator + 1); - } - IHierarchy hierarchy = asm.getHierarchy(); - IProgramElement typeElem = hierarchy.findElementForType(pkg, type); - if (typeElem == null) - return; - - IProgramElement fieldElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.FIELD, field.getName()); - if (fieldElem == null) - return; - - String targetHandle = fieldElem.getHandleIdentifier(); - if (targetHandle == null) - return; - - IProgramElement sourceNode = hierarchy.findElementForSourceLine(sourceLocation); - String sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); - if (sourceHandle == null) - return; - - IRelationshipMap mapper = asm.getRelationshipMap(); - IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true); - foreward.addTarget(targetHandle); - - IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true); - back.addTarget(sourceHandle); - } - -} diff --git a/weaver/src/org/aspectj/weaver/AsmRelationshipUtils.java b/weaver/src/org/aspectj/weaver/AsmRelationshipUtils.java deleted file mode 100644 index 722ddb09c..000000000 --- a/weaver/src/org/aspectj/weaver/AsmRelationshipUtils.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************** - * Copyright (c) 2006 Contributors. All rights reserved. - * This program and the accompanying materials are made available - * under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution and is available at - * http://eclipse.org/legal/epl-v10.html - * - * Contributors: IBM Corporation - initial API and implementation - * Helen Hawkins - initial version - *******************************************************************/ -package org.aspectj.weaver; - -import org.aspectj.weaver.patterns.AndPointcut; -import org.aspectj.weaver.patterns.OrPointcut; -import org.aspectj.weaver.patterns.Pointcut; -import org.aspectj.weaver.patterns.ReferencePointcut; - -/** - * Provides utility methods for generating details for IProgramElements used when creating the model both from source (via - * AsmElementFormatter.visit(..)) and when filling in the model for binary aspects (via AsmRelationshipProvider bug 145963) - */ -public class AsmRelationshipUtils { - - // public static final String UNDEFINED=""; - public static final String DECLARE_PRECEDENCE = "precedence"; - public static final String DECLARE_SOFT = "soft"; - public static final String DECLARE_PARENTS = "parents"; - public static final String DECLARE_WARNING = "warning"; - public static final String DECLARE_ERROR = "error"; - public static final String DECLARE_UNKNONWN = ""; - public static final String POINTCUT_ABSTRACT = ""; - public static final String POINTCUT_ANONYMOUS = ""; - public static final String DOUBLE_DOTS = ".."; - public static final int MAX_MESSAGE_LENGTH = 18; - public static final String DEC_LABEL = "declare"; - - /** - * Generates the declare message used in the details, for example if the declare warning statement has message - * "There should be no printlns" will return 'declare warning: "There should be n.."' - */ - public static String genDeclareMessage(String message) { - int length = message.length(); - if (length < MAX_MESSAGE_LENGTH) { - return message; - } else { - return message.substring(0, MAX_MESSAGE_LENGTH - 1) + DOUBLE_DOTS; - } - } - - /** - * Generates the pointcut details for the given pointcut, for example an anonymous pointcut will return '' - * and a named pointcut called p() will return 'p()..' - */ - public static String genPointcutDetails(Pointcut pcd) { - StringBuffer details = new StringBuffer(); - if (pcd instanceof ReferencePointcut) { - ReferencePointcut rp = (ReferencePointcut) pcd; - details.append(rp.name).append(DOUBLE_DOTS); - } else if (pcd instanceof AndPointcut) { - AndPointcut ap = (AndPointcut) pcd; - if (ap.getLeft() instanceof ReferencePointcut) { - details.append(ap.getLeft().toString()).append(DOUBLE_DOTS); - } else { - details.append(POINTCUT_ANONYMOUS).append(DOUBLE_DOTS); - } - } else if (pcd instanceof OrPointcut) { - OrPointcut op = (OrPointcut) pcd; - if (op.getLeft() instanceof ReferencePointcut) { - details.append(op.getLeft().toString()).append(DOUBLE_DOTS); - } else { - details.append(POINTCUT_ANONYMOUS).append(DOUBLE_DOTS); - } - } else { - details.append(POINTCUT_ANONYMOUS); - } - return details.toString(); - } - -} diff --git a/weaver/src/org/aspectj/weaver/Checker.java b/weaver/src/org/aspectj/weaver/Checker.java index 6f521b233..c56379240 100644 --- a/weaver/src/org/aspectj/weaver/Checker.java +++ b/weaver/src/org/aspectj/weaver/Checker.java @@ -20,6 +20,7 @@ import org.aspectj.asm.IRelationship; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.Message; +import org.aspectj.weaver.model.AsmRelationshipProvider; import org.aspectj.weaver.patterns.DeclareErrorOrWarning; import org.aspectj.weaver.patterns.PerClause; import org.aspectj.weaver.patterns.Pointcut; diff --git a/weaver/src/org/aspectj/weaver/Shadow.java b/weaver/src/org/aspectj/weaver/Shadow.java index 346d60ff3..ea3a891f2 100644 --- a/weaver/src/org/aspectj/weaver/Shadow.java +++ b/weaver/src/org/aspectj/weaver/Shadow.java @@ -32,6 +32,7 @@ import org.aspectj.lang.JoinPoint; import org.aspectj.util.PartialOrder; import org.aspectj.util.TypeSafeEnum; import org.aspectj.weaver.ast.Var; +import org.aspectj.weaver.model.AsmRelationshipProvider; /* * The superclass of anything representing a the shadow of a join point. A shadow represents diff --git a/weaver/src/org/aspectj/weaver/ShadowMunger.java b/weaver/src/org/aspectj/weaver/ShadowMunger.java index c99525459..c69589b29 100644 --- a/weaver/src/org/aspectj/weaver/ShadowMunger.java +++ b/weaver/src/org/aspectj/weaver/ShadowMunger.java @@ -25,6 +25,7 @@ import org.aspectj.asm.internal.ProgramElement; import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.SourceLocation; import org.aspectj.util.PartialOrder; +import org.aspectj.weaver.model.AsmRelationshipUtils; import org.aspectj.weaver.patterns.DeclareErrorOrWarning; import org.aspectj.weaver.patterns.PerClause; import org.aspectj.weaver.patterns.Pointcut; diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java index 1b0b82a8a..372dcb735 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java @@ -61,7 +61,6 @@ import org.aspectj.util.PartialOrder; import org.aspectj.weaver.AjAttribute; import org.aspectj.weaver.AjcMemberMaker; import org.aspectj.weaver.AnnotationAJ; -import org.aspectj.weaver.AsmRelationshipProvider; import org.aspectj.weaver.BCException; import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.IClassWeaver; @@ -82,6 +81,7 @@ import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.WeaverStateInfo; import org.aspectj.weaver.World; +import org.aspectj.weaver.model.AsmRelationshipProvider; import org.aspectj.weaver.patterns.DeclareAnnotation; import org.aspectj.weaver.patterns.ExactTypePattern; import org.aspectj.weaver.tools.Trace; diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index f0dee6d01..de8cf3a3c 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -41,7 +41,6 @@ import org.aspectj.bridge.context.ContextToken; import org.aspectj.weaver.AjcMemberMaker; import org.aspectj.weaver.AnnotationAJ; import org.aspectj.weaver.AnnotationOnTypeMunger; -import org.aspectj.weaver.AsmRelationshipProvider; import org.aspectj.weaver.BCException; import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.Member; @@ -63,6 +62,7 @@ import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.WeaverStateInfo; import org.aspectj.weaver.World; +import org.aspectj.weaver.model.AsmRelationshipProvider; import org.aspectj.weaver.patterns.DeclareAnnotation; import org.aspectj.weaver.patterns.Pointcut; diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java index d08d8d55e..eec8b5eac 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java @@ -56,7 +56,6 @@ import org.aspectj.util.FuzzyBoolean; import org.aspectj.weaver.Advice; import org.aspectj.weaver.AnnotationAJ; import org.aspectj.weaver.AnnotationOnTypeMunger; -import org.aspectj.weaver.AsmRelationshipProvider; import org.aspectj.weaver.BCException; import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.CrosscuttingMembersSet; @@ -74,6 +73,7 @@ import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.WeaverStateInfo; import org.aspectj.weaver.World; +import org.aspectj.weaver.model.AsmRelationshipProvider; import org.aspectj.weaver.patterns.AndPointcut; import org.aspectj.weaver.patterns.BindingPattern; import org.aspectj.weaver.patterns.BindingTypePattern; diff --git a/weaver/src/org/aspectj/weaver/model/AsmRelationshipProvider.java b/weaver/src/org/aspectj/weaver/model/AsmRelationshipProvider.java new file mode 100644 index 000000000..9d10f0ab4 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/model/AsmRelationshipProvider.java @@ -0,0 +1,500 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * PARC initial implementation + * ******************************************************************/ + +package org.aspectj.weaver.model; + +import java.util.Iterator; + +import org.aspectj.asm.AsmManager; +import org.aspectj.asm.IHierarchy; +import org.aspectj.asm.IProgramElement; +import org.aspectj.asm.IRelationship; +import org.aspectj.asm.IRelationshipMap; +import org.aspectj.asm.internal.ProgramElement; +import org.aspectj.bridge.ISourceLocation; +import org.aspectj.bridge.SourceLocation; +import org.aspectj.weaver.Advice; +import org.aspectj.weaver.AdviceKind; +import org.aspectj.weaver.Checker; +import org.aspectj.weaver.Lint; +import org.aspectj.weaver.Member; +import org.aspectj.weaver.ResolvedMember; +import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.ResolvedTypeMunger; +import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.ShadowMunger; +import org.aspectj.weaver.UnresolvedType; +import org.aspectj.weaver.World; +import org.aspectj.weaver.Lint.Kind; + +public class AsmRelationshipProvider { + + protected static AsmRelationshipProvider INSTANCE = new AsmRelationshipProvider(); + + public static final String ADVISES = "advises"; + public static final String ADVISED_BY = "advised by"; + public static final String DECLARES_ON = "declares on"; + public static final String DECLAREDY_BY = "declared by"; + public static final String SOFTENS = "softens"; + public static final String SOFTENED_BY = "softened by"; + public static final String MATCHED_BY = "matched by"; + public static final String MATCHES_DECLARE = "matches declare"; + public static final String INTER_TYPE_DECLARES = "declared on"; + public static final String INTER_TYPE_DECLARED_BY = "aspect declarations"; + + public static final String ANNOTATES = "annotates"; + public static final String ANNOTATED_BY = "annotated by"; + + public void checkerMunger(AsmManager asm, Shadow shadow, Checker checker) { + if (asm == null) // !AsmManager.isCreatingModel()) + return; + if (shadow.getSourceLocation() == null || checker.getSourceLocation() == null) + return; + + if (World.createInjarHierarchy) { + checker.createHierarchy(asm); + } + + // Ensure a node for the target exists + IProgramElement targetNode = getNode(asm, shadow); + if (targetNode == null) + return; + String targetHandle = asm.getHandleProvider().createHandleIdentifier(targetNode); + if (targetHandle == null) + return; + + IProgramElement sourceNode = asm.getHierarchy().findElementForSourceLine(checker.getSourceLocation()); + String sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); + if (sourceHandle == null) + return; + + IRelationshipMap mapper = asm.getRelationshipMap(); + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE, MATCHED_BY, false, true); + foreward.addTarget(targetHandle); + + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, MATCHES_DECLARE, false, true); + if (back != null && back.getTargets() != null) { + back.addTarget(sourceHandle); + } + if (sourceNode.getSourceLocation() != null) { + asm.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); + } + + } + + // For ITDs + public void addRelationship(AsmManager asm, ResolvedType onType, ResolvedTypeMunger munger, ResolvedType originatingAspect) { + + if (asm == null)// !AsmManager.isCreatingModel()) + return; + if (originatingAspect.getSourceLocation() != null) { + String sourceHandle = ""; + IProgramElement sourceNode = null; + if (munger.getSourceLocation() != null && munger.getSourceLocation().getOffset() != -1) { + sourceNode = asm.getHierarchy().findElementForSourceLine(munger.getSourceLocation()); + sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); + } else { + sourceNode = asm.getHierarchy().findElementForSourceLine(originatingAspect.getSourceLocation()); + sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); + } + if (sourceHandle == null) + return; + IProgramElement targetNode = asm.getHierarchy().findElementForSourceLine(onType.getSourceLocation()); + String targetHandle = asm.getHandleProvider().createHandleIdentifier(targetNode); + if (targetHandle == null) + return; + + IRelationshipMap mapper = asm.getRelationshipMap(); + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES, false, + true); + foreward.addTarget(targetHandle); + + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY, false, + true); + back.addTarget(sourceHandle); + asm.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); + } + } + + // public void addDeclareParentsRelationship(ISourceLocation decp, + // ResolvedType targetType, List newParents) { + // if (!AsmManager.isCreatingModel()) + // return; + // + // IProgramElement sourceNode = + // AsmManager.getDefault().getHierarchy().findElementForSourceLine(decp); + // String sourceHandle = + // AsmManager.getDefault().getHandleProvider().createHandleIdentifier + // (sourceNode); + // if (sourceHandle == null) + // return; + // + // IProgramElement targetNode = AsmManager.getDefault().getHierarchy() + // .findElementForSourceLine(targetType.getSourceLocation()); + // String targetHandle = + // AsmManager.getDefault().getHandleProvider().createHandleIdentifier + // (targetNode); + // if (targetHandle == null) + // return; + // + // IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap(); + // IRelationship foreward = mapper.get(sourceHandle, + // IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES, false, true); + // foreward.addTarget(targetHandle); + // + // IRelationship back = mapper.get(targetHandle, + // IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY, false, + // true); + // back.addTarget(sourceHandle); + // } + + /** + * Adds a declare annotation relationship, sometimes entities don't have source locs (methods/fields) so use other variants of + * this method if that is the case as they will look the entities up in the structure model. + */ + public void addDeclareAnnotationRelationship(AsmManager asm, ISourceLocation declareAnnotationLocation, + ISourceLocation annotatedLocation) { + if (asm == null) // !AsmManager.isCreatingModel()) + return; + + IProgramElement sourceNode = asm.getHierarchy().findElementForSourceLine(declareAnnotationLocation); + String sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); + if (sourceHandle == null) + return; + + IProgramElement targetNode = asm.getHierarchy().findElementForSourceLine(annotatedLocation); + String targetHandle = asm.getHandleProvider().createHandleIdentifier(targetNode); + if (targetHandle == null) + return; + + IRelationshipMap mapper = asm.getRelationshipMap(); + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true); + foreward.addTarget(targetHandle); + + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true); + back.addTarget(sourceHandle); + if (sourceNode.getSourceLocation() != null) { + asm.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); + } + } + + public void adviceMunger(AsmManager asm, Shadow shadow, ShadowMunger munger) { + if (asm == null) // !AsmManager.isCreatingModel()) + return; + if (munger instanceof Advice) { + Advice advice = (Advice) munger; + + if (advice.getKind().isPerEntry() || advice.getKind().isCflow()) { + // TODO: might want to show these in the future + return; + } + + if (World.createInjarHierarchy) { + munger.createHierarchy(asm); + } + + IRelationshipMap mapper = asm.getRelationshipMap(); + IProgramElement targetNode = getNode(asm, shadow); + if (targetNode == null) + return; + boolean runtimeTest = advice.hasDynamicTests(); + + // Work out extra info to inform interested UIs ! + IProgramElement.ExtraInformation ai = new IProgramElement.ExtraInformation(); + + String adviceHandle = advice.getHandle(asm); + if (adviceHandle == null) + return; + + // What kind of advice is it? + // TODO: Prob a better way to do this but I just want to + // get it into CVS !!! + AdviceKind ak = ((Advice) munger).getKind(); + ai.setExtraAdviceInformation(ak.getName()); + IProgramElement adviceElement = asm.getHierarchy().findElementForHandle(adviceHandle); + if (adviceElement != null) { + adviceElement.setExtraInfo(ai); + } + String targetHandle = targetNode.getHandleIdentifier(); + if (advice.getKind().equals(AdviceKind.Softener)) { + IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.DECLARE_SOFT, SOFTENS, runtimeTest, true); + if (foreward != null) + foreward.addTarget(targetHandle);// foreward.getTargets().add + // (targetHandle); + + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, SOFTENED_BY, runtimeTest, true); + if (back != null) + back.addTarget(adviceHandle);// back.getTargets().add( + // adviceHandle); + } else { + IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.ADVICE, ADVISES, runtimeTest, true); + if (foreward != null) + foreward.addTarget(targetHandle);// foreward.getTargets().add + // (targetHandle); + + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.ADVICE, ADVISED_BY, runtimeTest, true); + if (back != null) + back.addTarget(adviceHandle);// back.getTargets().add( + // adviceHandle); + } + if (adviceElement.getSourceLocation() != null) { + asm.addAspectInEffectThisBuild(adviceElement.getSourceLocation().getSourceFile()); + } + } + } + + protected IProgramElement getNode(AsmManager model, Shadow shadow) { + Member enclosingMember = shadow.getEnclosingCodeSignature(); + + IProgramElement enclosingNode = lookupMember(model.getHierarchy(), enclosingMember); + if (enclosingNode == null) { + Lint.Kind err = shadow.getIWorld().getLint().shadowNotInStructure; + if (err.isEnabled()) { + err.signal(shadow.toString(), shadow.getSourceLocation()); + } + return null; + } + + Member shadowSig = shadow.getSignature(); + // pr235204 + if (shadow.getKind() == Shadow.MethodCall || !shadowSig.equals(enclosingMember)) { + IProgramElement bodyNode = findOrCreateCodeNode(model, enclosingNode, shadowSig, shadow); + return bodyNode; + } else { + return enclosingNode; + } + } + + private boolean sourceLinesMatch(ISourceLocation loc1, ISourceLocation loc2) { + if (loc1.getLine() != loc2.getLine()) + return false; + return true; + } + + /** + * Finds or creates a code IProgramElement for the given shadow. + * + * The byteCodeName of the created node is set to 'shadowSig.getName() + "!" + counter', eg "println!3". The counter is the + * occurence count of children within the enclosingNode which have the same name. So, for example, if a method contains two + * System.out.println statements, the first one will have byteCodeName 'println!1' and the second will have byteCodeName + * 'println!2'. This is to ensure the two nodes have unique handles when the handles do not depend on sourcelocations. + * + * Currently the shadows are examined in the sequence they appear in the source file. This means that the counters are + * consistent over incremental builds. All aspects are compiled up front and any new aspect created will force a full build. + * Moreover, if the body of the enclosingShadow is changed, then the model for this is rebuilt from scratch. + */ + private IProgramElement findOrCreateCodeNode(AsmManager asm, IProgramElement enclosingNode, Member shadowSig, Shadow shadow) { + for (Iterator it = enclosingNode.getChildren().iterator(); it.hasNext();) { + IProgramElement node = (IProgramElement) it.next(); + int excl = node.getBytecodeName().lastIndexOf('!'); + if (((excl != -1 && shadowSig.getName().equals(node.getBytecodeName().substring(0, excl))) || shadowSig.getName() + .equals(node.getBytecodeName())) + && shadowSig.getSignature().equals(node.getBytecodeSignature()) + && sourceLinesMatch(node.getSourceLocation(), shadow.getSourceLocation())) { + return node; + } + } + + ISourceLocation sl = shadow.getSourceLocation(); + + // XXX why not use shadow file? new SourceLocation(sl.getSourceFile(), + // sl.getLine()), + SourceLocation peLoc = new SourceLocation(enclosingNode.getSourceLocation().getSourceFile(), sl.getLine()); + peLoc.setOffset(sl.getOffset()); + IProgramElement peNode = new ProgramElement(asm, shadow.toString(), IProgramElement.Kind.CODE, peLoc, 0, null, null); + + // check to see if the enclosing shadow already has children with the + // same name. If so we want to add a counter to the byteCodeName + // otherwise + // we wont get unique handles + int numberOfChildrenWithThisName = 0; + for (Iterator it = enclosingNode.getChildren().iterator(); it.hasNext();) { + IProgramElement child = (IProgramElement) it.next(); + if (child.getName().equals(shadow.toString())) { + numberOfChildrenWithThisName++; + } + } + peNode.setBytecodeName(shadowSig.getName() + "!" + String.valueOf(numberOfChildrenWithThisName + 1)); + peNode.setBytecodeSignature(shadowSig.getSignature()); + enclosingNode.addChild(peNode); + return peNode; + } + + protected IProgramElement lookupMember(IHierarchy model, Member member) { + UnresolvedType declaringType = member.getDeclaringType(); + IProgramElement classNode = model.findElementForType(declaringType.getPackageName(), declaringType.getClassName()); + return findMemberInClass(classNode, member); + } + + protected IProgramElement findMemberInClass(IProgramElement classNode, Member member) { + if (classNode == null) + return null; // XXX remove this check + for (Iterator it = classNode.getChildren().iterator(); it.hasNext();) { + IProgramElement node = (IProgramElement) it.next(); + if (member.getName().equals(node.getBytecodeName()) && member.getSignature().equals(node.getBytecodeSignature())) { + return node; + } + } + // if we can't find the member, we'll just put it in the class + return classNode; + } + + // private static IProgramElement.Kind genShadowKind(Shadow shadow) { + // IProgramElement.Kind shadowKind; + // if (shadow.getKind() == Shadow.MethodCall + // || shadow.getKind() == Shadow.ConstructorCall + // || shadow.getKind() == Shadow.FieldGet + // || shadow.getKind() == Shadow.FieldSet + // || shadow.getKind() == Shadow.ExceptionHandler) { + // return IProgramElement.Kind.CODE; + // + // } else if (shadow.getKind() == Shadow.MethodExecution) { + // return IProgramElement.Kind.METHOD; + // + // } else if (shadow.getKind() == Shadow.ConstructorExecution) { + // return IProgramElement.Kind.CONSTRUCTOR; + // + // } else if (shadow.getKind() == Shadow.PreInitialization + // || shadow.getKind() == Shadow.Initialization) { + // return IProgramElement.Kind.CLASS; + // + // } else if (shadow.getKind() == Shadow.AdviceExecution) { + // return IProgramElement.Kind.ADVICE; + // + // } else { + // return IProgramElement.Kind.ERROR; + // } + // } + + public static AsmRelationshipProvider getDefault() { + return INSTANCE; + } + + /** + * Add a relationship to the known set for a declare @method/@constructor construct. Locating the method is a messy (for messy + * read 'fragile') bit of code that could break at any moment but it's working for my simple testcase. Currently just fails + * silently if any of the lookup code doesn't find anything... + * + * @param hierarchy + */ + public void addDeclareAnnotationMethodRelationship(ISourceLocation sourceLocation, String typename, ResolvedMember method, + AsmManager structureModel) { + if (structureModel == null) // !AsmManager.isCreatingModel()) + return; + + String pkg = null; + String type = typename; + int packageSeparator = typename.lastIndexOf("."); + if (packageSeparator != -1) { + pkg = typename.substring(0, packageSeparator); + type = typename.substring(packageSeparator + 1); + } + + IHierarchy hierarchy = structureModel.getHierarchy(); + + IProgramElement typeElem = hierarchy.findElementForType(pkg, type); + if (typeElem == null) + return; + + StringBuffer parmString = new StringBuffer("("); + UnresolvedType[] args = method.getParameterTypes(); + // Type[] args = method.getArgumentTypes(); + for (int i = 0; i < args.length; i++) { + String s = args[i].getName();// Utility.signatureToString(args[i]. + // getName()getSignature(), false); + parmString.append(s); + if ((i + 1) < args.length) + parmString.append(","); + } + parmString.append(")"); + IProgramElement methodElem = null; + + if (method.getName().startsWith("")) { + // its a ctor + methodElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.CONSTRUCTOR, type + parmString); + if (methodElem == null && args.length == 0) + methodElem = typeElem; // assume default ctor + } else { + // its a method + methodElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.METHOD, method.getName() + parmString); + } + + if (methodElem == null) + return; + + try { + String targetHandle = methodElem.getHandleIdentifier(); + if (targetHandle == null) + return; + + IProgramElement sourceNode = hierarchy.findElementForSourceLine(sourceLocation); + String sourceHandle = structureModel.getHandleProvider().createHandleIdentifier(sourceNode); + if (sourceHandle == null) + return; + + IRelationshipMap mapper = structureModel.getRelationshipMap(); + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true); + foreward.addTarget(targetHandle); + + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true); + back.addTarget(sourceHandle); + } catch (Throwable t) { // I'm worried about that code above, this will + // make sure we don't explode if it plays up + t.printStackTrace(); // I know I know .. but I don't want to lose + // it! + } + } + + /** + * Add a relationship to the known set for a declare @field construct. Locating the field is trickier than it might seem since + * we have no line number info for it, we have to dig through the structure model under the fields' type in order to locate it. + * Currently just fails silently if any of the lookup code doesn't find anything... + */ + public void addDeclareAnnotationFieldRelationship(AsmManager asm, ISourceLocation sourceLocation, String typename, + ResolvedMember field) { + if (asm == null) // !AsmManager.isCreatingModel()) + return; + + String pkg = null; + String type = typename; + int packageSeparator = typename.lastIndexOf("."); + if (packageSeparator != -1) { + pkg = typename.substring(0, packageSeparator); + type = typename.substring(packageSeparator + 1); + } + IHierarchy hierarchy = asm.getHierarchy(); + IProgramElement typeElem = hierarchy.findElementForType(pkg, type); + if (typeElem == null) + return; + + IProgramElement fieldElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.FIELD, field.getName()); + if (fieldElem == null) + return; + + String targetHandle = fieldElem.getHandleIdentifier(); + if (targetHandle == null) + return; + + IProgramElement sourceNode = hierarchy.findElementForSourceLine(sourceLocation); + String sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); + if (sourceHandle == null) + return; + + IRelationshipMap mapper = asm.getRelationshipMap(); + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true); + foreward.addTarget(targetHandle); + + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true); + back.addTarget(sourceHandle); + } + +} diff --git a/weaver/src/org/aspectj/weaver/model/AsmRelationshipUtils.java b/weaver/src/org/aspectj/weaver/model/AsmRelationshipUtils.java new file mode 100644 index 000000000..f9c9f6ae2 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/model/AsmRelationshipUtils.java @@ -0,0 +1,79 @@ +/******************************************************************** + * Copyright (c) 2006 Contributors. All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + * Helen Hawkins - initial version + *******************************************************************/ +package org.aspectj.weaver.model; + +import org.aspectj.weaver.patterns.AndPointcut; +import org.aspectj.weaver.patterns.OrPointcut; +import org.aspectj.weaver.patterns.Pointcut; +import org.aspectj.weaver.patterns.ReferencePointcut; + +/** + * Provides utility methods for generating details for IProgramElements used when creating the model both from source (via + * AsmElementFormatter.visit(..)) and when filling in the model for binary aspects (via AsmRelationshipProvider bug 145963) + */ +public class AsmRelationshipUtils { + + // public static final String UNDEFINED=""; + public static final String DECLARE_PRECEDENCE = "precedence"; + public static final String DECLARE_SOFT = "soft"; + public static final String DECLARE_PARENTS = "parents"; + public static final String DECLARE_WARNING = "warning"; + public static final String DECLARE_ERROR = "error"; + public static final String DECLARE_UNKNONWN = ""; + public static final String POINTCUT_ABSTRACT = ""; + public static final String POINTCUT_ANONYMOUS = ""; + public static final String DOUBLE_DOTS = ".."; + public static final int MAX_MESSAGE_LENGTH = 18; + public static final String DEC_LABEL = "declare"; + + /** + * Generates the declare message used in the details, for example if the declare warning statement has message + * "There should be no printlns" will return 'declare warning: "There should be n.."' + */ + public static String genDeclareMessage(String message) { + int length = message.length(); + if (length < MAX_MESSAGE_LENGTH) { + return message; + } else { + return message.substring(0, MAX_MESSAGE_LENGTH - 1) + DOUBLE_DOTS; + } + } + + /** + * Generates the pointcut details for the given pointcut, for example an anonymous pointcut will return '' + * and a named pointcut called p() will return 'p()..' + */ + public static String genPointcutDetails(Pointcut pcd) { + StringBuffer details = new StringBuffer(); + if (pcd instanceof ReferencePointcut) { + ReferencePointcut rp = (ReferencePointcut) pcd; + details.append(rp.name).append(DOUBLE_DOTS); + } else if (pcd instanceof AndPointcut) { + AndPointcut ap = (AndPointcut) pcd; + if (ap.getLeft() instanceof ReferencePointcut) { + details.append(ap.getLeft().toString()).append(DOUBLE_DOTS); + } else { + details.append(POINTCUT_ANONYMOUS).append(DOUBLE_DOTS); + } + } else if (pcd instanceof OrPointcut) { + OrPointcut op = (OrPointcut) pcd; + if (op.getLeft() instanceof ReferencePointcut) { + details.append(op.getLeft().toString()).append(DOUBLE_DOTS); + } else { + details.append(POINTCUT_ANONYMOUS).append(DOUBLE_DOTS); + } + } else { + details.append(POINTCUT_ANONYMOUS); + } + return details.toString(); + } + +}