@@ -0,0 +1,25 @@ | |||
// little aspect and class for testing declaration of annotations | |||
@interface anInterface {} | |||
public aspect AspectDeclareAnnotations{ | |||
declare @type : Test : @anInterface; | |||
declare @constructor : Test.new(String,int) : @anInterface; | |||
declare @method : int Test.fac(int) : @anInterface; | |||
declare @field : int Test.a : @anInterface; | |||
} | |||
class Test{ | |||
public Test(String say, int something){ | |||
System.out.println(say + something); | |||
} | |||
public int fac(int n){ | |||
return (n == 0)? 1 : n * fac(n-1); | |||
} | |||
public int a = 1; | |||
} |
@@ -0,0 +1,2 @@ | |||
-1.5 | |||
AspectDeclareAnnotations.aj |
@@ -0,0 +1,3 @@ | |||
-showWeaveInfo | |||
-1.5 | |||
AspectDeclareAnnotations.aj |
@@ -0,0 +1,4 @@ | |||
'Test' (AspectDeclareAnnotations.aj:14) is annotated with @anInterface type annotation from 'AspectDeclareAnnotations' (AspectDeclareAnnotations.aj:7) | |||
'public void Test.new(String,int)' (AspectDeclareAnnotations.aj:16) is annotated with @anInterface constructor annotation from 'AspectDeclareAnnotations' (AspectDeclareAnnotations.aj:8) | |||
'public int Test.fac(int)' (AspectDeclareAnnotations.aj:20) is annotated with @anInterface method annotation from 'AspectDeclareAnnotations' (AspectDeclareAnnotations.aj:9) | |||
'public int a' of type 'Test' (AspectDeclareAnnotations.aj) is annotated with @anInterface field annotation from 'AspectDeclareAnnotations' (AspectDeclareAnnotations.aj:10) |
@@ -95,8 +95,7 @@ public class ShowWeaveMessagesTestCase extends AjdeTestCase { | |||
if (rogueSymFile.exists()) rogueSymFile.delete(); | |||
} | |||
/** | |||
* Weave all the possible kinds of advice and verify the messages that come out. | |||
@@ -158,6 +157,28 @@ public class ShowWeaveMessagesTestCase extends AjdeTestCase { | |||
verifyWeavingMessages("declare.soft",true); | |||
} | |||
/** | |||
* Weave 'declare @type, @constructor, @method and @field' and check the weave messages that come out. | |||
*/ | |||
public void testWeaveMessagesDeclareAnnotation() { | |||
if (debugTests) System.out.println("\ntestWeaveMessagesDeclareAnnotation: Building with Six.lst"); | |||
compilerAdapter = new CompilerAdapter(); | |||
compilerAdapter.showInfoMessages(true); | |||
compilerAdapter.compile((String) openFile("Six.lst").getAbsolutePath(),new BPM(),false); | |||
verifyWeavingMessages("declare.annotation",true); | |||
} | |||
/** | |||
* Weave 'declare @type, @constructor, @method and @field' and check the weave messages don't come out without the -showWeaveInfo arg. | |||
*/ | |||
public void testWeaveMessagesDeclareAnnotationWeaveInfoOff() { | |||
if (debugTests) System.out.println("\ntestWeaveMessagesDeclareAnnotation: Building with Seven.lst"); | |||
compilerAdapter = new CompilerAdapter(); | |||
compilerAdapter.showInfoMessages(true); | |||
compilerAdapter.compile((String) openFile("Seven.lst").getAbsolutePath(),new BPM(),false); | |||
verifyWeavingMessages("declare.annotationNoWeaveInfo",true); | |||
} | |||
// BINARY WEAVING TESTS | |||
@@ -328,6 +349,7 @@ public class ShowWeaveMessagesTestCase extends AjdeTestCase { | |||
List l = ideManager.getCompilationSourceLineTasks(); | |||
for (Iterator iter = l.iterator(); iter.hasNext();) { | |||
IMessage msg = ((NullIdeTaskListManager.SourceLineTask) iter.next()).message; | |||
if (debugTests) System.out.println("Looking at ["+msg+"]"); | |||
if (msg.getKind().equals(IMessage.WEAVEINFO)) { | |||
if (!fileContents.contains(msg.getMessage())) { | |||
fail("Could not find message '"+msg.getMessage()+"' in the expected results\n"+ |
@@ -33,8 +33,7 @@ public class WeaveMessage extends Message { | |||
new WeaveMessageKind(5,"Softening exceptions in type '%1' (%2) as defined by aspect '%3' (%4)"); | |||
public static WeaveMessageKind WEAVEMESSAGE_ANNOTATES = | |||
new WeaveMessageKind(6,"'%1' (%2) is annoted with %3 from '%4' (%5)"); | |||
new WeaveMessageKind(6,"'%1' (%2) is annotated with %3 %4 annotation from '%5' (%6)"); | |||
private String affectedtypename; | |||
private String aspectname; |
@@ -51,6 +51,7 @@ import org.aspectj.apache.bcel.generic.Select; | |||
import org.aspectj.apache.bcel.generic.Type; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.WeaveMessage; | |||
import org.aspectj.util.FuzzyBoolean; | |||
import org.aspectj.util.PartialOrder; | |||
import org.aspectj.weaver.AjAttribute; | |||
@@ -457,6 +458,8 @@ class BcelClassWeaver implements IClassWeaver { | |||
if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) continue; // skip this one... | |||
mg.addAnnotation(decaM.getAnnotationX()); | |||
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaM.getSourceLocation(),clazz.getName(),mg.getMethod()); | |||
reportMethodCtorWeavingMessage(clazz, mg, decaM); | |||
isChanged = true; | |||
modificationOccured = true; | |||
} else { | |||
@@ -488,6 +491,52 @@ class BcelClassWeaver implements IClassWeaver { | |||
} | |||
return isChanged; | |||
} | |||
// TAG: WeavingMessage | |||
private void reportMethodCtorWeavingMessage(LazyClassGen clazz, LazyMethodGen mg, DeclareAnnotation decaM) { | |||
if (!getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)){ | |||
StringBuffer parmString = new StringBuffer("("); | |||
Type[] args = mg.getMethod().getArgumentTypes(); | |||
for (int i = 0; i < args.length; i++) { | |||
Type type2 = args[i]; | |||
String s = org.aspectj.apache.bcel.classfile.Utility.signatureToString(type2.getSignature()); | |||
if (s.lastIndexOf(".")!=-1) s =s.substring(s.lastIndexOf(".")+1); | |||
parmString.append(s); | |||
if ((i+1)<args.length) parmString.append(","); | |||
} | |||
parmString.append(")"); | |||
String methodName = mg.getMethod().getName(); | |||
StringBuffer sig = new StringBuffer(); | |||
sig.append(org.aspectj.apache.bcel.classfile.Utility.accessToString(mg.getMethod().getAccessFlags()) ); | |||
sig.append(" "); | |||
sig.append(mg.getMethod().getReturnType().toString()); | |||
sig.append(" "); | |||
sig.append(clazz.getName()); | |||
sig.append("."); | |||
sig.append(methodName.equals("<init>")?"new":methodName); | |||
sig.append(parmString); | |||
StringBuffer loc = new StringBuffer(); | |||
if (clazz.getFileName()==null) { | |||
loc.append("no debug info available"); | |||
} else { | |||
loc.append(clazz.getFileName()); | |||
if (mg.getDeclarationLineNumber()!=-1) { | |||
loc.append(":"+mg.getDeclarationLineNumber()); | |||
} | |||
} | |||
getWorld().getMessageHandler().handleMessage( | |||
WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ANNOTATES, | |||
new String[]{ | |||
sig.toString(), | |||
loc.toString(), | |||
decaM.getAnnotationString(), | |||
methodName.startsWith("<init>")?"constructor":"method", | |||
decaM.getAspect().toString(), | |||
Utility.beautifyLocation(decaM.getSourceLocation()) | |||
})); | |||
} | |||
} | |||
/** | |||
* Looks through a list of declare annotation statements and only returns | |||
@@ -710,6 +759,7 @@ class BcelClassWeaver implements IClassWeaver { | |||
if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)) continue; // skip this one... | |||
aBcelField.addAnnotation(decaF.getAnnotationX()); | |||
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]); | |||
reportFieldAnnotationWeavingMessage(clazz, fields, fieldCounter, decaF); | |||
isChanged = true; | |||
modificationOccured = true; | |||
} else { | |||
@@ -741,6 +791,22 @@ class BcelClassWeaver implements IClassWeaver { | |||
} | |||
return isChanged; | |||
} | |||
// TAG: WeavingMessage | |||
private void reportFieldAnnotationWeavingMessage(LazyClassGen clazz, Field[] fields, int fieldCounter, DeclareAnnotation decaF) { | |||
if (!getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)){ | |||
Field theField = fields[fieldCounter]; | |||
world.getMessageHandler().handleMessage( | |||
WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ANNOTATES, | |||
new String[]{ | |||
theField.toString() + "' of type '" + clazz.getName(), | |||
clazz.getFileName(), | |||
decaF.getAnnotationString(), | |||
"field", | |||
decaF.getAspect().toString(), | |||
Utility.beautifyLocation(decaF.getSourceLocation())})); | |||
} | |||
} | |||
/** | |||
* Check if a resolved member (field/method/ctor) already has an annotation, if it |
@@ -51,6 +51,7 @@ import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.Message; | |||
import org.aspectj.bridge.MessageUtil; | |||
import org.aspectj.bridge.SourceLocation; | |||
import org.aspectj.bridge.WeaveMessage; | |||
import org.aspectj.util.FileUtil; | |||
import org.aspectj.util.FuzzyBoolean; | |||
import org.aspectj.weaver.Advice; | |||
@@ -1199,6 +1200,7 @@ public class BcelWeaver implements IWeaver { | |||
} | |||
} | |||
/** | |||
* Apply a declare @type - return true if we change the type | |||
*/ | |||
@@ -1206,9 +1208,25 @@ public class BcelWeaver implements IWeaver { | |||
boolean didSomething = false; | |||
if (decA.matches(onType)) { | |||
//FIXME asc important this should be guarded by the 'already has annotation' check below but isn't since the compiler is producing classfiles with deca affected things in... | |||
// FIXME asc important this should be guarded by the 'already has annotation' check below but isn't since the compiler is producing classfiles with deca affected things in... | |||
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decA.getSourceLocation(),onType.getSourceLocation()); | |||
// FIXME asc same comment above applies here | |||
// TAG: WeavingMessage | |||
if (!getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)){ | |||
getWorld().getMessageHandler().handleMessage( | |||
WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ANNOTATES, | |||
new String[]{ | |||
onType.toString(), | |||
Utility.beautifyLocation(onType.getSourceLocation()), | |||
decA.getAnnotationString(), | |||
"type", | |||
decA.getAspect().toString(), | |||
Utility.beautifyLocation(decA.getSourceLocation()) | |||
})); | |||
} | |||
if (onType.hasAnnotation(decA.getAnnotationX().getSignature())) { | |||
// FIXME asc Could put out a lint here for an already annotated type - the problem is that it may have | |||
// picked up the annotation during 'source weaving' in which case the message is misleading. Leaving it |
@@ -49,6 +49,7 @@ import org.aspectj.apache.bcel.generic.SWITCH; | |||
import org.aspectj.apache.bcel.generic.Select; | |||
import org.aspectj.apache.bcel.generic.TargetLostException; | |||
import org.aspectj.apache.bcel.generic.Type; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.Member; | |||
@@ -60,6 +61,26 @@ public class Utility { | |||
private Utility() { | |||
super(); | |||
} | |||
/* | |||
* Ensure we report a nice source location - particular in the case | |||
* where the source info is missing (binary weave). | |||
*/ | |||
public static String beautifyLocation(ISourceLocation isl) { | |||
StringBuffer nice = new StringBuffer(); | |||
if (isl==null || isl.getSourceFile()==null || isl.getSourceFile().getName().indexOf("no debug info available")!=-1) { | |||
nice.append("no debug info available"); | |||
} else { | |||
// can't use File.getName() as this fails when a Linux box encounters a path created on Windows and vice-versa | |||
int takeFrom = isl.getSourceFile().getPath().lastIndexOf('/'); | |||
if (takeFrom == -1) { | |||
takeFrom = isl.getSourceFile().getPath().lastIndexOf('\\'); | |||
} | |||
nice.append(isl.getSourceFile().getPath().substring(takeFrom +1)); | |||
if (isl.getLine()!=0) nice.append(":").append(isl.getLine()); | |||
} | |||
return nice.toString(); | |||
} | |||
public static Instruction createSuperInvoke( |