woven join pointstags/v1_1_0_RC1
@@ -5666,4 +5666,23 @@ | |||
<compile files="CflowCycles.java"/> | |||
<run class="CflowCycles"/> | |||
</ajc-test> | |||
<ajc-test dir="new" | |||
title="incompatible advice throws clause are a compile-time error" | |||
keywords="from-resolved_10x"> | |||
<compile files="AdviceThrowsCf.java"> | |||
<message kind="error" line="13"/> | |||
<message kind="error" line="28"/> | |||
<message kind="error" line="47"/> | |||
<message kind="error" line="48"/> | |||
<message kind="error" line="50"/> | |||
<message kind="error" line="70"/> | |||
<message kind="error" line="74"/> | |||
<message kind="error" line="76"/> | |||
<message kind="error" line="78"/> | |||
<message kind="error" line="85"/> | |||
</compile> | |||
</ajc-test> | |||
</suite> |
@@ -2,18 +2,6 @@ | |||
<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"> | |||
<suite> | |||
<ajc-test dir="new" | |||
title="incompatible advice throws clause are a compile-time error" | |||
keywords="from-resolved_10x"> | |||
<compile files="AdviceThrowsCf.java"> | |||
<message kind="error" line="70"/> | |||
<message kind="error" line="74"/> | |||
<message kind="error" line="76"/> | |||
<message kind="error" line="78"/> | |||
</compile> | |||
</ajc-test> | |||
<ajc-test dir="new" pr="660" title="illegal name binding in around cflow" | |||
keywords="from-resolved_104"> | |||
<compile files="ArgsInCflowCf.java"> |
@@ -1,14 +1,15 @@ | |||
<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"> | |||
<suite> | |||
<ajc-test dir="new" pr="29934" | |||
title="can't apply around advice to the execution of around advice" | |||
keywords="from-resolved_10x"> | |||
<compile files="CflowCycles.java"/> | |||
<run class="CflowCycles"/> | |||
</ajc-test> | |||
<!-- | |||
<ajc-test dir="new" pr="885" | |||
title="source locations within expressions"> | |||
<compile files="SourceLocationWithinExpr.java" options="-1.4"/> | |||
<run class="SourceLocationWithinExpr"/> | |||
</ajc-test> | |||
--> | |||
</suite> |
@@ -77,4 +77,17 @@ aspect A { | |||
} | |||
before() throws CheckedExc: staticinitialization(C) { //ERR: can't throw | |||
} | |||
void around() throws CheckedExc: canThrowChecked() { | |||
proceed(); | |||
} | |||
void around() throws CheckedExc: canThrowUnchecked() { // ERR: can't throw | |||
proceed(); | |||
} | |||
void around() throws UncheckedExc: canThrowUnchecked() || set(int C.x) { | |||
proceed(); | |||
} | |||
} |
@@ -13,6 +13,9 @@ | |||
package org.aspectj.weaver; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.Message; | |||
import org.aspectj.weaver.patterns.DeclareErrorOrWarning; | |||
@@ -58,5 +61,7 @@ public class Checker extends ShadowMunger { | |||
public int compareTo(Object other) { | |||
return 0; | |||
} | |||
public Collection getThrownExceptions() { return Collections.EMPTY_LIST; } | |||
} |
@@ -268,8 +268,42 @@ public abstract class Shadow { | |||
} | |||
} | |||
protected boolean checkMunger(ShadowMunger munger) { | |||
for (Iterator i = munger.getThrownExceptions().iterator(); i.hasNext(); ) { | |||
if (!checkCanThrow(munger, (ResolvedTypeX)i.next() )) return false; | |||
} | |||
return true; | |||
} | |||
protected boolean checkCanThrow(ShadowMunger munger, ResolvedTypeX resolvedTypeX) { | |||
if (getKind() == ExceptionHandler) { | |||
//XXX much too lenient rules here, need to walk up exception handlers | |||
return true; | |||
} | |||
if (!isDeclaredException(resolvedTypeX, getSignature())) { | |||
getIWorld().showMessage(IMessage.ERROR, "can't throw checked exception \'" + resolvedTypeX + | |||
"\' at this join point \'" + this +"\'", // from advice in \'" + munger. + "\'", | |||
getSourceLocation(), munger.getSourceLocation()); | |||
} | |||
return true; | |||
} | |||
private boolean isDeclaredException( | |||
ResolvedTypeX resolvedTypeX, | |||
Member member) | |||
{ | |||
ResolvedTypeX[] excs = getIWorld().resolve(member.getExceptions(getIWorld())); | |||
for (int i=0, len=excs.length; i < len; i++) { | |||
if (excs[i].isAssignableFrom(resolvedTypeX)) return true; | |||
} | |||
return false; | |||
} | |||
public void addMunger(ShadowMunger munger) { | |||
this.mungers.add(munger); | |||
if (checkMunger(munger)) this.mungers.add(munger); | |||
} | |||
public final void implement() { | |||
@@ -323,16 +357,4 @@ public abstract class Shadow { | |||
public String toString() { | |||
return getKind() + "(" + getSignature() + ")"; // + getSourceLines(); | |||
} | |||
// ---- type access methods | |||
} |
@@ -13,6 +13,8 @@ | |||
package org.aspectj.weaver; | |||
import java.util.Collection; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.util.PartialOrder; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
@@ -88,4 +90,10 @@ public abstract class ShadowMunger implements PartialOrder.PartialComparable, IH | |||
return pointcut; | |||
} | |||
/** | |||
* @return a Collection of ResolvedTypeX for all checked exceptions that | |||
* might be thrown by this munger | |||
*/ | |||
public abstract Collection getThrownExceptions(); | |||
} |
@@ -541,6 +541,8 @@ public class TypeX { | |||
public static final TypeX CLONEABLE = forSignature("Ljava/lang/Cloneable;"); | |||
public static final TypeX SERIALIZABLE = forSignature("Ljava/io/Serializable;"); | |||
public static final TypeX THROWABLE = forSignature("Ljava/lang/Throwable;"); | |||
public static final TypeX RUNTIME_EXCEPTION = forSignature("Ljava/lang/RuntimeException;"); | |||
public static final TypeX ERROR = forSignature("Ljava/lang/Error;"); | |||
// ---- helpers | |||
@@ -13,25 +13,15 @@ | |||
package org.aspectj.weaver.bcel; | |||
import org.apache.bcel.generic.InstructionFactory; | |||
import org.apache.bcel.generic.InstructionHandle; | |||
import org.apache.bcel.generic.InstructionList; | |||
import org.aspectj.weaver.Advice; | |||
import org.aspectj.weaver.AdviceKind; | |||
import org.aspectj.weaver.AjAttribute; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.Member; | |||
import org.aspectj.weaver.ResolvedTypeX; | |||
import org.aspectj.weaver.Shadow; | |||
import org.aspectj.weaver.TypeX; | |||
import org.aspectj.weaver.WeaverStateKind; | |||
import org.aspectj.weaver.World; | |||
import java.util.*; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import org.apache.bcel.generic.*; | |||
import org.aspectj.weaver.*; | |||
import org.aspectj.weaver.ast.Literal; | |||
import org.aspectj.weaver.ast.Test; | |||
import org.aspectj.weaver.patterns.ExactTypePattern; | |||
import org.aspectj.weaver.patterns.ExposedState; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
import org.aspectj.weaver.patterns.*; | |||
/** | |||
* Advice implemented for bcel. | |||
@@ -53,13 +43,14 @@ public class BcelAdvice extends Advice { | |||
this.concreteAspect = concreteAspect; | |||
} | |||
// !!! only used for testing | |||
// !!! must only be used for testing | |||
public BcelAdvice(AdviceKind kind, Pointcut pointcut, Member signature, | |||
int extraArgumentFlags, | |||
int start, int end, ISourceContext sourceContext, ResolvedTypeX concreteAspect) | |||
{ | |||
this(new AjAttribute.AdviceAttribute(kind, pointcut, extraArgumentFlags, start, end, sourceContext), | |||
pointcut, signature, concreteAspect); | |||
thrownExceptions = Collections.EMPTY_LIST; //!!! interaction with unit tests | |||
} | |||
// ---- implementations of ShadowMunger's methods | |||
@@ -147,6 +138,46 @@ public class BcelAdvice extends Advice { | |||
} | |||
// ---- implementations | |||
private Collection collectCheckedExceptions(TypeX[] excs) { | |||
if (excs == null || excs.length == 0) return Collections.EMPTY_LIST; | |||
Collection ret = new ArrayList(); | |||
World world = concreteAspect.getWorld(); | |||
ResolvedTypeX runtimeException = world.resolve(TypeX.RUNTIME_EXCEPTION); | |||
ResolvedTypeX error = world.resolve(TypeX.ERROR); | |||
for (int i=0, len=excs.length; i < len; i++) { | |||
ResolvedTypeX t = world.resolve(excs[i]); | |||
if (!(runtimeException.isAssignableFrom(t) || error.isAssignableFrom(t))) { | |||
ret.add(t); | |||
} | |||
} | |||
return ret; | |||
} | |||
private Collection thrownExceptions = null; | |||
public Collection getThrownExceptions() { | |||
if (thrownExceptions == null) { | |||
//??? can we really lump in Around here, how does this interact with Throwable | |||
if (concreteAspect != null && concreteAspect.getWorld() != null && // null tests for test harness | |||
(getKind().isAfter() || getKind() == AdviceKind.Before || getKind() == AdviceKind.Around)) | |||
{ | |||
World world = concreteAspect.getWorld(); | |||
ResolvedMember m = world.resolve(signature); | |||
if (m == null) { | |||
thrownExceptions = Collections.EMPTY_LIST; | |||
} else { | |||
thrownExceptions = collectCheckedExceptions(m.getExceptions()); | |||
} | |||
} else { | |||
thrownExceptions = Collections.EMPTY_LIST; | |||
} | |||
} | |||
return thrownExceptions; | |||
} | |||
// only call me after prepare has been called | |||
public boolean hasDynamicTests() { |