This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 95f36bc52c `groovy-contracts`: refactor attribute replacement
95f36bc52c is described below

commit 95f36bc52cdca47ca7722e45aabb57152dcc86f7
Author: Eric Milles <[email protected]>
AuthorDate: Mon Aug 14 15:33:45 2023 -0500

    `groovy-contracts`: refactor attribute replacement
---
 .../groovy/classgen/AsmClassGenerator.java         |  22 +--
 .../classgen/asm/WriterControllerFactory.java      |   1 +
 .../ast/visitor/AnnotationClosureVisitor.java      | 117 +++++++---------
 .../ast/visitor/AnnotationProcessorVisitor.java    | 154 ++++++++-------------
 .../groovy/contracts/ast/visitor/BaseVisitor.java  |  51 ++++++-
 .../classgen/asm/ContractClosureWriter.java        |  49 +++----
 .../groovy/contracts/generation/BaseGenerator.java |  95 +++++--------
 .../generation/ClassInvariantGenerator.java        |  32 +----
 .../main/resources/dsld/contract_transform.dsld    |   4 +-
 9 files changed, 221 insertions(+), 304 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java 
b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index d56efbfd25..dcba562e5f 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -1093,28 +1093,28 @@ public class AsmClassGenerator extends ClassGenerator {
 
             MethodVisitor mv = controller.getMethodVisitor();
             mv.visitVarInsn(ALOAD, 0);
-            ClassNode iterType = classNode;
-            while (!iterType.equals(type)) {
-                String ownerName = 
BytecodeHelper.getClassInternalName(iterType);
-                if (iterType.getOuterClass() == null) break;
-                FieldNode thisField = iterType.getField("this$0");
-                iterType = iterType.getOuterClass();
+            ClassNode thisType = classNode;
+            while (!thisType.equals(type)) {
+                if (thisType.getOuterClass() == null) break;
+                String ownerName = 
BytecodeHelper.getClassInternalName(thisType);
+                FieldNode thisField = thisType.getField("this$0");
+                thisType = thisType.getOuterClass();
                 if (thisField == null) {
                     // closure within inner class
-                    while (ClassHelper.isGeneratedFunction(iterType)) {
+                    while (ClassHelper.isGeneratedFunction(thisType)) {
                         // GROOVY-8881: cater for closures within closures - 
getThisObject is already outer class of all closures
-                        iterType = iterType.getOuterClass();
+                        thisType = thisType.getOuterClass();
                     }
                     mv.visitMethodInsn(INVOKEVIRTUAL, 
BytecodeHelper.getClassInternalName(ClassHelper.CLOSURE_TYPE), "getThisObject", 
"()Ljava/lang/Object;", false);
-                    mv.visitTypeInsn(CHECKCAST, 
BytecodeHelper.getClassInternalName(iterType));
+                    mv.visitTypeInsn(CHECKCAST, 
BytecodeHelper.getClassInternalName(thisType));
                 } else {
                     ClassNode thisFieldType = thisField.getType();
                     if (ClassHelper.CLOSURE_TYPE.equals(thisFieldType)) {
                         mv.visitFieldInsn(GETFIELD, ownerName, "this$0", 
BytecodeHelper.getTypeDescription(ClassHelper.CLOSURE_TYPE));
                         mv.visitMethodInsn(INVOKEVIRTUAL, 
BytecodeHelper.getClassInternalName(ClassHelper.CLOSURE_TYPE), "getThisObject", 
"()Ljava/lang/Object;", false);
-                        mv.visitTypeInsn(CHECKCAST, 
BytecodeHelper.getClassInternalName(iterType));
+                        mv.visitTypeInsn(CHECKCAST, 
BytecodeHelper.getClassInternalName(thisType));
                     } else {
-                        String typeName = 
BytecodeHelper.getTypeDescription(iterType);
+                        String typeName = 
BytecodeHelper.getTypeDescription(thisType);
                         mv.visitFieldInsn(GETFIELD, ownerName, "this$0", 
typeName);
                     }
                 }
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/WriterControllerFactory.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/WriterControllerFactory.java
index 9d683edc07..eddc1fb1b5 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/WriterControllerFactory.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/WriterControllerFactory.java
@@ -21,6 +21,7 @@ package org.codehaus.groovy.classgen.asm;
 /**
  * A non-static factory to get alternative writer controller to be stored in 
the metadata
  */
+@FunctionalInterface
 public interface WriterControllerFactory {
     WriterController makeController(WriterController normalController);
 }
diff --git 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationClosureVisitor.java
 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationClosureVisitor.java
index 4f6bcb05c2..5ff5d506f9 100644
--- 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationClosureVisitor.java
+++ 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationClosureVisitor.java
@@ -39,7 +39,6 @@ import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
 import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.ConstructorNode;
 import org.codehaus.groovy.ast.FieldNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
@@ -49,7 +48,6 @@ import org.codehaus.groovy.ast.VariableScope;
 import org.codehaus.groovy.ast.expr.BinaryExpression;
 import org.codehaus.groovy.ast.expr.BooleanExpression;
 import org.codehaus.groovy.ast.expr.CastExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
 import org.codehaus.groovy.ast.expr.ClosureExpression;
 import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
 import org.codehaus.groovy.ast.expr.Expression;
@@ -105,74 +103,63 @@ public class AnnotationClosureVisitor extends BaseVisitor 
implements ASTNodeMeta
         super(sourceUnit, source);
     }
 
+    
//--------------------------------------------------------------------------
+
     @Override
-    public void visitClass(ClassNode node) {
-        if (node == null) return;
-        if (!(CandidateChecks.isInterfaceContractsCandidate(node) || 
CandidateChecks.isContractsCandidate(node)))
-            return;
+    public void visitClass(ClassNode classNode) {
+        if (classNode == null || 
!(CandidateChecks.isInterfaceContractsCandidate(classNode) || 
CandidateChecks.isContractsCandidate(classNode))) return;
 
-        classNode = node;
+        this.classNode = classNode;
 
-        if (classNode.getNodeMetaData(PROCESSED) == null && 
CandidateChecks.isContractsCandidate(node)) {
-            final List<AnnotationNode> annotationNodes = 
AnnotationUtils.hasMetaAnnotations(node, ContractElement.class.getName());
+        if (classNode.getNodeMetaData(PROCESSED) == null && 
CandidateChecks.isContractsCandidate(classNode)) {
+            List<AnnotationNode> annotationNodes = 
AnnotationUtils.hasMetaAnnotations(classNode, ContractElement.class.getName());
             for (AnnotationNode annotationNode : annotationNodes) {
-                Expression expression = 
annotationNode.getMember(CLOSURE_ATTRIBUTE_NAME);
-                if (expression == null || expression instanceof 
ClassExpression) continue;
-
-                ClosureExpression closureExpression = (ClosureExpression) 
expression;
+                ClosureExpression closureExpression = 
getOriginalCondition(annotationNode);
+                if (closureExpression == null) continue;
 
                 ClosureExpressionValidator validator = new 
ClosureExpressionValidator(classNode, null, annotationNode, sourceUnit);
                 validator.visitClosureExpression(closureExpression);
                 validator.secondPass(closureExpression);
 
-                List<Parameter> parameters = new 
ArrayList<>(Arrays.asList(closureExpression.getParameters()));
-
-                final List<BooleanExpression> booleanExpressions = 
ExpressionUtils.getBooleanExpression(closureExpression);
+                List<BooleanExpression> booleanExpressions = 
ExpressionUtils.getBooleanExpression(closureExpression);
                 if (booleanExpressions == null || 
booleanExpressions.isEmpty()) continue;
 
-                BlockStatement closureBlockStatement = (BlockStatement) 
closureExpression.getCode();
-
                 BlockStatement newClosureBlockStatement = 
TryCatchBlockGenerator.generateTryCatchBlock(
                         
ClassHelper.makeWithoutCaching(ClassInvariantViolation.class),
                         "<" + annotationNode.getClassNode().getName() + "> " + 
classNode.getName() + " \n\n",
                         
AssertStatementCreationUtility.getAssertionStatements(booleanExpressions)
                 );
+                
newClosureBlockStatement.setSourcePosition(closureExpression.getCode());
 
-                
newClosureBlockStatement.setSourcePosition(closureBlockStatement);
-
-                ClosureExpression rewrittenClosureExpression = new 
ClosureExpression(parameters.toArray(Parameter.EMPTY_ARRAY), 
newClosureBlockStatement);
-                
rewrittenClosureExpression.setSourcePosition(closureExpression);
+                ClosureExpression rewrittenClosureExpression = new 
ClosureExpression(closureExpression.getParameters(), newClosureBlockStatement);
                 
rewrittenClosureExpression.setDeclaringClass(closureExpression.getDeclaringClass());
+                
rewrittenClosureExpression.setSourcePosition(closureExpression);
                 rewrittenClosureExpression.setSynthetic(true);
                 
rewrittenClosureExpression.setVariableScope(closureExpression.getVariableScope());
-                
rewrittenClosureExpression.setType(closureExpression.getType());
 
                 ClassNode closureClassNode = 
contractClosureWriter.createClosureClass(classNode, null, 
rewrittenClosureExpression, false, false, Opcodes.ACC_PUBLIC);
                 classNode.getModule().addClass(closureClassNode);
 
-                final ClassExpression value = new 
ClassExpression(closureClassNode);
-                value.setSourcePosition(annotationNode);
-
-                BlockStatement value1 = 
TryCatchBlockGenerator.generateTryCatchBlockForInlineMode(
+                BlockStatement block = 
TryCatchBlockGenerator.generateTryCatchBlockForInlineMode(
                         
ClassHelper.makeWithoutCaching(ClassInvariantViolation.class),
                         "<" + annotationNode.getClassNode().getName() + "> " + 
classNode.getName() + " \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);
+                block.setNodeMetaData(META_DATA_USE_EXECUTION_TRACKER, 
validator.isMethodCalls());
 
+                Expression value = 
classX(closureClassNode.getPlainNodeReference());
+                value.setNodeMetaData(META_DATA_ORIGINAL_TRY_CATCH_BLOCK, 
block);
+                value.setSourcePosition(annotationNode);
+                replaceCondition(annotationNode, value);
                 markClosureReplaced(classNode);
             }
         }
 
-        super.visitClass(node);
+        super.visitClass(classNode);
 
         // generate closure classes for the super class and all implemented 
interfaces
-        visitClass(node.getSuperClass());
-        for (ClassNode i : node.getInterfaces()) {
+        visitClass(classNode.getSuperClass());
+        for (ClassNode i : classNode.getInterfaces()) {
             visitClass(i);
         }
 
@@ -181,11 +168,9 @@ public class AnnotationClosureVisitor extends BaseVisitor 
implements ASTNodeMeta
 
     @Override
     public void visitConstructorOrMethod(MethodNode methodNode, boolean 
isConstructor) {
-        if (!CandidateChecks.couldBeContractElementMethodNode(classNode, 
methodNode) && !(CandidateChecks.isPreconditionCandidate(classNode, 
methodNode)))
-            return;
-        if (methodNode.getNodeMetaData(PROCESSED) != null) return;
+        if (methodNode.getNodeMetaData(PROCESSED) != null || 
!(CandidateChecks.couldBeContractElementMethodNode(classNode, methodNode) || 
CandidateChecks.isPreconditionCandidate(classNode, methodNode))) return;
 
-        final List<AnnotationNode> annotationNodes = 
AnnotationUtils.hasMetaAnnotations(methodNode, ContractElement.class.getName());
+        List<AnnotationNode> annotationNodes = 
AnnotationUtils.hasMetaAnnotations(methodNode, ContractElement.class.getName());
         for (AnnotationNode annotationNode : annotationNodes) {
             replaceWithClosureClassReference(annotationNode, methodNode);
         }
@@ -199,13 +184,9 @@ public class AnnotationClosureVisitor extends BaseVisitor 
implements ASTNodeMeta
         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());
+        ClosureExpression closureExpression = 
getOriginalCondition(annotationNode);
+        if (closureExpression == null) return;
 
-        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);
@@ -215,52 +196,46 @@ public class AnnotationClosureVisitor extends BaseVisitor 
implements ASTNodeMeta
         validator.secondPass(closureExpression);
 
         List<Parameter> parameters = new 
ArrayList<>(Arrays.asList(closureExpression.getParameters()));
+        parameters.addAll(Arrays.asList(methodNode.getParameters()));
 
-        parameters.addAll(new 
ArrayList<>(Arrays.asList(methodNode.getParameters())));
-
-        final List<BooleanExpression> booleanExpressions = 
ExpressionUtils.getBooleanExpression(closureExpression);
+        List<BooleanExpression> booleanExpressions = 
ExpressionUtils.getBooleanExpression(closureExpression);
         if (booleanExpressions == null || booleanExpressions.isEmpty()) return;
 
-        BlockStatement closureBlockStatement = (BlockStatement) 
closureExpression.getCode();
+        boolean isConstructor = methodNode.isConstructor();
+        boolean isPostcondition = 
AnnotationUtils.hasAnnotationOfType(annotationNode.getClassNode(), 
POSTCONDITION_TYPE_NAME);
 
         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);
+        
newClosureBlockStatement.setSourcePosition(closureExpression.getCode());
 
         ClosureExpression rewrittenClosureExpression = new 
ClosureExpression(parameters.toArray(Parameter.EMPTY_ARRAY), 
newClosureBlockStatement);
-        rewrittenClosureExpression.setSourcePosition(closureExpression);
         
rewrittenClosureExpression.setDeclaringClass(closureExpression.getDeclaringClass());
+        rewrittenClosureExpression.setSourcePosition(closureExpression);
         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(
+        BlockStatement block = 
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);
+        block.setNodeMetaData(META_DATA_USE_EXECUTION_TRACKER, 
validator.isMethodCalls());
 
+        Expression value = classX(closureClassNode.getPlainNodeReference());
+        value.setNodeMetaData(META_DATA_ORIGINAL_TRY_CATCH_BLOCK, block);
+        value.setSourcePosition(annotationNode);
+        replaceCondition(annotationNode, value);
         markClosureReplaced(methodNode);
     }
 
     private VariableScope correctVariableScope(VariableScope variableScope, 
MethodNode methodNode) {
-        if (variableScope == null) return null;
-        if (methodNode == null || methodNode.getParameters() == null || 
methodNode.getParameters().length == 0)
+        if (variableScope == null || methodNode == null || 
methodNode.getParameters() == null || methodNode.getParameters().length == 0)
             return variableScope;
 
         VariableScope copy = copy(variableScope);
@@ -291,15 +266,17 @@ public class AnnotationClosureVisitor extends BaseVisitor 
implements ASTNodeMeta
         return copy;
     }
 
+    private void markClosureReplaced(ASTNode someNode) {
+        if (someNode.getNodeMetaData(CLOSURE_REPLACED) == null)
+            someNode.setNodeMetaData(CLOSURE_REPLACED, Boolean.TRUE);
+    }
+
     private void markProcessed(ASTNode someNode) {
         if (someNode.getNodeMetaData(PROCESSED) == null)
             someNode.setNodeMetaData(PROCESSED, Boolean.TRUE);
     }
 
-    private void markClosureReplaced(ASTNode someNode) {
-        if (someNode.getNodeMetaData(CLOSURE_REPLACED) == null)
-            someNode.setNodeMetaData(CLOSURE_REPLACED, Boolean.TRUE);
-    }
+    
//--------------------------------------------------------------------------
 
     static class ClosureExpressionValidator extends ClassCodeVisitorSupport {
 
@@ -490,7 +467,7 @@ public class AnnotationClosureVisitor extends BaseVisitor 
implements ASTNodeMeta
 
     private static class OldPropertyExpressionTransformer extends 
ClassCodeExpressionTransformer {
         private final MethodNode methodNode;
-        private CastExpression currentCast = null;
+        private CastExpression currentCast;
 
         public OldPropertyExpressionTransformer(MethodNode methodNode) {
             this.methodNode = methodNode;
@@ -531,4 +508,4 @@ public class AnnotationClosureVisitor extends BaseVisitor 
implements ASTNodeMeta
             return expr.transformExpression(this);
         }
     }
-}
\ No newline at end of file
+}
diff --git 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationProcessorVisitor.java
 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationProcessorVisitor.java
index b09df6191c..b23e38ab96 100644
--- 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationProcessorVisitor.java
+++ 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationProcessorVisitor.java
@@ -19,6 +19,7 @@
 package org.apache.groovy.contracts.ast.visitor;
 
 import org.apache.groovy.contracts.annotations.meta.ContractElement;
+import org.apache.groovy.contracts.annotations.meta.Postcondition;
 import org.apache.groovy.contracts.common.spi.AnnotationProcessor;
 import org.apache.groovy.contracts.common.spi.ProcessingContextInformation;
 import org.apache.groovy.contracts.generation.CandidateChecks;
@@ -26,31 +27,25 @@ import org.apache.groovy.contracts.util.AnnotationUtils;
 import org.apache.groovy.contracts.util.Validate;
 import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.ConstructorNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
+import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.MethodCallExpression;
-import org.codehaus.groovy.ast.expr.VariableExpression;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.control.io.ReaderSource;
 
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
-import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.boolX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static 
org.apache.groovy.contracts.ast.visitor.AnnotationClosureVisitor.META_DATA_ORIGINAL_TRY_CATCH_BLOCK;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
 
 /**
  * Visits annotations of meta-type {@link ContractElement} and applies the AST 
transformations of the underlying
@@ -60,13 +55,11 @@ import static 
org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
  */
 public class AnnotationProcessorVisitor extends BaseVisitor {
 
-    private static final String DO_CALL = "doCall";
     private ProcessingContextInformation pci;
 
     public AnnotationProcessorVisitor(final SourceUnit sourceUnit, final 
ReaderSource source, final ProcessingContextInformation pci) {
         super(sourceUnit, source);
         Validate.notNull(pci);
-
         this.pci = pci;
     }
 
@@ -79,10 +72,9 @@ public class AnnotationProcessorVisitor extends BaseVisitor {
         methodNodes.addAll(type.getDeclaredConstructors());
 
         for (MethodNode methodNode : methodNodes) {
-            if (!CandidateChecks.isClassInvariantCandidate(type, methodNode) 
&& !CandidateChecks.isPreOrPostconditionCandidate(type, methodNode))
-                continue;
-
-            handleMethodAnnotations(methodNode, 
AnnotationUtils.hasMetaAnnotations(methodNode, 
ContractElement.class.getName()));
+            if (CandidateChecks.isClassInvariantCandidate(type, methodNode) || 
CandidateChecks.isPreOrPostconditionCandidate(type, methodNode)) {
+                handleMethodAnnotations(methodNode, 
AnnotationUtils.hasMetaAnnotations(methodNode, 
ContractElement.class.getName()));
+            }
         }
 
         // visit all interfaces of this class
@@ -91,23 +83,18 @@ public class AnnotationProcessorVisitor extends BaseVisitor 
{
     }
 
     private void visitAbstractBaseClassesForInterfaceMethodNodes(ClassNode 
origin, ClassNode superClass) {
-        if (superClass == null) return;
-        if (!Modifier.isAbstract(superClass.getModifiers())) return;
-
-        for (ClassNode interfaceClassNode : superClass.getInterfaces()) {
-            List<MethodNode> methodNodes = new 
ArrayList<>(interfaceClassNode.getMethods());
-
-            for (MethodNode interfaceMethodNode : methodNodes) {
-                final List<AnnotationNode> annotationNodes = 
AnnotationUtils.hasMetaAnnotations(interfaceMethodNode, 
ContractElement.class.getName());
+        if (superClass == null || !superClass.isAbstract()) return;
+        for (ClassNode interfaceNode : superClass.getInterfaces()) {
+            List<MethodNode> interfaceMethods = new 
ArrayList<>(interfaceNode.getMethods());
+            for (MethodNode interfaceMethod : interfaceMethods) {
+                List<AnnotationNode> annotationNodes = 
AnnotationUtils.hasMetaAnnotations(interfaceMethod, 
ContractElement.class.getName());
                 if (annotationNodes == null || annotationNodes.isEmpty()) 
continue;
 
-                MethodNode implementingMethodNode = 
superClass.getMethod(interfaceMethodNode.getName(), 
interfaceMethodNode.getParameters());
+                MethodNode implementingMethod = 
superClass.getMethod(interfaceMethod.getName(), 
interfaceMethod.getParameters());
+                // if implementingMethodNode == null, then superClass is 
abstract and does not implement the interface methodNode
+                if (implementingMethod != null) continue;
 
-                // if implementingMethodNode == null, then superClass is 
abstract and does not implement
-                // the current interface methodNode
-                if (implementingMethodNode != null) continue;
-
-                MethodNode implementationInOriginClassNode = 
origin.getMethod(interfaceMethodNode.getName(), 
interfaceMethodNode.getParameters());
+                MethodNode implementationInOriginClassNode = 
origin.getMethod(interfaceMethod.getName(), interfaceMethod.getParameters());
                 if (implementationInOriginClassNode == null) continue;
 
                 handleMethodAnnotations(implementationInOriginClassNode, 
annotationNodes);
@@ -116,41 +103,29 @@ public class AnnotationProcessorVisitor extends 
BaseVisitor {
     }
 
     private void visitInterfaces(final ClassNode classNode, final ClassNode[] 
interfaces) {
-        for (ClassNode interfaceClassNode : interfaces) {
-            List<MethodNode> methodNodes = new 
ArrayList<>(interfaceClassNode.getMethods());
-
+        for (ClassNode interfaceNode : interfaces) {
+            List<MethodNode> interfaceMethods = new 
ArrayList<>(interfaceNode.getMethods());
             // @ContractElement annotations are by now only supported on 
method interfaces
-            for (MethodNode interfaceMethodNode : methodNodes) {
-                MethodNode implementingMethodNode = 
classNode.getMethod(interfaceMethodNode.getName(), 
interfaceMethodNode.getParameters());
-                if (implementingMethodNode == null) continue;
+            for (MethodNode interfaceMethod : interfaceMethods) {
+                MethodNode implementingMethod = 
classNode.getMethod(interfaceMethod.getName(), interfaceMethod.getParameters());
+                if (implementingMethod == null) continue;
 
-                final List<AnnotationNode> annotationNodes = 
AnnotationUtils.hasMetaAnnotations(interfaceMethodNode, 
ContractElement.class.getName());
-                handleInterfaceMethodNode(classNode, implementingMethodNode, 
annotationNodes);
+                List<AnnotationNode> annotationNodes = 
AnnotationUtils.hasMetaAnnotations(interfaceMethod, 
ContractElement.class.getName());
+                handleInterfaceMethodNode(classNode, implementingMethod, 
annotationNodes);
             }
 
-            visitInterfaces(classNode, interfaceClassNode.getInterfaces());
+            visitInterfaces(classNode, interfaceNode.getInterfaces());
         }
     }
 
     private void handleClassNode(final ClassNode classNode) {
-        final List<AnnotationNode> annotationNodes = 
AnnotationUtils.hasMetaAnnotations(classNode, ContractElement.class.getName());
-
+        List<AnnotationNode> annotationNodes = 
AnnotationUtils.hasMetaAnnotations(classNode, ContractElement.class.getName());
         for (AnnotationNode annotationNode : annotationNodes) {
-            final AnnotationProcessor annotationProcessor = 
createAnnotationProcessor(annotationNode);
-
-            if (annotationProcessor != null && 
annotationNode.getMember(CLOSURE_ATTRIBUTE_NAME) instanceof ClassExpression) {
-                final ClassExpression closureClassExpression = 
(ClassExpression) annotationNode.getMember(CLOSURE_ATTRIBUTE_NAME);
-
-                MethodCallExpression doCall = callX(
-                        ctorX(closureClassExpression.getType(), 
args(VariableExpression.THIS_EXPRESSION, VariableExpression.THIS_EXPRESSION)),
-                        DO_CALL
-                );
-                
doCall.setMethodTarget(closureClassExpression.getType().getMethods(DO_CALL).get(0));
-
-                final BooleanExpression booleanExpression = boolX(doCall);
-                booleanExpression.setSourcePosition(annotationNode);
-
-                annotationProcessor.process(pci, pci.contract(), classNode, 
closureClassExpression.getNodeMetaData(AnnotationClosureVisitor.META_DATA_ORIGINAL_TRY_CATCH_BLOCK),
 booleanExpression);
+            AnnotationProcessor annotationProcessor = 
createAnnotationProcessor(annotationNode);
+            if (annotationProcessor != null) {
+                Expression valueExpression = 
getReplacedCondition(annotationNode);
+                BlockStatement blockStatement = 
valueExpression.getNodeMetaData(META_DATA_ORIGINAL_TRY_CATCH_BLOCK);
+                annotationProcessor.process(pci, pci.contract(), classNode, 
blockStatement, asConditionExecution(annotationNode));
             }
         }
     }
@@ -162,73 +137,58 @@ public class AnnotationProcessorVisitor extends 
BaseVisitor {
     private void handleMethodAnnotations(MethodNode methodNode, 
List<AnnotationNode> annotationNodes) {
         if (methodNode == null) return;
         for (AnnotationNode annotationNode : annotationNodes) {
-            final AnnotationProcessor annotationProcessor = 
createAnnotationProcessor(annotationNode);
-            if (annotationProcessor != null && 
annotationNode.getMember(CLOSURE_ATTRIBUTE_NAME) instanceof ClassExpression) {
+            AnnotationProcessor annotationProcessor = 
createAnnotationProcessor(annotationNode);
+            if (annotationProcessor != null && 
getReplacedCondition(annotationNode) != null) {
                 handleMethodAnnotation(methodNode, annotationNode, 
annotationProcessor);
             }
         }
     }
 
     private void handleMethodAnnotation(MethodNode methodNode, AnnotationNode 
annotationNode, AnnotationProcessor annotationProcessor) {
-        boolean isPostcondition = 
AnnotationUtils.hasAnnotationOfType(annotationNode.getClassNode(), 
org.apache.groovy.contracts.annotations.meta.Postcondition.class.getName());
-
-        ClassExpression closureClassExpression = (ClassExpression) 
annotationNode.getMember(CLOSURE_ATTRIBUTE_NAME);
-
-        ArgumentListExpression closureArgumentList = new 
ArgumentListExpression();
+        boolean isPostcondition = 
AnnotationUtils.hasAnnotationOfType(annotationNode.getClassNode(), 
Postcondition.class.getName());
 
+        ArgumentListExpression argumentList = new ArgumentListExpression();
         for (Parameter parameter : methodNode.getParameters()) {
-            closureArgumentList.addExpression(varX(parameter));
+            argumentList.addExpression(varX(parameter));
         }
-
-        if (!isPrimitiveVoid(methodNode.getReturnType()) && isPostcondition && 
!(methodNode instanceof ConstructorNode)) {
-            closureArgumentList.addExpression(localVarX("result", 
methodNode.getReturnType()));
+        if (isPostcondition && !methodNode.isVoidMethod()) {
+            argumentList.addExpression(localVarX("result", 
methodNode.getReturnType()));
         }
-
-        if (isPostcondition && !(methodNode instanceof ConstructorNode)) {
-            closureArgumentList.addExpression(localVarX("old", new 
ClassNode(Map.class)));
+        if (isPostcondition && !methodNode.isConstructor()) {
+            argumentList.addExpression(localVarX("old", 
ClassHelper.MAP_TYPE.getPlainNodeReference()));
         }
 
-        MethodCallExpression doCall = callX(
-                
ctorX(annotationNode.getMember(CLOSURE_ATTRIBUTE_NAME).getType(), 
args(VariableExpression.THIS_EXPRESSION, VariableExpression.THIS_EXPRESSION)),
-                DO_CALL,
-                closureArgumentList
-        );
-        ClassNode type = 
annotationNode.getMember(CLOSURE_ATTRIBUTE_NAME).getType();
-        doCall.setMethodTarget(type.getMethods(DO_CALL).get(0));
-
-        final BooleanExpression booleanExpression = boolX(doCall);
-        booleanExpression.setSourcePosition(annotationNode);
-
-        annotationProcessor.process(pci, pci.contract(), 
methodNode.getDeclaringClass(), methodNode, 
closureClassExpression.getNodeMetaData(AnnotationClosureVisitor.META_DATA_ORIGINAL_TRY_CATCH_BLOCK),
 booleanExpression);
+        Expression valueExpression = getReplacedCondition(annotationNode);
+        BooleanExpression booleanExpression = 
asConditionExecution(annotationNode);
+        ((MethodCallExpression) 
booleanExpression.getExpression()).setArguments(argumentList);
+        BlockStatement blockStatement = 
valueExpression.getNodeMetaData(META_DATA_ORIGINAL_TRY_CATCH_BLOCK);
+        annotationProcessor.process(pci, pci.contract(), 
methodNode.getDeclaringClass(), methodNode, blockStatement, booleanExpression);
 
         // if the implementation method has no annotation, we need to set a 
dummy marker in order to find parent pre/postconditions
         if (!AnnotationUtils.hasAnnotationOfType(methodNode, 
annotationNode.getClassNode().getName())) {
-            AnnotationNode annotationMarker = new 
AnnotationNode(annotationNode.getClassNode());
-            annotationMarker.setMember(CLOSURE_ATTRIBUTE_NAME, 
annotationNode.getMember(CLOSURE_ATTRIBUTE_NAME));
-            annotationMarker.setRuntimeRetention(true);
-            annotationMarker.setSourceRetention(false);
-
-            methodNode.addAnnotation(annotationMarker);
+            AnnotationNode markerAnnotation = new 
AnnotationNode(annotationNode.getClassNode());
+            replaceCondition(markerAnnotation, valueExpression);
+            markerAnnotation.setRuntimeRetention(true);
+            markerAnnotation.setSourceRetention(false);
+            methodNode.addAnnotation(markerAnnotation);
         }
     }
 
     private AnnotationProcessor createAnnotationProcessor(AnnotationNode 
annotationNode) {
-        ClassExpression annotationProcessingAnno = null;
+        Expression annotationProcessor = null;
 
-        List<AnnotationNode> annotations = 
annotationNode.getClassNode().redirect().getAnnotations();
+        List<AnnotationNode> annotations = 
annotationNode.getClassNode().getAnnotations();
         for (AnnotationNode anno : annotations) {
-            Class<?> typeClass = anno.getClassNode().getTypeClass();
-
-            if 
(typeClass.getName().equals("org.apache.groovy.contracts.annotations.meta.AnnotationProcessorImplementation"))
 {
-                annotationProcessingAnno = (ClassExpression) 
anno.getMember("value");
+            if 
(anno.getClassNode().getName().equals("org.apache.groovy.contracts.annotations.meta.AnnotationProcessorImplementation"))
 {
+                annotationProcessor = anno.getMember("value");
                 break;
             }
         }
 
-        if (annotationProcessingAnno != null) {
+        if (annotationProcessor != null) {
             try {
-                final Class<?> clz = 
Class.forName(annotationProcessingAnno.getType().getTypeClass().getName());
-                return (AnnotationProcessor) 
clz.getDeclaredConstructor().newInstance();
+                var apt = 
Class.forName(annotationProcessor.getType().getName());
+                return (AnnotationProcessor) 
apt.getDeclaredConstructor().newInstance();
             } catch (InstantiationException | IllegalAccessException | 
ClassNotFoundException | NoSuchMethodException | InvocationTargetException 
ignore) {
             }
         }
diff --git 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/BaseVisitor.java
 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/BaseVisitor.java
index f620378cb3..2337cdd1ef 100644
--- 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/BaseVisitor.java
+++ 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/BaseVisitor.java
@@ -18,10 +18,23 @@
  */
 package org.apache.groovy.contracts.ast.visitor;
 
+import org.codehaus.groovy.ast.AnnotationNode;
 import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
+import org.codehaus.groovy.ast.expr.BooleanExpression;
+import org.codehaus.groovy.ast.expr.ClosureExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.control.io.ReaderSource;
 
+import java.util.Objects;
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.boolX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+
 /**
  * <p>
  * Base class for {@link org.codehaus.groovy.ast.ClassCodeVisitorSupport} 
descendants. This class is used in groovy-contracts
@@ -34,18 +47,44 @@ public abstract class BaseVisitor extends 
ClassCodeVisitorSupport {
 
     public static final String GCONTRACTS_ENABLED_VAR = "$GCONTRACTS_ENABLED";
 
-    public static final String CLOSURE_ATTRIBUTE_NAME = "value";
+    protected final SourceUnit sourceUnit;
 
-    protected SourceUnit sourceUnit;
-    protected ReaderSource source;
+    @Override
+    protected SourceUnit getSourceUnit() {
+        return sourceUnit;
+    }
 
     public BaseVisitor(final SourceUnit sourceUnit, final ReaderSource source) 
{
         this.sourceUnit = sourceUnit;
-        this.source = source;
     }
 
-    @Override
-    protected SourceUnit getSourceUnit() {
+    public    static BooleanExpression asConditionExecution(final 
AnnotationNode annotation) {
+        var conditionClass = annotation.getMember("value").getType();
+        var createInstance = ctorX(conditionClass, 
args(VariableExpression.THIS_EXPRESSION, VariableExpression.THIS_EXPRESSION));
+        final MethodCallExpression doCall = callX(createInstance, "doCall");
+        doCall.setMethodTarget(conditionClass.getMethods("doCall").get(0));
+        BooleanExpression asBoolean = boolX(doCall);
+        asBoolean.setSourcePosition(annotation);
+        return asBoolean;
+    }
+
+    protected static ClosureExpression getOriginalCondition(final 
AnnotationNode annotation) {
+        Expression value = annotation.getMember("value");
+        if (value instanceof ClosureExpression) {
+            return (ClosureExpression) value;
+        }
         return null;
     }
+
+    protected static /*???*/Expression getReplacedCondition(final 
AnnotationNode annotation) {
+        Expression value = annotation.getMember("value");
+        if (!(value instanceof ClosureExpression)) {
+            return value;
+        }
+        return null;
+    }
+
+    protected static void replaceCondition(final AnnotationNode node, final 
Expression expr) {
+        node.setMember("value", Objects.requireNonNull(expr));
+    }
 }
diff --git 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/classgen/asm/ContractClosureWriter.java
 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/classgen/asm/ContractClosureWriter.java
index 1b32e0281c..9bc6ba4e6c 100644
--- 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/classgen/asm/ContractClosureWriter.java
+++ 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/classgen/asm/ContractClosureWriter.java
@@ -18,7 +18,6 @@
  */
 package org.apache.groovy.contracts.classgen.asm;
 
-import org.codehaus.groovy.ast.ASTNode;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.CodeVisitorSupport;
@@ -30,7 +29,6 @@ import org.codehaus.groovy.ast.Variable;
 import org.codehaus.groovy.ast.VariableScope;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.ClosureExpression;
-import org.codehaus.groovy.ast.expr.TupleExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.ast.stmt.BlockStatement;
 
@@ -39,14 +37,13 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
+import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorSuperX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
 import static org.objectweb.asm.Opcodes.ACC_FINAL;
 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
 
@@ -78,26 +75,23 @@ public class ContractClosureWriter {
         }
 
         // contains all params of the original method
-        ArrayList<Parameter> closureParameters = new ArrayList<Parameter>();
+        List<Parameter> closureParameters = new ArrayList<>();
         for (Parameter param : parametersTemp) {
-            Parameter closureParameter = new 
Parameter(param.getType().getPlainNodeReference(), param.getName());
-            closureParameters.add(closureParameter);
+            closureParameters.add(new 
Parameter(param.getType().getPlainNodeReference(), param.getName()));
         }
 
         ClassNode answer = new ClassNode(name, mods | ACC_FINAL, 
ClassHelper.CLOSURE_TYPE.getPlainNodeReference());
-        answer.setSynthetic(true);
         answer.setSourcePosition(expression);
+        answer.setSynthetic(true);
 
-        MethodNode method =
-                answer.addMethod("doCall", ACC_PUBLIC, 
ClassHelper.Boolean_TYPE, closureParameters.toArray(new 
Parameter[closureParameters.size()]), ClassNode.EMPTY_ARRAY, 
expression.getCode());
-        method.setSourcePosition(expression);
+        MethodNode doCall = answer.addMethod("doCall", ACC_PUBLIC, 
ClassHelper.Boolean_TYPE, closureParameters.toArray(Parameter.EMPTY_ARRAY), 
ClassNode.EMPTY_ARRAY, expression.getCode());
+        doCall.setSourcePosition(expression);
 
         VariableScope varScope = expression.getVariableScope();
         if (varScope == null) {
-            throw new RuntimeException(
-                    "Must have a VariableScope by now! for expression: " + 
expression + " class: " + name);
+            throw new RuntimeException("Must have a VariableScope by now! for 
expression: " + expression + " class: " + name);
         } else {
-            method.setVariableScope(varScope.copy());
+            doCall.setVariableScope(varScope.copy());
         }
 
         // let's add a typesafe call method
@@ -110,10 +104,10 @@ public class ContractClosureWriter {
                 "call",
                 ACC_PUBLIC,
                 ClassHelper.Boolean_TYPE,
-                closureParameters.toArray(new 
Parameter[closureParameters.size()]),
+                closureParameters.toArray(Parameter.EMPTY_ARRAY),
                 ClassNode.EMPTY_ARRAY,
-                returnS(callThisX("doCall", arguments)));
-
+                returnS(callThisX("doCall", arguments))
+        );
         call.setSourcePosition(expression);
         call.setSynthetic(true);
 
@@ -127,16 +121,15 @@ public class ContractClosureWriter {
         VariableExpression thisObject = varX("_thisObject");
         thisObject.setSourcePosition(expression);
         block.getVariableScope().putReferencedLocalVariable(thisObject);
-        TupleExpression conArgs = new TupleExpression(outer, thisObject);
-        block.addStatement(stmt(ctorSuperX(conArgs)));
-
-        Parameter[] consParams = params(
-                param(ClassHelper.OBJECT_TYPE, "_outerInstance"),
-                param(ClassHelper.OBJECT_TYPE, "_thisObject"));
+        block.addStatement(stmt(ctorSuperX(args(outer, thisObject))));
 
-        ASTNode sn = answer.addConstructor(ACC_PUBLIC, consParams, 
ClassNode.EMPTY_ARRAY, block);
-        sn.setSourcePosition(expression);
-        correctAccessedVariable(method, expression);
+        Parameter[] ctorParams = {
+                new Parameter(ClassHelper.OBJECT_TYPE, "_outerInstance"),
+                new Parameter(ClassHelper.OBJECT_TYPE, "_thisObject")
+        };
+        var ctor = answer.addConstructor(ACC_PUBLIC, ctorParams, 
ClassNode.EMPTY_ARRAY, block);
+        ctor.setSourcePosition(expression);
+        correctAccessedVariable(doCall, expression);
         return answer;
     }
 
@@ -151,7 +144,7 @@ public class ContractClosureWriter {
         return outermostClass;
     }
 
-    private void correctAccessedVariable(final MethodNode methodNode, 
ClosureExpression ce) {
+    private void correctAccessedVariable(MethodNode methodNode, 
ClosureExpression ce) {
         CodeVisitorSupport visitor = new CodeVisitorSupport() {
             @Override
             public void visitVariableExpression(VariableExpression expression) 
{
diff --git 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/generation/BaseGenerator.java
 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/generation/BaseGenerator.java
index 84bb65a458..718d8d5271 100644
--- 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/generation/BaseGenerator.java
+++ 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/generation/BaseGenerator.java
@@ -25,33 +25,24 @@ import org.apache.groovy.contracts.util.ExpressionUtils;
 import org.codehaus.groovy.ast.AnnotationNode;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.ConstructorNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.VariableScope;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.ast.expr.ArrayExpression;
 import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
 import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.MethodCallExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.ast.stmt.BlockStatement;
 import org.codehaus.groovy.ast.stmt.TryCatchStatement;
 import org.codehaus.groovy.control.io.ReaderSource;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.syntax.Token;
-import org.codehaus.groovy.syntax.Types;
 
 import java.lang.annotation.Annotation;
-import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
 
+import static org.codehaus.groovy.ast.tools.GeneralUtils.andX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.boolX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
@@ -61,10 +52,10 @@ import static 
org.codehaus.groovy.ast.tools.GeneralUtils.declS;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.notX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.orX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.tryCatchS;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
 
 /**
  * Base class for groovy-contracts code generators.
@@ -97,19 +88,18 @@ public abstract class BaseGenerator {
     }
 
     protected BlockStatement getInlineModeBlockStatement(BlockStatement 
blockStatement) {
-        final BooleanExpression combinedBooleanExpression = 
ExpressionUtils.getBooleanExpression(ExpressionUtils.getBooleanExpressionsFromAssertionStatements(blockStatement));
+        BooleanExpression combinedBooleanExpression = 
ExpressionUtils.getBooleanExpression(ExpressionUtils.getBooleanExpressionsFromAssertionStatements(blockStatement));
         return block(ifS(
                 boolX(varX(BaseVisitor.GCONTRACTS_ENABLED_VAR, 
ClassHelper.boolean_TYPE)),
                 block(ifS(notX(combinedBooleanExpression), blockStatement))));
     }
 
     protected BlockStatement wrapAssertionBooleanExpression(ClassNode type, 
MethodNode methodNode, BooleanExpression classInvariantExpression, String 
assertionType) {
-
-        final ClassNode violationTrackerClassNode = 
ClassHelper.makeWithoutCaching(ViolationTracker.class);
-        final VariableExpression $_gc_result = varX("$_gc_result", 
ClassHelper.boolean_TYPE);
+        ClassNode violationTrackerClassNode = 
ClassHelper.makeWithoutCaching(ViolationTracker.class);
+        VariableExpression $_gc_result = varX("$_gc_result", 
ClassHelper.boolean_TYPE);
         $_gc_result.setAccessedVariable($_gc_result);
 
-        final BlockStatement ifBlockStatement = block(
+        BlockStatement ifBlockStatement = block(
                 declS($_gc_result, ConstantExpression.FALSE),
                 stmt(callX(classX(violationTrackerClassNode), "init")),
                 assignS($_gc_result, classInvariantExpression),
@@ -124,7 +114,7 @@ public abstract class BaseGenerator {
                 )
         );
 
-        final TryCatchStatement lockTryCatchStatement = tryCatchS(
+        TryCatchStatement lockTryCatchStatement = tryCatchS(
                 block(ifS(
                         
boolX(callX(classX(ClassHelper.make(ContractExecutionTracker.class)), "track", 
args(constX(type.getName()), constX(methodNode.getTypeDescriptor()), 
constX(assertionType), methodNode.isStatic() ? ConstantExpression.TRUE : 
ConstantExpression.FALSE))),
                         ifBlockStatement)),
@@ -139,55 +129,32 @@ public abstract class BaseGenerator {
 
     // TODO: what about constructor method nodes - does it find a constructor 
node in the super class?
     protected BooleanExpression 
addCallsToSuperMethodNodeAnnotationClosure(final ClassNode type, final 
MethodNode methodNode, final Class<? extends Annotation> annotationType, 
BooleanExpression booleanExpression, boolean isPostcondition) {
-
-        final List<AnnotationNode> nextContractElementAnnotations = 
AnnotationUtils.getAnnotationNodeInHierarchyWithMetaAnnotation(type.getSuperClass(),
 methodNode, ClassHelper.makeWithoutCaching(annotationType));
-        if (nextContractElementAnnotations.isEmpty()) {
-            if (methodNode.getNodeMetaData(META_DATA_USE_INLINE_MODE) == null)
-                methodNode.setNodeMetaData(META_DATA_USE_INLINE_MODE, 
Boolean.TRUE);
-            return booleanExpression;
-        }
-
-        for (AnnotationNode nextContractElementAnnotation : 
nextContractElementAnnotations) {
-            ClassExpression classExpression = (ClassExpression) 
nextContractElementAnnotation.getMember(BaseVisitor.CLOSURE_ATTRIBUTE_NAME);
-            if (classExpression == null) continue;
-
-            ArgumentListExpression callArgumentList = new 
ArgumentListExpression();
-            for (Parameter parameter : methodNode.getParameters()) {
-                callArgumentList.addExpression(varX(parameter));
+        List<AnnotationNode> contractElementAnnotations = 
AnnotationUtils.getAnnotationNodeInHierarchyWithMetaAnnotation(type.getSuperClass(),
 methodNode, ClassHelper.makeWithoutCaching(annotationType));
+        if (contractElementAnnotations.isEmpty()) {
+            methodNode.putNodeMetaData(META_DATA_USE_INLINE_MODE, 
Boolean.TRUE);
+        } else {
+            for (AnnotationNode contractElementAnnotation : 
contractElementAnnotations) {
+                ArgumentListExpression argumentList = new 
ArgumentListExpression();
+                for (Parameter parameter : methodNode.getParameters()) {
+                    argumentList.addExpression(varX(parameter));
+                }
+                if (isPostcondition && !methodNode.isVoidMethod()) {
+                    argumentList.addExpression(localVarX("result", 
methodNode.getReturnType()));
+                }
+                if (isPostcondition && !methodNode.isConstructor()) {
+                    argumentList.addExpression(localVarX("old", 
ClassHelper.MAP_TYPE.getPlainNodeReference()));
+                }
+
+                BooleanExpression predicate = 
BaseVisitor.asConditionExecution(contractElementAnnotation);
+                ((MethodCallExpression) 
predicate.getExpression()).setArguments(argumentList);
+
+                if (isPostcondition) {
+                    booleanExpression = boolX(andX(booleanExpression, 
predicate));
+                } else {
+                    booleanExpression = boolX(orX(booleanExpression, 
predicate));
+                }
             }
-
-            if (isPostcondition && 
!isPrimitiveVoid(methodNode.getReturnType()) && !(methodNode instanceof 
ConstructorNode)) {
-                callArgumentList.addExpression(localVarX("result", 
methodNode.getReturnType()));
-            }
-
-            if (isPostcondition && !(methodNode instanceof ConstructorNode)) {
-                callArgumentList.addExpression(localVarX("old", new 
ClassNode(Map.class)));
-            }
-
-            ArgumentListExpression newInstanceArguments = args(
-                    classExpression,
-                    new ArrayExpression(
-                            ClassHelper.OBJECT_TYPE,
-                            
Arrays.<Expression>asList(VariableExpression.THIS_EXPRESSION, 
VariableExpression.THIS_EXPRESSION)
-                    )
-            );
-
-            MethodCallExpression doCall = callX(
-                    callX(ClassHelper.makeWithoutCaching(InvokerHelper.class), 
"invokeConstructorOf", newInstanceArguments),
-                    "doCall",
-                    callArgumentList);
-            
doCall.setMethodTarget(classExpression.getType().getMethods("doCall").get(0));
-
-            booleanExpression.setSourcePosition(nextContractElementAnnotation);
-
-            booleanExpression = boolX(
-                    binX(
-                            booleanExpression,
-                            isPostcondition ? 
Token.newSymbol(Types.LOGICAL_AND, -1, -1) : Token.newSymbol(Types.LOGICAL_OR, 
-1, -1),
-                            boolX(doCall))
-            );
         }
-
         return booleanExpression;
     }
 }
diff --git 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/generation/ClassInvariantGenerator.java
 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/generation/ClassInvariantGenerator.java
index a2d8f145b7..3bb7ebabb7 100644
--- 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/generation/ClassInvariantGenerator.java
+++ 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/generation/ClassInvariantGenerator.java
@@ -29,9 +29,6 @@ import org.codehaus.groovy.ast.ConstructorNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.MethodCallExpression;
-import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.ast.stmt.BlockStatement;
 import org.codehaus.groovy.ast.stmt.ReturnStatement;
 import org.codehaus.groovy.ast.stmt.Statement;
@@ -41,15 +38,11 @@ import org.objectweb.asm.Opcodes;
 import java.lang.annotation.Annotation;
 import java.util.List;
 
-import static org.codehaus.groovy.ast.tools.GeneralUtils.AND;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
+import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.andX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.boolX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
-import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
 
 /**
  * <p>
@@ -84,25 +77,10 @@ public class ClassInvariantGenerator extends BaseGenerator {
     }
 
     private BooleanExpression addCallsToSuperAnnotationClosure(final ClassNode 
type, final Class<? extends Annotation> annotationType, BooleanExpression 
booleanExpression) {
-
-        final List<AnnotationNode> nextContractElementAnnotations = 
AnnotationUtils.getAnnotationNodeInHierarchyWithMetaAnnotation(type.getSuperClass(),
 ClassHelper.makeWithoutCaching(annotationType));
-        if (nextContractElementAnnotations.isEmpty()) return booleanExpression;
-
-        for (AnnotationNode nextContractElementAnnotation : 
nextContractElementAnnotations) {
-            ClassExpression classExpression = (ClassExpression) 
nextContractElementAnnotation.getMember(BaseVisitor.CLOSURE_ATTRIBUTE_NAME);
-            if (classExpression == null) continue;
-
-            MethodCallExpression doCall = callX(
-                    ctorX(classExpression.getType(), 
args(VariableExpression.THIS_EXPRESSION, VariableExpression.THIS_EXPRESSION)),
-                    "doCall"
-            );
-            
doCall.setMethodTarget(classExpression.getType().getMethods("doCall").get(0));
-
-            final BooleanExpression rightExpression = boolX(doCall);
-            booleanExpression.setSourcePosition(nextContractElementAnnotation);
-            booleanExpression = boolX(binX(booleanExpression, AND, 
rightExpression));
+        List<AnnotationNode> contractElementAnnotations = 
AnnotationUtils.getAnnotationNodeInHierarchyWithMetaAnnotation(type.getSuperClass(),
 ClassHelper.makeWithoutCaching(annotationType));
+        for (AnnotationNode contractElementAnnotation : 
contractElementAnnotations) {
+            booleanExpression = boolX(andX(booleanExpression, 
BaseVisitor.asConditionExecution(contractElementAnnotation)));
         }
-
         return booleanExpression;
     }
 
diff --git 
a/subprojects/groovy-contracts/src/main/resources/dsld/contract_transform.dsld 
b/subprojects/groovy-contracts/src/main/resources/dsld/contract_transform.dsld
index d219ff5f75..7948ca6201 100644
--- 
a/subprojects/groovy-contracts/src/main/resources/dsld/contract_transform.dsld
+++ 
b/subprojects/groovy-contracts/src/main/resources/dsld/contract_transform.dsld
@@ -73,7 +73,9 @@ contribute(bind(closure: inClosure()) & isThisType() & 
bind(methods: enclosingMe
       for (Parameter parameter : methods[0].parameters) {
         property name: parameter.name, type: parameter.type, readOnly: true
       }
-      property name: 'old', type: Map, readOnly: true, doc: 'Property values 
before the method call.'
+      if (!methods[0].isConstructor()) {
+        property name: 'old', type: Map, readOnly: true, doc: 'Property values 
before the method call.'
+      }
       if (!methods[0].isVoidMethod()) {
         property name: 'result', type: methods[0].returnType, readOnly: true, 
doc: 'Return value of the method call.'
       }

Reply via email to