ruff/crates
Dan Parizher 1ade9a5943
[pydoclint] Fix false positive on explicit exception re-raising (DOC501, DOC502) (#21011)
## Summary
Fixes #20973 (`docstring-extraneous-exception`) false positive when
exceptions mentioned in docstrings are caught and explicitly re-raised
using `raise e` or `raise e from None`.

## Problem Analysis
The DOC502 rule was incorrectly flagging exceptions mentioned in
docstrings as "not explicitly raised" when they were actually being
explicitly re-raised through exception variables bound in `except`
clauses.

**Root Cause**: The `BodyVisitor` in `check_docstring.rs` only checked
for direct exception references (like `raise OSError()`) but didn't
recognize when a variable bound to an exception in an `except` clause
was being re-raised.

**Example of the bug**:
```python
def f():
    """Do nothing.

    Raises
    ------
    OSError
        If the OS errors.
    """
    try:
        pass
    except OSError as e:
        raise e  # This was incorrectly flagged as not explicitly raising OSError
```

The issue occurred because `resolve_qualified_name(e)` couldn't resolve
the variable `e` to a qualified exception name, since `e` is just a
variable binding, not a direct reference to an exception class.

## Approach
Modified the `BodyVisitor` in
`crates/ruff_linter/src/rules/pydoclint/rules/check_docstring.rs` to:

1. **Track exception variable bindings**: Added `exception_variables`
field to map exception variable names to their exception types within
`except` clauses
2. **Enhanced raise statement detection**: Updated `visit_stmt` to check
if a `raise` statement uses a variable name that's bound to an exception
in the current `except` clause
3. **Proper scope management**: Clear exception variable mappings when
leaving `except` handlers to prevent cross-contamination

**Key changes**:
- Added `exception_variables: FxHashMap<&'a str, QualifiedName<'a>>` to
track variable-to-exception mappings
- Enhanced `visit_except_handler` to store exception variable bindings
when entering `except` clauses
- Modified `visit_stmt` to check for variable-based re-raising: `raise
e` → lookup `e` in `exception_variables`
- Clear mappings when exiting `except` handlers to maintain proper scope

---------

Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-10-24 16:54:09 -04:00
..
ruff Bump 0.14.2 (#21051) 2025-10-23 15:17:22 -04:00
ruff_annotate_snippets Display diffs for ruff format --check and add support for different output formats (#20443) 2025-09-30 12:00:51 -04:00
ruff_benchmark [ty] Infer type for implicit self parameters in method bodies (#20922) 2025-10-23 09:34:39 +02:00
ruff_cache
ruff_db Standardize syntax error construction (#20903) 2025-10-16 11:56:32 -04:00
ruff_dev Document when a rule was added (#21035) 2025-10-23 14:48:41 -04:00
ruff_diagnostics
ruff_formatter Display diffs for ruff format --check and add support for different output formats (#20443) 2025-09-30 12:00:51 -04:00
ruff_graph [ty] Limit shown import paths to at most 5 unless ty runs with -v (#20912) 2025-10-16 13:18:09 +02:00
ruff_index
ruff_linter [pydoclint] Fix false positive on explicit exception re-raising (DOC501, DOC502) (#21011) 2025-10-24 16:54:09 -04:00
ruff_macros Document when a rule was added (#21035) 2025-10-23 14:48:41 -04:00
ruff_memory_usage [ty] Clean up inherited generic contexts (#20647) 2025-10-03 13:55:43 -04:00
ruff_notebook Display diffs for ruff format --check and add support for different output formats (#20443) 2025-09-30 12:00:51 -04:00
ruff_options_metadata
ruff_python_ast [ruff] Autogenerate TypeParam nodes (#21028) 2025-10-22 14:06:24 +02:00
ruff_python_ast_integration_tests
ruff_python_codegen Configurable "unparse mode" for ruff_python_codegen::Generator (#21041) 2025-10-24 15:44:48 +00:00
ruff_python_formatter Render a diagnostic for syntax errors introduced in formatter tests (#21021) 2025-10-21 13:47:26 -04:00
ruff_python_importer [ruff] Add API for splicing into an existing import statement 2025-09-17 13:59:28 -04:00
ruff_python_index
ruff_python_literal
ruff_python_parser [ruff] Autogenerate TypeParam nodes (#21028) 2025-10-22 14:06:24 +02:00
ruff_python_semantic [flake8-pyi] Fix PYI034 to not trigger on metaclasses (PYI034) (#20881) 2025-10-24 13:40:26 +00:00
ruff_python_stdlib [ruff] Extend FA102 with listed PEP 585-compatible APIs (#20659) 2025-10-03 09:45:32 -04:00
ruff_python_trivia Handle t-string prefixes in SimpleTokenizer (#20578) 2025-09-25 14:33:37 -05:00
ruff_python_trivia_integration_tests Handle t-string prefixes in SimpleTokenizer (#20578) 2025-09-25 14:33:37 -05:00
ruff_server Use Annotation::tags instead of hardcoded rule matching in ruff server (#20565) 2025-09-26 09:06:26 +02:00
ruff_source_file
ruff_text_size [ruff] Update schemars to v1 (#20942) 2025-10-20 08:59:52 +02:00
ruff_wasm Bump 0.14.2 (#21051) 2025-10-23 15:17:22 -04:00
ruff_workspace [ruff] Update schemars to v1 (#20942) 2025-10-20 08:59:52 +02:00
ty [ty] Add --no-progress option (#21063) 2025-10-24 18:00:00 +02:00
ty_combine
ty_completion_eval [ty] Consider type_check_only when ranking completions (#20910) 2025-10-23 15:09:13 +01:00
ty_ide [ty] Consider __len__ when determining the truthiness of an instance of a tuple class or a @final class (#21049) 2025-10-24 09:29:55 +00:00
ty_project [ruff] Update schemars to v1 (#20942) 2025-10-20 08:59:52 +02:00
ty_python_semantic [ty] Use constructor parameter types as type context (#21054) 2025-10-24 20:14:18 +00:00
ty_server [ty] Timeout based workspace diagnostic progress reports (#21019) 2025-10-24 09:06:19 +02:00
ty_static [ty] improve base conda distinction from child conda (#20675) 2025-10-03 13:56:06 +00:00
ty_test [ty] Fix rare panic with highly cyclic TypeVar definitions (#21059) 2025-10-24 18:30:54 +02:00
ty_vendored [ty] Consider domain of BDD when checking whether always satisfiable (#21050) 2025-10-24 13:37:56 -04:00
ty_wasm [ruff,ty] Enable tracing's log feature 2025-10-03 08:18:03 -04:00