|
Groovy example source code file (AssertionWriter.java)
The Groovy AssertionWriter.java source code
/*
* Copyright 2003-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.codehaus.groovy.classgen.asm;
import java.util.ArrayList;
import java.util.List;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.expr.BinaryExpression;
import org.codehaus.groovy.ast.expr.BooleanExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.AssertStatement;
import org.codehaus.groovy.control.Janitor;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.powerassert.SourceText;
import org.codehaus.groovy.runtime.powerassert.SourceTextNotAvailableException;
import org.codehaus.groovy.syntax.Token;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import static org.objectweb.asm.Opcodes.*;
public class AssertionWriter {
// assert
private static final MethodCaller assertFailedMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "assertFailed");
private static class AssertionTracker {
int recorderIndex;
SourceText sourceText;
}
private WriterController controller;
private AssertionTracker assertionTracker;
private AssertionTracker disabledTracker;
public AssertionWriter(WriterController wc) {
this.controller = wc;
}
public void writeAssertStatement(AssertStatement statement) {
MethodVisitor mv = controller.getMethodVisitor();
OperandStack operandStack = controller.getOperandStack();
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");
//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) {
// 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");
}
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;"
);
} 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");
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();
}
private void writeSourcelessAssertText(AssertStatement statement) {
MethodVisitor mv = controller.getMethodVisitor();
OperandStack operandStack = controller.getOperandStack();
BooleanExpression booleanExpression = statement.getBooleanExpression();
// push expression string onto stack
String expressionText = booleanExpression.getText();
List<String> list = new ArrayList
Other Groovy examples (source code examples)Here is a short list of links related to this Groovy AssertionWriter.java source code file: |
Other websites by Alvin Alexander:
Life/living in Alaska (OneMansAlaska.com)
How I Sold My Business (HowISoldMyBusiness.com)
Copyright 1998-2011 Alvin Alexander, devdaily.com
All Rights Reserved.