private static void getExpectedInformation(final PsiExpression expression,
                                             List<ExpectedTypeInfo[]> types,
                                             List<? super String> expectedMethodNames,
                                             List<? super String> expectedFieldNames) {
    Comparator<ExpectedTypeInfo> expectedTypesComparator = (o1, o2) -> compareExpectedTypes(o1, o2, expression);
    for (PsiExpression expr : collectExpressions(expression, PsiMember.class, PsiFile.class)) {
      PsiElement parent = PsiUtil.skipParenthesizedExprUp(expr.getParent());

      if (!(parent instanceof PsiReferenceExpression)) {
        boolean isAssignmentToFunctionalExpression = PsiUtil.isOnAssignmentLeftHand(expr) &&
                                                     ((PsiAssignmentExpression)PsiUtil.skipParenthesizedExprUp(parent)).getRExpression() instanceof PsiFunctionalExpression;
        PsiElement gParent = parent.getParent();
        PsiExpressionList expressionList = ObjectUtils
          .tryCast(PsiUtil.skipParenthesizedExprUp(isAssignmentToFunctionalExpression ? gParent : parent), PsiExpressionList.class);
        boolean forCompletion;
        if (expressionList != null) {
          forCompletion = true;
        }
        else if (parent instanceof PsiPolyadicExpression) {
          forCompletion = !(gParent instanceof PsiPolyadicExpression);
        }
        else {
          forCompletion = gParent instanceof PsiPolyadicExpression && !(gParent.getParent() instanceof PsiPolyadicExpression);
        }
        ExpectedTypeInfo[] someExpectedTypes = ExpectedTypesProvider.getExpectedTypes(expr, forCompletion);
        if (someExpectedTypes.length > 0) {
          Comparator<ExpectedTypeInfo> comparator = expectedTypesComparator;
          if (expressionList != null) {
            int argCount = expressionList.getExpressionCount();
            Comparator<ExpectedTypeInfo> mostSuitableMethodComparator =
              Comparator.comparingInt(typeInfo -> typeInfo.getCalledMethod().getParameterList().getParametersCount() == argCount ? 0 : 1);
            comparator = mostSuitableMethodComparator.thenComparing(comparator);
          }
          Arrays.sort(someExpectedTypes, comparator);
          types.add(someExpectedTypes);
        }
        continue;
      }

      String refName = ((PsiReferenceExpression)parent).getReferenceName();
      if (refName == null) {
        continue;
      }

      PsiElement pparent = PsiUtil.skipParenthesizedExprUp(parent.getParent());
      if (pparent instanceof PsiMethodCallExpression) {
        expectedMethodNames.add(refName);
        if (refName.equals("equals")) {
          ExpectedTypeInfo[] someExpectedTypes = equalsExpectedTypes((PsiMethodCallExpression)pparent);
          if (someExpectedTypes.length > 0) {
            Arrays.sort(someExpectedTypes, expectedTypesComparator);
            types.add(someExpectedTypes);
          }
        }
        continue;
      }

      if (pparent instanceof PsiVariable ||
          pparent instanceof PsiExpression) {
        expectedFieldNames.add(refName);
      }
    }
  }
private static void getExpectedInformation(final PsiExpression expression,
                                             List<ExpectedTypeInfo[]> types,
                                             List<? super String> expectedMethodNames,
                                             List<? super String> expectedFieldNames)