diff options
20 files changed, 311 insertions, 33 deletions
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/World.java b/org.aspectj.matcher/src/org/aspectj/weaver/World.java index 7e6116e0e..91571713b 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/World.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/World.java @@ -55,21 +55,18 @@ import org.aspectj.weaver.tools.TraceFactory; * A World is a collection of known types and crosscutting members. */ public abstract class World implements Dump.INode { + /** handler for any messages produced during resolution etc. */ private IMessageHandler messageHandler = IMessageHandler.SYSTEM_ERR; - /** - * handler for cross-reference information produced during the weaving process - */ + /** handler for cross-reference information produced during the weaving process */ private ICrossReferenceHandler xrefHandler = null; - /** - * Currently 'active' scope in which to lookup (resolve) typevariable references - */ + /** Currently 'active' scope in which to lookup (resolve) typevariable references */ private TypeVariableDeclaringElement typeVariableLookupScope; /** The heart of the world, a map from type signatures to resolved types */ - protected TypeMap typeMap = new TypeMap(this); // Signature to ResolvedType + protected TypeMap typeMap = new TypeMap(this); /** New pointcut designators this world supports */ private Set<PointcutDesignatorHandler> pointcutDesignators; @@ -99,9 +96,7 @@ public abstract class World implements Dump.INode { /** XhasMember option setting passed down to weaver */ private boolean XhasMember = false; - /** - * Xpinpoint controls whether we put out developer info showing the source of messages - */ + /** Xpinpoint controls whether we put out developer info showing the source of messages */ private boolean Xpinpoint = false; /** When behaving in a Java 5 way autoboxing is considered */ @@ -117,13 +112,9 @@ public abstract class World implements Dump.INode { /** The level of the aspectjrt.jar the code we generate needs to run on */ private String targetAspectjRuntimeLevel = Constants.RUNTIME_LEVEL_DEFAULT; - /** Flags for the new joinpoints that are 'optional' */ - private boolean optionalJoinpoint_ArrayConstruction = false; // Command line - // flag: - // "-Xjoinpoints:arrayconstruction" - private boolean optionalJoinpoint_Synchronization = false; // Command line - // flag: - // "-Xjoinpoints:synchronization" + /** Flags for the new joinpoints that are 'optional': -Xjoinpoints:arrayconstruction -Xjoinpoints:synchronization */ + private boolean optionalJoinpoint_ArrayConstruction = false; + private boolean optionalJoinpoint_Synchronization = false; private boolean addSerialVerUID = false; diff --git a/tests/bugs170/ltw/Anno.java b/tests/bugs170/ltw/Anno.java new file mode 100644 index 000000000..cf40d6f9c --- /dev/null +++ b/tests/bugs170/ltw/Anno.java @@ -0,0 +1,11 @@ +package ch.annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Anno { + +} diff --git a/tests/bugs170/ltw/Main.java b/tests/bugs170/ltw/Main.java new file mode 100644 index 000000000..efbd8a9b6 --- /dev/null +++ b/tests/bugs170/ltw/Main.java @@ -0,0 +1,10 @@ +package ch.tests; + +public class Main { + + public static void main(String[] args) { + MyObject mo = new MyObject(); + mo.myInt = 13; + mo.setMyInt(13); + } +} diff --git a/tests/bugs170/ltw/MyObject.java b/tests/bugs170/ltw/MyObject.java new file mode 100644 index 000000000..46cb9301a --- /dev/null +++ b/tests/bugs170/ltw/MyObject.java @@ -0,0 +1,13 @@ +package ch.tests; + +public class MyObject { + public int myInt; + + public int getMyInt() { + return myInt; + } + + public void setMyInt(int myInt) { + this.myInt = myInt; + } +} diff --git a/tests/bugs170/ltw/TriggerAll.java b/tests/bugs170/ltw/TriggerAll.java new file mode 100644 index 000000000..dcfdeb06b --- /dev/null +++ b/tests/bugs170/ltw/TriggerAll.java @@ -0,0 +1,11 @@ +package ch.aspects; + +import ch.annotation.Anno; + +public aspect TriggerAll { + declare @field : * *.myInt : @Anno; + + before(Anno anno) : @annotation(anno) && set(* *.myInt) { + System.out.println("Triggered"); + } +} diff --git a/tests/bugs170/ltw/aop.xml b/tests/bugs170/ltw/aop.xml new file mode 100644 index 000000000..a06aa21e6 --- /dev/null +++ b/tests/bugs170/ltw/aop.xml @@ -0,0 +1,7 @@ +<aspectj> +<aspects> +<aspect name="ch.aspects.TriggerAll"/> +</aspects> +<weaver options="-Xset:completeBinaryTypes=true"/> +</aspectj> + diff --git a/tests/bugs170/ltw/ch/annotation/Anno.class b/tests/bugs170/ltw/ch/annotation/Anno.class Binary files differnew file mode 100644 index 000000000..aa04cccb8 --- /dev/null +++ b/tests/bugs170/ltw/ch/annotation/Anno.class diff --git a/tests/bugs170/ltw/ch/aspects/TriggerAll.class b/tests/bugs170/ltw/ch/aspects/TriggerAll.class Binary files differnew file mode 100644 index 000000000..e812f6479 --- /dev/null +++ b/tests/bugs170/ltw/ch/aspects/TriggerAll.class diff --git a/tests/bugs170/ltw/ch/tests/Main.class b/tests/bugs170/ltw/ch/tests/Main.class Binary files differnew file mode 100644 index 000000000..ef3360e45 --- /dev/null +++ b/tests/bugs170/ltw/ch/tests/Main.class diff --git a/tests/bugs170/ltw/ch/tests/MyObject.class b/tests/bugs170/ltw/ch/tests/MyObject.class Binary files differnew file mode 100644 index 000000000..edb3b1d99 --- /dev/null +++ b/tests/bugs170/ltw/ch/tests/MyObject.class diff --git a/tests/bugs170/ltw/ch/tests/X b/tests/bugs170/ltw/ch/tests/X new file mode 100644 index 000000000..b39f1f3cd --- /dev/null +++ b/tests/bugs170/ltw/ch/tests/X @@ -0,0 +1,153 @@ +Compiled from "Main.java" +public class ch.tests.Main extends java.lang.Object + SourceFile: "Main.java" + org.aspectj.weaver.WeaverVersion: length = 0xC + 00 07 00 00 00 00 01 34 47 FFFFFFCD 60 28 + org.aspectj.weaver.WeaverState: length = 0xED + 53 00 00 00 00 01 00 17 4C 63 68 2F 61 73 70 65 + 63 74 73 2F 54 72 69 67 67 65 72 41 6C 6C 3B 00 + 00 00 FFFFFFCA 00 22 00 00 01 79 00 21 00 01 00 03 00 + 00 00 00 00 02 00 01 00 05 00 06 00 01 00 07 00 + 00 00 2F 00 01 00 01 00 00 00 05 2A FFFFFFB7 00 08 FFFFFFB1 + 00 00 00 02 00 0A 00 00 00 06 00 01 00 00 00 03 + 00 0B 00 00 00 0C 00 01 00 00 00 05 00 0C 00 0D + 00 00 00 09 00 0E 00 0F 00 02 00 10 00 00 00 08 + 00 00 00 05 00 00 00 43 00 07 00 00 00 55 00 02 + 00 02 00 00 00 15 FFFFFFBB 00 11 59 FFFFFFB7 00 13 4C 2B 10 + 0D FFFFFFB5 00 14 2B 10 0D FFFFFFB6 00 18 FFFFFFB1 00 00 00 02 00 + 0A 00 00 00 12 00 04 00 00 00 06 00 08 00 07 00 + 0E 00 08 00 14 00 09 00 0B 00 00 00 16 00 02 00 + 00 00 15 00 1C 00 1D 00 00 00 08 00 0D 00 1E 00 + 1F 00 01 00 01 00 20 00 00 00 02 00 21 + minor version: 0 + major version: 49 + Constant pool: +const #1 = class #2; // ch/tests/Main +const #2 = Asciz ch/tests/Main; +const #3 = class #4; // java/lang/Object +const #4 = Asciz java/lang/Object; +const #5 = Asciz <init>; +const #6 = Asciz ()V; +const #7 = Asciz Code; +const #8 = Method #3.#9; // java/lang/Object."<init>":()V +const #9 = NameAndType #5:#6;// "<init>":()V +const #10 = Asciz LineNumberTable; +const #11 = Asciz LocalVariableTable; +const #12 = Asciz this; +const #13 = Asciz Lch/tests/Main;; +const #14 = Asciz main; +const #15 = Asciz ([Ljava/lang/String;)V; +const #16 = Asciz org.aspectj.weaver.MethodDeclarationLineNumber; +const #17 = class #18; // ch/tests/MyObject +const #18 = Asciz ch/tests/MyObject; +const #19 = Method #17.#9; // ch/tests/MyObject."<init>":()V +const #20 = Field #17.#21; // ch/tests/MyObject.myInt:I +const #21 = NameAndType #22:#23;// myInt:I +const #22 = Asciz myInt; +const #23 = Asciz I; +const #24 = Method #17.#25; // ch/tests/MyObject.setMyInt:(I)V +const #25 = NameAndType #26:#27;// setMyInt:(I)V +const #26 = Asciz setMyInt; +const #27 = Asciz (I)V; +const #28 = Asciz args; +const #29 = Asciz [Ljava/lang/String;; +const #30 = Asciz mo; +const #31 = Asciz Lch/tests/MyObject;; +const #32 = Asciz SourceFile; +const #33 = Asciz Main.java; +const #34 = Asciz aspectOf; +const #35 = Asciz ()Lch/aspects/TriggerAll;; +const #36 = NameAndType #34:#35;// aspectOf:()Lch/aspects/TriggerAll; +const #37 = Asciz ch/aspects/TriggerAll; +const #38 = class #37; // ch/aspects/TriggerAll +const #39 = Method #38.#36; // ch/aspects/TriggerAll.aspectOf:()Lch/aspects/TriggerAll; +const #40 = Asciz ch/annotation/Anno; +const #41 = class #40; // ch/annotation/Anno +const #42 = Asciz Synthetic; +const #43 = Asciz ajc$anno$0; +const #44 = Asciz Ljava/lang/annotation/Annotation;; +const #45 = NameAndType #43:#44;// ajc$anno$0:Ljava/lang/annotation/Annotation; +const #46 = Field #1.#45; // ch/tests/Main.ajc$anno$0:Ljava/lang/annotation/Annotation; +const #47 = String #22; // myInt +const #48 = Asciz getDeclaredField; +const #49 = Asciz (Ljava/lang/String;)Ljava/lang/reflect/Field;; +const #50 = NameAndType #48:#49;// getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field; +const #51 = Asciz java/lang/Class; +const #52 = class #51; // java/lang/Class +const #53 = Method #52.#50; // java/lang/Class.getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field; +const #54 = Asciz getAnnotation; +const #55 = Asciz (Ljava/lang/Class;)Ljava/lang/annotation/Annotation;; +const #56 = NameAndType #54:#55;// getAnnotation:(Ljava/lang/Class;)Ljava/lang/annotation/Annotation; +const #57 = Asciz java/lang/reflect/Field; +const #58 = class #57; // java/lang/reflect/Field +const #59 = Method #58.#56; // java/lang/reflect/Field.getAnnotation:(Ljava/lang/Class;)Ljava/lang/annotation/Annotation; +const #60 = Asciz ajc$before$ch_aspects_TriggerAll$1$daa92a69; +const #61 = Asciz (Lch/annotation/Anno;)V; +const #62 = NameAndType #60:#61;// ajc$before$ch_aspects_TriggerAll$1$daa92a69:(Lch/annotation/Anno;)V +const #63 = Method #38.#62; // ch/aspects/TriggerAll.ajc$before$ch_aspects_TriggerAll$1$daa92a69:(Lch/annotation/Anno;)V +const #64 = Asciz org.aspectj.weaver.WeaverVersion; +const #65 = Asciz org.aspectj.weaver.WeaverState; + +{ +private static java.lang.annotation.Annotation ajc$anno$0; + Synthetic: true + +public ch.tests.Main(); + Code: + Stack=1, Locals=1, Args_size=1 + 0: aload_0 + 1: invokespecial #8; //Method java/lang/Object."<init>":()V + 4: return + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lch/tests/Main; + + LineNumberTable: + line 3: 0 + + +public static void main(java.lang.String[]); + org.aspectj.weaver.MethodDeclarationLineNumber: length = 0x8 + 00 00 00 05 00 00 00 43 + Code: + Stack=5, Locals=2, Args_size=1 + 0: new #17; //class ch/tests/MyObject + 3: dup + 4: invokespecial #19; //Method ch/tests/MyObject."<init>":()V + 7: astore_1 + 8: aload_1 + 9: bipush 13 + 11: invokestatic #39; //Method ch/aspects/TriggerAll.aspectOf:()Lch/aspects/TriggerAll; + 14: getstatic #46; //Field ajc$anno$0:Ljava/lang/annotation/Annotation; + 17: dup + 18: ifnonnull 38 + 21: pop + 22: ldc #17; //class ch/tests/MyObject + 24: ldc #47; //String myInt + 26: invokevirtual #53; //Method java/lang/Class.getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field; + 29: ldc #41; //class ch/annotation/Anno + 31: invokevirtual #59; //Method java/lang/reflect/Field.getAnnotation:(Ljava/lang/Class;)Ljava/lang/annotation/Annotation; + 34: dup + 35: putstatic #46; //Field ajc$anno$0:Ljava/lang/annotation/Annotation; + 38: nop + 39: checkcast #41; //class ch/annotation/Anno + 42: invokevirtual #63; //Method ch/aspects/TriggerAll.ajc$before$ch_aspects_TriggerAll$1$daa92a69:(Lch/annotation/Anno;)V + 45: putfield #20; //Field ch/tests/MyObject.myInt:I + 48: aload_1 + 49: bipush 13 + 51: invokevirtual #24; //Method ch/tests/MyObject.setMyInt:(I)V + 54: return + LocalVariableTable: + Start Length Slot Name Signature + 0 55 0 args [Ljava/lang/String; + 8 47 1 mo Lch/tests/MyObject; + + LineNumberTable: + line 6: 0 + line 7: 8 + line 8: 48 + line 9: 54 + + +} + diff --git a/tests/bugs170/xmldefs/AnnoBoolean.class b/tests/bugs170/xmldefs/AnnoBoolean.class Binary files differdeleted file mode 100644 index 33b76156a..000000000 --- a/tests/bugs170/xmldefs/AnnoBoolean.class +++ /dev/null diff --git a/tests/bugs170/xmldefs/AnnoClass.class b/tests/bugs170/xmldefs/AnnoClass.class Binary files differdeleted file mode 100644 index 4071d56d6..000000000 --- a/tests/bugs170/xmldefs/AnnoClass.class +++ /dev/null diff --git a/tests/bugs170/xmldefs/AnnoLong.class b/tests/bugs170/xmldefs/AnnoLong.class Binary files differdeleted file mode 100644 index a7990fbad..000000000 --- a/tests/bugs170/xmldefs/AnnoLong.class +++ /dev/null diff --git a/tests/bugs170/xmldefs/AnnoString.class b/tests/bugs170/xmldefs/AnnoString.class Binary files differdeleted file mode 100644 index ba0e8eaf7..000000000 --- a/tests/bugs170/xmldefs/AnnoString.class +++ /dev/null diff --git a/tests/bugs170/xmldefs/Foo.class b/tests/bugs170/xmldefs/Foo.class Binary files differdeleted file mode 100644 index eaa12c965..000000000 --- a/tests/bugs170/xmldefs/Foo.class +++ /dev/null diff --git a/tests/src/org/aspectj/systemtest/ajc170/Ajc170Tests.java b/tests/src/org/aspectj/systemtest/ajc170/Ajc170Tests.java index 907464990..c78bd02bd 100644 --- a/tests/src/org/aspectj/systemtest/ajc170/Ajc170Tests.java +++ b/tests/src/org/aspectj/systemtest/ajc170/Ajc170Tests.java @@ -31,6 +31,19 @@ import org.aspectj.weaver.tools.StandardPointcutParser; */ public class Ajc170Tests extends org.aspectj.testing.XMLBasedAjcTestCase { + + public void testDecAtFieldOrderingLTW1() { + runTest("dec at field ordering ltw 1"); + } + + public void testDecAtFieldOrdering1() { + runTest("dec at field ordering 1"); + } + +// public void testDecAtFieldOrdering2() { +// runTest("dec at field ordering 2"); +// } + public void testXmlDefsDeclareAnnoMethod() { runTest("xml defined dec at method"); } diff --git a/tests/src/org/aspectj/systemtest/ajc170/ajc170.xml b/tests/src/org/aspectj/systemtest/ajc170/ajc170.xml index daed3a8e7..953edf874 100644 --- a/tests/src/org/aspectj/systemtest/ajc170/ajc170.xml +++ b/tests/src/org/aspectj/systemtest/ajc170/ajc170.xml @@ -3,6 +3,37 @@ <suite> + <ajc-test dir="bugs170/ltw" title="dec at field ordering 1"> + <compile files="Anno.java TriggerAll.java MyObject.java Main.java" options="-1.5"/> + <run class="ch.tests.Main"> + <stdout> + <line text="Triggered"/> + <line text="Triggered"/> + </stdout> + </run> + </ajc-test> + + <ajc-test dir="bugs170/ltw" title="dec at field ordering 2"> + <compile files="Anno.java Main.java TriggerAll.java MyObject.java" options="-1.5"/> + <run class="ch.tests.Main"> + <stdout> + <line text="Triggered"/> + <line text="Triggered"/> + </stdout> + </run> + </ajc-test> + + <ajc-test dir="bugs170/ltw" title="dec at field ordering ltw 1"> + <compile files="Anno.java Main.java MyObject.java" options="-1.5"/> + <compile files="TriggerAll.java" options="-Xlint:ignore -1.5 "/> + <run class="ch.tests.Main" ltw="aop.xml"> + <stdout> + <line text="Triggered"/> + <line text="Triggered"/> + </stdout> + </run> + </ajc-test> + <ajc-test dir="bugs170/xmldefs" title="xml defined dec at method"> <compile files="Hello.java Anno.java" options="-1.5"/> <run class="Hello" ltw="aop.xml"> diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index fcf61a085..ac9bacf84 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Set; import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ClassFormatException; import org.aspectj.apache.bcel.classfile.ConstantPool; import org.aspectj.apache.bcel.classfile.Signature; import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; @@ -739,13 +740,19 @@ public class BcelTypeMunger extends ConcreteTypeMunger { } protected LazyMethodGen makeMethodGen(LazyClassGen gen, ResolvedMember member) { - LazyMethodGen ret = new LazyMethodGen(member.getModifiers(), BcelWorld.makeBcelType(member.getReturnType()), - member.getName(), BcelWorld.makeBcelTypes(member.getParameterTypes()), UnresolvedType.getNames(member - .getExceptions()), gen); - - // 43972 : Static crosscutting makes interfaces unusable for javac - // ret.makeSynthetic(); - return ret; + try { + Type returnType = BcelWorld.makeBcelType(member.getReturnType()); + Type[] parameterTypes = BcelWorld.makeBcelTypes(member.getParameterTypes()); + LazyMethodGen ret = new LazyMethodGen(member.getModifiers(), returnType, + member.getName(), parameterTypes, UnresolvedType.getNames(member + .getExceptions()), gen); + + // 43972 : Static crosscutting makes interfaces unusable for javac + // ret.makeSynthetic(); + return ret; + } catch (ClassFormatException cfe) { + throw new RuntimeException("Problem with makeMethodGen for method "+member.getName()+" in type "+gen.getName()+" ret="+member.getReturnType(),cfe); + } } protected FieldGen makeFieldGen(LazyClassGen gen, ResolvedMember member) { diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java index f16ed3491..c46c68985 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java @@ -791,7 +791,28 @@ public class BcelWorld extends World implements Repository { } return didSomething; } - + + /** + * Apply the specified declare @field construct to any matching fields in the specified type. + * @param deca the declare annotation targeting fields + * @param type the type to check for members matching the declare annotation + * @return true if something matched and the type was modified + */ + private boolean applyDeclareAtField(DeclareAnnotation deca, ResolvedType type) { + boolean changedType = false; + ResolvedMember[] fields = type.getDeclaredFields(); + for (ResolvedMember field: fields) { + if (deca.matches(field, this)) { + AnnotationAJ anno = deca.getAnnotation(); + if (!field.hasAnnotation(anno.getType())) { + field.addAnnotation(anno); + changedType=true; + } + } + } + return changedType; + } + /** * Checks for an @target() on the annotation and if found ensures it allows the annotation to be attached to the target type * that matched. @@ -842,29 +863,39 @@ public class BcelWorld extends World implements Repository { anAnnotationChangeOccurred = true; } } + + // apply declare @field + for (DeclareAnnotation deca: getCrosscuttingMembersSet().getDeclareAnnotationOnFields()) { + if (applyDeclareAtField(deca,onType)) { + anAnnotationChangeOccurred = true; + } + } while ((aParentChangeOccurred || anAnnotationChangeOccurred) && !decpToRepeat.isEmpty()) { anAnnotationChangeOccurred = aParentChangeOccurred = false; List<DeclareParents> decpToRepeatNextTime = new ArrayList<DeclareParents>(); - for (Iterator<DeclareParents> iter = decpToRepeat.iterator(); iter.hasNext();) { - DeclareParents decp = iter.next(); - boolean typeChanged = applyDeclareParents(decp, onType); - if (typeChanged) { + for (DeclareParents decp: decpToRepeat) { + if (applyDeclareParents(decp, onType)) { aParentChangeOccurred = true; } else { decpToRepeatNextTime.add(decp); } } - for (Iterator iter = getCrosscuttingMembersSet().getDeclareAnnotationOnTypes().iterator(); iter.hasNext();) { - DeclareAnnotation decA = (DeclareAnnotation) iter.next(); - boolean typeChanged = applyDeclareAtType(decA, onType, false); - if (typeChanged) { + for (DeclareAnnotation deca: getCrosscuttingMembersSet().getDeclareAnnotationOnTypes()) { + if (applyDeclareAtType(deca, onType, false)) { + anAnnotationChangeOccurred = true; + } + } + + for (DeclareAnnotation deca: getCrosscuttingMembersSet().getDeclareAnnotationOnFields()) { + if (applyDeclareAtField(deca, onType)) { anAnnotationChangeOccurred = true; } } decpToRepeat = decpToRepeatNextTime; } + } @Override |