Skip to content

Commit c2c96bc

Browse files
committed
Use the function in ruff_python_semantic
1 parent f452453 commit c2c96bc

File tree

2 files changed

+15
-41
lines changed
  • crates/ruff_linter

2 files changed

+15
-41
lines changed

crates/ruff_linter/resources/test/fixtures/flake8_return/RET501.py

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ def prop(self) -> None:
1919
return None
2020

2121

22-
import abc
23-
import enum
24-
import types
2522
from functools import cached_property
2623

2724

@@ -30,18 +27,3 @@ class BaseCache2:
3027
def prop(self) -> None:
3128
print("Property not found")
3229
return None
33-
34-
@abc.abstractproperty
35-
def prop2(self) -> None:
36-
print("Override me")
37-
return None
38-
39-
@types.DynamicClassAttribute
40-
def prop3(self) -> None:
41-
print("Gotta make this a multiline function for it to be a meaningful test")
42-
return None
43-
44-
@enum.property
45-
def prop4(self) -> None:
46-
print("I've run out of things to say")
47-
return None

crates/ruff_linter/src/rules/flake8_return/rules/function.rs

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ use ruff_diagnostics::{AlwaysFixableViolation, FixAvailability, Violation};
66
use ruff_diagnostics::{Diagnostic, Edit, Fix};
77
use ruff_macros::{derive_message_formats, violation};
88
use ruff_python_ast::helpers::{is_const_false, is_const_true};
9+
use ruff_python_ast::name::QualifiedName;
910
use ruff_python_ast::stmt_if::elif_else_range;
1011
use ruff_python_ast::visitor::Visitor;
1112
use ruff_python_ast::whitespace::indentation;
1213
use ruff_python_ast::{self as ast, Decorator, ElifElseClause, Expr, Stmt};
1314
use ruff_python_codegen::Stylist;
1415
use ruff_python_index::Indexer;
16+
use ruff_python_semantic::analyze::visibility::is_property;
1517
use ruff_python_semantic::SemanticModel;
1618
use ruff_python_trivia::{is_python_whitespace, SimpleTokenKind, SimpleTokenizer};
1719
use ruff_source_file::Locator;
@@ -373,11 +375,20 @@ fn unnecessary_return_none(checker: &mut Checker, decorator_list: &[Decorator],
373375
continue;
374376
}
375377

376-
// Skip properties and other stdlib property-like decorators.
377-
if decorator_list
378+
let extra_property_decorators = checker
379+
.settings
380+
.pydocstyle
381+
.property_decorators
378382
.iter()
379-
.any(|decorator| is_property_like_decorator(decorator, checker.semantic()))
380-
{
383+
.map(|decorator| QualifiedName::from_dotted_name(decorator))
384+
.collect::<Vec<QualifiedName>>();
385+
386+
// Skip property functions
387+
if is_property(
388+
decorator_list,
389+
&extra_property_decorators,
390+
checker.semantic(),
391+
) {
381392
return;
382393
}
383394

@@ -390,25 +401,6 @@ fn unnecessary_return_none(checker: &mut Checker, decorator_list: &[Decorator],
390401
}
391402
}
392403

393-
/// Determine whether `decorator` is `@property`,
394-
/// or another stdlib decorator similar to `@property`.
395-
///
396-
/// TODO: be more principled here once we have type inference;
397-
/// hardcoding these is a little hacky.
398-
fn is_property_like_decorator(decorator: &Decorator, semantic: &SemanticModel) -> bool {
399-
semantic
400-
.resolve_qualified_name(&decorator.expression)
401-
.is_some_and(|qualified_name| {
402-
matches!(
403-
qualified_name.segments(),
404-
["" | "builtins" | "enum", "property"]
405-
| ["functools", "cached_property"]
406-
| ["abc", "abstractproperty"]
407-
| ["types", "DynamicClassAttribute"]
408-
)
409-
})
410-
}
411-
412404
/// RET502
413405
fn implicit_return_value(checker: &mut Checker, stack: &Stack) {
414406
for stmt in &stack.returns {

0 commit comments

Comments
 (0)