private void checkForConvenienceForm(AnnotationNode node, boolean exclude) {
    Object val = node.getMember("value");
    if (val == null || !(val instanceof ConstantExpression)) return;
    Object allParts = ((ConstantExpression) val).getValue();
    if (!(allParts instanceof String)) return;
    String allstr = (String) allParts;

    // strip off trailing attributes
    boolean done = false;
    while (!done) {
      Matcher attrs = ATTRIBUTES_PATTERN.matcher(allstr);
      if (attrs.find()) {
        String attrName = attrs.group(2);
        String attrValue = attrs.group(3);
        if (attrName == null || attrValue == null) continue;
        boolean isBool = GRAB_BOOLEAN.contains(attrName);
        ConstantExpression value =
            new ConstantExpression(isBool ? Boolean.valueOf(attrValue) : attrValue);
        value.setSourcePosition(node);
        node.addMember(attrName, value);
        int lastSemi = allstr.lastIndexOf(';');
        if (lastSemi == -1) {
          allstr = "";
          break;
        }
        allstr = allstr.substring(0, lastSemi);
      } else {
        done = true;
      }
    }

    if (allstr.contains("#")) {
      // see: http://ant.apache.org/ivy/history/latest-milestone/textual.html
      Matcher m = IVY_PATTERN.matcher(allstr);
      if (!m.find()) return;
      if (m.group(1) == null || m.group(2) == null) return;
      node.addMember("module", new ConstantExpression(m.group(2)));
      node.addMember("group", new ConstantExpression(m.group(1)));
      if (m.group(6) != null) node.addMember("conf", new ConstantExpression(m.group(6)));
      if (m.group(4) != null) node.addMember("version", new ConstantExpression(m.group(4)));
      else if (!exclude && node.getMember("version") == null)
        node.addMember("version", new ConstantExpression("*"));
      node.getMembers().remove("value");
    } else if (allstr.contains(":")) {
      // assume gradle syntax
      // see:
      // http://www.gradle.org/latest/docs/userguide/dependency_management.html#sec:how_to_declare_your_dependencies
      Map<String, Object> parts = GrapeUtil.getIvyParts(allstr);
      for (String key : parts.keySet()) {
        String value = parts.get(key).toString();
        if (!key.equals("version") || !value.equals("*") || !exclude) {
          node.addMember(key, new ConstantExpression(value));
        }
      }
      node.getMembers().remove("value");
    }
  }
 public void visit(GroovyCodeVisitor visitor) {
   AnnotationNode node = (AnnotationNode) getValue();
   Map<String, Expression> attrs = node.getMembers();
   for (Expression expr : attrs.values()) {
     expr.visit(visitor);
   }
   super.visit(visitor);
 }
 private void printAnnotation(PrintWriter out, AnnotationNode annotation) {
   out.print("@" + annotation.getClassNode().getName() + "(");
   boolean first = true;
   Map<String, Expression> members = annotation.getMembers();
   for (String key : members.keySet()) {
     if (first) first = false;
     else out.print(", ");
     out.print(key + "=" + getAnnotationValue(members.get(key)));
   }
   out.print(") ");
 }
 public void visitAnnotations(AnnotatedNode node) {
   List<AnnotationNode> annotations = node.getAnnotations();
   if (annotations.isEmpty()) return;
   for (AnnotationNode an : annotations) {
     // skip built-in properties
     if (an.isBuiltIn()) continue;
     for (Map.Entry<String, Expression> member : an.getMembers().entrySet()) {
       Expression annMemberValue = member.getValue();
       annMemberValue.visit(this);
     }
   }
 }
 public Expression transform(Expression exp) {
   if (exp == null) return null;
   if (exp.getClass() == VariableExpression.class) {
     return transformVariableExpression((VariableExpression) exp);
   }
   if (exp.getClass() == BinaryExpression.class) {
     return transformBinaryExpression((BinaryExpression) exp);
   }
   if (exp.getClass() == PropertyExpression.class) {
     return transformPropertyExpression((PropertyExpression) exp);
   }
   if (exp.getClass() == MethodCallExpression.class) {
     return transformMethodCallExpression((MethodCallExpression) exp);
   }
   if (exp.getClass() == ClosureExpression.class) {
     return transformClosureExpression((ClosureExpression) exp);
   }
   if (exp.getClass() == ConstructorCallExpression.class) {
     return transformConstructorCallExpression((ConstructorCallExpression) exp);
   }
   if (exp.getClass() == ArgumentListExpression.class) {
     Expression result = exp.transformExpression(this);
     if (inPropertyExpression) {
       foundArgs = result;
     }
     return result;
   }
   if (exp instanceof ConstantExpression) {
     Expression result = exp.transformExpression(this);
     if (inPropertyExpression) {
       foundConstant = result;
     }
     if (inAnnotation && exp instanceof AnnotationConstantExpression) {
       ConstantExpression ce = (ConstantExpression) result;
       if (ce.getValue() instanceof AnnotationNode) {
         // replicate a little bit of AnnotationVisitor here
         // because we can't wait until later to do this
         AnnotationNode an = (AnnotationNode) ce.getValue();
         Map<String, Expression> attributes = an.getMembers();
         for (Map.Entry<String, Expression> entry : attributes.entrySet()) {
           Expression attrExpr = transform(entry.getValue());
           entry.setValue(attrExpr);
         }
       }
     }
     return result;
   }
   return exp.transformExpression(this);
 }
  private static boolean hasClosureMember(AnnotationNode annotation) {

    Map<String, Expression> members = annotation.getMembers();
    for (Map.Entry<String, Expression> member : members.entrySet()) {
      if (member.getValue() instanceof ClosureExpression) return true;

      if (member.getValue() instanceof ClassExpression) {
        ClassExpression classExpression = (ClassExpression) member.getValue();
        Class<?> typeClass =
            classExpression.getType().isResolved()
                ? classExpression.getType().redirect().getTypeClass()
                : null;
        if (typeClass != null && GeneratedClosure.class.isAssignableFrom(typeClass)) return true;
      }
    }

    return false;
  }
  /**
   * Copies all <tt>candidateAnnotations</tt> with retention policy {@link
   * java.lang.annotation.RetentionPolicy#RUNTIME} and {@link
   * java.lang.annotation.RetentionPolicy#CLASS}.
   *
   * <p>Annotations with {@link org.codehaus.groovy.runtime.GeneratedClosure} members are not
   * supported at present.
   */
  public static void copyAnnotatedNodeAnnotations(
      final AnnotatedNode annotatedNode,
      final List<AnnotationNode> copied,
      List<AnnotationNode> notCopied) {
    List<AnnotationNode> annotationList = annotatedNode.getAnnotations();
    for (AnnotationNode annotation : annotationList) {

      List<AnnotationNode> annotations =
          annotation.getClassNode().getAnnotations(AbstractASTTransformation.RETENTION_CLASSNODE);
      if (annotations.isEmpty()) continue;

      if (hasClosureMember(annotation)) {
        notCopied.add(annotation);
        continue;
      }

      AnnotationNode retentionPolicyAnnotation = annotations.get(0);
      Expression valueExpression = retentionPolicyAnnotation.getMember("value");
      if (!(valueExpression instanceof PropertyExpression)) continue;

      PropertyExpression propertyExpression = (PropertyExpression) valueExpression;
      boolean processAnnotation =
          propertyExpression.getProperty() instanceof ConstantExpression
              && ("RUNTIME"
                      .equals(((ConstantExpression) (propertyExpression.getProperty())).getValue())
                  || "CLASS"
                      .equals(
                          ((ConstantExpression) (propertyExpression.getProperty())).getValue()));

      if (processAnnotation) {
        AnnotationNode newAnnotation = new AnnotationNode(annotation.getClassNode());
        for (Map.Entry<String, Expression> member : annotation.getMembers().entrySet()) {
          newAnnotation.addMember(member.getKey(), member.getValue());
        }
        newAnnotation.setSourcePosition(annotatedNode);

        copied.add(newAnnotation);
      }
    }
  }