@Override
  protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PyBinaryExpression element) {
    if (!(context.file() instanceof PyFile)) {
      return null;
    }

    PyBinaryExpression topmostBinaryExpr = getTopmostBinaryExpression(element);

    List<PyElementType> operators = getOperators(topmostBinaryExpr);
    for (PyElementType operator : operators) {
      if (operator != PyTokenTypes.PLUS) {
        return null;
      }
    }

    List<PyExpression> operands = getOperands(topmostBinaryExpr);
    if (operands.isEmpty()) {
      return null;
    }
    LanguageLevel languageLevel = LanguageLevel.forElement(element);
    TypeEvalContext typeEvalContext = TypeEvalContext.codeAnalysis(context.project(), context.file());
    PyType stringType = PyBuiltinCache.getInstance(element).getStringType(languageLevel);
    for (PyExpression operand : operands) {
      if (operand == null) {
        return null;
      }
      if (operand instanceof PyStringLiteralExpression) {
        continue;
      }
      PyType operandType = typeEvalContext.getType(operand);
      boolean isStringReference = operandType != null && PyTypeChecker.match(stringType, operandType, typeEvalContext);
      if (!isStringReference) {
        return null;
      }
    }
    if (languageLevel.isAtLeast(LanguageLevel.PYTHON27)) {
      return Presentation.of(PyPsiBundle.message("INTN.replace.plus.with.str.format"));
    }
    else {
      return Presentation.of(PyPsiBundle.message("INTN.replace.plus.with.format.operator"));
    }
  }
@Override
  protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PyBinaryExpression element)