private static String buildAnnotationText(PsiAnnotation annotation) {
   final StringBuilder out = new StringBuilder("@");
   final PsiJavaCodeReferenceElement nameReferenceElement = annotation.getNameReferenceElement();
   assert nameReferenceElement != null;
   out.append(nameReferenceElement.getText());
   final PsiAnnotationParameterList parameterList = annotation.getParameterList();
   final PsiNameValuePair[] attributes = parameterList.getAttributes();
   if (attributes.length == 0) {
     return out.toString();
   }
   out.append('(');
   if (attributes.length == 1) {
     final PsiNameValuePair attribute = attributes[0];
     @NonNls final String name = attribute.getName();
     if (name != null && !PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(name)) {
       out.append(name).append('=');
     }
     buildAttributeValueText(attribute.getValue(), out);
   } else {
     for (int i = 0; i < attributes.length; i++) {
       final PsiNameValuePair attribute = attributes[i];
       if (i > 0) {
         out.append(',');
       }
       out.append(attribute.getName()).append('=');
       buildAttributeValueText(attribute.getValue(), out);
     }
   }
   out.append(')');
   return out.toString();
 }
    private static boolean containsError(PsiAnnotation annotation) {
      final PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
      if (nameRef == null) {
        return true;
      }
      final PsiClass aClass = (PsiClass) nameRef.resolve();
      if (aClass == null || !aClass.isAnnotationType()) {
        return true;
      }
      final Set<String> names = new HashSet<String>();
      final PsiAnnotationParameterList annotationParameterList = annotation.getParameterList();
      if (PsiUtilCore.hasErrorElementChild(annotationParameterList)) {
        return true;
      }
      final PsiNameValuePair[] attributes = annotationParameterList.getAttributes();
      for (PsiNameValuePair attribute : attributes) {
        final PsiReference reference = attribute.getReference();
        if (reference == null) {
          return true;
        }
        final PsiMethod method = (PsiMethod) reference.resolve();
        if (method == null) {
          return true;
        }
        final PsiAnnotationMemberValue value = attribute.getValue();
        if (value == null || PsiUtilCore.hasErrorElementChild(value)) {
          return true;
        }
        if (value instanceof PsiAnnotation && containsError((PsiAnnotation) value)) {
          return true;
        }
        if (!hasCorrectType(value, method.getReturnType())) {
          return true;
        }
        final String name = attribute.getName();
        if (!names.add(name != null ? name : PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME)) {
          return true;
        }
      }

      for (PsiMethod method : aClass.getMethods()) {
        if (!(method instanceof PsiAnnotationMethod)) {
          continue;
        }
        final PsiAnnotationMethod annotationMethod = (PsiAnnotationMethod) method;
        if (annotationMethod.getDefaultValue() == null
            && !names.contains(annotationMethod.getName())) {
          return true; // missing a required argument
        }
      }
      return false;
    }
 private static boolean processAnnotationAttributes(
     @Nullable Map<String, Object> annotationAttributeValues, @NotNull PsiAnnotation annotation) {
   if (annotationAttributeValues != null) {
     final PsiAnnotationParameterList parameterList = annotation.getParameterList();
     final PsiNameValuePair[] attributes = parameterList.getAttributes();
     for (PsiNameValuePair attribute : attributes) {
       final String name = attribute.getName();
       if (annotationAttributeValues.containsKey(name)) {
         annotationAttributeValues.put(name, attribute.getValue());
       }
     }
   }
   return true;
 }
  @Override
  @NotNull
  public PsiAnnotationParameterList getParameterList() {
    synchronized (lock) {
      if (myParameterList == null) {
        final PsiAnnotationStub stub = getStub();
        final CompositeElement mirror = stub.getTreeElement();

        final PsiAnnotationParameterList paramList =
            (PsiAnnotationParameterList)
                mirror.findChildByRoleAsPsiElement(ChildRole.PARAMETER_LIST);

        myParameterList = new ClsAnnotationParameterListImpl(this, paramList.getAttributes());
      }

      return myParameterList;
    }
  }
  @Nullable
  private static HighlightInfo checkDuplicateAttribute(PsiNameValuePair pair) {
    PsiAnnotationParameterList annotation = (PsiAnnotationParameterList) pair.getParent();
    PsiNameValuePair[] attributes = annotation.getAttributes();
    for (PsiNameValuePair attribute : attributes) {
      if (attribute == pair) break;
      String name = pair.getName();
      if (Comparing.equal(attribute.getName(), name)) {
        String description =
            JavaErrorMessages.message(
                "annotation.duplicate.attribute",
                name == null ? PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME : name);
        return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
            .range(pair)
            .descriptionAndTooltip(description)
            .create();
      }
    }

    return null;
  }
 @Override
 public List<PsiLiteralExpression> getTargets() {
   final List<PsiLiteralExpression> result = new ArrayList<PsiLiteralExpression>();
   if (mySuppressedExpression != null) {
     result.add(mySuppressedExpression);
     return result;
   }
   final PsiAnnotationParameterList list = myTarget.getParameterList();
   final PsiNameValuePair[] attributes = list.getAttributes();
   for (PsiNameValuePair attribute : attributes) {
     final PsiAnnotationMemberValue value = attribute.getValue();
     if (value instanceof PsiArrayInitializerMemberValue) {
       final PsiAnnotationMemberValue[] initializers =
           ((PsiArrayInitializerMemberValue) value).getInitializers();
       for (PsiAnnotationMemberValue initializer : initializers) {
         if (initializer instanceof PsiLiteralExpression) {
           result.add((PsiLiteralExpression) initializer);
         }
       }
     }
   }
   return result;
 }
  public static AnnotationValueElement getValueStringFromAnnotationWithDefault(
      PsiAnnotation annotation) {
    final PsiAnnotationParameterList parameterList = annotation.getParameterList();
    final PsiNameValuePair[] attributes = parameterList.getAttributes();
    final PsiElement logicalElement = getImmediateOwnerElement(annotation);

    if (logicalElement == null) {
      return null;
    }

    final String value;
    final PsiElement errorElement;

    if (attributes.length == 0) {
      value = getNameOfElement(logicalElement);
      errorElement = annotation;
    } else {
      final String text = attributes[0].getText();
      value = text.substring(1, text.length() - 1);
      errorElement = attributes[0];
    }

    return new AnnotationValueElement(value, errorElement);
  }
 @Override
 public void visitAnnotation(PsiAnnotation annotation) {
   super.visitAnnotation(annotation);
   final PsiAnnotationParameterList parameterList = annotation.getParameterList();
   final PsiJavaCodeReferenceElement nameReferenceElement = annotation.getNameReferenceElement();
   if (nameReferenceElement == null) {
     return;
   }
   final PsiNameValuePair[] attributes = parameterList.getAttributes();
   final PsiElement[] annotationChildren = annotation.getChildren();
   if (annotationChildren.length >= 2
       && annotationChildren[1] instanceof PsiWhiteSpace
       && !containsError(annotation)) {
     registerError(annotationChildren[1], Boolean.TRUE);
   }
   if (attributes.length == 0) {
     if (parameterList.getChildren().length > 0 && !containsError(annotation)) {
       registerError(parameterList, ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
     }
   } else if (attributes.length == 1) {
     final PsiNameValuePair attribute = attributes[0];
     final PsiIdentifier identifier = attribute.getNameIdentifier();
     final PsiAnnotationMemberValue attributeValue = attribute.getValue();
     if (identifier != null && attributeValue != null) {
       @NonNls final String name = attribute.getName();
       if (PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(name)
           && !containsError(annotation)) {
         registerErrorAtOffset(
             attribute,
             0,
             attributeValue.getStartOffsetInParent(),
             ProblemHighlightType.LIKE_UNUSED_SYMBOL,
             Boolean.FALSE);
       }
     }
     if (!(attributeValue instanceof PsiArrayInitializerMemberValue)) {
       return;
     }
     final PsiArrayInitializerMemberValue arrayValue =
         (PsiArrayInitializerMemberValue) attributeValue;
     final PsiAnnotationMemberValue[] initializers = arrayValue.getInitializers();
     if (initializers.length != 1) {
       return;
     }
     if (!containsError(annotation)) {
       registerError(
           arrayValue.getFirstChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
       registerError(
           arrayValue.getLastChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
     }
   } else if (attributes.length > 1) {
     for (PsiNameValuePair attribute : attributes) {
       final PsiAnnotationMemberValue value = attribute.getValue();
       if (!(value instanceof PsiArrayInitializerMemberValue)) {
         continue;
       }
       final PsiArrayInitializerMemberValue arrayValue = (PsiArrayInitializerMemberValue) value;
       final PsiAnnotationMemberValue[] initializers = arrayValue.getInitializers();
       if (initializers.length != 1) {
         continue;
       }
       if (!containsError(annotation)) {
         registerError(
             arrayValue.getFirstChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
         registerError(
             arrayValue.getLastChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
       }
     }
   }
 }
  private static void completeAnnotationAttributeName(
      CompletionResultSet result, PsiElement insertedElement, CompletionParameters parameters) {
    PsiNameValuePair pair = PsiTreeUtil.getParentOfType(insertedElement, PsiNameValuePair.class);
    PsiAnnotationParameterList parameterList = (PsiAnnotationParameterList) pair.getParent();
    PsiAnnotation anno = (PsiAnnotation) parameterList.getParent();
    boolean showClasses = psiElement().afterLeaf("(").accepts(insertedElement);
    PsiClass annoClass = null;
    final PsiJavaCodeReferenceElement referenceElement = anno.getNameReferenceElement();
    if (referenceElement != null) {
      final PsiElement element = referenceElement.resolve();
      if (element instanceof PsiClass) {
        annoClass = (PsiClass) element;
        if (annoClass.findMethodsByName("value", false).length == 0) {
          showClasses = false;
        }
      }
    }

    if (showClasses && insertedElement.getParent() instanceof PsiReferenceExpression) {
      final Set<LookupElement> set =
          JavaCompletionUtil.processJavaReference(
              insertedElement,
              (PsiJavaReference) insertedElement.getParent(),
              new ElementExtractorFilter(createAnnotationFilter(insertedElement)),
              JavaCompletionProcessor.Options.DEFAULT_OPTIONS,
              result.getPrefixMatcher(),
              parameters);
      for (final LookupElement element : set) {
        result.addElement(element);
      }
      addAllClasses(parameters, result, new InheritorsHolder(insertedElement, result));
    }

    if (annoClass != null) {
      final PsiNameValuePair[] existingPairs = parameterList.getAttributes();

      methods:
      for (PsiMethod method : annoClass.getMethods()) {
        if (!(method instanceof PsiAnnotationMethod)) continue;

        final String attrName = method.getName();
        for (PsiNameValuePair existingAttr : existingPairs) {
          if (PsiTreeUtil.isAncestor(existingAttr, insertedElement, false)) break;
          if (Comparing.equal(existingAttr.getName(), attrName)
              || PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(attrName)
                  && existingAttr.getName() == null) continue methods;
        }
        LookupElementBuilder element =
            LookupElementBuilder.createWithIcon(method)
                .withInsertHandler(
                    new InsertHandler<LookupElement>() {
                      @Override
                      public void handleInsert(InsertionContext context, LookupElement item) {
                        final Editor editor = context.getEditor();
                        TailType.EQ.processTail(editor, editor.getCaretModel().getOffset());
                        context.setAddCompletionChar(false);

                        context.commitDocument();
                        PsiAnnotationParameterList paramList =
                            PsiTreeUtil.findElementOfClassAtOffset(
                                context.getFile(),
                                context.getStartOffset(),
                                PsiAnnotationParameterList.class,
                                false);
                        if (paramList != null
                            && paramList.getAttributes().length > 0
                            && paramList.getAttributes()[0].getName() == null) {
                          int valueOffset =
                              paramList.getAttributes()[0].getTextRange().getStartOffset();
                          context
                              .getDocument()
                              .insertString(
                                  valueOffset, PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME);
                          TailType.EQ.processTail(
                              editor,
                              valueOffset + PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.length());
                        }
                      }
                    });

        PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod) method).getDefaultValue();
        if (defaultValue != null) {
          Object constant =
              JavaPsiFacade.getInstance(method.getProject())
                  .getConstantEvaluationHelper()
                  .computeConstantExpression(defaultValue);
          if (constant != null) {
            element =
                element.withTailText(
                    " default " + (constant instanceof String ? "\"" + constant + "\"" : constant),
                    true);
          }
        }

        result.addElement(element);
      }
    }
  }