/**
  * 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;
 }
  @Nullable
  public static List<String> findTestDataFiles(@NotNull DataContext context) {
    final PsiMethod method = findTargetMethod(context);
    if (method == null) {
      return null;
    }
    final String name = method.getName();

    if (name.startsWith("test")) {
      String testDataPath =
          TestDataLineMarkerProvider.getTestDataBasePath(method.getContainingClass());
      final TestDataReferenceCollector collector =
          new TestDataReferenceCollector(testDataPath, name.substring(4));
      return collector.collectTestDataReferences(method);
    }

    final Location<?> location = Location.DATA_KEY.getData(context);
    if (location instanceof PsiMemberParameterizedLocation) {
      PsiClass containingClass = ((PsiMemberParameterizedLocation) location).getContainingClass();
      if (containingClass == null) {
        containingClass =
            PsiTreeUtil.getParentOfType(location.getPsiElement(), PsiClass.class, false);
      }
      if (containingClass != null) {
        final PsiAnnotation annotation =
            AnnotationUtil.findAnnotationInHierarchy(
                containingClass, Collections.singleton(JUnitUtil.RUN_WITH));
        if (annotation != null) {
          final PsiAnnotationMemberValue memberValue = annotation.findAttributeValue("value");
          if (memberValue instanceof PsiClassObjectAccessExpression) {
            final PsiTypeElement operand =
                ((PsiClassObjectAccessExpression) memberValue).getOperand();
            if (operand.getType().equalsToText(Parameterized.class.getName())) {
              final String testDataPath =
                  TestDataLineMarkerProvider.getTestDataBasePath(containingClass);
              final String paramSetName =
                  ((PsiMemberParameterizedLocation) location).getParamSetName();
              final String baseFileName =
                  StringUtil.trimEnd(StringUtil.trimStart(paramSetName, "["), "]");
              final ProjectFileIndex fileIndex =
                  ProjectRootManager.getInstance(containingClass.getProject()).getFileIndex();
              return TestDataGuessByExistingFilesUtil.suggestTestDataFiles(
                  fileIndex, baseFileName, testDataPath, containingClass);
            }
          }
        }
      }
    }

    return null;
  }
 @Nullable
 public static String getTestDataBasePath(PsiClass psiClass) {
   final PsiAnnotation annotation =
       AnnotationUtil.findAnnotationInHierarchy(
           psiClass, Collections.singleton(TEST_DATA_PATH_ANNOTATION_QUALIFIED_NAME));
   if (annotation != null) {
     final PsiAnnotationMemberValue value =
         annotation.findAttributeValue(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME);
     if (value instanceof PsiExpression) {
       final Project project = value.getProject();
       final PsiConstantEvaluationHelper evaluationHelper =
           JavaPsiFacade.getInstance(project).getConstantEvaluationHelper();
       final Object constantValue = evaluationHelper.computeConstantExpression(value, false);
       if (constantValue instanceof String) {
         String path = (String) constantValue;
         if (path.contains(CONTENT_ROOT_VARIABLE)) {
           final ProjectFileIndex fileIndex =
               ProjectRootManager.getInstance(project).getFileIndex();
           final VirtualFile file = psiClass.getContainingFile().getVirtualFile();
           if (file == null) {
             return null;
           }
           final VirtualFile contentRoot = fileIndex.getContentRootForFile(file);
           if (contentRoot == null) return null;
           path = path.replace(CONTENT_ROOT_VARIABLE, contentRoot.getPath());
         }
         if (path.contains(PROJECT_ROOT_VARIABLE)) {
           final VirtualFile baseDir = project.getBaseDir();
           if (baseDir == null) {
             return null;
           }
           path = path.replace(PROJECT_ROOT_VARIABLE, baseDir.getPath());
         }
         return path;
       }
     }
   }
   return null;
 }
  public static boolean hasTest(
      PsiModifierListOwner element,
      boolean checkHierarchy,
      boolean checkDisabled,
      boolean checkJavadoc) {
    // LanguageLevel effectiveLanguageLevel = element.getManager().getEffectiveLanguageLevel();
    // boolean is15 = effectiveLanguageLevel != LanguageLevel.JDK_1_4 && effectiveLanguageLevel !=
    // LanguageLevel.JDK_1_3;
    boolean hasAnnotation =
        AnnotationUtil.isAnnotated(element, TEST_ANNOTATION_FQN, checkHierarchy, true);
    if (hasAnnotation) {
      if (checkDisabled) {
        PsiAnnotation annotation =
            AnnotationUtil.findAnnotation(element, true, TEST_ANNOTATION_FQN);
        if (annotation != null) {
          if (isDisabled(annotation)) return false;
        }
      }
      return true;
    }
    if (element instanceof PsiDocCommentOwner
        && checkJavadoc
        && getTextJavaDoc((PsiDocCommentOwner) element) != null) return true;
    // now we check all methods for the test annotation
    if (element instanceof PsiClass) {
      PsiClass psiClass = (PsiClass) element;
      for (PsiMethod method : psiClass.getAllMethods()) {
        PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, true, TEST_ANNOTATION_FQN);
        if (annotation != null) {
          if (checkDisabled) {
            if (isDisabled(annotation)) continue;
          }
          return true;
        }
        if (AnnotationUtil.isAnnotated(method, FACTORY_ANNOTATION_FQN, false, true)) return true;
        if (checkJavadoc && getTextJavaDoc(method) != null) return true;
      }
      return false;
    } else if (element instanceof PsiMethod) {
      // even if it has a global test, we ignore private and static methods
      if (element.hasModifierProperty(PsiModifier.PRIVATE)
          || element.hasModifierProperty(PsiModifier.STATIC)) {
        return false;
      }

      // if it's a method, we check if the class it's in has a global @Test annotation
      PsiClass psiClass = ((PsiMethod) element).getContainingClass();
      if (psiClass != null) {
        final PsiAnnotation annotation =
            checkHierarchy
                ? AnnotationUtil.findAnnotationInHierarchy(
                    psiClass, Collections.singleton(TEST_ANNOTATION_FQN))
                : AnnotationUtil.findAnnotation(psiClass, true, TEST_ANNOTATION_FQN);
        if (annotation != null) {
          if (checkDisabled && isDisabled(annotation)) return false;
          return !hasConfig(element);
        } else if (checkJavadoc && getTextJavaDoc(psiClass) != null) return true;
      }
    }
    return false;
  }