diff options
author | aclement <aclement> | 2005-10-27 15:49:49 +0000 |
---|---|---|
committer | aclement <aclement> | 2005-10-27 15:49:49 +0000 |
commit | 2da9b31be2c1e5af9d33b25be798f3a47362fb88 (patch) | |
tree | b4d01bfd737ce18060059f4a052938a632753522 | |
parent | 6ab78ee0e1d49a0e3f882ddf604061dc572cb427 (diff) | |
download | aspectj-2da9b31be2c1e5af9d33b25be798f3a47362fb88.tar.gz aspectj-2da9b31be2c1e5af9d33b25be798f3a47362fb88.zip |
testcode and fixes for pr99191: thanks to Helen.
-rw-r--r-- | tests/bugs150/pr99191/pr99191_1.java | 10 | ||||
-rw-r--r-- | tests/bugs150/pr99191/pr99191_2.java | 14 | ||||
-rw-r--r-- | tests/bugs150/pr99191/pr99191_3.java | 10 | ||||
-rw-r--r-- | tests/bugs150/pr99191/pr99191_4.java | 16 | ||||
-rw-r--r-- | tests/bugs150/pr99191/pr99191_5.java | 10 | ||||
-rw-r--r-- | tests/bugs150/pr99191/pr99191_6.java | 15 | ||||
-rw-r--r-- | tests/src/org/aspectj/systemtest/ajc150/Ajc150Tests.java | 7 | ||||
-rw-r--r-- | tests/src/org/aspectj/systemtest/ajc150/ajc150.xml | 42 | ||||
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java | 91 |
9 files changed, 211 insertions, 4 deletions
diff --git a/tests/bugs150/pr99191/pr99191_1.java b/tests/bugs150/pr99191/pr99191_1.java new file mode 100644 index 000000000..f716b2748 --- /dev/null +++ b/tests/bugs150/pr99191/pr99191_1.java @@ -0,0 +1,10 @@ +@interface Annotation{} +aspect B { + + declare @field : int C.noSuchField : @Annotation; // should be an error + declare @field : int B.noSuchField : @Annotation; // should be an error + +} + +class C { +} diff --git a/tests/bugs150/pr99191/pr99191_2.java b/tests/bugs150/pr99191/pr99191_2.java new file mode 100644 index 000000000..aca5b53f2 --- /dev/null +++ b/tests/bugs150/pr99191/pr99191_2.java @@ -0,0 +1,14 @@ +@interface Annotation{} +aspect B { + declare @field : int C.anotherField : @Annotation; // should be woven + declare @field : int someField : @Annotation; // shouldn't have any errors + declare @field : int C.aField : @Annotation; // shouldn't have any errors +} + +class C { + @Annotation int aField = 1; +} + +aspect D { + public int C.anotherField; +} diff --git a/tests/bugs150/pr99191/pr99191_3.java b/tests/bugs150/pr99191/pr99191_3.java new file mode 100644 index 000000000..40bbbcad0 --- /dev/null +++ b/tests/bugs150/pr99191/pr99191_3.java @@ -0,0 +1,10 @@ +@interface Annotation{} +aspect B { + + declare @method : public * C.noSuchMethod(..) : @Annotation; // should be an error + declare @method : * B.noSuchMethod(..) : @Annotation; // should be an error + +} + +class C { +} diff --git a/tests/bugs150/pr99191/pr99191_4.java b/tests/bugs150/pr99191/pr99191_4.java new file mode 100644 index 000000000..600e804ce --- /dev/null +++ b/tests/bugs150/pr99191/pr99191_4.java @@ -0,0 +1,16 @@ +@interface Annotation{} +aspect B { + declare @method : public void C.anotherMethod(..) : @Annotation; // shouldn't have any errors + declare @method : * someMethod(..) : @Annotation; // shouldn't have any errors + declare @method : public void C.amethod(..) : @Annotation; // already get a warning for this, don't want an error saying method doesn't exist +} + +class C { + @Annotation public void amethod() { + } +} + +aspect D { + public void C.anotherMethod() { + } +} diff --git a/tests/bugs150/pr99191/pr99191_5.java b/tests/bugs150/pr99191/pr99191_5.java new file mode 100644 index 000000000..71a697316 --- /dev/null +++ b/tests/bugs150/pr99191/pr99191_5.java @@ -0,0 +1,10 @@ +@interface Annotation{} +aspect B { + + declare @constructor : C.new(String) : @Annotation; // should be an error + declare @constructor : B.new(int) : @Annotation; // should be an error + +} + +class C { +} diff --git a/tests/bugs150/pr99191/pr99191_6.java b/tests/bugs150/pr99191/pr99191_6.java new file mode 100644 index 000000000..4f176bb66 --- /dev/null +++ b/tests/bugs150/pr99191/pr99191_6.java @@ -0,0 +1,15 @@ +@interface Annotation{} +aspect B { + declare @constructor : C.new(String) : @Annotation; // shouldn't have any errors + declare @constructor : *.new(int) : @Annotation; // shouldn't have any errors + declare @constructor : *.new(int) : @Annotation; // already get a warning for this, don't want an error saying method doesn't exist +} + +class C { + @Annotation public C(int i) { + } +} + +aspect D { + public C.new(String s){} +} diff --git a/tests/src/org/aspectj/systemtest/ajc150/Ajc150Tests.java b/tests/src/org/aspectj/systemtest/ajc150/Ajc150Tests.java index fc05dad53..1829956cf 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/Ajc150Tests.java +++ b/tests/src/org/aspectj/systemtest/ajc150/Ajc150Tests.java @@ -64,6 +64,13 @@ public class Ajc150Tests extends org.aspectj.testing.XMLBasedAjcTestCase { public void testIncompatibleClassChangeError_pr113630_1() {runTest("IncompatibleClassChangeError - errorscenario");} public void testIncompatibleClassChangeError_pr113630_2() {runTest("IncompatibleClassChangeError - workingscenario");} + + public void testDeclareAnnotationOnNonExistentType_pr99191_1() { runTest("declare annotation on non existent type - 1");} + public void testDeclareAnnotationOnNonExistentType_pr99191_2() { runTest("declare annotation on non existent type - 2");} + public void testDeclareAnnotationOnNonExistentType_pr99191_3() { runTest("declare annotation on non existent type - 3");} + public void testDeclareAnnotationOnNonExistentType_pr99191_4() { runTest("declare annotation on non existent type - 4");} + public void testDeclareAnnotationOnNonExistentType_pr99191_5() { runTest("declare annotation on non existent type - 5");} + public void testBadGenericSigAttribute_pr110927() { runTest("cant create signature attribute"); Signature sig = GenericsTests.getClassSignature(ajc,"I"); diff --git a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml index b476f9e39..78e4d9318 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml @@ -10,6 +10,48 @@ <ajc-test dir="bugs150" title="Problem with constructor ITDs"> <compile files="pr112783.aj" options="-1.5"/> </ajc-test> + + + <ajc-test dir="bugs150/pr99191" title="declare annotation on non existent type - 1"> + <compile files="pr99191_1.java" options="-1.5"> + <message kind="error" line="4" text="The field 'int C.noSuchField' does not exist"/> + <message kind="error" line="5" text="The field 'int B.noSuchField' does not exist"/> + </compile> + </ajc-test> + + <!-- Currently a warning doesn't occur if the annotation is already on the field + (see bug 113029). If this is fixed, need to add check for this warning to this + test as in test "declare annotation on non existent type - 4" --> + <ajc-test dir="bugs150/pr99191" title="declare annotation on non existent type - 2"> + <compile files="pr99191_2.java" options="-1.5"> + </compile> + </ajc-test> + + <ajc-test dir="bugs150/pr99191" title="declare annotation on non existent type - 3"> + <compile files="pr99191_3.java" options="-1.5"> + <message kind="error" line="4" text="The method 'public * C.noSuchMethod(..)' does not exist"/> + <message kind="error" line="5" text="The method '* B.noSuchMethod(..)' does not exist"/> + </compile> + </ajc-test> + + <ajc-test dir="bugs150/pr99191" title="declare annotation on non existent type - 4"> + <compile files="pr99191_4.java" options="-1.5"> + <message kind="warning" text="void C.amethod() - already has an annotation of type Annotation, cannot add a second instance [Xlint:elementAlreadyAnnotated]"/> + </compile> + </ajc-test> + + <ajc-test dir="bugs150/pr99191" title="declare annotation on non existent type - 5"> + <compile files="pr99191_5.java" options="-1.5"> + <message kind="error" line="4" text="The method 'C.new(java.lang.String)' does not exist"/> + <message kind="error" line="5" text="The method 'B.new(int)' does not exist"/> + </compile> + </ajc-test> + + <ajc-test dir="bugs150/pr99191" title="declare annotation on non existent type - 6"> + <compile files="pr99191_6.java" options="-1.5"> + <message kind="warning" text="void C.<init>(int) - already has an annotation of type Annotation, cannot add a second instance [Xlint:elementAlreadyAnnotated]"/> + </compile> + </ajc-test> <ajc-test dir="bugs150/pr113630/case1" title="IncompatibleClassChangeError - errorscenario"> <compile files="Bean.java,BeanTestCase.java,javaBean.java,propertyChanger.java,PropertySupportAspect5.aj" options="-1.5"> diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java index f4cb5ab32..179ec31b6 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java @@ -56,6 +56,7 @@ import org.aspectj.apache.bcel.generic.Type; import org.aspectj.apache.bcel.generic.annotation.AnnotationGen; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; +import org.aspectj.bridge.Message; import org.aspectj.bridge.WeaveMessage; import org.aspectj.bridge.context.CompilationAndWeavingContext; import org.aspectj.bridge.context.ContextToken; @@ -82,6 +83,7 @@ import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.WeaverMetrics; import org.aspectj.weaver.WeaverStateInfo; import org.aspectj.weaver.patterns.DeclareAnnotation; +import org.aspectj.weaver.patterns.ExactTypePattern; class BcelClassWeaver implements IClassWeaver { @@ -467,6 +469,8 @@ class BcelClassWeaver implements IClassWeaver { List decaMs = getMatchingSubset(allDecams,clazz.getType()); if (decaMs.isEmpty()) return false; // nothing to do if (!members.isEmpty()) { + Set unusedDecams = new HashSet(); + unusedDecams.addAll(decaMs); for (int memberCounter = 0;memberCounter<members.size();memberCounter++) { LazyMethodGen mg = (LazyMethodGen)members.get(memberCounter); if (!mg.getName().startsWith(NameMangler.PREFIX)) { @@ -479,7 +483,12 @@ class BcelClassWeaver implements IClassWeaver { DeclareAnnotation decaM = (DeclareAnnotation) iter.next(); if (decaM.matches(mg.getMemberView(),world)) { - if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) continue; // skip this one... + if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) { + // remove the declare @method since don't want an error when + // the annotation is already there + unusedDecams.remove(decaM); + continue; // skip this one... + } Annotation a = decaM.getAnnotationX().getBcelAnnotation(); AnnotationGen ag = new AnnotationGen(a,clazz.getConstantPoolGen(),true); @@ -494,6 +503,8 @@ class BcelClassWeaver implements IClassWeaver { reportMethodCtorWeavingMessage(clazz, mg.getMemberView(), decaM,mg.getDeclarationLineNumber()); isChanged = true; modificationOccured = true; + // remove the declare @method since have matched against it + unusedDecams.remove(decaM); } else { if (!decaM.isStarredAnnotationPattern()) worthRetrying.add(decaM); // an annotation is specified that might be put on by a subsequent decaf @@ -508,18 +519,26 @@ class BcelClassWeaver implements IClassWeaver { for (Iterator iter = worthRetrying.iterator(); iter.hasNext();) { DeclareAnnotation decaM = (DeclareAnnotation) iter.next(); if (decaM.matches(mg.getMemberView(),world)) { - if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) continue; // skip this one... + if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) { + // remove the declare @method since don't want an error when + // the annotation is already there + unusedDecams.remove(decaM); + continue; // skip this one... + } mg.addAnnotation(decaM.getAnnotationX()); AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaM.getSourceLocation(),clazz.getName(),mg.getMethod()); isChanged = true; modificationOccured = true; forRemoval.add(decaM); + // remove the declare @method since have matched against it + unusedDecams.remove(decaM); } } worthRetrying.removeAll(forRemoval); } } } + checkUnusedDeclareAtTypes(unusedDecams, false); } return isChanged; } @@ -791,7 +810,8 @@ class BcelClassWeaver implements IClassWeaver { if (decaFs.isEmpty()) return false; // nothing more to do Field[] fields = clazz.getFieldGens(); if (fields!=null) { - + Set unusedDecafs = new HashSet(); + unusedDecafs.addAll(decaFs); for (int fieldCounter = 0;fieldCounter<fields.length;fieldCounter++) { BcelField aBcelField = new BcelField(clazz.getBcelObjectType(),fields[fieldCounter]); if (!aBcelField.getName().startsWith(NameMangler.PREFIX)) { @@ -808,6 +828,9 @@ class BcelClassWeaver implements IClassWeaver { if (!dontAddTwice(decaF,dontAddMeTwice)){ if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)){ + // remove the declare @field since don't want an error when + // the annotation is already there + unusedDecafs.remove(decaF); continue; } @@ -833,6 +856,8 @@ class BcelClassWeaver implements IClassWeaver { reportFieldAnnotationWeavingMessage(clazz, fields, fieldCounter, decaF); isChanged = true; modificationOccured = true; + // remove the declare @field since have matched against it + unusedDecafs.remove(decaF); } else { if (!decaF.isStarredAnnotationPattern()) worthRetrying.add(decaF); // an annotation is specified that might be put on by a subsequent decaf @@ -848,22 +873,80 @@ class BcelClassWeaver implements IClassWeaver { DeclareAnnotation decaF = (DeclareAnnotation) iter.next(); if (decaF.matches(aBcelField,world)) { // below code is for recursive things - if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)) continue; // skip this one... + if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)) { + // remove the declare @field since don't want an error when + // the annotation is already there + unusedDecafs.remove(decaF); + continue; // skip this one... + } aBcelField.addAnnotation(decaF.getAnnotationX()); AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]); isChanged = true; modificationOccured = true; forRemoval.add(decaF); + // remove the declare @field since have matched against it + unusedDecafs.remove(decaF); } } worthRetrying.removeAll(forRemoval); } } } + checkUnusedDeclareAtTypes(unusedDecafs,true); } return isChanged; } + // bug 99191 - put out an error message if the type doesn't exist + /** + * Report an error if the reason a "declare @method/ctor/field" was not used was because the member + * specified does not exist. This method is passed some set of declare statements that didn't + * match and a flag indicating whether the set contains declare @field or declare @method/ctor + * entries. + */ + private void checkUnusedDeclareAtTypes(Set unusedDecaTs, boolean isDeclareAtField) { + for (Iterator iter = unusedDecaTs.iterator(); iter.hasNext();) { + DeclareAnnotation declA = (DeclareAnnotation) iter.next(); + + // Error if an exact type pattern was specified + if ((declA.isExactPattern() || + (declA.getSignaturePattern().getDeclaringType() instanceof ExactTypePattern)) + && (!declA.getSignaturePattern().getName().isAny() + || (declA.getKind() == DeclareAnnotation.AT_CONSTRUCTOR))) { + + // Quickly check if an ITD meets supplies the 'missing' member + boolean itdMatch = false; + List lst = clazz.getType().getInterTypeMungers(); + for (Iterator iterator = lst.iterator(); iterator.hasNext() && !itdMatch;) { + BcelTypeMunger element = (BcelTypeMunger) iterator.next(); + if (element.getMunger() instanceof NewFieldTypeMunger) { + NewFieldTypeMunger nftm = (NewFieldTypeMunger)element.getMunger(); + itdMatch = declA.getSignaturePattern().matches(nftm.getSignature(),world,false); + }else if (element.getMunger() instanceof NewMethodTypeMunger) { + NewMethodTypeMunger nmtm = (NewMethodTypeMunger)element.getMunger(); + itdMatch = declA.getSignaturePattern().matches(nmtm.getSignature(),world,false); + } else if (element.getMunger() instanceof NewConstructorTypeMunger) { + NewConstructorTypeMunger nctm = (NewConstructorTypeMunger)element.getMunger(); + itdMatch = declA.getSignaturePattern().matches(nctm.getSignature(),world,false); + } + } + if (!itdMatch) { + IMessage message = null; + if (isDeclareAtField) { + message = new Message( + "The field '"+ declA.getSignaturePattern().toString() + + "' does not exist", declA.getSourceLocation() , true); + } else { + message = new Message( + "The method '"+ declA.getSignaturePattern().toString() + + "' does not exist", declA.getSourceLocation() , true); + } + world.getMessageHandler().handleMessage(message); + } + } + } + } + // TAG: WeavingMessage private void reportFieldAnnotationWeavingMessage(LazyClassGen clazz, Field[] fields, int fieldCounter, DeclareAnnotation decaF) { if (!getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)){ |