Browse Source

418129: annos on top most implementor method

tags/V1_7_4
Andy Clement 10 years ago
parent
commit
2393befbdf

+ 27
- 0
tests/bugs174/pr418129/Target.java View File

@@ -0,0 +1,27 @@
import java.lang.annotation.*;

interface Behavior {
String hello();
}

aspect Trait {
// public String Behavior.name;
public String Behavior.hello() {
return "hello";
}
}

public class Target implements Behavior {
public static aspect A {
// declare @field: * Target.name: @Tagged; // NO WORKY
declare @method: * Target.hello(..): @Tagged; // NO WORKY
}

public static void main(String []argv) throws Exception {
System.out.println(Target.class.getDeclaredMethod("hello").getDeclaredAnnotations()[0]);
}
}

@Retention(RetentionPolicy.RUNTIME)
@interface Tagged {}

+ 27
- 0
tests/bugs174/pr418129/Target2.java View File

@@ -0,0 +1,27 @@
import java.lang.annotation.*;

interface Behavior {
String hello();
}

aspect Trait {
// public String Behavior.name;
public String Behavior.hello() throws java.io.IOException {
return "hello";
}
}

public class Target2 implements Behavior {
public static aspect A {
// declare @field: * Target2.name: @Tagged; // NO WORKY
declare @method: * Target2.hello(..): @Tagged; // NO WORKY
}

public static void main(String []argv) throws Exception {
System.out.println(Target2.class.getDeclaredMethod("hello").getDeclaredAnnotations()[0]);
}
}

@Retention(RetentionPolicy.RUNTIME)
@interface Tagged {}

+ 27
- 0
tests/bugs174/pr418129/Target3.java View File

@@ -0,0 +1,27 @@
import java.lang.annotation.*;

interface Behavior {
String hello();
}

aspect Trait {
@Wibble
public String Behavior.hello() throws java.io.IOException {
return "hello";
}
}

public class Target3 implements Behavior {
public static aspect A {
declare @method: * Target3.hello(..): @Tagged;
}

public static void main(String []argv) throws Exception {
System.out.println(Target3.class.getDeclaredMethod("hello").getDeclaredAnnotations().length);
System.out.println(Target3.class.getDeclaredMethod("hello").getDeclaredAnnotations()[0]);
System.out.println(Target3.class.getDeclaredMethod("hello").getDeclaredAnnotations()[1]);
}
}

@Retention(RetentionPolicy.RUNTIME) @interface Tagged {}
@Retention(RetentionPolicy.RUNTIME) @interface Wibble {}

+ 25
- 0
tests/bugs174/pr418129/Target4.java View File

@@ -0,0 +1,25 @@
import java.lang.annotation.*;

interface Behavior {
String hello();
}

aspect Trait {
@Tagged(31)
public String Behavior.hello() throws java.io.IOException {
return "hello";
}
}

public class Target4 implements Behavior {
public static aspect A {
declare @method: * Target4.hello(..): @Tagged;
}

public static void main(String []argv) throws Exception {
System.out.println(Target4.class.getDeclaredMethod("hello").getDeclaredAnnotations().length);
System.out.println(Target4.class.getDeclaredMethod("hello").getDeclaredAnnotations()[0]);
}
}

@Retention(RetentionPolicy.RUNTIME) @interface Tagged { int value() default 42;}

+ 16
- 0
tests/src/org/aspectj/systemtest/ajc174/Ajc174Tests.java View File

@@ -21,6 +21,22 @@ import org.aspectj.testing.XMLBasedAjcTestCase;
*/
public class Ajc174Tests extends org.aspectj.testing.XMLBasedAjcTestCase {
public void testAnnotatedItd_418129() throws Exception {
runTest("annotated itd");
}
public void testAnnotatedItd_418129_2() throws Exception {
runTest("annotated itd 2");
}
public void testAnnotatedItd_418129_3() throws Exception {
runTest("annotated itd 3");
}
public void testAnnotatedItd_418129_4() throws Exception {
runTest("annotated itd 4");
}

public void testSuperItdCtor_413378() throws Exception {
runTest("super itd ctor");
}

+ 61
- 0
tests/src/org/aspectj/systemtest/ajc174/ajc174.xml View File

@@ -2,6 +2,67 @@

<suite>

<ajc-test dir="bugs174/pr418129" title="annotated itd">
<compile files="Target.java" options="-1.5 -showWeaveInfo">
<message kind="weave" text="Type 'Behavior' (Target.java) has intertyped method from 'Trait' (Target.java:'java.lang.String Behavior.hello()')"/>
<message kind="weave" text="Type 'Target' (Target.java) has intertyped method from 'Trait' (Target.java:'java.lang.String Behavior.hello()')"/>
<message kind="weave" text="'public java.lang.String Target.hello()' (Target.java) is annotated with @Tagged method annotation from 'Target$A' (Target.java:18)"/>
</compile>
<run class="Target">
<stdout>
<line text="@Tagged()"/>
</stdout>
</run>
</ajc-test>
<!-- declared with throws exception -->
<ajc-test dir="bugs174/pr418129" title="annotated itd 2">
<compile files="Target2.java" options="-1.5 -showWeaveInfo">
<message kind="weave" text="Type 'Behavior' (Target2.java) has intertyped method from 'Trait' (Target2.java:'java.lang.String Behavior.hello()')"/>
<message kind="weave" text="Type 'Target2' (Target2.java) has intertyped method from 'Trait' (Target2.java:'java.lang.String Behavior.hello()')"/>
<message kind="weave" text="'public java.lang.String Target2.hello()' (Target2.java) is annotated with @Tagged method annotation from 'Target2$A' (Target2.java:18)"/>
</compile>
<run class="Target2">
<stdout>
<line text="@Tagged()"/>
</stdout>
</run>
</ajc-test>
<!-- already annotated with another annotation -->
<ajc-test dir="bugs174/pr418129" title="annotated itd 3">
<compile files="Target3.java" options="-1.5 -showWeaveInfo">
<message kind="weave" text="Type 'Behavior' (Target3.java) has intertyped method from 'Trait' (Target3.java:'java.lang.String Behavior.hello()')"/>
<message kind="weave" text="Type 'Target3' (Target3.java) has intertyped method from 'Trait' (Target3.java:'java.lang.String Behavior.hello()')"/>
<message kind="weave" text="'public java.lang.String Target3.hello()' (Target3.java) is annotated with @Tagged method annotation from 'Target3$A' (Target3.java:16)"/>
</compile>
<run class="Target3">
<stdout>
<line text="2"/>
<line text="@Wibble()"/>
<line text="@Tagged()"/>
</stdout>
</run>
</ajc-test>
<!-- already annotated with the same annotation -->
<ajc-test dir="bugs174/pr418129" title="annotated itd 4">
<compile files="Target4.java" options="-1.5 -showWeaveInfo">
<message kind="weave" text="Type 'Behavior' (Target4.java) has intertyped method from 'Trait' (Target4.java:'java.lang.String Behavior.hello()')"/>
<message kind="weave" text="Type 'Target4' (Target4.java) has intertyped method from 'Trait' (Target4.java:'java.lang.String Behavior.hello()')"/>
<!-- warning turned off as it gets confusing - when the itd on the interface is hit by a deca -->
<!--
<message kind="warning" text="java.lang.String Target4.hello() - already has an annotation of type Tagged, cannot add a second instance [Xlint:elementAlreadyAnnotated]"/>
-->
</compile>
<run class="Target4">
<stdout>
<line text="1"/>
<line text="@Tagged(value=31)"/>
</stdout>
</run>
</ajc-test>
<ajc-test dir="bugs174/pr413378" title="super itd ctor">
<compile files="Code.java" options="-1.5 -showWeaveInfo">
<message kind="weave" text="Type 'Child' (Code.java) has intertyped constructor from 'MyTest' (Code.java:'void Child.&lt;init&gt;(java.lang.String, int)')"/>

+ 88
- 12
weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java View File

@@ -68,6 +68,7 @@ import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.IClassWeaver;
import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.MissingResolvedTypeWithKnownSignature;
import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.NewConstructorTypeMunger;
@@ -532,8 +533,7 @@ class BcelClassWeaver implements IClassWeaver {
// finally, if we changed, we add in the introduced methods.
if (isChanged) {
clazz.getOrCreateWeaverStateInfo(inReweavableMode);
weaveInAddedMethods(); // FIXME asc are these potentially affected
// by declare annotation?
weaveInAddedMethods();
}

if (inReweavableMode) {
@@ -893,15 +893,91 @@ class BcelClassWeaver implements IClassWeaver {
isChanged = weaveAtMethodOnITDSRepeatedly(allDecams, itdMethodsCtors, reportedProblems);
}

// deal with all the other methods...
List<LazyMethodGen> members = clazz.getMethodGens();
List<DeclareAnnotation> decaMs = getMatchingSubset(allDecams, clazz.getType());
if (decaMs.isEmpty()) {
return false; // nothing to do
}
Set<DeclareAnnotation> unusedDecams = new HashSet<DeclareAnnotation>();
unusedDecams.addAll(decaMs);

// These methods may have been targeted with declare annotation. Example: ITD on an interface
// where the top most implementor gets a real method. The top most implementor method
// is an 'addedLazyMethodGen'
if (addedLazyMethodGens!=null) {
for (LazyMethodGen method: addedLazyMethodGens) {
// They have no resolvedmember of their own, conjure one up for matching purposes
ResolvedMember resolvedmember =
new ResolvedMemberImpl(ResolvedMember.METHOD,method.getEnclosingClass().getType(),method.getAccessFlags(),
BcelWorld.fromBcel(method.getReturnType()),method.getName(),
BcelWorld.fromBcel(method.getArgumentTypes()),UnresolvedType.forNames(method.getDeclaredExceptions()));
resolvedmember.setAnnotationTypes(method.getAnnotationTypes());
resolvedmember.setAnnotations(method.getAnnotations());

List<DeclareAnnotation> worthRetrying = new ArrayList<DeclareAnnotation>();
boolean modificationOccured = false;
for (DeclareAnnotation decam: decaMs) {
if (decam.matches(resolvedmember, world)) {
if (doesAlreadyHaveAnnotation(resolvedmember, decam, reportedProblems,false)) {
// remove the declare @method since don't want an error when the annotation is already there
unusedDecams.remove(decam);
continue;
}

AnnotationGen a = ((BcelAnnotation) decam.getAnnotation()).getBcelAnnotation();
// create copy to get the annotation type into the right constant pool
AnnotationAJ aj = new BcelAnnotation(new AnnotationGen(a, clazz.getConstantPool(), true),world);
method.addAnnotation(aj);
resolvedmember.addAnnotation(decam.getAnnotation());

AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decam.getSourceLocation(),
clazz.getName(), resolvedmember, world.getModelAsAsmManager());
reportMethodCtorWeavingMessage(clazz, resolvedmember, decam, method.getDeclarationLineNumber());
isChanged = true;
modificationOccured = true;
unusedDecams.remove(decam);
} else if (!decam.isStarredAnnotationPattern()) {
// an annotation is specified that might be put on by a subsequent decaf
worthRetrying.add(decam);
}
}

// Multiple secondary passes
while (!worthRetrying.isEmpty() && modificationOccured) {
modificationOccured = false;
// lets have another go
List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
for (DeclareAnnotation decam : worthRetrying) {
if (decam.matches(resolvedmember, world)) {
if (doesAlreadyHaveAnnotation(resolvedmember, decam, reportedProblems,false)) {
// remove the declare @method since don't
// want an error when
// the annotation is already there
unusedDecams.remove(decam);
continue; // skip this one...
}
AnnotationGen a = ((BcelAnnotation) decam.getAnnotation()).getBcelAnnotation();
// create copy to get the annotation type into the right constant pool
AnnotationAJ aj = new BcelAnnotation(new AnnotationGen(a, clazz.getConstantPool(), true),world);
method.addAnnotation(aj);
resolvedmember.addAnnotation(decam.getAnnotation());
AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decam.getSourceLocation(),
clazz.getName(), resolvedmember, world.getModelAsAsmManager());// getMethod());
isChanged = true;
modificationOccured = true;
forRemoval.add(decam);
unusedDecams.remove(decam);
}
}
worthRetrying.removeAll(forRemoval);
}
}
}
// deal with all the other methods...
List<LazyMethodGen> members = clazz.getMethodGens();
if (!members.isEmpty()) {
Set<DeclareAnnotation> unusedDecams = new HashSet<DeclareAnnotation>();
unusedDecams.addAll(decaMs);
for (int memberCounter = 0; memberCounter < members.size(); memberCounter++) {
LazyMethodGen mg = members.get(memberCounter);
if (!mg.getName().startsWith(NameMangler.PREFIX)) {
@@ -913,7 +989,7 @@ class BcelClassWeaver implements IClassWeaver {
for (DeclareAnnotation decaM : decaMs) {

if (decaM.matches(mg.getMemberView(), world)) {
if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems)) {
if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems,true)) {
// remove the declare @method since don't want
// an error when the annotation is already there
unusedDecams.remove(decaM);
@@ -954,7 +1030,7 @@ class BcelClassWeaver implements IClassWeaver {
List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
for (DeclareAnnotation decaM : worthRetrying) {
if (decaM.matches(mg.getMemberView(), world)) {
if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems)) {
if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems,true)) {
// remove the declare @method since don't
// want an error when
// the annotation is already there
@@ -1347,7 +1423,7 @@ class BcelClassWeaver implements IClassWeaver {
unusedDecafs.remove(decaf);
} else {
if (!dontAddTwice(decaf, dontAddMeTwice)) {
if (doesAlreadyHaveAnnotation(field, decaf, reportedProblems)) {
if (doesAlreadyHaveAnnotation(field, decaf, reportedProblems,true )) {
// remove the declare @field since don't want an error when the annotation is already there
unusedDecafs.remove(decaf);
continue;
@@ -1389,7 +1465,7 @@ class BcelClassWeaver implements IClassWeaver {
} else {
// below code is for recursive things
unusedDecafs.remove(decaF);
if (doesAlreadyHaveAnnotation(field, decaF, reportedProblems)) {
if (doesAlreadyHaveAnnotation(field, decaF, reportedProblems,true)) {
continue;
}
field.addAnnotation(decaF.getAnnotation());
@@ -1486,9 +1562,9 @@ class BcelClassWeaver implements IClassWeaver {
/**
* Check if a resolved member (field/method/ctor) already has an annotation, if it does then put out a warning and return true
*/
private boolean doesAlreadyHaveAnnotation(ResolvedMember rm, DeclareAnnotation deca, List<Integer> reportedProblems) {
private boolean doesAlreadyHaveAnnotation(ResolvedMember rm, DeclareAnnotation deca, List<Integer> reportedProblems, boolean reportError) {
if (rm.hasAnnotation(deca.getAnnotationType())) {
if (world.getLint().elementAlreadyAnnotated.isEnabled()) {
if (reportError && world.getLint().elementAlreadyAnnotated.isEnabled()) {
Integer uniqueID = new Integer(rm.hashCode() * deca.hashCode());
if (!reportedProblems.contains(uniqueID)) {
reportedProblems.add(uniqueID);

+ 17
- 0
weaver/src/org/aspectj/weaver/bcel/BcelWorld.java View File

@@ -345,6 +345,22 @@ public class BcelWorld extends World implements Repository {
return ret;
}

public static Type[] makeBcelTypes(String[] types) {
if (types == null || types.length==0 ) {
return null;
}
Type[] ret = new Type[types.length];
for (int i=0, len=types.length; i<len; i++) {
ret[i] = makeBcelType(types[i]);
}
return ret;
}
public static Type makeBcelType(String type) {
return Type.getType(type);
}


static String[] makeBcelTypesAsClassNames(UnresolvedType[] types) {
String[] ret = new String[types.length];
for (int i = 0, len = types.length; i < len; i++) {
@@ -1239,4 +1255,5 @@ public class BcelWorld extends World implements Repository {
public void demote(ResolvedType type) {
typeMap.demote(type);
}

}

+ 30
- 0
weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java View File

@@ -124,6 +124,15 @@ public final class LazyMethodGen implements Traceable {
List<BcelShadow> matchedShadows;
// Used for interface introduction - this is the type of the interface the method is technically on
public ResolvedType definingType = null;
static class LightweightBcelMethod extends BcelMethod {

LightweightBcelMethod(BcelObjectType declaringType, Method method) {
super(declaringType, method);
// TODO Auto-generated constructor stub
}
}

public LazyMethodGen(int modifiers, Type returnType, String name, Type[] paramTypes, String[] declaredExceptions,
LazyClassGen enclosingClass) {
@@ -304,6 +313,27 @@ public final class LazyMethodGen implements Traceable {
memberView.addParameterAnnotation(parameterNumber, anno);
}
}
public ResolvedType[] getAnnotationTypes() {
initialize();
if (memberView == null && newAnnotations!=null && newAnnotations.size()!=0) {
// TODO Ignoring removed annotations for now
ResolvedType[] annotationTypes = new ResolvedType[newAnnotations.size()];
for (int a=0,len=newAnnotations.size();a<len;a++) {
annotationTypes[a] = newAnnotations.get(a).getType();
}
return annotationTypes;
}
return null;
}
public AnnotationAJ[] getAnnotations() {
initialize();
if (memberView == null && newAnnotations!=null && newAnnotations.size()!=0) {
return newAnnotations.toArray(new AnnotationAJ[newAnnotations.size()]);
}
return null;
}

public boolean hasAnnotation(UnresolvedType annotationType) {
initialize();

Loading…
Cancel
Save