boolean rewriteAssert = true;
// don't rewrite assertions with message
rewriteAssert = statement.getMessageExpression() == ConstantExpression.NULL;
AssertionTracker oldTracker = assertionTracker;
Janitor janitor = new Janitor();
final Label tryStart = new Label();
if (rewriteAssert){
assertionTracker = new AssertionTracker();
try {
// because source position seems to be more reliable for statements
// than for expressions, we get the source text for the whole statement
assertionTracker.sourceText = new SourceText(statement, controller.getSourceUnit(), janitor);
mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/powerassert/ValueRecorder");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/powerassert/ValueRecorder", "<init>", "()V", false);
//TODO: maybe use more specialized type here
controller.getOperandStack().push(ClassHelper.OBJECT_TYPE);
assertionTracker.recorderIndex = controller.getCompileStack().defineTemporaryVariable("recorder", true);
mv.visitLabel(tryStart);
} catch (SourceTextNotAvailableException e) {
// set assertionTracker to null to deactivate AssertionWriter#record calls
assertionTracker = null;
// don't rewrite assertions w/o source text
rewriteAssert = false;
}
}
statement.getBooleanExpression().visit(controller.getAcg());
Label exceptionThrower = operandStack.jump(IFEQ);
// do nothing, but clear the value recorder
if (rewriteAssert) {
//clean up assertion recorder
mv.visitVarInsn(ALOAD, assertionTracker.recorderIndex);
mv.visitMethodInsn(INVOKEVIRTUAL, "org/codehaus/groovy/runtime/powerassert/ValueRecorder", "clear", "()V", false);
}
Label afterAssert = new Label();
mv.visitJumpInsn(GOTO, afterAssert);
mv.visitLabel(exceptionThrower);
if (rewriteAssert) {
mv.visitLdcInsn(assertionTracker.sourceText.getNormalizedText());
mv.visitVarInsn(ALOAD, assertionTracker.recorderIndex);
mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/runtime/powerassert/AssertionRenderer", "render", "(Ljava/lang/String;Lorg/codehaus/groovy/runtime/powerassert/ValueRecorder;)Ljava/lang/String;", false);
} else {
writeSourcelessAssertText(statement);
}
operandStack.push(ClassHelper.STRING_TYPE);
AssertionTracker savedTracker = assertionTracker;
assertionTracker = null;
// now the optional exception expression
statement.getMessageExpression().visit(controller.getAcg());
operandStack.box();
assertFailedMethod.call(mv);
operandStack.remove(2); // assertFailed called static with 2 arguments
if (rewriteAssert) {
final Label tryEnd = new Label();
mv.visitLabel(tryEnd);
mv.visitJumpInsn(GOTO, afterAssert);
// finally block to clean assertion recorder
final Label catchAny = new Label();
mv.visitLabel(catchAny);
mv.visitVarInsn(ALOAD, savedTracker.recorderIndex);
mv.visitMethodInsn(INVOKEVIRTUAL, "org/codehaus/groovy/runtime/powerassert/ValueRecorder", "clear", "()V", false);
mv.visitInsn(ATHROW);
// add catch any block to exception table
controller.getCompileStack().addExceptionBlock(tryStart, tryEnd, catchAny, null);
}
mv.visitLabel(afterAssert);
if (rewriteAssert) {
controller.getCompileStack().removeVar(savedTracker.recorderIndex);
}
assertionTracker = oldTracker;
// close possibly open file handles from getting a sample for
// power asserts
janitor.cleanup();
}