@Override
 public void visitReferenceExpression(PsiReferenceExpression expression) {
   if (argumentsContainCatchParameter || !visited.add(expression)) {
     return;
   }
   super.visitReferenceExpression(expression);
   final PsiElement target = expression.resolve();
   if (!parameter.equals(target)) {
     if (target instanceof PsiLocalVariable) {
       final PsiLocalVariable variable = (PsiLocalVariable) target;
       final Query<PsiReference> query =
           ReferencesSearch.search(variable, variable.getUseScope(), false);
       query.forEach(
           reference -> {
             final PsiElement element = reference.getElement();
             final PsiElement parent =
                 PsiTreeUtil.skipParentsOfType(element, PsiParenthesizedExpression.class);
             if (!(parent instanceof PsiReferenceExpression)) {
               return true;
             }
             final PsiElement grandParent = parent.getParent();
             if (!(grandParent instanceof PsiMethodCallExpression)) {
               return true;
             }
             final PsiMethodCallExpression methodCallExpression =
                 (PsiMethodCallExpression) grandParent;
             final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
             final PsiExpression[] arguments = argumentList.getExpressions();
             for (PsiExpression argument : arguments) {
               argument.accept(ReferenceFinder.this);
             }
             return true;
           });
       final PsiExpression initializer = variable.getInitializer();
       if (initializer != null) {
         initializer.accept(this);
       }
     }
     return;
   }
   if (ignoreGetMessage) {
     argumentsContainCatchParameter = true;
   } else {
     final PsiElement parent = expression.getParent();
     if (parent instanceof PsiReferenceExpression) {
       final PsiElement grandParent = parent.getParent();
       if (grandParent instanceof PsiMethodCallExpression) {
         return;
       }
     }
     argumentsContainCatchParameter = true;
   }
 }
    private static boolean hasDirectoriesInScope(
        Query<VirtualFile> dirs, final GlobalSearchScope scope) {
      CommonProcessors.FindProcessor<VirtualFile> findProcessor =
          new CommonProcessors.FindProcessor<VirtualFile>() {
            @Override
            protected boolean accept(VirtualFile file) {
              return scope.accept(file);
            }
          };

      dirs.forEach(findProcessor);
      return findProcessor.isFound();
    }
  public static void processSubTypes(
      PsiType psiType,
      final PsiElement context,
      boolean getRawSubtypes,
      @NotNull final PrefixMatcher matcher,
      Consumer<PsiType> consumer) {
    int arrayDim = psiType.getArrayDimensions();

    psiType = psiType.getDeepComponentType();
    if (!(psiType instanceof PsiClassType)) return;

    final Condition<String> shortNameCondition =
        new Condition<String>() {
          @Override
          public boolean value(String s) {
            return matcher.prefixMatches(s);
          }
        };

    final PsiClassType baseType = (PsiClassType) psiType;
    final PsiClassType.ClassResolveResult baseResult =
        ApplicationManager.getApplication()
            .runReadAction(
                new Computable<PsiClassType.ClassResolveResult>() {
                  @Override
                  public PsiClassType.ClassResolveResult compute() {
                    return JavaCompletionUtil.originalize(baseType).resolveGenerics();
                  }
                });
    final PsiClass baseClass = baseResult.getElement();
    final PsiSubstitutor baseSubstitutor = baseResult.getSubstitutor();
    if (baseClass == null) return;

    final GlobalSearchScope scope =
        ApplicationManager.getApplication()
            .runReadAction(
                new Computable<GlobalSearchScope>() {
                  @Override
                  public GlobalSearchScope compute() {
                    return context.getResolveScope();
                  }
                });

    final Processor<PsiClass> inheritorsProcessor =
        createInheritorsProcessor(
            context, baseType, arrayDim, getRawSubtypes, consumer, baseClass, baseSubstitutor);
    if (matcher.getPrefix().length() > 2) {
      AllClassesGetter.processJavaClasses(
          matcher,
          context.getProject(),
          scope,
          new Processor<PsiClass>() {
            @Override
            public boolean process(PsiClass psiClass) {
              if (psiClass.isInheritor(baseClass, true)) {
                return inheritorsProcessor.process(psiClass);
              }
              return true;
            }
          });
    } else {
      final Query<PsiClass> baseQuery =
          ClassInheritorsSearch.search(
              new ClassInheritorsSearch.SearchParameters(
                  baseClass, scope, true, false, false, shortNameCondition));
      final Query<PsiClass> query =
          new FilteredQuery<PsiClass>(
              baseQuery,
              new Condition<PsiClass>() {
                @Override
                public boolean value(final PsiClass psiClass) {
                  return !(psiClass instanceof PsiTypeParameter);
                }
              });
      query.forEach(inheritorsProcessor);
    }
  }
 public void runQuery() {
   query.forEach(processor);
 }