diff options
author | aclement <aclement> | 2011-01-31 19:38:13 +0000 |
---|---|---|
committer | aclement <aclement> | 2011-01-31 19:38:13 +0000 |
commit | ecb01f75fdc9ad3e0fcff013437a549398f87788 (patch) | |
tree | 90ef0146170df91acbc0a71901691138a05d79f3 /weaver | |
parent | 91c176061b3941ade42081732a04ed8bbecb1bf8 (diff) | |
download | aspectj-ecb01f75fdc9ad3e0fcff013437a549398f87788.tar.gz aspectj-ecb01f75fdc9ad3e0fcff013437a549398f87788.zip |
335619
Diffstat (limited to 'weaver')
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java | 148 |
1 files changed, 107 insertions, 41 deletions
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java index b3bdf783f..46df5ae02 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java @@ -39,7 +39,6 @@ import java.util.zip.ZipOutputStream; import org.aspectj.apache.bcel.classfile.ClassParser; import org.aspectj.apache.bcel.classfile.JavaClass; import org.aspectj.asm.AsmManager; -import org.aspectj.asm.IHierarchy; import org.aspectj.asm.IProgramElement; import org.aspectj.asm.internal.AspectJElementHierarchy; import org.aspectj.bridge.IMessage; @@ -228,7 +227,8 @@ public class BcelWeaver { /** * - * @param inFile directory containing classes or zip/jar class archive + * @param inFile + * directory containing classes or zip/jar class archive */ public void addLibraryJarFile(File inFile) throws IOException { List<ResolvedType> addedAspects = null; @@ -281,7 +281,8 @@ public class BcelWeaver { /** * Look for .class files that represent aspects in the supplied directory - return the list of accumulated aspects. * - * @param directory the directory in which to look for Aspect .class files + * @param directory + * the directory in which to look for Aspect .class files * @return the list of discovered aspects * @throws FileNotFoundException * @throws IOException @@ -309,9 +310,12 @@ public class BcelWeaver { * Determine if the supplied bytes represent an aspect, if they do then create a ResolvedType instance for the aspect and return * it, otherwise return null * - * @param classbytes the classbytes that might represent an aspect - * @param name the name of the class - * @param directory directory which contained the class file + * @param classbytes + * the classbytes that might represent an aspect + * @param name + * the name of the class + * @param directory + * directory which contained the class file * @return a ResolvedType if the classbytes represent an aspect, otherwise null */ private ResolvedType isAspect(byte[] classbytes, String name, File dir) throws IOException { @@ -1004,6 +1008,8 @@ public class BcelWeaver { return c; } + private Set<IProgramElement> candidatesForRemoval = null; + // variation of "weave" that sources class files from an external source. public Collection<String> weave(IClassFileProvider input) throws IOException { if (trace.isTraceEnabled()) { @@ -1013,11 +1019,16 @@ public class BcelWeaver { Collection<String> wovenClassNames = new ArrayList<String>(); IWeaveRequestor requestor = input.getRequestor(); - for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) { - UnwovenClassFile classFile = i.next(); - if (world.getModel() != null /* AsmManager.isCreatingModel() */&& !isBatchWeave) { - // remove all relationships where this file being woven is the target of the relationship - world.getModelAsAsmManager().removeRelationshipsTargettingThisType(classFile.getClassName()); + if (world.getModel() != null && world.isMinimalModel()) { + candidatesForRemoval = new HashSet<IProgramElement>(); + } + if (world.getModel() != null && !isBatchWeave) { + AsmManager manager = world.getModelAsAsmManager(); + for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) { + UnwovenClassFile classFile = i.next(); + // remove all relationships where this file being woven is + // the target of the relationship + manager.removeRelationshipsTargettingThisType(classFile.getClassName()); } } @@ -1184,6 +1195,9 @@ public class BcelWeaver { if (trace.isTraceEnabled()) { trace.exit("weave", wovenClassNames); } + if (world.getModel() != null && world.isMinimalModel()) { + candidatesForRemoval.clear(); + } return wovenClassNames; } @@ -1716,45 +1730,37 @@ public class BcelWeaver { // can we remove it from the model now? we know it contains no relationship endpoints... AsmManager model = world.getModelAsAsmManager(); if (world.isMinimalModel() && model != null && !classType.isAspect()) { - IHierarchy hierarchy = model.getHierarchy(); + AspectJElementHierarchy hierarchy = (AspectJElementHierarchy) model.getHierarchy(); String pkgname = classType.getResolvedTypeX().getPackageName(); String tname = classType.getResolvedTypeX().getSimpleBaseName(); IProgramElement typeElement = hierarchy.findElementForType(pkgname, tname); + if (typeElement != null && hasInnerType(typeElement)) { + // Cannot remove it right now (has inner type), schedule it + // for possible deletion later if all inner types are + // removed + candidatesForRemoval.add(typeElement); + } if (typeElement != null && !hasInnerType(typeElement)) { - - // Set<String> deleted = new HashSet<String>(); - // deleted.add(model.getCanonicalFilePath(typeElement.getSourceLocation().getSourceFile())); - // hierarchy.updateHandleMap(deleted); IProgramElement parent = typeElement.getParent(); // parent may have children: PACKAGE DECL, IMPORT-REFERENCE, TYPE_DECL if (parent != null) { - // if it was the only type we should probably remove the others too. + // if it was the only type we should probably remove + // the others too. parent.removeChild(typeElement); if (parent.getKind().isSourceFile()) { - IProgramElement compilationUnit = parent; - boolean anyOtherTypeDeclarations = false; - for (IProgramElement child : compilationUnit.getChildren()) { - IProgramElement.Kind k = child.getKind(); - if (k.isType()) { - anyOtherTypeDeclarations = true; - break; - } - } - // If the compilation unit node contained no other types, there is no need to keep it - if (!anyOtherTypeDeclarations) { - IProgramElement cuParent = compilationUnit.getParent(); - if (cuParent != null) { - compilationUnit.setParent(null); - cuParent.removeChild(compilationUnit); - } - // need to update some caches and structures too? - ((AspectJElementHierarchy) model.getHierarchy()).forget(parent, typeElement); - } else { - ((AspectJElementHierarchy) model.getHierarchy()).forget(null, typeElement); - } + removeSourceFileIfNoMoreTypeDeclarationsInside(hierarchy, typeElement, parent); } else { - ((AspectJElementHierarchy) model.getHierarchy()).forget(null, typeElement); + hierarchy.forget(null, typeElement); + // At this point, the child has been removed. We + // should now check if the parent is in our + // 'candidatesForRemoval' set. If it is then that + // means we were going to remove it but it had a + // child. Now we can check if it still has a child - + // if it doesn't it can also be removed! + + walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(hierarchy, tname, parent); } + } } } @@ -1779,6 +1785,64 @@ public class BcelWeaver { } } + private void walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(AspectJElementHierarchy hierarchy, String tname, + IProgramElement typeThatHasChildRemoved) { + // typeThatHasChildRemoved might be a source file, type or a method/ctor + // - for a method/ctor find the type/sourcefile + while (typeThatHasChildRemoved != null + && !(typeThatHasChildRemoved.getKind().isType() || typeThatHasChildRemoved.getKind().isSourceFile())) { + // this will take us 'up' through methods that contain anonymous + // inner classes + typeThatHasChildRemoved = typeThatHasChildRemoved.getParent(); + } + // now typeThatHasChildRemoved points to the type or sourcefile that has + // had something removed + if (candidatesForRemoval.contains(typeThatHasChildRemoved) && !hasInnerType(typeThatHasChildRemoved)) { + // now we can get rid of it + IProgramElement parent = typeThatHasChildRemoved.getParent(); + if (parent != null) { + parent.removeChild(typeThatHasChildRemoved); + candidatesForRemoval.remove(typeThatHasChildRemoved); + if (parent.getKind().isSourceFile()) { + removeSourceFileIfNoMoreTypeDeclarationsInside(hierarchy, typeThatHasChildRemoved, parent); + // System.out.println("Removed on second pass: " + + // typeThatHasChildRemoved.getName()); + } else { + // System.out.println("On later pass, parent of type " + + // typeThatHasChildRemoved.getName() + // + " was found not to be a sourcefile, recursing up..."); + walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(hierarchy, tname, parent); + } + } + } + } + + private void removeSourceFileIfNoMoreTypeDeclarationsInside(AspectJElementHierarchy hierarchy, IProgramElement typeElement, + IProgramElement sourceFileNode) { + IProgramElement compilationUnit = sourceFileNode; + boolean anyOtherTypeDeclarations = false; + for (IProgramElement child : compilationUnit.getChildren()) { + IProgramElement.Kind k = child.getKind(); + if (k.isType()) { + anyOtherTypeDeclarations = true; + break; + } + } + // If the compilation unit node contained no + // other types, there is no need to keep it + if (!anyOtherTypeDeclarations) { + IProgramElement cuParent = compilationUnit.getParent(); + if (cuParent != null) { + compilationUnit.setParent(null); + cuParent.removeChild(compilationUnit); + } + // need to update some caches and structures too? + hierarchy.forget(sourceFileNode, typeElement); + } else { + hierarchy.forget(null, typeElement); + } + } + // ---- writing // TODO could be smarter - really only matters if inner type has been woven, but there is a chance we haven't woven it *yet* @@ -1858,8 +1922,10 @@ public class BcelWeaver { * Perform a fast match of the specified list of shadowmungers against the specified type. A subset of those that might match is * returned. * - * @param list list of all shadow mungers that might match - * @param type the target type + * @param list + * list of all shadow mungers that might match + * @param type + * the target type * @return a list of shadow mungers that might match with those that cannot (according to fast match rules) removed */ private List<ShadowMunger> fastMatch(List<ShadowMunger> list, ResolvedType type) { |