@Override
  public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
                                                 boolean isOnTheFly) {
    return new JavaElementVisitor() {
      @Override
      public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
        if (!STRING_REPLACE.test(call)) return;
        PsiLiteralExpression qualifier = tryCast(
          PsiUtil.skipParenthesizedExprDown(call.getMethodExpression().getQualifierExpression()), PsiLiteralExpression.class);
        if (qualifier == null || qualifier.getTextLength() > MAX_QUALIFIER_LENGTH) return;
        String str = tryCast(qualifier.getValue(), String.class);
        if (str == null) return;
        PsiExpression pattern = PsiUtil.skipParenthesizedExprDown(call.getArgumentList().getExpressions()[0]);
        String name = call.getMethodExpression().getReferenceName();
        if (!isRedundant(str, pattern, "replace".equals(name))) return;
        PsiElement refName = Objects.requireNonNull(call.getMethodExpression().getReferenceNameElement());
        holder.registerProblem(call, InspectionGadgetsBundle.message("inspection.replace.on.literal.display.name"),
                               ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
                               TextRange.create(refName.getTextRangeInParent().getStartOffset(), call.getTextLength()),
                               ExpressionUtils.isVoidContext(call) ? LocalQuickFix.EMPTY_ARRAY : new LocalQuickFix[]{new ReplaceOnLiteralWithQualifierFix()});
      }

      private boolean isRedundant(@NotNull String str, PsiExpression pattern, boolean literalMatch) {
        Object constValue = ExpressionUtils.computeConstantExpression(pattern);
        if (constValue != null) {
          return isRedundantLiteralMatch(str, constValue, literalMatch);
        }
        if (literalMatch && pattern instanceof PsiPolyadicExpression &&
            ((PsiPolyadicExpression)pattern).getOperationTokenType().equals(JavaTokenType.PLUS)) {
          PsiExpression[] operands = ((PsiPolyadicExpression)pattern).getOperands();
          boolean stringType = false;
          for (int i = 0; i < operands.length; i++) {
            PsiExpression operand = operands[i];
            stringType = stringType || TypeUtils.isJavaLangString(operand.getType());
            if (!stringType && (i > 0 || !TypeUtils.isJavaLangString(operands[1].getType()))) continue;
            constValue = ExpressionUtils.computeConstantExpression(operand);
            if (constValue == null) continue;
            if (isRedundantLiteralMatch(str, constValue, true)) return true;
          }
        }
        return false;
      }

      private static boolean isRedundantLiteralMatch(@NotNull String str, Object value, boolean literalMatch) {
        String patternValue;
        if (value instanceof String) {
          patternValue = (String)value;
        } else if (value instanceof Character) {
          patternValue = value.toString();
        } else {
          return false;
        }
        if (literalMatch) return !str.contains(patternValue);
        if (patternValue.length() > MAX_PATTERN_LENGTH) return false;
        Pattern regex;
        try {
          regex = Pattern.compile(patternValue);
        }
        catch (PatternSyntaxException e) {
          return false;
        }
        return !regex.matcher(str).find();
      }
    };
  }
@Override
  public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
                                                 boolean isOnTheFly)