import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.Clinit;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel;
+import org.eclipse.jdt.internal.compiler.codegen.Label;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
public class AspectClinit extends Clinit {
private boolean hasPre, hasPost;
+ private FieldBinding initFailureField;
- public AspectClinit(Clinit old, CompilationResult compilationResult, boolean hasPre, boolean hasPost) {
+ public AspectClinit(Clinit old, CompilationResult compilationResult, boolean hasPre, boolean hasPost, FieldBinding initFailureField) {
super(compilationResult);
this.needFreeReturn = old.needFreeReturn;
this.sourceEnd = old.sourceEnd;
this.hasPre = hasPre;
this.hasPost = hasPost;
+ this.initFailureField = initFailureField;
}
+
+ private ExceptionLabel handlerLabel;
protected void generateSyntheticCode(
ClassScope classScope,
CodeStream codeStream)
{
+ if (initFailureField != null) {
+ handlerLabel = new ExceptionLabel(codeStream, classScope.getJavaLangThrowable());
+ }
+
if (hasPre) {
final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
)));
}
+ if (initFailureField != null) {
+ handlerLabel.placeEnd();
+ Label endLabel = new Label(codeStream);
+ codeStream.goto_(endLabel);
+
+ handlerLabel.place();
+ codeStream.putstatic(initFailureField);
+ endLabel.place();
+ }
+
}
}
}
}
-
+ private FieldBinding initFailureField= null;
public void generateCode(ClassFile enclosingClassFile) {
if (ignoreFurtherInvestigation) {
if (!isAbstract()) {
+ initFailureField = factory.makeFieldBinding(AjcMemberMaker.initFailureCauseField(typeX));
+ binding.addField(initFailureField);
+
if (perClause == null) {
// we've already produced an error for this
} else if (perClause.getKind() == PerClause.SINGLETON) {
binding.addField(factory.makeFieldBinding(AjcMemberMaker.perSingletonField(
typeX)));
- methods[0] = new AspectClinit((Clinit)methods[0], compilationResult, false, true);
+
+ methods[0] = new AspectClinit((Clinit)methods[0], compilationResult, false, true, initFailureField);
} else if (perClause.getKind() == PerClause.PERCFLOW) {
binding.addField(
factory.makeFieldBinding(
AjcMemberMaker.perCflowField(
typeX)));
- methods[0] = new AspectClinit((Clinit)methods[0], compilationResult, true, false);
+ methods[0] = new AspectClinit((Clinit)methods[0], compilationResult, true, false, null);
} else if (perClause.getKind() == PerClause.PEROBJECT) {
// binding.addField(
// world.makeFieldBinding(
codeStream.ifnull(isNull);
codeStream.areturn();
isNull.place();
+
codeStream.new_(world.makeTypeBinding(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION));
codeStream.dup();
+ codeStream.ldc(typeX.getNameAsIdentifier());
+ codeStream.getstatic(initFailureField);
codeStream.invokespecial(world.makeMethodBindingForCall(
- AjcMemberMaker.noAspectBoundExceptionInit()
+ AjcMemberMaker.noAspectBoundExceptionInitWithCause()
));
codeStream.athrow();
// body ends here
* when there is no aspect of that type currently bound.
*/
public class NoAspectBoundException extends RuntimeException {
+ Throwable cause;
+ public NoAspectBoundException(String aspectName, Throwable inner) {
+ super(inner == null ? aspectName :
+ "Exception while initializing " +aspectName + ": " +inner);
+ this.cause = inner;
+ }
+
+ public NoAspectBoundException() {
+ }
+
+ public Throwable getCause() { return cause; }
+
}
// default package
+import org.aspectj.lang.NoAspectBoundException;
+
import junit.framework.*;
public class RuntimeModuleTests extends TestCase {
public RuntimeModuleTests(String name) { super(name); }
public void testNothing() {}
+
+ public void testNoAspectBoundException() {
+ RuntimeException fun = new RuntimeException("fun");
+ NoAspectBoundException nab = new NoAspectBoundException("Foo", fun);
+ assertEquals(fun,nab.getCause());
+ }
}
<run class="Main1"/>
</ajc-test>
+ <ajc-test dir="bugs" pr="44587"
+ title="Erroneous exception conversion">
+ <compile files="ErroneousExceptionConversion.java">
+ </compile>
+ <run class="ErroneousExceptionConversion"/>
+ </ajc-test>
+
+ <ajc-test dir="bugs" pr="34206"
+ title="before():execution(new(..)) does not throw NoAspectBoundException">
+ <compile files="ErroneousExceptionConversion1.java">
+ </compile>
+ <run class="ErroneousExceptionConversion1"/>
+ </ajc-test>
+
</suite>
--- /dev/null
+// pr 44587
+import org.aspectj.testing.Tester;
+import org.aspectj.lang.NoAspectBoundException;
+public class ErroneousExceptionConversion {
+
+ public static void main(String[] args) {
+ try {
+ new ErroneousExceptionConversion();
+ Tester.checkFailed("Wanted an exception in initializer error");
+ } catch (NoAspectBoundException nabEx) {
+ // good
+ // check nabEx.getCause instanceof RuntimeException and has explanation "boom..."
+ Throwable cause = nabEx.getCause();
+ if (!(cause instanceof RuntimeException)) {
+ Tester.checkFailed("Should have a RuntimeException as cause");
+ }
+ } catch(Throwable t) {
+ Tester.checkFailed("Wanted an ExceptionInInitializerError but got " + t);
+ }
+ }
+
+
+}
+
+aspect A {
+
+ int ErroneousExceptionConversion.someField = throwIt();
+
+ public static int throwIt() {
+ throw new RuntimeException("Exception during aspect initialization");
+ }
+
+ public A() {
+ System.err.println("boom in 5...");
+ throw new RuntimeException("boom");
+ }
+
+ // if I change this to execution the test passes...
+ after() throwing : initialization(ErroneousExceptionConversion.new(..)) {
+ System.out.println("After throwing");
+ }
+
+}
+
--- /dev/null
+import org.aspectj.lang.*;
+import org.aspectj.testing.Tester;
+
+aspect Watchcall {
+ pointcut myConstructor(): execution(new(..));
+
+ before(): myConstructor() {
+ System.err.println("Entering Constructor");
+ }
+
+ after(): myConstructor() {
+ System.err.println("Leaving Constructor");
+ }
+}
+
+public class ErroneousExceptionConversion1 {
+ public static void main(String[] args) {
+ try {
+ ErroneousExceptionConversion1 c = new ErroneousExceptionConversion1();
+ Tester.checkFailed("shouldn't get here");
+ } catch (NoAspectBoundException nab) {
+ // expected
+ }
+
+ }
+}
import org.aspectj.testing.*;
+import org.aspectj.lang.*;
/**
* -usejavac mode: no error
public static void main(String[] args) {
try {
new ConstructorExecInitFails();
- } catch (ExceptionInInitializerError e) {
+ } catch (NoAspectBoundException e) {
+
+ Tester.check(e.getCause() instanceof NoAspectBoundException,
+ "Expected NoAspectBoundException, found " + e.getCause());
return;
}
Tester.checkFailed("shouldn't be able to run");
import java.lang.reflect.Modifier;
+import org.aspectj.weaver.ResolvedTypeX.Name;
+
public class AjcMemberMaker {
private static final int PUBLIC_STATIC_FINAL =
public static Member noAspectBoundExceptionInit() {
return new ResolvedMember(
- Member.METHOD,
- NO_ASPECT_BOUND_EXCEPTION,
- Modifier.PUBLIC,
- "<init>",
- "()V");
+ Member.METHOD,
+ NO_ASPECT_BOUND_EXCEPTION,
+ Modifier.PUBLIC,
+ "<init>",
+ "()V");
}
+ public static Member noAspectBoundExceptionInitWithCause() {
+ return new ResolvedMember(
+ Member.METHOD,
+ NO_ASPECT_BOUND_EXCEPTION,
+ Modifier.PUBLIC,
+ "<init>",
+ "(Ljava/lang/String;Ljava/lang/Throwable;)V");
+ }
+
public static ResolvedMember perCflowPush(TypeX declaringType) {
return new ResolvedMember(
Member.METHOD,
declaringType.getSignature());
}
+
+ public static ResolvedMember initFailureCauseField(TypeX declaringType) {
+ return new ResolvedMember(
+ Member.FIELD,
+ declaringType,
+ PRIVATE_STATIC,
+ NameMangler.INITFAILURECAUSE_FIELD_NAME,
+ TypeX.THROWABLE.getSignature());
+ }
public static ResolvedMember perObjectField(TypeX declaringType, ResolvedTypeX aspectType) {
int modifiers = Modifier.PRIVATE;
public static final String AJC_POST_CLINIT_NAME = PREFIX + "postClinit";
-
-
+ public static final String INITFAILURECAUSE_FIELD_NAME = PREFIX + "initFailureCause";
+
public static String perObjectInterfaceGet(TypeX aspectType) {
return makeName(aspectType.getNameAsIdentifier(), "perObjectGet");
}
// assert t.getHandler() == ih
ExceptionRange er = (ExceptionRange) t;
if (er.getCatchType() == null) continue;
+ if (isInitFailureHandler(ih)) return;
+
match(
BcelShadow.makeExceptionHandler(
world,
}
}
+ private boolean isInitFailureHandler(InstructionHandle ih) {
+ if (ih.getInstruction() instanceof PUTSTATIC) {
+ String name = ((PUTSTATIC)ih.getInstruction()).getFieldName(cpg);
+ if (name.equals(NameMangler.INITFAILURECAUSE_FIELD_NAME)) return true;
+ }
+ return false;
+ }
+
private void matchSetInstruction(
LazyMethodGen mg,
List shadowAccumulator) {
FieldInstruction fi = (FieldInstruction) ih.getInstruction();
Member field = BcelWorld.makeFieldSignature(clazz, fi);
+
+ // synthetic fields are never join points
+ if (field.getName().startsWith(NameMangler.PREFIX)) return;
+
ResolvedMember resolvedField = field.resolve(world);
if (resolvedField == null) {
// we can't find the field, so it's not a join point.
private void matchGetInstruction(LazyMethodGen mg, InstructionHandle ih, BcelShadow enclosingShadow, List shadowAccumulator) {
FieldInstruction fi = (FieldInstruction) ih.getInstruction();
Member field = BcelWorld.makeFieldSignature(clazz, fi);
+
+ // synthetic fields are never join points
+ if (field.getName().startsWith(NameMangler.PREFIX)) return;
+
ResolvedMember resolvedField = field.resolve(world);
if (resolvedField == null) {
// we can't find the field, so it's not a join point.