@Override
 protected ClassNode createClosureClass(final ClosureExpression expression, final int mods) {
   ClassNode closureClass = super.createClosureClass(expression, mods);
   List<MethodNode> methods = closureClass.getDeclaredMethods("call");
   List<MethodNode> doCall = closureClass.getMethods("doCall");
   if (doCall.size() != 1) {
     throw new GroovyBugError(
         "Expected to find one (1) doCall method on generated closure, but found "
             + doCall.size());
   }
   MethodNode doCallMethod = doCall.get(0);
   if (methods.isEmpty() && doCallMethod.getParameters().length == 1) {
     createDirectCallMethod(closureClass, doCallMethod);
   }
   MethodTargetCompletionVisitor visitor = new MethodTargetCompletionVisitor(doCallMethod);
   Object dynamic = expression.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION);
   if (dynamic != null) {
     doCallMethod.putNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION, dynamic);
   }
   for (MethodNode method : methods) {
     visitor.visitMethod(method);
   }
   closureClass.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, Boolean.TRUE);
   return closureClass;
 }
 public ClassNode getOrAddClosureClass(ClosureExpression expression, int mods) {
   ClassNode closureClass = closureClassMap.get(expression);
   if (closureClass == null) {
     closureClass = createClosureClass(expression, mods);
     closureClassMap.put(expression, closureClass);
     controller.getAcg().addInnerClass(closureClass);
     closureClass.addInterface(ClassHelper.GENERATED_CLOSURE_Type);
     closureClass.putNodeMetaData(WriterControllerFactory.class, factory);
   }
   return closureClass;
 }
 @Override
 public void visitClass(final ClassNode node) {
   boolean skip = shouldSkipClassNode(node);
   if (!skip && !anyMethodSkip(node)) {
     node.putNodeMetaData(MopWriter.Factory.class, StaticCompilationMopWriter.FACTORY);
   }
   ClassNode oldCN = classNode;
   classNode = node;
   Iterator<InnerClassNode> innerClasses = classNode.getInnerClasses();
   while (innerClasses.hasNext()) {
     InnerClassNode innerClassNode = innerClasses.next();
     boolean innerStaticCompile = !(skip || isSkippedInnerClass(innerClassNode));
     innerClassNode.putNodeMetaData(STATIC_COMPILE_NODE, innerStaticCompile);
     innerClassNode.putNodeMetaData(
         WriterControllerFactory.class, node.getNodeMetaData(WriterControllerFactory.class));
     if (innerStaticCompile && !anyMethodSkip(innerClassNode)) {
       innerClassNode.putNodeMetaData(MopWriter.Factory.class, StaticCompilationMopWriter.FACTORY);
     }
   }
   super.visitClass(node);
   addPrivateFieldAndMethodAccessors(node);
   classNode = oldCN;
 }