Skip to content

Conversation

@danparizher
Copy link
Contributor

Summary

Fixes FURB105 (print-empty-string) to detect empty f-strings in addition to regular empty strings. Previously, the rule only flagged print("") but missed print(f""). This fix ensures both cases are detected and can be automatically fixed.

Fixes #21346

Problem Analysis

The FURB105 rule checks for unnecessary empty strings passed to print() calls. The is_empty_string helper function was only checking for Expr::StringLiteral with empty values, but did not handle Expr::FString (f-strings). As a result, print(f"") was not being flagged as a violation, even though it's semantically equivalent to print("") and should be simplified to print().

The issue occurred because the function used a matches! macro that only checked for string literals:

fn is_empty_string(expr: &Expr) -> bool {
    matches!(
        expr,
        Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) if value.is_empty()
    )
}

Approach

  1. Import the helper function: Added is_empty_f_string to the imports from ruff_python_ast::helpers, which already provides logic to detect empty f-strings.

  2. Update is_empty_string function: Changed the implementation from a matches! macro to a match expression that handles both string literals and f-strings:

    fn is_empty_string(expr: &Expr) -> bool {
        match expr {
            Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => value.is_empty(),
            Expr::FString(f_string) => is_empty_f_string(f_string),
            _ => false,
        }
    }

The fix leverages the existing is_empty_f_string helper function which properly handles the complexity of f-strings, including nested f-strings and interpolated expressions. This ensures the detection is accurate and consistent with how empty strings are detected elsewhere in the codebase.

Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

I'm just going to close and reopen to try to trigger the ecosystem comment.

@ntBre ntBre closed this Nov 10, 2025
@ntBre ntBre reopened this Nov 10, 2025
@ntBre ntBre added the rule Implementing or modifying a lint rule label Nov 10, 2025
@ntBre
Copy link
Contributor

ntBre commented Nov 10, 2025

Still no comment, but I downloaded the artifact:

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@ntBre ntBre merged commit e4dc406 into astral-sh:main Nov 10, 2025
74 checks passed
@danparizher danparizher deleted the fix-21346 branch November 10, 2025 17:51
dcreager added a commit that referenced this pull request Nov 11, 2025
* origin/main: (38 commits)
  [ty] Make implicit submodule imports only occur in global scope (#21370)
  [ty] introduce local variables for `from` imports of submodules in `__init__.py(i)` (#21173)
  [`ruff`] Ignore `str()` when not used for simple conversion (`RUF065`) (#21330)
  [ty] implement `typing.NewType` by adding `Type::NewTypeInstance`
  [ty] supress inlay hints for `+1` and `-1` (#21368)
  [ty] Use type context for inference of generic constructors (#20933)
  [ty] Improve generic call expression inference (#21210)
  [ty] supress some trivial expr inlay hints (#21367)
  [`configuration`] Fix unclear error messages for line-length values exceeding `u16::MAX` (#21329)
  [ty] Fix incorrect inference of `enum.auto()` for enums with non-`int` mixins, and imprecise inference of `enum.auto()` for single-member enums (#20541)
  [`refurb`] Detect empty f-strings (`FURB105`) (#21348)
  [ty] provide `import` completion when in `from <name> <name>` statement (#21291)
  [ty] elide redundant inlay hints for function args (#21365)
  Fix syntax error false positive on alternative `match` patterns (#21362)
  Add a new "Opening a PR" section to the contribution guide (#21298)
  [`flake8-simplify`] Fix SIM222 false positive for `tuple(generator) or None` (`SIM222`) (#21187)
  Rebuild ruff binary instead of sharing it across jobs (#21361)
  [ty] Fix `--exclude` and `src.exclude` merging (#21341)
  [ty] Add support for properties that return `Self` (#21335)
  Add upstream linter URL to `ruff linter --output-format=json` (#21316)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rule Implementing or modifying a lint rule

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FURB105 should detect empty f-strings

2 participants