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

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

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

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

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

*/ */
public class Ajc174Tests extends 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 { public void testSuperItdCtor_413378() throws Exception {
runTest("super itd ctor"); runTest("super itd ctor");
} }

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



<suite> <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"> <ajc-test dir="bugs174/pr413378" title="super itd ctor">
<compile files="Code.java" options="-1.5 -showWeaveInfo"> <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)')"/> <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

import org.aspectj.weaver.IClassWeaver; import org.aspectj.weaver.IClassWeaver;
import org.aspectj.weaver.IntMap; import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.Member; import org.aspectj.weaver.Member;
import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.MissingResolvedTypeWithKnownSignature; import org.aspectj.weaver.MissingResolvedTypeWithKnownSignature;
import org.aspectj.weaver.NameMangler; import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.NewConstructorTypeMunger; import org.aspectj.weaver.NewConstructorTypeMunger;
// finally, if we changed, we add in the introduced methods. // finally, if we changed, we add in the introduced methods.
if (isChanged) { if (isChanged) {
clazz.getOrCreateWeaverStateInfo(inReweavableMode); clazz.getOrCreateWeaverStateInfo(inReweavableMode);
weaveInAddedMethods(); // FIXME asc are these potentially affected
// by declare annotation?
weaveInAddedMethods();
} }


if (inReweavableMode) { if (inReweavableMode) {
isChanged = weaveAtMethodOnITDSRepeatedly(allDecams, itdMethodsCtors, reportedProblems); isChanged = weaveAtMethodOnITDSRepeatedly(allDecams, itdMethodsCtors, reportedProblems);
} }


// deal with all the other methods...
List<LazyMethodGen> members = clazz.getMethodGens();
List<DeclareAnnotation> decaMs = getMatchingSubset(allDecams, clazz.getType()); List<DeclareAnnotation> decaMs = getMatchingSubset(allDecams, clazz.getType());
if (decaMs.isEmpty()) { if (decaMs.isEmpty()) {
return false; // nothing to do 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()) { if (!members.isEmpty()) {
Set<DeclareAnnotation> unusedDecams = new HashSet<DeclareAnnotation>();
unusedDecams.addAll(decaMs);
for (int memberCounter = 0; memberCounter < members.size(); memberCounter++) { for (int memberCounter = 0; memberCounter < members.size(); memberCounter++) {
LazyMethodGen mg = members.get(memberCounter); LazyMethodGen mg = members.get(memberCounter);
if (!mg.getName().startsWith(NameMangler.PREFIX)) { if (!mg.getName().startsWith(NameMangler.PREFIX)) {
for (DeclareAnnotation decaM : decaMs) { for (DeclareAnnotation decaM : decaMs) {


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

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

return ret; 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) { static String[] makeBcelTypesAsClassNames(UnresolvedType[] types) {
String[] ret = new String[types.length]; String[] ret = new String[types.length];
for (int i = 0, len = types.length; i < len; i++) { for (int i = 0, len = types.length; i < len; i++) {
public void demote(ResolvedType type) { public void demote(ResolvedType type) {
typeMap.demote(type); typeMap.demote(type);
} }

} }

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

List<BcelShadow> matchedShadows; List<BcelShadow> matchedShadows;
// Used for interface introduction - this is the type of the interface the method is technically on // Used for interface introduction - this is the type of the interface the method is technically on
public ResolvedType definingType = null; 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, public LazyMethodGen(int modifiers, Type returnType, String name, Type[] paramTypes, String[] declaredExceptions,
LazyClassGen enclosingClass) { LazyClassGen enclosingClass) {
memberView.addParameterAnnotation(parameterNumber, anno); 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) { public boolean hasAnnotation(UnresolvedType annotationType) {
initialize(); initialize();

Loading…
Cancel
Save