public static void fillCompletionVariants(
      CompletionParameters parameters, CompletionResultSet result) {
    if (parameters.getCompletionType() != CompletionType.BASIC
        && parameters.getCompletionType() != CompletionType.SMART) {
      return;
    }

    PsiElement position = parameters.getPosition();
    if (psiElement(PsiIdentifier.class)
        .withParents(PsiJavaCodeReferenceElement.class, PsiTypeElement.class, PsiClass.class)
        .andNot(JavaCompletionData.AFTER_DOT)
        .andNot(psiElement().afterLeaf(psiElement().inside(PsiModifierList.class)))
        .accepts(position)) {
      suggestGeneratedMethods(result, position);
    } else if (psiElement(PsiIdentifier.class)
        .withParents(
            PsiJavaCodeReferenceElement.class,
            PsiAnnotation.class,
            PsiModifierList.class,
            PsiClass.class)
        .accepts(position)) {
      PsiAnnotation annotation =
          ObjectUtils.assertNotNull(PsiTreeUtil.getParentOfType(position, PsiAnnotation.class));
      int annoStart = annotation.getTextRange().getStartOffset();
      suggestGeneratedMethods(
          result.withPrefixMatcher(
              annotation.getText().substring(0, parameters.getOffset() - annoStart)),
          position);
    }
  }
 /**
  * The parameter <code>allowIndirect</code> determines if the method should look for indirect
  * annotations, i.e. annotations which have themselves been annotated by the supplied annotation
  * name. Currently, this only allows one level of indirection and returns an array of
  * [base-annotation, indirect annotation]
  *
  * <p>The <code>annotationName</code> parameter is a pair of the target annotation class' fully
  * qualified name as a String and as a Set. This is done for performance reasons because the Set
  * is required by the {@link com.intellij.codeInsight.AnnotationUtil} utility class and allows to
  * avoid unnecessary object constructions.
  */
 public static PsiAnnotation[] getAnnotationsFromImpl(
     PsiModifierListOwner owner,
     Pair<String, ? extends Set<String>> annotationName,
     boolean allowIndirect,
     boolean inHierarchy) {
   final PsiAnnotation directAnnotation =
       inHierarchy
           ? AnnotationUtil.findAnnotationInHierarchy(owner, annotationName.second)
           : AnnotationUtil.findAnnotation(owner, annotationName.second);
   if (directAnnotation != null) {
     return new PsiAnnotation[] {directAnnotation};
   }
   if (allowIndirect) {
     final PsiAnnotation[] annotations = getAnnotations(owner, inHierarchy);
     for (PsiAnnotation annotation : annotations) {
       PsiJavaCodeReferenceElement nameReference = annotation.getNameReferenceElement();
       if (nameReference == null) continue;
       PsiElement resolved = nameReference.resolve();
       if (resolved instanceof PsiClass) {
         final PsiAnnotation psiAnnotation =
             AnnotationUtil.findAnnotationInHierarchy(
                 (PsiModifierListOwner) resolved, annotationName.second);
         if (psiAnnotation != null) {
           return new PsiAnnotation[] {psiAnnotation, annotation};
         }
       }
     }
   }
   return PsiAnnotation.EMPTY_ARRAY;
 }
 public static PsiClass getProviderClass(final PsiElement element, final PsiClass topLevelClass) {
   final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(element, PsiAnnotation.class);
   if (annotation != null) {
     final PsiAnnotationMemberValue value =
         annotation.findDeclaredAttributeValue("dataProviderClass");
     if (value instanceof PsiClassObjectAccessExpression) {
       final PsiTypeElement operand = ((PsiClassObjectAccessExpression) value).getOperand();
       final PsiClass psiClass = PsiUtil.resolveClassInType(operand.getType());
       if (psiClass != null) {
         return psiClass;
       }
     }
   }
   return topLevelClass;
 }
  private static AllowedValues getAllowedValuesFromMagic(
      @NotNull PsiModifierListOwner element, @NotNull PsiType type, PsiAnnotation magic) {
    if (magic == null) return null;
    PsiAnnotationMemberValue[] allowedValues;
    final boolean canBeOred;
    if (TypeConversionUtil.getTypeRank(type) <= TypeConversionUtil.LONG_RANK) {
      PsiAnnotationMemberValue intValues = magic.findAttributeValue("intValues");
      allowedValues =
          intValues instanceof PsiArrayInitializerMemberValue
              ? ((PsiArrayInitializerMemberValue) intValues).getInitializers()
              : PsiAnnotationMemberValue.EMPTY_ARRAY;
      if (allowedValues.length == 0) {
        PsiAnnotationMemberValue orValue = magic.findAttributeValue("flags");
        allowedValues =
            orValue instanceof PsiArrayInitializerMemberValue
                ? ((PsiArrayInitializerMemberValue) orValue).getInitializers()
                : PsiAnnotationMemberValue.EMPTY_ARRAY;
        canBeOred = true;
      } else {
        canBeOred = false;
      }
    } else if (type.equals(
        PsiType.getJavaLangString(
            element.getManager(), GlobalSearchScope.allScope(element.getProject())))) {
      PsiAnnotationMemberValue strValuesAttr = magic.findAttributeValue("stringValues");
      allowedValues =
          strValuesAttr instanceof PsiArrayInitializerMemberValue
              ? ((PsiArrayInitializerMemberValue) strValuesAttr).getInitializers()
              : PsiAnnotationMemberValue.EMPTY_ARRAY;
      canBeOred = false;
    } else {
      return null; // other types not supported
    }

    if (allowedValues.length != 0) {
      return new AllowedValues(allowedValues, canBeOred);
    }

    // last resort: try valuesFromClass
    PsiAnnotationMemberValue[] values = readFromClass("valuesFromClass", magic, type);
    boolean ored = false;
    if (values == null) {
      values = readFromClass("flagsFromClass", magic, type);
      ored = true;
    }
    if (values == null) return null;
    return new AllowedValues(values, ored);
  }
  private static PsiAnnotationMemberValue[] readFromClass(
      @NonNls String attributeName, @NotNull PsiAnnotation magic, PsiType type) {
    PsiAnnotationMemberValue fromClassAttr = magic.findAttributeValue(attributeName);
    PsiType fromClassType =
        fromClassAttr instanceof PsiClassObjectAccessExpression
            ? ((PsiClassObjectAccessExpression) fromClassAttr).getOperand().getType()
            : null;
    PsiClass fromClass =
        fromClassType instanceof PsiClassType ? ((PsiClassType) fromClassType).resolve() : null;
    if (fromClass == null) return null;
    String fqn = fromClass.getQualifiedName();
    if (fqn == null) return null;
    List<PsiAnnotationMemberValue> constants = new ArrayList<PsiAnnotationMemberValue>();
    for (PsiField field : fromClass.getFields()) {
      if (!field.hasModifierProperty(PsiModifier.PUBLIC)
          || !field.hasModifierProperty(PsiModifier.STATIC)
          || !field.hasModifierProperty(PsiModifier.FINAL)) continue;
      PsiType fieldType = field.getType();
      if (!Comparing.equal(fieldType, type)) continue;
      PsiAssignmentExpression e =
          (PsiAssignmentExpression)
              JavaPsiFacade.getElementFactory(field.getProject())
                  .createExpressionFromText("x=" + fqn + "." + field.getName(), field);
      PsiReferenceExpression refToField = (PsiReferenceExpression) e.getRExpression();
      constants.add(refToField);
    }
    if (constants.isEmpty()) return null;

    return constants.toArray(new PsiAnnotationMemberValue[constants.size()]);
  }
 @Nullable
 public static String checkFunctionalInterface(
     @NotNull PsiAnnotation annotation, @NotNull LanguageLevel languageLevel) {
   if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)
       && Comparing.strEqual(annotation.getQualifiedName(), JAVA_LANG_FUNCTIONAL_INTERFACE)) {
     final PsiAnnotationOwner owner = annotation.getOwner();
     if (owner instanceof PsiModifierList) {
       final PsiElement parent = ((PsiModifierList) owner).getParent();
       if (parent instanceof PsiClass) {
         return LambdaHighlightingUtil.checkInterfaceFunctional(
             (PsiClass) parent, ((PsiClass) parent).getName() + " is not a functional interface");
       }
     }
   }
   return null;
 }
 @Nullable
 public static String calcAnnotationValue(@NotNull PsiAnnotation annotation, @NonNls String attr) {
   PsiElement value = annotation.findAttributeValue(attr);
   Object o = CONSTANT_EVALUATION_HELPER.computeConstantExpression(value);
   if (o instanceof String) {
     return (String) o;
   }
   return null;
 }
 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;
 }
 public static boolean isAnnotatedWithParameter(
     PsiAnnotation annotation, String parameter, Set<String> values) {
   final PsiAnnotationMemberValue attributeValue =
       annotation.findDeclaredAttributeValue(parameter);
   if (attributeValue != null) {
     Collection<String> matches = extractValuesFromParameter(attributeValue);
     for (String s : matches) {
       if (values.contains(s)) {
         return true;
       }
     }
   }
   return false;
 }
 public static boolean isTestNGAnnotation(PsiAnnotation annotation) {
   String qName = annotation.getQualifiedName();
   if (qName != null) {
     if (qName.equals(TEST_ANNOTATION_FQN)) return true;
     for (String qn : CONFIG_ANNOTATIONS_FQN) {
       if (qName.equals(qn)) return true;
     }
     if (qName.equals(TEST_ANNOTATION_FQN)) return true;
     for (String qn : CONFIG_ANNOTATIONS_FQN) {
       if (qName.equals(qn)) return true;
     }
   }
   return false;
 }
  static AllowedValues getAllowedValues(
      @NotNull PsiModifierListOwner element, PsiType type, Set<PsiClass> visited) {
    PsiAnnotation[] annotations = AnnotationUtil.getAllAnnotations(element, true, null);
    for (PsiAnnotation annotation : annotations) {
      AllowedValues values;
      if (type != null && MagicConstant.class.getName().equals(annotation.getQualifiedName())) {
        // PsiAnnotation magic = AnnotationUtil.findAnnotationInHierarchy(element,
        // Collections.singleton(MagicConstant.class.getName()));
        values = getAllowedValuesFromMagic(element, type, annotation);
        if (values != null) return values;
      }

      PsiJavaCodeReferenceElement ref = annotation.getNameReferenceElement();
      PsiElement resolved = ref == null ? null : ref.resolve();
      if (!(resolved instanceof PsiClass) || !((PsiClass) resolved).isAnnotationType()) continue;
      PsiClass aClass = (PsiClass) resolved;
      if (visited == null) visited = new THashSet<PsiClass>();
      if (!visited.add(aClass)) continue;
      values = getAllowedValues(aClass, type, visited);
      if (values != null) return values;
    }

    return parseBeanInfo(element);
  }
 private static void appendAnnotationAttributeValues(
     final Map<String, Collection<String>> results,
     final PsiAnnotation annotation,
     final PsiDocCommentOwner commentOwner) {
   for (String parameter : results.keySet()) {
     final Collection<String> values = results.get(parameter);
     if (annotation != null) {
       final PsiAnnotationMemberValue value = annotation.findDeclaredAttributeValue(parameter);
       if (value != null) {
         values.addAll(extractValuesFromParameter(value));
       }
     } else {
       values.addAll(extractAnnotationValuesFromJavaDoc(getTextJavaDoc(commentOwner), parameter));
     }
   }
 }
  private static AllowedValues parseBeanInfo(@NotNull PsiModifierListOwner owner) {
    PsiMethod method = null;
    if (owner instanceof PsiParameter) {
      PsiParameter parameter = (PsiParameter) owner;
      PsiElement scope = parameter.getDeclarationScope();
      if (!(scope instanceof PsiMethod)) return null;
      PsiElement nav = scope.getNavigationElement();
      if (!(nav instanceof PsiMethod)) return null;
      method = (PsiMethod) nav;
      if (method.isConstructor()) {
        // not a property, try the @ConstructorProperties({"prop"})
        PsiAnnotation annotation =
            AnnotationUtil.findAnnotation(method, "java.beans.ConstructorProperties");
        if (annotation == null) return null;
        PsiAnnotationMemberValue value = annotation.findAttributeValue("value");
        if (!(value instanceof PsiArrayInitializerMemberValue)) return null;
        PsiAnnotationMemberValue[] initializers =
            ((PsiArrayInitializerMemberValue) value).getInitializers();
        PsiElement parent = parameter.getParent();
        if (!(parent instanceof PsiParameterList)) return null;
        int index = ((PsiParameterList) parent).getParameterIndex(parameter);
        if (index >= initializers.length) return null;
        PsiAnnotationMemberValue initializer = initializers[index];
        if (!(initializer instanceof PsiLiteralExpression)) return null;
        Object val = ((PsiLiteralExpression) initializer).getValue();
        if (!(val instanceof String)) return null;
        PsiMethod setter =
            PropertyUtil.findPropertySetter(
                method.getContainingClass(), (String) val, false, false);
        if (setter == null) return null;
        // try the @beaninfo of the corresponding setter
        method = (PsiMethod) setter.getNavigationElement();
      }
    } else if (owner instanceof PsiMethod) {
      PsiElement nav = owner.getNavigationElement();
      if (!(nav instanceof PsiMethod)) return null;
      method = (PsiMethod) nav;
    }
    if (method == null) return null;

    PsiClass aClass = method.getContainingClass();
    if (aClass == null) return null;
    if (PropertyUtil.isSimplePropertyGetter(method)) {
      List<PsiMethod> setters =
          PropertyUtil.getSetters(aClass, PropertyUtil.getPropertyNameByGetter(method));
      if (setters.size() != 1) return null;
      method = setters.get(0);
    }
    if (!PropertyUtil.isSimplePropertySetter(method)) return null;
    PsiDocComment doc = method.getDocComment();
    if (doc == null) return null;
    PsiDocTag beaninfo = doc.findTagByName("beaninfo");
    if (beaninfo == null) return null;
    String data =
        StringUtil.join(
            beaninfo.getDataElements(),
            new Function<PsiElement, String>() {
              @Override
              public String fun(PsiElement element) {
                return element.getText();
              }
            },
            "\n");
    int enumIndex = StringUtil.indexOfSubstringEnd(data, "enum:");
    if (enumIndex == -1) return null;
    data = data.substring(enumIndex);
    int colon = data.indexOf(":");
    int last = colon == -1 ? data.length() : data.substring(0, colon).lastIndexOf("\n");
    data = data.substring(0, last);

    List<PsiAnnotationMemberValue> values = new ArrayList<PsiAnnotationMemberValue>();
    for (String line : StringUtil.splitByLines(data)) {
      List<String> words = StringUtil.split(line, " ", true, true);
      if (words.size() != 2) continue;
      String ref = words.get(1);
      PsiExpression constRef =
          JavaPsiFacade.getElementFactory(aClass.getProject())
              .createExpressionFromText(ref, aClass);
      if (!(constRef instanceof PsiReferenceExpression)) continue;
      PsiReferenceExpression expr = (PsiReferenceExpression) constRef;
      values.add(expr);
    }
    if (values.isEmpty()) return null;
    PsiAnnotationMemberValue[] array = values.toArray(new PsiAnnotationMemberValue[values.size()]);
    return new AllowedValues(array, false);
  }
 public static boolean isDisabled(PsiAnnotation annotation) {
   final PsiAnnotationMemberValue attributeValue =
       annotation.findDeclaredAttributeValue("enabled");
   return attributeValue != null && attributeValue.textMatches("false");
 }