@Nullable
 private static PsiClass getFieldOrMethodAccessedClass(
     PsiReferenceExpression ref, PsiClass fieldOrMethodClass) {
   PsiElement[] children = ref.getChildren();
   if (children.length > 1 && children[0] instanceof PsiExpression) {
     PsiExpression expr = (PsiExpression) children[0];
     PsiType type = expr.getType();
     if (type != null) {
       if (!(type instanceof PsiClassType)) return null;
       return PsiUtil.resolveClassInType(type);
     } else {
       if (expr instanceof PsiReferenceExpression) {
         PsiElement refElement = ((PsiReferenceExpression) expr).resolve();
         if (refElement instanceof PsiClass) return (PsiClass) refElement;
       }
       return null;
     }
   }
   PsiManager manager = ref.getManager();
   for (PsiElement parent = ref; parent != null; parent = parent.getParent()) {
     if (parent instanceof PsiClass
         && (manager.areElementsEquivalent(parent, fieldOrMethodClass)
             || ((PsiClass) parent).isInheritor(fieldOrMethodClass, true))) {
       return (PsiClass) parent;
     }
   }
   return null;
 }
 private static void addFieldsUsages(
     final PsiClass aClass,
     final Processor<UsageInfo> results,
     final JavaClassFindUsagesOptions options) {
   if (options.isIncludeInherited) {
     final PsiManager manager = aClass.getManager();
     PsiField[] fields = aClass.getAllFields();
     FieldsLoop:
     for (int i = 0; i < fields.length; i++) {
       final PsiField field = fields[i];
       // filter hidden fields
       for (int j = 0; j < i; j++) {
         if (Comparing.strEqual(field.getName(), fields[j].getName())) continue FieldsLoop;
       }
       final PsiClass fieldClass = field.getContainingClass();
       if (manager.areElementsEquivalent(fieldClass, aClass)) {
         addElementUsages(fields[i], results, options);
       } else {
         ReferencesSearch.search(
                 new ReferencesSearch.SearchParameters(
                     field, options.searchScope, false, options.fastTrack))
             .forEach(
                 new ReadActionProcessor<PsiReference>() {
                   @Override
                   public boolean processInReadAction(final PsiReference reference) {
                     addResultFromReference(
                         reference, fieldClass, manager, aClass, results, options);
                     return true;
                   }
                 });
       }
     }
   } else {
     PsiField[] fields =
         ApplicationManager.getApplication()
             .runReadAction(
                 new Computable<PsiField[]>() {
                   @Override
                   public PsiField[] compute() {
                     return aClass.getFields();
                   }
                 });
     for (PsiField field : fields) {
       addElementUsages(field, results, options);
     }
   }
 }
 private static void addResultFromReference(
     final PsiReference reference,
     final PsiClass methodClass,
     final PsiManager manager,
     final PsiClass aClass,
     final Processor<UsageInfo> results,
     final FindUsagesOptions options) {
   PsiElement refElement = reference.getElement();
   if (refElement instanceof PsiReferenceExpression) {
     PsiClass usedClass =
         getFieldOrMethodAccessedClass((PsiReferenceExpression) refElement, methodClass);
     if (usedClass != null) {
       if (manager.areElementsEquivalent(usedClass, aClass)
           || usedClass.isInheritor(aClass, true)) {
         addResult(results, refElement, options);
       }
     }
   }
 }
 private static void addMethodsUsages(
     final PsiClass aClass,
     final Processor<UsageInfo> results,
     final JavaClassFindUsagesOptions options) {
   if (options.isIncludeInherited) {
     final PsiManager manager = aClass.getManager();
     PsiMethod[] methods = aClass.getAllMethods();
     MethodsLoop:
     for (int i = 0; i < methods.length; i++) {
       final PsiMethod method = methods[i];
       // filter overriden methods
       MethodSignature methodSignature = method.getSignature(PsiSubstitutor.EMPTY);
       for (int j = 0; j < i; j++) {
         if (methodSignature.equals(methods[j].getSignature(PsiSubstitutor.EMPTY)))
           continue MethodsLoop;
       }
       final PsiClass methodClass = method.getContainingClass();
       if (methodClass != null && manager.areElementsEquivalent(methodClass, aClass)) {
         addElementUsages(methods[i], results, options);
       } else {
         MethodReferencesSearch.search(
                 new MethodReferencesSearch.SearchParameters(
                     method, options.searchScope, true, options.fastTrack))
             .forEach(
                 new PsiReferenceProcessorAdapter(
                     new PsiReferenceProcessor() {
                       @Override
                       public boolean execute(PsiReference reference) {
                         addResultFromReference(
                             reference, methodClass, manager, aClass, results, options);
                         return true;
                       }
                     }));
       }
     }
   } else {
     for (PsiMethod method : aClass.getMethods()) {
       addElementUsages(method, results, options);
     }
   }
 }