@Override
 public void visitAnnotations(AnnotatedNode node) {
   boolean oldInAnnotation = inAnnotation;
   inAnnotation = true;
   super.visitAnnotations(node);
   inAnnotation = oldInAnnotation;
 }
 @Override
 public void visitMethod(MethodNode node) {
   if (node.isScriptBody()) super.visitMethod(node);
 }
  public void visit(ASTNode[] nodes, final SourceUnit source) {
    init(nodes, source);
    AnnotatedNode targetClass = (AnnotatedNode) nodes[1];
    AnnotationNode logAnnotation = (AnnotationNode) nodes[0];

    final GroovyClassLoader classLoader =
        compilationUnit != null ? compilationUnit.getTransformLoader() : source.getClassLoader();
    final LoggingStrategy loggingStrategy = createLoggingStrategy(logAnnotation, classLoader);
    if (loggingStrategy == null) return;

    final String logFieldName = lookupLogFieldName(logAnnotation);

    final String categoryName = lookupCategoryName(logAnnotation);

    if (!(targetClass instanceof ClassNode))
      throw new GroovyBugError(
          "Class annotation "
              + logAnnotation.getClassNode().getName()
              + " annotated no Class, this must not happen.");

    final ClassNode classNode = (ClassNode) targetClass;

    ClassCodeExpressionTransformer transformer =
        new ClassCodeExpressionTransformer() {
          private FieldNode logNode;

          @Override
          protected SourceUnit getSourceUnit() {
            return source;
          }

          public Expression transform(Expression exp) {
            if (exp == null) return null;
            if (exp instanceof MethodCallExpression) {
              return transformMethodCallExpression(exp);
            }
            if (exp instanceof ClosureExpression) {
              return transformClosureExpression((ClosureExpression) exp);
            }
            return super.transform(exp);
          }

          @Override
          public void visitClass(ClassNode node) {
            FieldNode logField = node.getField(logFieldName);
            if (logField != null && logField.getOwner().equals(node)) {
              addError(
                  "Class annotated with Log annotation cannot have log field declared", logField);
            } else if (logField != null && !Modifier.isPrivate(logField.getModifiers())) {
              addError(
                  "Class annotated with Log annotation cannot have log field declared because the field exists in the parent class: "
                      + logField.getOwner().getName(),
                  logField);
            } else {
              logNode = loggingStrategy.addLoggerFieldToClass(node, logFieldName, categoryName);
            }
            super.visitClass(node);
          }

          private Expression transformClosureExpression(ClosureExpression exp) {
            if (exp.getCode() instanceof BlockStatement) {
              BlockStatement code = (BlockStatement) exp.getCode();
              super.visitBlockStatement(code);
            }
            return exp;
          }

          private Expression transformMethodCallExpression(Expression exp) {
            MethodCallExpression mce = (MethodCallExpression) exp;
            if (!(mce.getObjectExpression() instanceof VariableExpression)) {
              return exp;
            }
            VariableExpression variableExpression = (VariableExpression) mce.getObjectExpression();
            if (!variableExpression.getName().equals(logFieldName)
                || !(variableExpression.getAccessedVariable() instanceof DynamicVariable)) {
              return exp;
            }
            String methodName = mce.getMethodAsString();
            if (methodName == null) return exp;
            if (usesSimpleMethodArgumentsOnly(mce)) return exp;

            variableExpression.setAccessedVariable(logNode);

            if (!loggingStrategy.isLoggingMethod(methodName)) return exp;

            return loggingStrategy.wrapLoggingMethodCall(variableExpression, methodName, exp);
          }

          private boolean usesSimpleMethodArgumentsOnly(MethodCallExpression mce) {
            Expression arguments = mce.getArguments();
            if (arguments instanceof TupleExpression) {
              TupleExpression tuple = (TupleExpression) arguments;
              for (Expression exp : tuple.getExpressions()) {
                if (!isSimpleExpression(exp)) return false;
              }
              return true;
            }
            return !isSimpleExpression(arguments);
          }

          private boolean isSimpleExpression(Expression exp) {
            if (exp instanceof ConstantExpression) return true;
            if (exp instanceof VariableExpression) return true;
            return false;
          }
        };
    transformer.visitClass(classNode);

    // GROOVY-6373: references to 'log' field are normally already FieldNodes by now, so revisit
    // scoping
    new VariableScopeVisitor(sourceUnit, true).visitClass(classNode);
  }
 @Override
 protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
   this.currentMethod = node;
   super.visitConstructorOrMethod(node, isConstructor);
   this.currentMethod = null;
 }
 public void visitClass(ClassNode node, SourceUnit source) {
   this.currentClass = node;
   this.source = source;
   super.visitClass(node);
 }