mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 14:21:53 +00:00
Implement D410 (EmptyDocstring) (#395)
This commit is contained in:
parent
323a5c857c
commit
71d3a84b14
6 changed files with 95 additions and 4 deletions
13
resources/test/fixtures/D419.py
vendored
Normal file
13
resources/test/fixtures/D419.py
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
""""""
|
||||||
|
|
||||||
|
|
||||||
|
def f1() -> None:
|
||||||
|
""""""
|
||||||
|
|
||||||
|
|
||||||
|
def f2() -> None:
|
||||||
|
""
|
||||||
|
|
||||||
|
|
||||||
|
def f3() -> None:
|
||||||
|
"""Hello, world!"""
|
|
@ -1888,6 +1888,12 @@ impl<'a> Checker<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_docstrings(&mut self) {
|
||||||
|
while let Some(docstring) = self.docstrings.pop() {
|
||||||
|
docstrings::docstring_empty(self, &docstring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check_builtin_shadowing(&mut self, name: &str, location: Range, is_attribute: bool) {
|
fn check_builtin_shadowing(&mut self, name: &str, location: Range, is_attribute: bool) {
|
||||||
let scope = self.current_scope();
|
let scope = self.current_scope();
|
||||||
|
|
||||||
|
@ -1955,5 +1961,8 @@ pub fn check_ast(
|
||||||
checker.pop_scope();
|
checker.pop_scope();
|
||||||
checker.check_dead_scopes();
|
checker.check_dead_scopes();
|
||||||
|
|
||||||
|
// Check docstrings.
|
||||||
|
checker.check_docstrings();
|
||||||
|
|
||||||
checker.checks
|
checker.checks
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,6 +150,8 @@ pub enum CheckCode {
|
||||||
U006,
|
U006,
|
||||||
U007,
|
U007,
|
||||||
U008,
|
U008,
|
||||||
|
// pydocstyle
|
||||||
|
D419,
|
||||||
// Meta
|
// Meta
|
||||||
M001,
|
M001,
|
||||||
}
|
}
|
||||||
|
@ -246,6 +248,8 @@ pub enum CheckKind {
|
||||||
UsePEP585Annotation(String),
|
UsePEP585Annotation(String),
|
||||||
UsePEP604Annotation,
|
UsePEP604Annotation,
|
||||||
SuperCallWithParameters,
|
SuperCallWithParameters,
|
||||||
|
// pydocstyle
|
||||||
|
EmptyDocstring,
|
||||||
// Meta
|
// Meta
|
||||||
UnusedNOQA(Option<Vec<String>>),
|
UnusedNOQA(Option<Vec<String>>),
|
||||||
}
|
}
|
||||||
|
@ -354,6 +358,8 @@ impl CheckCode {
|
||||||
CheckCode::U006 => CheckKind::UsePEP585Annotation("List".to_string()),
|
CheckCode::U006 => CheckKind::UsePEP585Annotation("List".to_string()),
|
||||||
CheckCode::U007 => CheckKind::UsePEP604Annotation,
|
CheckCode::U007 => CheckKind::UsePEP604Annotation,
|
||||||
CheckCode::U008 => CheckKind::SuperCallWithParameters,
|
CheckCode::U008 => CheckKind::SuperCallWithParameters,
|
||||||
|
// pydocstyle
|
||||||
|
CheckCode::D419 => CheckKind::EmptyDocstring,
|
||||||
// Meta
|
// Meta
|
||||||
CheckCode::M001 => CheckKind::UnusedNOQA(None),
|
CheckCode::M001 => CheckKind::UnusedNOQA(None),
|
||||||
}
|
}
|
||||||
|
@ -441,6 +447,8 @@ impl CheckKind {
|
||||||
CheckKind::UsePEP604Annotation => &CheckCode::U007,
|
CheckKind::UsePEP604Annotation => &CheckCode::U007,
|
||||||
CheckKind::UselessObjectInheritance(_) => &CheckCode::U004,
|
CheckKind::UselessObjectInheritance(_) => &CheckCode::U004,
|
||||||
CheckKind::SuperCallWithParameters => &CheckCode::U008,
|
CheckKind::SuperCallWithParameters => &CheckCode::U008,
|
||||||
|
// pydocstyle
|
||||||
|
CheckKind::EmptyDocstring => &CheckCode::D419,
|
||||||
// Meta
|
// Meta
|
||||||
CheckKind::UnusedNOQA(_) => &CheckCode::M001,
|
CheckKind::UnusedNOQA(_) => &CheckCode::M001,
|
||||||
}
|
}
|
||||||
|
@ -684,6 +692,8 @@ impl CheckKind {
|
||||||
CheckKind::SuperCallWithParameters => {
|
CheckKind::SuperCallWithParameters => {
|
||||||
"Use `super()` instead of `super(__class__, self)`".to_string()
|
"Use `super()` instead of `super(__class__, self)`".to_string()
|
||||||
}
|
}
|
||||||
|
// pydocstyle
|
||||||
|
CheckKind::EmptyDocstring => "Docstring is empty".to_string(),
|
||||||
// Meta
|
// Meta
|
||||||
CheckKind::UnusedNOQA(codes) => match codes {
|
CheckKind::UnusedNOQA(codes) => match codes {
|
||||||
None => "Unused `noqa` directive".to_string(),
|
None => "Unused `noqa` directive".to_string(),
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
use crate::ast::types::Range;
|
||||||
use crate::check_ast::Checker;
|
use crate::check_ast::Checker;
|
||||||
use rustpython_ast::{Expr, Stmt, StmtKind};
|
use crate::checks::{Check, CheckKind};
|
||||||
|
use rustpython_ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum DocstringKind {
|
pub enum DocstringKind {
|
||||||
|
@ -12,7 +14,7 @@ pub enum DocstringKind {
|
||||||
pub struct Docstring<'a> {
|
pub struct Docstring<'a> {
|
||||||
pub kind: DocstringKind,
|
pub kind: DocstringKind,
|
||||||
pub parent: Option<&'a Stmt>,
|
pub parent: Option<&'a Stmt>,
|
||||||
pub node: &'a Expr,
|
pub expr: &'a Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract a docstring from an expression.
|
/// Extract a docstring from an expression.
|
||||||
|
@ -32,7 +34,7 @@ pub fn extract<'a, 'b>(
|
||||||
return Some(Docstring {
|
return Some(Docstring {
|
||||||
kind: DocstringKind::Module,
|
kind: DocstringKind::Module,
|
||||||
parent: None,
|
parent: None,
|
||||||
node: expr,
|
expr,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +51,7 @@ pub fn extract<'a, 'b>(
|
||||||
DocstringKind::Function
|
DocstringKind::Function
|
||||||
},
|
},
|
||||||
parent: None,
|
parent: None,
|
||||||
node: expr,
|
expr,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,3 +60,19 @@ pub fn extract<'a, 'b>(
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn docstring_empty(checker: &mut Checker, docstring: &Docstring) {
|
||||||
|
// Extract the source.
|
||||||
|
if let ExprKind::Constant {
|
||||||
|
value: Constant::Str(string),
|
||||||
|
..
|
||||||
|
} = &docstring.expr.node
|
||||||
|
{
|
||||||
|
if string.trim().is_empty() {
|
||||||
|
checker.add_check(Check::new(
|
||||||
|
CheckKind::EmptyDocstring,
|
||||||
|
Range::from_located(docstring.expr),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -978,6 +978,18 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn d419() -> Result<()> {
|
||||||
|
let mut checks = check_path(
|
||||||
|
Path::new("./resources/test/fixtures/D419.py"),
|
||||||
|
&settings::Settings::for_rule(CheckCode::D419),
|
||||||
|
&fixer::Mode::Generate,
|
||||||
|
)?;
|
||||||
|
checks.sort_by_key(|check| check.location);
|
||||||
|
insta::assert_yaml_snapshot!(checks);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn u008() -> Result<()> {
|
fn u008() -> Result<()> {
|
||||||
let mut checks = check_path(
|
let mut checks = check_path(
|
||||||
|
|
29
src/snapshots/ruff__linter__tests__d419.snap
Normal file
29
src/snapshots/ruff__linter__tests__d419.snap
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
---
|
||||||
|
source: src/linter.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind: EmptyDocstring
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 2
|
||||||
|
end_location:
|
||||||
|
row: 1
|
||||||
|
column: 7
|
||||||
|
fix: ~
|
||||||
|
- kind: EmptyDocstring
|
||||||
|
location:
|
||||||
|
row: 5
|
||||||
|
column: 6
|
||||||
|
end_location:
|
||||||
|
row: 5
|
||||||
|
column: 11
|
||||||
|
fix: ~
|
||||||
|
- kind: EmptyDocstring
|
||||||
|
location:
|
||||||
|
row: 9
|
||||||
|
column: 6
|
||||||
|
end_location:
|
||||||
|
row: 9
|
||||||
|
column: 7
|
||||||
|
fix: ~
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue