public void registerCastActions(CandidateInfo @NotNull [] candidates, @NotNull PsiCall call, @NotNull HighlightInfo.Builder highlightInfo, final TextRange fixRange) {
    if (candidates.length == 0) return;
    List<CandidateInfo> methodCandidates = new ArrayList<>(Arrays.asList(candidates));
    PsiExpressionList list = call.getArgumentList();
    if (list == null) return;
    PsiExpression[] expressions = list.getExpressions();
    if (expressions.length == 0) return;
    // filter out not cast-able candidates
    nextMethod:
    for (int i = methodCandidates.size() - 1; i >= 0; i--) {
      CandidateInfo candidate = methodCandidates.get(i);
      PsiMethod method = (PsiMethod) candidate.getElement();
      PsiSubstitutor substitutor = candidate.getSubstitutor();
      PsiParameter[] parameters = method.getParameterList().getParameters();
      if (expressions.length != parameters.length && !method.isVarArgs()) {
        methodCandidates.remove(i);
        continue;
      }
      for (int j = 0; j < Math.min(parameters.length, expressions.length); j++) {
        PsiParameter parameter = parameters[j];
        PsiExpression expression = expressions[j];
        // check if we can cast to this method
        PsiType exprType = expression.getType();
        PsiType parameterType = substitutor.substitute(parameter.getType());
        if (exprType == null
            || parameterType == null
            || !areTypesConvertible(exprType, parameterType, call)) {
          methodCandidates.remove(i);
          continue nextMethod;
        }
      }
    }

    if (methodCandidates.isEmpty()) return;

    try {
      PsiType expectedTypeByParent = PsiTypesUtil.getExpectedTypeByParent(call);
      Map<Integer, Set<String>> suggestedCasts = new HashMap<>();
      // find to which type we can cast this param to get valid method call
      for (CandidateInfo candidate : methodCandidates) {
        PsiMethod method = (PsiMethod)candidate.getElement();
        PsiSubstitutor substitutor = candidate.getSubstitutor();
        PsiParameter[] parameters = method.getParameterList().getParameters();
        Map<Integer, PsiType> potentialCasts = new HashMap<>();
        for (int i = 0; i < expressions.length; i++) {
          PsiExpression expression = expressions[i];
          PsiType exprType = expression.getType();
          PsiType originalParameterType = PsiTypesUtil.getParameterType(parameters, i, true);
          PsiType parameterType = substitutor.substitute(originalParameterType);
          if (!PsiTypesUtil.isDenotableType(parameterType, call)) continue;
          if (suggestedCasts.computeIfAbsent(i, __ -> new HashSet<>()).contains(parameterType.getCanonicalText())) continue;
          if (TypeConversionUtil.isPrimitiveAndNotNull(exprType) && parameterType instanceof PsiClassType) {
            PsiType unboxedParameterType = PsiPrimitiveType.getUnboxedType(parameterType);
            if (unboxedParameterType != null) {
              parameterType = unboxedParameterType;
            }
          }
          // strict compare since even widening cast may help
          if (Comparing.equal(exprType, parameterType)) continue;
          potentialCasts.put(i, parameterType);
        }

        if (!potentialCasts.isEmpty()) {
          PsiCall newCall = call;
          for (Map.Entry<Integer, PsiType> entry : potentialCasts.entrySet()) {
            newCall = replaceWithCast(expressions, newCall, entry, newCall == call);
            if (newCall == null) {
              break;
            }
          }
          if (newCall != null) {
            doCheckNewCall(expectedTypeByParent, newCall, () -> {
              for (Map.Entry<Integer, PsiType> entry : potentialCasts.entrySet()) {
                registerCastIntention(highlightInfo, fixRange, list, suggestedCasts, entry);
              }
              potentialCasts.clear();
            });
          }
          
          for (Map.Entry<Integer, PsiType> entry : potentialCasts.entrySet()) {
            PsiCall callWithSingleCast = replaceWithCast(expressions, call, entry, true);
            if (callWithSingleCast == null) continue;
            doCheckNewCall(expectedTypeByParent, callWithSingleCast, () -> registerCastIntention(highlightInfo, fixRange, list, suggestedCasts, entry));
          }
        }
      }
    }
    catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }
public void registerCastActions(CandidateInfo @NotNull [] candidates, @NotNull PsiCall call, @NotNull HighlightInfo.Builder highlightInfo, final TextRange fixRange)