public static void setupAndRunProcessor(@NotNull MethodsProcessor processor,
                                          @NotNull PsiCallExpression call,
                                          boolean dummyImplicitConstructor)
  throws MethodProcessorSetupFailedException {
    if (call instanceof PsiMethodCallExpression) {
      final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)call;
      final PsiJavaCodeReferenceElement ref = methodCall.getMethodExpression();


      processor.setArgumentList(methodCall.getArgumentList());
      processor.obtainTypeArguments(methodCall);
      if (!ref.isQualified() || ref.getReferenceNameElement() instanceof PsiKeyword) {
        final PsiElement referenceNameElement = ref.getReferenceNameElement();
        if (referenceNameElement == null) return;
        if (referenceNameElement instanceof PsiKeyword) {
          final PsiKeyword keyword = (PsiKeyword)referenceNameElement;

          if (keyword.getTokenType() == JavaTokenType.THIS_KEYWORD) {
            final PsiClass aClass = JavaResolveUtil.getContextClass(methodCall);
            if (aClass == null) {
              throw new MethodProcessorSetupFailedException("Can't resolve class for this expression");
            }

            processor.setIsConstructor(true);
            processor.setAccessClass(aClass);
            aClass.processDeclarations(processor, ResolveState.initial(), null, call);

            if (dummyImplicitConstructor) {
              processDummyConstructor(processor, aClass);
            }
          }
          else if (keyword.getTokenType() == JavaTokenType.SUPER_KEYWORD) {
            PsiClass aClass = JavaResolveUtil.getContextClass(methodCall);
            if (aClass == null) {
              throw new MethodProcessorSetupFailedException("Can't resolve class for super expression");
            }

            JvmReferenceType type = aClass.getSuperClassType();
            final PsiClass superClass = type == null ? null : ObjectUtils.tryCast(type.resolve(), PsiClass.class);
            if (superClass != null) {
              PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
              PsiClass runSuper = superClass;
              List<PsiSubstitutor> contextSubstitutors = new ArrayList<>();
              do {
                if (runSuper != null) {
                  PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(runSuper, aClass, PsiSubstitutor.EMPTY);
                  contextSubstitutors.add(superSubstitutor);
                }
                if (aClass.hasModifierProperty(PsiModifier.STATIC)) break;
                aClass = JavaResolveUtil.getContextClass(aClass);
                if (aClass != null) runSuper = aClass.getSuperClass();
              }
              while (aClass != null);
              //apply substitutors in 'outer classes down to inner classes' order because inner class subst take precedence
              for (int i = contextSubstitutors.size() - 1; i >= 0; i--) {
                PsiSubstitutor contextSubstitutor = contextSubstitutors.get(i);
                substitutor = substitutor.putAll(contextSubstitutor);
              }

              processor.setIsConstructor(true);
              processor.setAccessClass(null);
              final PsiMethod[] constructors = superClass.getConstructors();
              ResolveState state = ResolveState.initial().put(PsiSubstitutor.KEY, substitutor);
              for (PsiMethod constructor : constructors) {
                if (!processor.execute(constructor, state)) return;
              }

              if (dummyImplicitConstructor) processDummyConstructor(processor, superClass);
            }
          }
          else {
            LOG.error("Unknown name element " + referenceNameElement + " in reference " + ref.getText() + "(" + ref + ")");
          }
        }
        else if (referenceNameElement instanceof PsiIdentifier) {
          processor.setIsConstructor(false);
          processor.setName(referenceNameElement.getText());
          processor.setAccessClass(null);
          resolveAndWalk(processor, ref, null);
        }
        else {
          LOG.error("Unknown name element " + referenceNameElement + " in reference " + ref.getText() + "(" + ref + ")");
        }
      }
      else {
        // Complex expression
        final PsiElement referenceName = methodCall.getMethodExpression().getReferenceNameElement();
        final PsiManager manager = call.getManager();
        final PsiElement qualifier = ref.getQualifier();
        if (referenceName == null) {
          // e.g. "manager.(beginTransaction)"
          throw new MethodProcessorSetupFailedException("Can't resolve method name for this expression");
        }
        if (referenceName instanceof PsiIdentifier && qualifier instanceof PsiExpression) {
          PsiType type = ((PsiExpression)qualifier).getType();
          if (type != null && qualifier instanceof PsiReferenceExpression) {
            final PsiElement resolve = ((PsiReferenceExpression)qualifier).resolve();
            if (resolve instanceof PsiEnumConstant) {
              final PsiEnumConstantInitializer initializingClass = ((PsiEnumConstant)resolve).getInitializingClass();
              if (initializingClass != null && getOverridingMethod(initializingClass, methodCall.getMethodExpression().getReferenceName()) != null) {
                processQualifierResult(new ClassCandidateInfo(initializingClass, PsiSubstitutor.EMPTY), processor, methodCall);
                return;
              }
            }
          }
          if (type == null) {
            if (qualifier instanceof PsiJavaCodeReferenceElement) {
              final JavaResolveResult result = ((PsiJavaCodeReferenceElement)qualifier).advancedResolve(false);
              if (result.getElement() instanceof PsiClass) {
                processor.handleEvent(JavaScopeProcessorEvent.START_STATIC, null);
                processQualifierResult(result, processor, methodCall);
              }
            }
            else {
              throw new MethodProcessorSetupFailedException("Cant determine qualifier type!");
            }
          }
          else if (type instanceof PsiDisjunctionType) {
            processQualifierType(((PsiDisjunctionType)type).getLeastUpperBound(), processor, manager, methodCall);
          }
          else if (type instanceof PsiCapturedWildcardType) {
            final PsiType psiType = convertToTypeParameter((PsiCapturedWildcardType)type, methodCall);
            if (psiType != null) {
              processQualifierType(psiType, processor, manager, methodCall);
            }
          }
          else {
            processQualifierType(type, processor, manager, methodCall);
          }
        }
        else {
          LOG.error("ref: " + ref + " (" + ref.getClass() + ")," +
                    " ref.getReferenceNameElement()=" + ref.getReferenceNameElement() +
                    "; methodCall.getMethodExpression().getReferenceNameElement()=" + methodCall.getMethodExpression().getReferenceNameElement() +
                    "; qualifier="+qualifier);
        }
      }
    }
    else {
      LOG.assertTrue(call instanceof PsiNewExpression);
      PsiNewExpression newExpr = (PsiNewExpression)call;
      PsiJavaCodeReferenceElement classRef = newExpr.getClassOrAnonymousClassReference();
      if (classRef == null) {
        throw new MethodProcessorSetupFailedException("Cant get reference to class in new expression");
      }

      final JavaResolveResult result = classRef.advancedResolve(false);
      PsiClass aClass = (PsiClass)result.getElement();
      if (aClass == null) {
        throw new MethodProcessorSetupFailedException("Cant resolve class in new expression");
      }
      processor.setIsConstructor(true);
      processor.setAccessClass(aClass);
      processor.setArgumentList(newExpr.getArgumentList());
      processor.obtainTypeArguments(newExpr);
      aClass.processDeclarations(processor, ResolveState.initial().put(PsiSubstitutor.KEY, result.getSubstitutor()), null, call);

      if (dummyImplicitConstructor) {
        processDummyConstructor(processor, aClass);
      }
    }
  }
public static void setupAndRunProcessor(@NotNull MethodsProcessor processor,
                                          @NotNull PsiCallExpression call,
                                          boolean dummyImplicitConstructor)