[`pydocstyle`] Implement autofix for `D403` (#3731)

This commit is contained in:
Jonathan Plasse 2023-03-25 20:21:45 +01:00 committed by GitHub
parent 6a40a5c5a2
commit 50a7916e84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 9 deletions

View File

@ -0,0 +1,15 @@
def bad_function():
"""this docstring is not capitalized"""
def good_function():
"""This docstring is capitalized."""
def other_function():
"""
This docstring is capitalized."""
def another_function():
""" This docstring is capitalized."""
def utf8_function():
"""éste docstring is capitalized."""

View File

@ -30,7 +30,8 @@ mod tests {
#[test_case(Rule::EndsInPeriod, Path::new("D.py"); "D400_0")]
#[test_case(Rule::EndsInPeriod, Path::new("D400.py"); "D400_1")]
#[test_case(Rule::EndsInPunctuation, Path::new("D.py"); "D415")]
#[test_case(Rule::FirstLineCapitalized, Path::new("D.py"); "D403")]
#[test_case(Rule::FirstLineCapitalized, Path::new("D.py"); "D403_0")]
#[test_case(Rule::FirstLineCapitalized, Path::new("D403.py"); "D403_1")]
#[test_case(Rule::FitsOnOneLine, Path::new("D.py"); "D200")]
#[test_case(Rule::IndentWithSpaces, Path::new("D.py"); "D206")]
#[test_case(Rule::UndocumentedMagicMethod, Path::new("D.py"); "D105")]

View File

@ -1,17 +1,33 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::str::leading_quote;
use ruff_python_ast::types::Range;
use unicode_width::UnicodeWidthStr;
use crate::checkers::ast::Checker;
use crate::docstrings::definition::{DefinitionKind, Docstring};
use crate::registry::AsRule;
#[violation]
pub struct FirstLineCapitalized;
pub struct FirstLineCapitalized {
pub first_word: String,
pub capitalized_word: String,
}
impl Violation for FirstLineCapitalized {
impl AlwaysAutofixableViolation for FirstLineCapitalized {
#[derive_message_formats]
fn message(&self) -> String {
format!("First word of the first line should be properly capitalized")
format!(
"First word of the first line should be capitalized: `{}` -> `{}`",
self.first_word, self.capitalized_word
)
}
fn autofix_title(&self) -> String {
format!(
"Capitalize `{}` to `{}`",
self.first_word, self.capitalized_word
)
}
}
@ -37,14 +53,36 @@ pub fn capitalized(checker: &mut Checker, docstring: &Docstring) {
return;
}
}
let Some(first_char) = first_word.chars().next() else {
let mut first_word_chars = first_word.chars();
let Some(first_char) = first_word_chars.next() else {
return;
};
if first_char.is_uppercase() {
return;
};
checker.diagnostics.push(Diagnostic::new(
FirstLineCapitalized,
let capitalized_word = first_char.to_uppercase().to_string() + first_word_chars.as_str();
let mut diagnostic = Diagnostic::new(
FirstLineCapitalized {
first_word: first_word.to_string(),
capitalized_word: capitalized_word.to_string(),
},
Range::from(docstring.expr),
));
);
if checker.patch(diagnostic.kind.rule()) {
if let Some(pattern) = leading_quote(docstring.contents) {
diagnostic.amend(Edit::replacement(
capitalized_word,
docstring.expr.location.with_col_offset(pattern.width()),
docstring
.expr
.location
.with_col_offset(pattern.width() + first_word.width()),
));
}
}
checker.diagnostics.push(diagnostic);
}

View File

@ -0,0 +1,25 @@
---
source: crates/ruff/src/rules/pydocstyle/mod.rs
expression: diagnostics
---
- kind:
name: FirstLineCapitalized
body: "First word of the first line should be capitalized: `this` -> `This`"
suggestion: "Capitalize `this` to `This`"
fixable: true
location:
row: 2
column: 4
end_location:
row: 2
column: 43
fix:
content: This
location:
row: 2
column: 7
end_location:
row: 2
column: 11
parent: ~