use of org.apache.groovy.contracts.annotations.meta.Postcondition in project groovy by apache.
the class AnnotationClosureVisitor method replaceWithClosureClassReference.
private void replaceWithClosureClassReference(AnnotationNode annotationNode, MethodNode methodNode) {
Validate.notNull(annotationNode);
Validate.notNull(methodNode);
// check whether this is a pre- or postcondition
boolean isPostcondition = AnnotationUtils.hasAnnotationOfType(annotationNode.getClassNode(), org.apache.groovy.contracts.annotations.meta.Postcondition.class.getName());
Expression expression = annotationNode.getMember(CLOSURE_ATTRIBUTE_NAME);
if (expression == null || expression instanceof ClassExpression)
return;
ClosureExpression closureExpression = (ClosureExpression) expression;
ClassCodeExpressionTransformer transformer = new OldPropertyExpressionTransformer(methodNode);
TransformingCodeVisitor visitor = new TransformingCodeVisitor(transformer);
visitor.visitClosureExpression(closureExpression);
ClosureExpressionValidator validator = new ClosureExpressionValidator(classNode, methodNode, annotationNode, sourceUnit);
validator.visitClosureExpression(closureExpression);
validator.secondPass(closureExpression);
List<Parameter> parameters = new ArrayList<>(Arrays.asList(closureExpression.getParameters()));
parameters.addAll(new ArrayList<>(Arrays.asList(methodNode.getParameters())));
final List<BooleanExpression> booleanExpressions = ExpressionUtils.getBooleanExpression(closureExpression);
if (booleanExpressions == null || booleanExpressions.isEmpty())
return;
BlockStatement closureBlockStatement = (BlockStatement) closureExpression.getCode();
BlockStatement newClosureBlockStatement = TryCatchBlockGenerator.generateTryCatchBlock(isPostcondition ? ClassHelper.makeWithoutCaching(PostconditionViolation.class) : ClassHelper.makeWithoutCaching(PreconditionViolation.class), "<" + annotationNode.getClassNode().getName() + "> " + classNode.getName() + "." + methodNode.getTypeDescriptor() + " \n\n", AssertStatementCreationUtility.getAssertionStatements(booleanExpressions));
newClosureBlockStatement.setSourcePosition(closureBlockStatement);
ClosureExpression rewrittenClosureExpression = new ClosureExpression(parameters.toArray(Parameter.EMPTY_ARRAY), newClosureBlockStatement);
rewrittenClosureExpression.setSourcePosition(closureExpression);
rewrittenClosureExpression.setDeclaringClass(closureExpression.getDeclaringClass());
rewrittenClosureExpression.setSynthetic(true);
rewrittenClosureExpression.setVariableScope(correctVariableScope(closureExpression.getVariableScope(), methodNode));
rewrittenClosureExpression.setType(closureExpression.getType());
boolean isConstructor = methodNode instanceof ConstructorNode;
ClassNode closureClassNode = contractClosureWriter.createClosureClass(classNode, methodNode, rewrittenClosureExpression, isPostcondition && !isConstructor, isPostcondition && !isConstructor, Opcodes.ACC_PUBLIC);
classNode.getModule().addClass(closureClassNode);
final ClassExpression value = new ClassExpression(closureClassNode);
value.setSourcePosition(annotationNode);
BlockStatement value1 = TryCatchBlockGenerator.generateTryCatchBlockForInlineMode(isPostcondition ? ClassHelper.makeWithoutCaching(PostconditionViolation.class) : ClassHelper.makeWithoutCaching(PreconditionViolation.class), "<" + annotationNode.getClassNode().getName() + "> " + classNode.getName() + "." + methodNode.getTypeDescriptor() + " \n\n", AssertStatementCreationUtility.getAssertionStatements(booleanExpressions));
value1.setNodeMetaData(META_DATA_USE_EXECUTION_TRACKER, validator.isMethodCalls());
value.setNodeMetaData(META_DATA_ORIGINAL_TRY_CATCH_BLOCK, value1);
annotationNode.setMember(CLOSURE_ATTRIBUTE_NAME, value);
markClosureReplaced(methodNode);
}
use of org.apache.groovy.contracts.annotations.meta.Postcondition in project groovy by apache.
the class PostconditionGenerator method generateDefaultPostconditionStatement.
/**
* Adds a default postcondition if a postcondition has already been defined for this {@link org.codehaus.groovy.ast.MethodNode}
* in a super-class.
*
* @param type the current {@link org.codehaus.groovy.ast.ClassNode} of the given <tt>methodNode</tt>
* @param method the {@link org.codehaus.groovy.ast.MethodNode} to create the default postcondition for
*/
public void generateDefaultPostconditionStatement(final ClassNode type, final MethodNode method) {
// if another precondition is available we'll evaluate to false
boolean isAnotherPostconditionAvailable = AnnotationUtils.getAnnotationNodeInHierarchyWithMetaAnnotation(type.getSuperClass(), method, ClassHelper.makeWithoutCaching(Postcondition.class)).size() > 0;
if (!isAnotherPostconditionAvailable)
return;
// if another post-condition is available we need to add a default expression of TRUE
// since post-conditions are usually connected with a logical AND
final BooleanExpression postconditionBooleanExpression = addCallsToSuperMethodNodeAnnotationClosure(method.getDeclaringClass(), method, Postcondition.class, new BooleanExpression(ConstantExpression.TRUE), true);
if (postconditionBooleanExpression.getExpression() == ConstantExpression.TRUE)
return;
final BlockStatement blockStatement = wrapAssertionBooleanExpression(type, method, postconditionBooleanExpression, "postcondition");
addPostcondition(method, blockStatement);
}
Aggregations