public AdviceKind kind; // set during parsing, referenced by Proceed and AsmElementFormatter | public AdviceKind kind; // set during parsing, referenced by Proceed and AsmElementFormatter | ||||
private int extraArgumentFlags = 0; | private int extraArgumentFlags = 0; | ||||
public int adviceSequenceNumberInType; | |||||
public MethodBinding proceedMethodBinding; // set during this.resolveStaments, referenced by Proceed | public MethodBinding proceedMethodBinding; // set during this.resolveStaments, referenced by Proceed | ||||
public List proceedCalls = new ArrayList(2); // populated during Proceed.findEnclosingAround | public List proceedCalls = new ArrayList(2); // populated during Proceed.findEnclosingAround | ||||
// override, Called by ClassScope.postParse | // override, Called by ClassScope.postParse | ||||
public void postParse(TypeDeclaration typeDec) { | public void postParse(TypeDeclaration typeDec) { | ||||
AspectDeclaration aspectDecl = (AspectDeclaration) typeDec; | AspectDeclaration aspectDecl = (AspectDeclaration) typeDec; | ||||
int adviceSequenceNumberInType = aspectDecl.adviceCounter++; | |||||
adviceSequenceNumberInType = aspectDecl.adviceCounter++; | |||||
StringBuffer stringifiedPointcut = new StringBuffer(30); | StringBuffer stringifiedPointcut = new StringBuffer(30); | ||||
pointcutDesignator.print(0, stringifiedPointcut); | pointcutDesignator.print(0, stringifiedPointcut); |
import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; | import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; | ||||
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding; | import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding; | ||||
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser; | import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser; | ||||
import org.aspectj.weaver.BCException; | |||||
import org.aspectj.weaver.Member; | import org.aspectj.weaver.Member; | ||||
import org.aspectj.weaver.ResolvedMemberImpl; | import org.aspectj.weaver.ResolvedMemberImpl; | ||||
import org.aspectj.weaver.UnresolvedType; | import org.aspectj.weaver.UnresolvedType; | ||||
/** | /** | ||||
* enclosingDec is either AdviceDeclaration or PointcutDeclaration | * enclosingDec is either AdviceDeclaration or PointcutDeclaration | ||||
*/ | */ | ||||
public void postParse(TypeDeclaration typeDec, | |||||
MethodDeclaration enclosingDec) { | |||||
public int postParse(TypeDeclaration typeDec, | |||||
MethodDeclaration enclosingDec, int counter) { | |||||
// typeDec.scope.problemReporter().signalError(sourceStart, sourceEnd, | // typeDec.scope.problemReporter().signalError(sourceStart, sourceEnd, | ||||
// "if pcd is not implemented in 1.1alpha1"); | // "if pcd is not implemented in 1.1alpha1"); | ||||
// XXX need to implement correctly | // XXX need to implement correctly | ||||
if (pointcut == null) | if (pointcut == null) | ||||
return; | |||||
return 0; | |||||
testMethod = makeIfMethod(enclosingDec.compilationResult, enclosingDec, | |||||
typeDec); | |||||
testMethod = makeIfMethod(enclosingDec.compilationResult, enclosingDec, typeDec, counter); | |||||
AstUtil.addMethodDeclaration(typeDec, testMethod); | AstUtil.addMethodDeclaration(typeDec, testMethod); | ||||
return 1; | |||||
} | } | ||||
private final static char[] CodeGenerationHint = "CodeGenerationHint".toCharArray(); | private final static char[] CodeGenerationHint = "CodeGenerationHint".toCharArray(); | ||||
private final static char[] IfNameSuffix = "ifNameSuffix".toCharArray(); | private final static char[] IfNameSuffix = "ifNameSuffix".toCharArray(); | ||||
// XXX todo: make sure that errors in Arguments only get displayed once | // XXX todo: make sure that errors in Arguments only get displayed once | ||||
private MethodDeclaration makeIfMethod(CompilationResult result, | |||||
MethodDeclaration enclosingDec, TypeDeclaration containingTypeDec) { | |||||
private MethodDeclaration makeIfMethod(CompilationResult result, MethodDeclaration enclosingDec, TypeDeclaration containingTypeDec, int counter) { | |||||
MethodDeclaration ret = new IfMethodDeclaration(result, pointcut); | MethodDeclaration ret = new IfMethodDeclaration(result, pointcut); | ||||
ret.modifiers = ClassFileConstants.AccStatic | |||||
| ClassFileConstants.AccFinal | ClassFileConstants.AccPublic; | |||||
ret.modifiers = ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccPublic; | |||||
ret.returnType = AstUtil.makeTypeReference(TypeBinding.BOOLEAN); | ret.returnType = AstUtil.makeTypeReference(TypeBinding.BOOLEAN); | ||||
String nameSuffix = null; | String nameSuffix = null; | ||||
StringBuffer ifSelector = new StringBuffer(); | StringBuffer ifSelector = new StringBuffer(); | ||||
ifSelector.append("ajc$if$"); | ifSelector.append("ajc$if$"); | ||||
if (nameSuffix == null || nameSuffix.length()==0) { | if (nameSuffix == null || nameSuffix.length()==0) { | ||||
ifSelector.append(Integer.toHexString(expr.sourceStart)); | |||||
boolean computedName = false; | |||||
try { | |||||
// possibly even better logic for more reliable name: | |||||
if (enclosingDec instanceof AdviceDeclaration) { | |||||
// name is ajc$if$<adviceSequenceNumber>[$<ifnumberinPcd>]$<hashcodeOfIfExpressionInHex> | |||||
ifSelector.append(((AdviceDeclaration)enclosingDec).adviceSequenceNumberInType).append("$"); | |||||
if (counter!=0) { | |||||
ifSelector.append(counter); | |||||
ifSelector.append("$"); | |||||
} | |||||
ifSelector.append(Integer.toHexString(expr.toString().hashCode())); | |||||
computedName = true; | |||||
} else if (enclosingDec instanceof PointcutDeclaration) { | |||||
if (counter!=0) { | |||||
ifSelector.append(counter); | |||||
ifSelector.append("$"); | |||||
} | |||||
StringBuilder toHash = new StringBuilder(((PointcutDeclaration) enclosingDec).getPointcutText()); | |||||
toHash.append(expr.toString()); | |||||
// name is pointcut selector then $if[$<ifnumberinpcd>]$<hashcodeofpointcuttextandexpressiontext> | |||||
ifSelector.append(Integer.toHexString(toHash.toString().hashCode())); | |||||
computedName = true; | |||||
} | |||||
} catch (Throwable t) { | |||||
throw new IllegalStateException(t); | |||||
// let it build a name the 'old way' | |||||
} | |||||
if (!computedName) { | |||||
ifSelector.append(Integer.toHexString(expr.sourceStart)); | |||||
} | |||||
} else { | } else { | ||||
ifSelector.append(nameSuffix); | ifSelector.append(nameSuffix); | ||||
} | } | ||||
// possibly even better logic for more reliable name: | |||||
// if (enclosingDec instanceof AdviceDeclaration) { | |||||
// // name is | |||||
// ajc$if$<adviceSequenceNumber>$<hashcodeOfIfExpressionInHex> | |||||
// ifSelector.append("ajc$if$"); | |||||
// ifSelector.append(((AdviceDeclaration) | |||||
// enclosingDec).adviceSequenceNumberInType); | |||||
// ifSelector.append("$").append(Integer.toHexString(expr.toString().hashCode())); | |||||
// } else if (enclosingDec instanceof PointcutDeclaration) { | |||||
// // name is pointcut selector then $if$<hashcodeOfIfExpressionInHex> | |||||
// ifSelector.append(((PointcutDeclaration) enclosingDec).selector); | |||||
// ifSelector.append("$if$"); | |||||
// ifSelector.append(Integer.toHexString(expr.toString().hashCode())); | |||||
// } else { | |||||
// throw new BCException("Unexpected enclosing declaration of " + | |||||
// enclosingDec + " for if pointcut designator"); | |||||
// } | |||||
// hashcode of expression | |||||
ret.selector = ifSelector.toString().toCharArray(); | ret.selector = ifSelector.toString().toCharArray(); | ||||
ret.arguments = makeArguments(enclosingDec, containingTypeDec); | ret.arguments = makeArguments(enclosingDec, containingTypeDec); | ||||
ret.statements = new Statement[] { new ReturnStatement(expr, | ret.statements = new Statement[] { new ReturnStatement(expr, |
generateSyntheticPointcutMethod = true; | generateSyntheticPointcutMethod = true; | ||||
} | } | ||||
private String getPointcutText() { | |||||
public String getPointcutText() { | |||||
String text = getPointcut().toString(); | String text = getPointcut().toString(); | ||||
if (text.indexOf("BindingTypePattern") == -1) | if (text.indexOf("BindingTypePattern") == -1) | ||||
return text; | return text; |
return "unknown"; | return "unknown"; | ||||
} | } | ||||
public void postParse(TypeDeclaration typeDec, MethodDeclaration enclosingDec) { | |||||
public int postParse(TypeDeclaration typeDec, MethodDeclaration enclosingDec, int tokenNumber) { | |||||
// nothing to do typically | // nothing to do typically | ||||
return 0; | |||||
} | } | ||||
/* (non-Javadoc) | /* (non-Javadoc) |
public void postParse(TypeDeclaration typeDec, MethodDeclaration enclosingDec) { | public void postParse(TypeDeclaration typeDec, MethodDeclaration enclosingDec) { | ||||
int counter = 0; // Counter can be used by postParse as a value to compute uniqueness (if required) | |||||
for (int i=0, len=tokens.length; i < len; i++) { | for (int i=0, len=tokens.length; i < len; i++) { | ||||
tokens[i].postParse(typeDec, enclosingDec); | |||||
counter+=tokens[i].postParse(typeDec, enclosingDec, counter); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
protected Method getMethodStartsWith(JavaClass jc, String prefix) { | protected Method getMethodStartsWith(JavaClass jc, String prefix) { | ||||
return getMethodStartsWith(jc,prefix,1); | |||||
} | |||||
protected Method getMethodStartsWith(JavaClass jc, String prefix, int whichone) { | |||||
Method[] meths = jc.getMethods(); | Method[] meths = jc.getMethods(); | ||||
for (int i = 0; i < meths.length; i++) { | for (int i = 0; i < meths.length; i++) { | ||||
Method method = meths[i]; | Method method = meths[i]; | ||||
System.out.println(method); | System.out.println(method); | ||||
if (method.getName().startsWith(prefix)) { | if (method.getName().startsWith(prefix)) { | ||||
return method; | |||||
whichone--; | |||||
if (whichone==0) { | |||||
return method; | |||||
} | |||||
} | } | ||||
} | } | ||||
return null; | return null; |
import java.lang.annotation.*; | |||||
public class Code5 { | |||||
public static boolean isTrue = true; | |||||
public void m() { | |||||
} | |||||
public static void main(String []argv) { | |||||
new Code5().m(); | |||||
} | |||||
} | |||||
aspect X { | |||||
pointcut p(): execution(* Code*.*(..)) && if(Code5.isTrue); | |||||
before(): p() { | |||||
System.out.println("advice"); | |||||
} | |||||
} |
import java.lang.annotation.*; | |||||
public class Code5a { | |||||
public static boolean isTrue = true; | |||||
public void m() { | |||||
} | |||||
public static void main(String []argv) { | |||||
new Code5a().m(); | |||||
} | |||||
} | |||||
// more white space, on purpose | |||||
aspect X2 { | |||||
pointcut p(): execution(* Code*.*(..)) && if(Code5.isTrue); | |||||
before(): p() { | |||||
System.out.println("advice"); | |||||
} | |||||
} |
import java.lang.annotation.*; | |||||
public class Code6 { | |||||
public static boolean isTrue = true; | |||||
public static boolean isTrue2 = true; | |||||
public void m() { | |||||
} | |||||
public static void main(String []argv) { | |||||
new Code6().m(); | |||||
} | |||||
} | |||||
aspect X { | |||||
pointcut p(): execution(* Code*.*(..)) && if(Code6.isTrue) && if(Code6.isTrue2); | |||||
before(): p() { | |||||
System.out.println("advice"); | |||||
} | |||||
} |
import java.lang.annotation.*; | |||||
public class Code7 { | |||||
public static boolean isTrue = true; | |||||
public static boolean isTrue2 = true; | |||||
public void m() { | |||||
} | |||||
public static void main(String []argv) { | |||||
new Code7().m(); | |||||
} | |||||
} | |||||
aspect X { | |||||
before(): execution(* Code*.*(..)) && if(Code7.isTrue) && if(Code7.isTrue2) { | |||||
System.out.println("advice"); | |||||
} | |||||
} |
*/ | */ | ||||
public class Ajc172Tests extends org.aspectj.testing.XMLBasedAjcTestCase { | public class Ajc172Tests extends org.aspectj.testing.XMLBasedAjcTestCase { | ||||
public void testIfPointcutNames_pr398246() throws Exception{ | |||||
public void testIfPointcutNames_pr398246() throws Exception { | |||||
runTest("if pointcut names"); | runTest("if pointcut names"); | ||||
JavaClass jc = getClassFrom(ajc.getSandboxDirectory(),"X"); | |||||
Method m = getMethodStartsWith(jc,"ajc$if"); | |||||
assertEquals("ajc$if$andy",m.getName()); | |||||
JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), "X"); | |||||
Method m = getMethodStartsWith(jc, "ajc$if"); | |||||
assertEquals("ajc$if$andy", m.getName()); | |||||
} | } | ||||
public void testIfPointcutNames_pr398246_2() throws Exception { | public void testIfPointcutNames_pr398246_2() throws Exception { | ||||
runTest("if pointcut names 2"); | runTest("if pointcut names 2"); | ||||
JavaClass jc = getClassFrom(ajc.getSandboxDirectory(),"X"); | |||||
Method m = getMethodStartsWith(jc,"ajc$if"); | |||||
assertEquals("ajc$if$fred",m.getName()); | |||||
JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), "X"); | |||||
Method m = getMethodStartsWith(jc, "ajc$if"); | |||||
assertEquals("ajc$if$fred", m.getName()); | |||||
} | } | ||||
// fully qualified annotation name is used | // fully qualified annotation name is used | ||||
public void testIfPointcutNames_pr398246_3() throws Exception { | public void testIfPointcutNames_pr398246_3() throws Exception { | ||||
runTest("if pointcut names 3"); | runTest("if pointcut names 3"); | ||||
JavaClass jc = getClassFrom(ajc.getSandboxDirectory(),"X"); | |||||
Method m = getMethodStartsWith(jc,"ajc$if"); | |||||
assertEquals("ajc$if$barney",m.getName()); | |||||
JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), "X"); | |||||
Method m = getMethodStartsWith(jc, "ajc$if"); | |||||
assertEquals("ajc$if$barney", m.getName()); | |||||
} | } | ||||
// compiling a class later than the initial build - does it pick up the right if clause name? | |||||
public void testIfPointcutNames_pr398246_4() throws Exception{ | |||||
// compiling a class later than the initial build - does it pick up the | |||||
// right if clause name? | |||||
public void testIfPointcutNames_pr398246_4() throws Exception { | |||||
runTest("if pointcut names 4"); | runTest("if pointcut names 4"); | ||||
JavaClass jc = getClassFrom(ajc.getSandboxDirectory(),"X"); | |||||
Method m = getMethodStartsWith(jc,"ajc$if"); | |||||
assertEquals("ajc$if$sid",m.getName()); | |||||
JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), "X"); | |||||
Method m = getMethodStartsWith(jc, "ajc$if"); | |||||
assertEquals("ajc$if$sid", m.getName()); | |||||
} | |||||
// new style generated names | |||||
public void testIfPointcutNames_pr398246_5() throws Exception { | |||||
runTest("if pointcut names 5"); | |||||
JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), "X"); | |||||
Method m = getMethodStartsWith(jc, "ajc$if"); | |||||
assertEquals("ajc$if$ac0cb804", m.getName()); | |||||
jc = getClassFrom(ajc.getSandboxDirectory(), "X2"); | |||||
m = getMethodStartsWith(jc, "ajc$if"); | |||||
assertEquals("ajc$if$ac0cb804", m.getName()); | |||||
} | } | ||||
// new style generated names - multiple ifs in one pointcut | |||||
public void testIfPointcutNames_pr398246_6() throws Exception { | |||||
runTest("if pointcut names 6"); | |||||
JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), "X"); | |||||
Method m = getMethodStartsWith(jc, "ajc$if",1); | |||||
assertEquals("ajc$if$aac93da8", m.getName()); | |||||
m = getMethodStartsWith(jc, "ajc$if",2); | |||||
assertEquals("ajc$if$1$ae5e778a", m.getName()); | |||||
} | |||||
// new style generated names - multiple ifs in one advice | |||||
public void testIfPointcutNames_pr398246_7() throws Exception { | |||||
runTest("if pointcut names 7"); | |||||
JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), "X"); | |||||
Method m = getMethodStartsWith(jc, "ajc$if",1); | |||||
assertEquals("ajc$if$1$ac0607c", m.getName()); | |||||
m = getMethodStartsWith(jc, "ajc$if",2); | |||||
assertEquals("ajc$if$1$1$4d4baf36", m.getName()); | |||||
} | |||||
public void testOptionalAspects_pr398588() { | public void testOptionalAspects_pr398588() { | ||||
runTest("optional aspects"); | runTest("optional aspects"); | ||||
} | } |
</stdout> | </stdout> | ||||
</run> | </run> | ||||
</ajc-test> | </ajc-test> | ||||
<ajc-test dir="bugs172/pr398246" title="if pointcut names 5"> | |||||
<compile files="Code5.java Code5a.java" options="-1.5"> | |||||
</compile> | |||||
<run class="Code5" options="-1.5"> | |||||
<stdout> | |||||
<line text="advice"/> | |||||
<line text="advice"/> | |||||
<line text="advice"/> | |||||
<line text="advice"/> | |||||
</stdout> | |||||
</run> | |||||
</ajc-test> | |||||
<ajc-test dir="bugs172/pr398246" title="if pointcut names 6"> | |||||
<compile files="Code6.java" options="-1.5"> | |||||
</compile> | |||||
<run class="Code6" options="-1.5"> | |||||
<stdout> | |||||
<line text="advice"/> | |||||
<line text="advice"/> | |||||
</stdout> | |||||
</run> | |||||
</ajc-test> | |||||
<ajc-test dir="bugs172/pr398246" title="if pointcut names 7"> | |||||
<compile files="Code7.java" options="-1.5"> | |||||
</compile> | |||||
<run class="Code7" options="-1.5"> | |||||
<stdout> | |||||
<line text="advice"/> | |||||
<line text="advice"/> | |||||
</stdout> | |||||
</run> | |||||
</ajc-test> | |||||
<ajc-test dir="bugs172/pr389750" title="inconsistent class file"> | <ajc-test dir="bugs172/pr389750" title="inconsistent class file"> | ||||
<compile files="Code.aj" options="-1.5"> | <compile files="Code.aj" options="-1.5"> |