code: public static int findFirstNonAnnotationLine(ASTNode node, SourceCode sourceCode) {
          if (node instanceof AnnotatedNode && !((AnnotatedNode) node).getAnnotations().isEmpty()) {
  
              // HACK: Groovy line numbers are broken when annotations have a parameter :(
              // so we must look at the lineNumber, not the lastLineNumber
              AnnotationNode lastAnnotation = null;
              for (AnnotationNode annotation : ((AnnotatedNode) node).getAnnotations()) {
                  if (lastAnnotation == null) lastAnnotation = annotation;
                  else if (lastAnnotation.getLineNumber() < annotation.getLineNumber()) lastAnnotation = annotation;
              }
  
              String rawLine = getRawLine(sourceCode, lastAnnotation.getLastLineNumber()-1);
  
              if(rawLine == null) {
                  return node.getLineNumber();
              }
  
              // is the annotation the last thing on the line?
              if (rawLine.length() > lastAnnotation.getLastColumnNumber()) {
                  // no it is not
                  return lastAnnotation.getLastLineNumber();
              }
              // yes it is the last thing, return the next thing
              return lastAnnotation.getLastLineNumber() + 1;
          }
          return node.getLineNumber();
      }
docs: gets the first non annotation line number of a node, taking into account annotations.