@Override public Void visitAnnotation(AnnotationTree node,Void p){
  List<? extends ExpressionTree> args=node.getArguments();
  if (args.isEmpty()) {
    return null;
  }
  Element anno=TreeInfo.symbol((JCTree)node.getAnnotationType());
  if (anno.toString().equals(DefaultQualifier.class.getName()) || anno.toString().equals(SuppressWarnings.class.getName())) {
    return null;
  }
  Map<String,AnnotatedTypeMirror> annoTypes=new HashMap<String,AnnotatedTypeMirror>();
  for (  Element encl : ElementFilter.methodsIn(anno.getEnclosedElements())) {
    AnnotatedExecutableType exeatm=(AnnotatedExecutableType)atypeFactory.getAnnotatedType(encl);
    AnnotatedTypeMirror retty=exeatm.getReturnType();
    annoTypes.put(encl.getSimpleName().toString(),retty);
  }
  for (  ExpressionTree arg : args) {
    if (!(arg instanceof AssignmentTree)) {
      continue;
    }
    AssignmentTree at=(AssignmentTree)arg;
    if (at.getExpression().getKind() == Tree.Kind.ANNOTATION) {
      visitAnnotation((AnnotationTree)at.getExpression(),p);
      continue;
    }
    if (at.getExpression().getKind() == Tree.Kind.NEW_ARRAY) {
      NewArrayTree nat=(NewArrayTree)at.getExpression();
      boolean isAnno=false;
      for (      ExpressionTree init : nat.getInitializers()) {
        if (init.getKind() == Tree.Kind.ANNOTATION) {
          visitAnnotation((AnnotationTree)init,p);
          isAnno=true;
        }
      }
      if (isAnno) {
        continue;
      }
    }
    AnnotatedTypeMirror expected=annoTypes.get(at.getVariable().toString());
    Pair<Tree,AnnotatedTypeMirror> preAssCtxt=visitorState.getAssignmentContext();
{
      ExpressionTree var=at.getVariable();
      assert var instanceof IdentifierTree : "Expected IdentifierTree as context. Found: " + var;
      AnnotatedTypeMirror meth=atypeFactory.getAnnotatedType(var);
      assert meth instanceof AnnotatedExecutableType : "Expected AnnotatedExecutableType as context. Found: " + meth;
      AnnotatedTypeMirror newctx=((AnnotatedExecutableType)meth).getReturnType();
      visitorState.setAssignmentContext(Pair.<Tree,AnnotatedTypeMirror>of((Tree)null,newctx));
    }
    try {
      AnnotatedTypeMirror actual=atypeFactory.getAnnotatedType(at.getExpression());
      if (expected.getKind() != TypeKind.ARRAY) {
        commonAssignmentCheck(expected,actual,at.getExpression(),"annotation.type.incompatible");
      }
 else {
        if (actual.getKind() == TypeKind.ARRAY) {
          commonAssignmentCheck(expected,actual,at.getExpression(),"annotation.type.incompatible");
        }
 else {
          commonAssignmentCheck(((AnnotatedArrayType)expected).getComponentType(),actual,at.getExpression(),"annotation.type.incompatible");
        }
      }
    }
  finally {
      visitorState.setAssignmentContext(preAssCtxt);
    }
  }
  return null;
}

@ Override public Void visitAnnotation ( AnnotationTree node , Void p ) { List < ? extends ExpressionTree > args = node . getArguments ( ) ; if ( args . isEmpty ( ) ) { return null ; } Element anno = TreeInfo . symbol ( ( JCTree ) node . getAnnotationType ( ) ) ; if ( anno . toString ( ) . equals ( DefaultQualifier . class . getName ( ) ) || anno . toString ( ) . equals ( SuppressWarnings . class . getName ( ) ) ) { return null ; } Map < String , AnnotatedTypeMirror > annoTypes = new HashMap < String , AnnotatedTypeMirror > ( ) ; for ( Element encl : ElementFilter . methodsIn ( anno . getEnclosedElements ( ) ) ) { AnnotatedExecutableType exeatm = ( AnnotatedExecutableType ) atypeFactory . getAnnotatedType ( encl ) ; AnnotatedTypeMirror retty = exeatm . getReturnType ( ) ; annoTypes . put ( encl . getSimpleName ( ) . toString ( ) , retty ) ; } for ( ExpressionTree arg : args ) { if ( ! ( arg instanceof AssignmentTree ) ) { continue ; } AssignmentTree at = ( AssignmentTree ) arg ; if ( at . getExpression ( ) . getKind ( ) == Tree . Kind . ANNOTATION ) { visitAnnotation ( ( AnnotationTree ) at . getExpression ( ) , p ) ; continue ; } if ( at . getExpression ( ) . getKind ( ) == Tree . Kind . NEW_ARRAY ) { NewArrayTree nat = ( NewArrayTree ) at . getExpression ( ) ; boolean isAnno = false ; for ( ExpressionTree init : nat . getInitializers ( ) ) { if ( init . getKind ( ) == Tree . Kind . ANNOTATION ) { visitAnnotation ( ( AnnotationTree ) init , p ) ; isAnno = true ; } } if ( isAnno ) { continue ; } } AnnotatedTypeMirror expected = annoTypes . get ( at . getVariable ( ) . toString ( ) ) ; Pair < Tree , AnnotatedTypeMirror > preAssCtxt = visitorState . getAssignmentContext ( ) ; { ExpressionTree var = at . getVariable ( ) ; assert var instanceof IdentifierTree : "Expected IdentifierTree as context. Found: " + var ; AnnotatedTypeMirror meth = atypeFactory . getAnnotatedType ( var ) ; assert meth instanceof AnnotatedExecutableType : "Expected AnnotatedExecutableType as context. Found: " + meth ; AnnotatedTypeMirror newctx = ( ( AnnotatedExecutableType ) meth ) . getReturnType ( ) ; visitorState . setAssignmentContext ( Pair . < Tree , AnnotatedTypeMirror > of ( ( Tree ) null , newctx ) ) ; } try { AnnotatedTypeMirror actual = atypeFactory . getAnnotatedType ( at . getExpression ( ) ) ; if ( expected . getKind ( ) != TypeKind . ARRAY ) { commonAssignmentCheck ( expected , actual , at . getExpression ( ) , "annotation.type.incompatible" ) ; } else { if ( actual . getKind ( ) == TypeKind . ARRAY ) { commonAssignmentCheck ( expected , actual , at . getExpression ( ) , "annotation.type.incompatible" ) ; } else { commonAssignmentCheck ( ( ( AnnotatedArrayType ) expected ) . getComponentType ( ) , actual , at . getExpression ( ) , "annotation.type.incompatible" ) ; } } } finally { visitorState . setAssignmentContext ( preAssCtxt ) ; } } return null ; }
ensure that the annotation arguments comply to their declarations . this needs some special casing , as annotation arguments form special trees .
