@NotNull
  private static Map<PsiExpression, String> foldParameters(ExtractMethodProcessor originalProcessor, List<Match> matches) {
    if (matches.isEmpty() || !originalProcessor.getInputVariables().isFoldable()) {
      return Collections.emptyMap();
    }

    // As folded parameters don't work along with extracted parameters we need to apply the finder again to actually fold the parameters
    DuplicatesFinder finder = createDuplicatesFinder(originalProcessor, DuplicatesFinder.MatchType.FOLDED, null);
    if (finder == null) {
      return Collections.emptyMap();
    }
    Map<Match, Match> foldedMatches = new HashMap<>();
    Map<DuplicatesFinder.Parameter, VariableData> parametersToFold = new LinkedHashMap<>();
    for (VariableData data : originalProcessor.getInputVariables().getInputVariables()) {
      parametersToFold.put(new DuplicatesFinder.Parameter(data.variable, data.type, true), data);
    }

    for (Match match : matches) {
      Match foldedMatch = finder.isDuplicate(match.getMatchStart(), false);
      LOG.assertTrue(foldedMatch != null, "folded match should exist");
      LOG.assertTrue(match.getMatchStart() == foldedMatch.getMatchStart() &&
                     match.getMatchEnd() == foldedMatch.getMatchEnd(), "folded match range should be the same");
      foldedMatches.put(match, foldedMatch);

      parametersToFold.keySet().removeIf(parameter -> !canFoldParameter(match, foldedMatch, parameter));
    }
    if (parametersToFold.isEmpty()) {
      return Collections.emptyMap();
    }

    Map<PsiExpression, String> predefinedNames = new HashMap<>();
    for (Match match : matches) {
      Match foldedMatch = foldedMatches.get(match);
      LOG.assertTrue(foldedMatch != null, "folded match");

      for (Map.Entry<DuplicatesFinder.Parameter, VariableData> entry : parametersToFold.entrySet()) {
        DuplicatesFinder.Parameter parameter = entry.getKey();
        VariableData variableData = entry.getValue();
        List<Pair.NonNull<PsiExpression, PsiExpression>> expressionMappings = foldedMatch.getFoldedExpressionMappings(parameter);
        LOG.assertTrue(!ContainerUtil.isEmpty(expressionMappings), "foldedExpressionMappings can't be empty");
        PsiType type = parameter.getType();

        ExtractedParameter extractedParameter = null;
        for (Pair.NonNull<PsiExpression, PsiExpression> expressionMapping : expressionMappings) {
          PsiExpression patternExpression = expressionMapping.getFirst();
          ExtractableExpressionPart patternPart = ExtractableExpressionPart.fromUsage(patternExpression, type);
          if (extractedParameter == null) {
            PsiExpression candidateExpression = expressionMapping.getSecond();
            ExtractableExpressionPart candidatePart = ExtractableExpressionPart.fromUsage(candidateExpression, type);
            extractedParameter = new ExtractedParameter(patternPart, candidatePart, type);
          }
          else {
            extractedParameter.addUsages(patternPart);
          }
          predefinedNames.put(patternExpression, variableData.name);
        }
        LOG.assertTrue(extractedParameter != null, "extractedParameter can't be null");
        match.getExtractedParameters().add(extractedParameter);
      }
    }

    return predefinedNames;
  }
@NotNull
  private static Map<PsiExpression, String> foldParameters(ExtractMethodProcessor originalProcessor, List<Match> matches)