Move pydocstyle violations (#2524)

This commit is contained in:
Aarni Koskela 2023-02-03 14:42:52 +02:00 committed by GitHub
parent 82784a7607
commit 87c3b0e4e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 860 additions and 799 deletions

View File

@ -5088,7 +5088,7 @@ impl<'a> Checker<'a> {
pydocstyle::rules::ends_with_period(self, &docstring); pydocstyle::rules::ends_with_period(self, &docstring);
} }
if self.settings.rules.enabled(&Rule::NonImperativeMood) { if self.settings.rules.enabled(&Rule::NonImperativeMood) {
pydocstyle::rules::non_imperative_mood::non_imperative_mood(self, &docstring); pydocstyle::rules::non_imperative_mood(self, &docstring);
} }
if self.settings.rules.enabled(&Rule::NoSignature) { if self.settings.rules.enabled(&Rule::NoSignature) {
pydocstyle::rules::no_signature(self, &docstring); pydocstyle::rules::no_signature(self, &docstring);

View File

@ -259,52 +259,52 @@ ruff_macros::define_rule_mapping!(
UP035 => rules::pyupgrade::rules::ImportReplacements, UP035 => rules::pyupgrade::rules::ImportReplacements,
UP036 => rules::pyupgrade::rules::OutdatedVersionBlock, UP036 => rules::pyupgrade::rules::OutdatedVersionBlock,
// pydocstyle // pydocstyle
D100 => violations::PublicModule, D100 => rules::pydocstyle::rules::PublicModule,
D101 => violations::PublicClass, D101 => rules::pydocstyle::rules::PublicClass,
D102 => violations::PublicMethod, D102 => rules::pydocstyle::rules::PublicMethod,
D103 => violations::PublicFunction, D103 => rules::pydocstyle::rules::PublicFunction,
D104 => violations::PublicPackage, D104 => rules::pydocstyle::rules::PublicPackage,
D105 => violations::MagicMethod, D105 => rules::pydocstyle::rules::MagicMethod,
D106 => violations::PublicNestedClass, D106 => rules::pydocstyle::rules::PublicNestedClass,
D107 => violations::PublicInit, D107 => rules::pydocstyle::rules::PublicInit,
D200 => violations::FitsOnOneLine, D200 => rules::pydocstyle::rules::FitsOnOneLine,
D201 => violations::NoBlankLineBeforeFunction, D201 => rules::pydocstyle::rules::NoBlankLineBeforeFunction,
D202 => violations::NoBlankLineAfterFunction, D202 => rules::pydocstyle::rules::NoBlankLineAfterFunction,
D203 => violations::OneBlankLineBeforeClass, D203 => rules::pydocstyle::rules::OneBlankLineBeforeClass,
D204 => violations::OneBlankLineAfterClass, D204 => rules::pydocstyle::rules::OneBlankLineAfterClass,
D205 => violations::BlankLineAfterSummary, D205 => rules::pydocstyle::rules::BlankLineAfterSummary,
D206 => violations::IndentWithSpaces, D206 => rules::pydocstyle::rules::IndentWithSpaces,
D207 => violations::NoUnderIndentation, D207 => rules::pydocstyle::rules::NoUnderIndentation,
D208 => violations::NoOverIndentation, D208 => rules::pydocstyle::rules::NoOverIndentation,
D209 => violations::NewLineAfterLastParagraph, D209 => rules::pydocstyle::rules::NewLineAfterLastParagraph,
D210 => violations::NoSurroundingWhitespace, D210 => rules::pydocstyle::rules::NoSurroundingWhitespace,
D211 => violations::NoBlankLineBeforeClass, D211 => rules::pydocstyle::rules::NoBlankLineBeforeClass,
D212 => violations::MultiLineSummaryFirstLine, D212 => rules::pydocstyle::rules::MultiLineSummaryFirstLine,
D213 => violations::MultiLineSummarySecondLine, D213 => rules::pydocstyle::rules::MultiLineSummarySecondLine,
D214 => violations::SectionNotOverIndented, D214 => rules::pydocstyle::rules::SectionNotOverIndented,
D215 => violations::SectionUnderlineNotOverIndented, D215 => rules::pydocstyle::rules::SectionUnderlineNotOverIndented,
D300 => violations::UsesTripleQuotes, D300 => rules::pydocstyle::rules::UsesTripleQuotes,
D301 => violations::UsesRPrefixForBackslashedContent, D301 => rules::pydocstyle::rules::UsesRPrefixForBackslashedContent,
D400 => violations::EndsInPeriod, D400 => rules::pydocstyle::rules::EndsInPeriod,
D401 => rules::pydocstyle::rules::non_imperative_mood::NonImperativeMood, D401 => rules::pydocstyle::rules::NonImperativeMood,
D402 => violations::NoSignature, D402 => rules::pydocstyle::rules::NoSignature,
D403 => violations::FirstLineCapitalized, D403 => rules::pydocstyle::rules::FirstLineCapitalized,
D404 => violations::NoThisPrefix, D404 => rules::pydocstyle::rules::NoThisPrefix,
D405 => violations::CapitalizeSectionName, D405 => rules::pydocstyle::rules::CapitalizeSectionName,
D406 => violations::NewLineAfterSectionName, D406 => rules::pydocstyle::rules::NewLineAfterSectionName,
D407 => violations::DashedUnderlineAfterSection, D407 => rules::pydocstyle::rules::DashedUnderlineAfterSection,
D408 => violations::SectionUnderlineAfterName, D408 => rules::pydocstyle::rules::SectionUnderlineAfterName,
D409 => violations::SectionUnderlineMatchesSectionLength, D409 => rules::pydocstyle::rules::SectionUnderlineMatchesSectionLength,
D410 => violations::BlankLineAfterSection, D410 => rules::pydocstyle::rules::BlankLineAfterSection,
D411 => violations::BlankLineBeforeSection, D411 => rules::pydocstyle::rules::BlankLineBeforeSection,
D412 => violations::NoBlankLinesBetweenHeaderAndContent, D412 => rules::pydocstyle::rules::NoBlankLinesBetweenHeaderAndContent,
D413 => violations::BlankLineAfterLastSection, D413 => rules::pydocstyle::rules::BlankLineAfterLastSection,
D414 => violations::NonEmptySection, D414 => rules::pydocstyle::rules::NonEmptySection,
D415 => violations::EndsInPunctuation, D415 => rules::pydocstyle::rules::EndsInPunctuation,
D416 => violations::SectionNameEndsInColon, D416 => rules::pydocstyle::rules::SectionNameEndsInColon,
D417 => violations::DocumentAllArguments, D417 => rules::pydocstyle::rules::DocumentAllArguments,
D418 => violations::SkipDocstring, D418 => rules::pydocstyle::rules::SkipDocstring,
D419 => violations::NonEmpty, D419 => rules::pydocstyle::rules::NonEmpty,
// pep8-naming // pep8-naming
N801 => violations::InvalidClassName, N801 => violations::InvalidClassName,
N802 => violations::InvalidFunctionName, N802 => violations::InvalidFunctionName,

View File

@ -3,7 +3,20 @@ use crate::checkers::ast::Checker;
use crate::docstrings::definition::Docstring; use crate::docstrings::definition::Docstring;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::rules::pydocstyle::rules::regexes::BACKSLASH_REGEX; use crate::rules::pydocstyle::rules::regexes::BACKSLASH_REGEX;
use crate::violations; use crate::violation::Violation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct UsesRPrefixForBackslashedContent;
);
impl Violation for UsesRPrefixForBackslashedContent {
#[derive_message_formats]
fn message(&self) -> String {
format!(r#"Use r""" if any backslashes in a docstring"#)
}
}
/// D301 /// D301
pub fn backslashes(checker: &mut Checker, docstring: &Docstring) { pub fn backslashes(checker: &mut Checker, docstring: &Docstring) {
@ -16,7 +29,7 @@ pub fn backslashes(checker: &mut Checker, docstring: &Docstring) {
if BACKSLASH_REGEX.is_match(contents) { if BACKSLASH_REGEX.is_match(contents) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::UsesRPrefixForBackslashedContent, UsesRPrefixForBackslashedContent,
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
)); ));
} }

View File

@ -4,7 +4,42 @@ use crate::docstrings::definition::Docstring;
use crate::fix::Fix; use crate::fix::Fix;
use crate::message::Location; use crate::message::Location;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violations; use crate::violation::{Availability, Violation};
use crate::{define_violation, AutofixKind};
use ruff_macros::derive_message_formats;
define_violation!(
pub struct BlankLineAfterSummary {
pub num_lines: usize,
}
);
fn fmt_blank_line_after_summary_autofix_msg(_: &BlankLineAfterSummary) -> String {
"Insert single blank line".to_string()
}
impl Violation for BlankLineAfterSummary {
const AUTOFIX: Option<AutofixKind> = Some(AutofixKind::new(Availability::Always));
#[derive_message_formats]
fn message(&self) -> String {
let BlankLineAfterSummary { num_lines } = self;
if *num_lines == 0 {
format!("1 blank line required between summary line and description")
} else {
format!(
"1 blank line required between summary line and description (found {num_lines})"
)
}
}
fn autofix_title_formatter(&self) -> Option<fn(&Self) -> String> {
let BlankLineAfterSummary { num_lines } = self;
if *num_lines > 0 {
return Some(fmt_blank_line_after_summary_autofix_msg);
}
None
}
}
/// D205 /// D205
pub fn blank_after_summary(checker: &mut Checker, docstring: &Docstring) { pub fn blank_after_summary(checker: &mut Checker, docstring: &Docstring) {
@ -22,7 +57,7 @@ pub fn blank_after_summary(checker: &mut Checker, docstring: &Docstring) {
} }
if lines_count > 1 && blanks_count != 1 { if lines_count > 1 && blanks_count != 1 {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::BlankLineAfterSummary { BlankLineAfterSummary {
num_lines: blanks_count, num_lines: blanks_count,
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),

View File

@ -5,7 +5,58 @@ use crate::fix::Fix;
use crate::message::Location; use crate::message::Location;
use crate::registry::{Diagnostic, Rule}; use crate::registry::{Diagnostic, Rule};
use crate::rules::pydocstyle::rules::regexes::COMMENT_REGEX; use crate::rules::pydocstyle::rules::regexes::COMMENT_REGEX;
use crate::violations; use crate::violation::AlwaysAutofixableViolation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct OneBlankLineBeforeClass {
pub lines: usize,
}
);
impl AlwaysAutofixableViolation for OneBlankLineBeforeClass {
#[derive_message_formats]
fn message(&self) -> String {
format!("1 blank line required before class docstring")
}
fn autofix_title(&self) -> String {
"Insert 1 blank line before class docstring".to_string()
}
}
define_violation!(
pub struct OneBlankLineAfterClass {
pub lines: usize,
}
);
impl AlwaysAutofixableViolation for OneBlankLineAfterClass {
#[derive_message_formats]
fn message(&self) -> String {
format!("1 blank line required after class docstring")
}
fn autofix_title(&self) -> String {
"Insert 1 blank line after class docstring".to_string()
}
}
define_violation!(
pub struct NoBlankLineBeforeClass {
pub lines: usize,
}
);
impl AlwaysAutofixableViolation for NoBlankLineBeforeClass {
#[derive_message_formats]
fn message(&self) -> String {
format!("No blank lines allowed before class docstring")
}
fn autofix_title(&self) -> String {
"Remove blank line(s) before class docstring".to_string()
}
}
/// D203, D204, D211 /// D203, D204, D211
pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) { pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
@ -40,7 +91,7 @@ pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
{ {
if blank_lines_before != 0 { if blank_lines_before != 0 {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::NoBlankLineBeforeClass { NoBlankLineBeforeClass {
lines: blank_lines_before, lines: blank_lines_before,
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -62,7 +113,7 @@ pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
{ {
if blank_lines_before != 1 { if blank_lines_before != 1 {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::OneBlankLineBeforeClass { OneBlankLineBeforeClass {
lines: blank_lines_before, lines: blank_lines_before,
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -105,7 +156,7 @@ pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
.count(); .count();
if blank_lines_after != 1 { if blank_lines_after != 1 {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::OneBlankLineAfterClass { OneBlankLineAfterClass {
lines: blank_lines_after, lines: blank_lines_after,
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),

View File

@ -5,7 +5,44 @@ use crate::fix::Fix;
use crate::message::Location; use crate::message::Location;
use crate::registry::{Diagnostic, Rule}; use crate::registry::{Diagnostic, Rule};
use crate::rules::pydocstyle::rules::regexes::{COMMENT_REGEX, INNER_FUNCTION_OR_CLASS_REGEX}; use crate::rules::pydocstyle::rules::regexes::{COMMENT_REGEX, INNER_FUNCTION_OR_CLASS_REGEX};
use crate::violations; use crate::violation::AlwaysAutofixableViolation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct NoBlankLineBeforeFunction {
pub num_lines: usize,
}
);
impl AlwaysAutofixableViolation for NoBlankLineBeforeFunction {
#[derive_message_formats]
fn message(&self) -> String {
let NoBlankLineBeforeFunction { num_lines } = self;
format!("No blank lines allowed before function docstring (found {num_lines})")
}
fn autofix_title(&self) -> String {
"Remove blank line(s) before function docstring".to_string()
}
}
define_violation!(
pub struct NoBlankLineAfterFunction {
pub num_lines: usize,
}
);
impl AlwaysAutofixableViolation for NoBlankLineAfterFunction {
#[derive_message_formats]
fn message(&self) -> String {
let NoBlankLineAfterFunction { num_lines } = self;
format!("No blank lines allowed after function docstring (found {num_lines})")
}
fn autofix_title(&self) -> String {
"Remove blank line(s) after function docstring".to_string()
}
}
/// D201, D202 /// D201, D202
pub fn blank_before_after_function(checker: &mut Checker, docstring: &Docstring) { pub fn blank_before_after_function(checker: &mut Checker, docstring: &Docstring) {
@ -35,7 +72,7 @@ pub fn blank_before_after_function(checker: &mut Checker, docstring: &Docstring)
.count(); .count();
if blank_lines_before != 0 { if blank_lines_before != 0 {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::NoBlankLineBeforeFunction { NoBlankLineBeforeFunction {
num_lines: blank_lines_before, num_lines: blank_lines_before,
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -82,7 +119,7 @@ pub fn blank_before_after_function(checker: &mut Checker, docstring: &Docstring)
if blank_lines_after != 0 { if blank_lines_after != 0 {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::NoBlankLineAfterFunction { NoBlankLineAfterFunction {
num_lines: blank_lines_after, num_lines: blank_lines_after,
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),

View File

@ -2,7 +2,20 @@ use crate::ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::docstrings::definition::{DefinitionKind, Docstring}; use crate::docstrings::definition::{DefinitionKind, Docstring};
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violations; use crate::violation::Violation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct FirstLineCapitalized;
);
impl Violation for FirstLineCapitalized {
#[derive_message_formats]
fn message(&self) -> String {
format!("First word of the first line should be properly capitalized")
}
}
/// D403 /// D403
pub fn capitalized(checker: &mut Checker, docstring: &Docstring) { pub fn capitalized(checker: &mut Checker, docstring: &Docstring) {
@ -30,7 +43,7 @@ pub fn capitalized(checker: &mut Checker, docstring: &Docstring) {
return; return;
}; };
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::FirstLineCapitalized, FirstLineCapitalized,
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
)); ));
} }

View File

@ -6,7 +6,24 @@ use crate::fix::Fix;
use crate::message::Location; use crate::message::Location;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::rules::pydocstyle::helpers::{leading_quote, logical_line}; use crate::rules::pydocstyle::helpers::{leading_quote, logical_line};
use crate::violations; use crate::violation::AlwaysAutofixableViolation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct EndsInPeriod;
);
impl AlwaysAutofixableViolation for EndsInPeriod {
#[derive_message_formats]
fn message(&self) -> String {
format!("First line should end with a period")
}
fn autofix_title(&self) -> String {
"Add period".to_string()
}
}
/// D400 /// D400
pub fn ends_with_period(checker: &mut Checker, docstring: &Docstring) { pub fn ends_with_period(checker: &mut Checker, docstring: &Docstring) {
@ -43,10 +60,7 @@ pub fn ends_with_period(checker: &mut Checker, docstring: &Docstring) {
let trimmed = line.trim_end(); let trimmed = line.trim_end();
if !trimmed.ends_with('.') { if !trimmed.ends_with('.') {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(EndsInPeriod, Range::from_located(docstring.expr));
violations::EndsInPeriod,
Range::from_located(docstring.expr),
);
// Best-effort autofix: avoid adding a period after other punctuation marks. // Best-effort autofix: avoid adding a period after other punctuation marks.
if checker.patch(diagnostic.kind.rule()) if checker.patch(diagnostic.kind.rule())
&& !trimmed.ends_with(':') && !trimmed.ends_with(':')

View File

@ -6,7 +6,24 @@ use crate::fix::Fix;
use crate::message::Location; use crate::message::Location;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::rules::pydocstyle::helpers::{leading_quote, logical_line}; use crate::rules::pydocstyle::helpers::{leading_quote, logical_line};
use crate::violations; use crate::violation::AlwaysAutofixableViolation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct EndsInPunctuation;
);
impl AlwaysAutofixableViolation for EndsInPunctuation {
#[derive_message_formats]
fn message(&self) -> String {
format!("First line should end with a period, question mark, or exclamation point")
}
fn autofix_title(&self) -> String {
"Add closing punctuation".to_string()
}
}
/// D415 /// D415
pub fn ends_with_punctuation(checker: &mut Checker, docstring: &Docstring) { pub fn ends_with_punctuation(checker: &mut Checker, docstring: &Docstring) {
@ -42,10 +59,8 @@ pub fn ends_with_punctuation(checker: &mut Checker, docstring: &Docstring) {
let line = body.lines().nth(index).unwrap(); let line = body.lines().nth(index).unwrap();
let trimmed = line.trim_end(); let trimmed = line.trim_end();
if !(trimmed.ends_with('.') || trimmed.ends_with('!') || trimmed.ends_with('?')) { if !(trimmed.ends_with('.') || trimmed.ends_with('!') || trimmed.ends_with('?')) {
let mut diagnostic = Diagnostic::new( let mut diagnostic =
violations::EndsInPunctuation, Diagnostic::new(EndsInPunctuation, Range::from_located(docstring.expr));
Range::from_located(docstring.expr),
);
// Best-effort autofix: avoid adding a period after other punctuation marks. // Best-effort autofix: avoid adding a period after other punctuation marks.
if checker.patch(diagnostic.kind.rule()) if checker.patch(diagnostic.kind.rule())
&& !trimmed.ends_with(':') && !trimmed.ends_with(':')

View File

@ -3,8 +3,21 @@ use crate::ast::helpers::identifier_range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::docstrings::definition::{DefinitionKind, Docstring}; use crate::docstrings::definition::{DefinitionKind, Docstring};
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violations; use crate::violation::Violation;
use crate::define_violation;
use crate::visibility::is_overload; use crate::visibility::is_overload;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct SkipDocstring;
);
impl Violation for SkipDocstring {
#[derive_message_formats]
fn message(&self) -> String {
format!("Function decorated with `@overload` shouldn't contain a docstring")
}
}
/// D418 /// D418
pub fn if_needed(checker: &mut Checker, docstring: &Docstring) { pub fn if_needed(checker: &mut Checker, docstring: &Docstring) {
@ -19,7 +32,7 @@ pub fn if_needed(checker: &mut Checker, docstring: &Docstring) {
return; return;
} }
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::SkipDocstring, SkipDocstring,
identifier_range(stmt, checker.locator), identifier_range(stmt, checker.locator),
)); ));
} }

View File

@ -6,7 +6,48 @@ use crate::docstrings::definition::Docstring;
use crate::fix::Fix; use crate::fix::Fix;
use crate::message::Location; use crate::message::Location;
use crate::registry::{Diagnostic, Rule}; use crate::registry::{Diagnostic, Rule};
use crate::violations; use crate::violation::{AlwaysAutofixableViolation, Violation};
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct IndentWithSpaces;
);
impl Violation for IndentWithSpaces {
#[derive_message_formats]
fn message(&self) -> String {
format!("Docstring should be indented with spaces, not tabs")
}
}
define_violation!(
pub struct NoUnderIndentation;
);
impl AlwaysAutofixableViolation for NoUnderIndentation {
#[derive_message_formats]
fn message(&self) -> String {
format!("Docstring is under-indented")
}
fn autofix_title(&self) -> String {
"Increase indentation".to_string()
}
}
define_violation!(
pub struct NoOverIndentation;
);
impl AlwaysAutofixableViolation for NoOverIndentation {
#[derive_message_formats]
fn message(&self) -> String {
format!("Docstring is over-indented")
}
fn autofix_title(&self) -> String {
"Remove over-indentation".to_string()
}
}
/// D206, D207, D208 /// D206, D207, D208
pub fn indent(checker: &mut Checker, docstring: &Docstring) { pub fn indent(checker: &mut Checker, docstring: &Docstring) {
@ -47,7 +88,7 @@ pub fn indent(checker: &mut Checker, docstring: &Docstring) {
&& line_indent.len() < docstring.indentation.len() && line_indent.len() < docstring.indentation.len()
{ {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::NoUnderIndentation, NoUnderIndentation,
Range::new( Range::new(
Location::new(docstring.expr.location.row() + i, 0), Location::new(docstring.expr.location.row() + i, 0),
Location::new(docstring.expr.location.row() + i, 0), Location::new(docstring.expr.location.row() + i, 0),
@ -82,7 +123,7 @@ pub fn indent(checker: &mut Checker, docstring: &Docstring) {
if checker.settings.rules.enabled(&Rule::IndentWithSpaces) { if checker.settings.rules.enabled(&Rule::IndentWithSpaces) {
if has_seen_tab { if has_seen_tab {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::IndentWithSpaces, IndentWithSpaces,
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
)); ));
} }
@ -97,7 +138,7 @@ pub fn indent(checker: &mut Checker, docstring: &Docstring) {
// We report over-indentation on every line. This isn't great, but // We report over-indentation on every line. This isn't great, but
// enables autofix. // enables autofix.
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::NoOverIndentation, NoOverIndentation,
Range::new( Range::new(
Location::new(docstring.expr.location.row() + i, 0), Location::new(docstring.expr.location.row() + i, 0),
Location::new(docstring.expr.location.row() + i, 0), Location::new(docstring.expr.location.row() + i, 0),
@ -121,7 +162,7 @@ pub fn indent(checker: &mut Checker, docstring: &Docstring) {
let line_indent = whitespace::leading_space(lines[i]); let line_indent = whitespace::leading_space(lines[i]);
if line_indent.len() > docstring.indentation.len() { if line_indent.len() > docstring.indentation.len() {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::NoOverIndentation, NoOverIndentation,
Range::new( Range::new(
Location::new(docstring.expr.location.row() + i, 0), Location::new(docstring.expr.location.row() + i, 0),
Location::new(docstring.expr.location.row() + i, 0), Location::new(docstring.expr.location.row() + i, 0),

View File

@ -1,22 +1,39 @@
pub use backslashes::backslashes; pub use backslashes::{backslashes, UsesRPrefixForBackslashedContent};
pub use blank_after_summary::blank_after_summary; pub use blank_after_summary::{blank_after_summary, BlankLineAfterSummary};
pub use blank_before_after_class::blank_before_after_class; pub use blank_before_after_class::{
pub use blank_before_after_function::blank_before_after_function; blank_before_after_class, NoBlankLineBeforeClass, OneBlankLineAfterClass,
pub use capitalized::capitalized; OneBlankLineBeforeClass,
pub use ends_with_period::ends_with_period; };
pub use ends_with_punctuation::ends_with_punctuation; pub use blank_before_after_function::{
pub use if_needed::if_needed; blank_before_after_function, NoBlankLineAfterFunction, NoBlankLineBeforeFunction,
pub use indent::indent; };
pub use multi_line_summary_start::multi_line_summary_start; pub use capitalized::{capitalized, FirstLineCapitalized};
pub use newline_after_last_paragraph::newline_after_last_paragraph; pub use ends_with_period::{ends_with_period, EndsInPeriod};
pub use no_signature::no_signature; pub use ends_with_punctuation::{ends_with_punctuation, EndsInPunctuation};
pub use no_surrounding_whitespace::no_surrounding_whitespace; pub use if_needed::{if_needed, SkipDocstring};
pub use not_empty::not_empty; pub use indent::{indent, IndentWithSpaces, NoOverIndentation, NoUnderIndentation};
pub use not_missing::not_missing; pub use multi_line_summary_start::{
pub use one_liner::one_liner; multi_line_summary_start, MultiLineSummaryFirstLine, MultiLineSummarySecondLine,
pub use sections::sections; };
pub use starts_with_this::starts_with_this; pub use newline_after_last_paragraph::{newline_after_last_paragraph, NewLineAfterLastParagraph};
pub use triple_quotes::triple_quotes; pub use no_signature::{no_signature, NoSignature};
pub use no_surrounding_whitespace::{no_surrounding_whitespace, NoSurroundingWhitespace};
pub use non_imperative_mood::{non_imperative_mood, NonImperativeMood};
pub use not_empty::{not_empty, NonEmpty};
pub use not_missing::{
not_missing, MagicMethod, PublicClass, PublicFunction, PublicInit, PublicMethod, PublicModule,
PublicNestedClass, PublicPackage,
};
pub use one_liner::{one_liner, FitsOnOneLine};
pub use sections::{
sections, BlankLineAfterLastSection, BlankLineAfterSection, BlankLineBeforeSection,
CapitalizeSectionName, DashedUnderlineAfterSection, DocumentAllArguments,
NewLineAfterSectionName, NoBlankLinesBetweenHeaderAndContent, NonEmptySection,
SectionNameEndsInColon, SectionNotOverIndented, SectionUnderlineAfterName,
SectionUnderlineMatchesSectionLength, SectionUnderlineNotOverIndented,
};
pub use starts_with_this::{starts_with_this, NoThisPrefix};
pub use triple_quotes::{triple_quotes, UsesTripleQuotes};
mod backslashes; mod backslashes;
mod blank_after_summary; mod blank_after_summary;
@ -31,7 +48,7 @@ mod multi_line_summary_start;
mod newline_after_last_paragraph; mod newline_after_last_paragraph;
mod no_signature; mod no_signature;
mod no_surrounding_whitespace; mod no_surrounding_whitespace;
pub mod non_imperative_mood; mod non_imperative_mood;
mod not_empty; mod not_empty;
mod not_missing; mod not_missing;
mod one_liner; mod one_liner;

View File

@ -7,7 +7,38 @@ use crate::fix::Fix;
use crate::message::Location; use crate::message::Location;
use crate::registry::{Diagnostic, Rule}; use crate::registry::{Diagnostic, Rule};
use crate::rules::pydocstyle::helpers::leading_quote; use crate::rules::pydocstyle::helpers::leading_quote;
use crate::violations; use crate::violation::AlwaysAutofixableViolation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct MultiLineSummaryFirstLine;
);
impl AlwaysAutofixableViolation for MultiLineSummaryFirstLine {
#[derive_message_formats]
fn message(&self) -> String {
format!("Multi-line docstring summary should start at the first line")
}
fn autofix_title(&self) -> String {
"Remove whitespace after opening quotes".to_string()
}
}
define_violation!(
pub struct MultiLineSummarySecondLine;
);
impl AlwaysAutofixableViolation for MultiLineSummarySecondLine {
#[derive_message_formats]
fn message(&self) -> String {
format!("Multi-line docstring summary should start at the second line")
}
fn autofix_title(&self) -> String {
"Insert line break and indentation after opening quotes".to_string()
}
}
/// D212, D213 /// D212, D213
pub fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstring) { pub fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstring) {
@ -31,7 +62,7 @@ pub fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstring) {
.enabled(&Rule::MultiLineSummaryFirstLine) .enabled(&Rule::MultiLineSummaryFirstLine)
{ {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::MultiLineSummaryFirstLine, MultiLineSummaryFirstLine,
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
); );
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
@ -58,7 +89,7 @@ pub fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstring) {
.enabled(&Rule::MultiLineSummarySecondLine) .enabled(&Rule::MultiLineSummarySecondLine)
{ {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::MultiLineSummarySecondLine, MultiLineSummarySecondLine,
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
); );
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {

View File

@ -6,7 +6,24 @@ use crate::docstrings::definition::Docstring;
use crate::fix::Fix; use crate::fix::Fix;
use crate::message::Location; use crate::message::Location;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violations; use crate::violation::AlwaysAutofixableViolation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct NewLineAfterLastParagraph;
);
impl AlwaysAutofixableViolation for NewLineAfterLastParagraph {
#[derive_message_formats]
fn message(&self) -> String {
format!("Multi-line docstring closing quotes should be on a separate line")
}
fn autofix_title(&self) -> String {
"Move closing quotes to new line".to_string()
}
}
/// D209 /// D209
pub fn newline_after_last_paragraph(checker: &mut Checker, docstring: &Docstring) { pub fn newline_after_last_paragraph(checker: &mut Checker, docstring: &Docstring) {
@ -22,7 +39,7 @@ pub fn newline_after_last_paragraph(checker: &mut Checker, docstring: &Docstring
if let Some(last_line) = contents.lines().last().map(str::trim) { if let Some(last_line) = contents.lines().last().map(str::trim) {
if last_line != "\"\"\"" && last_line != "'''" { if last_line != "\"\"\"" && last_line != "'''" {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::NewLineAfterLastParagraph, NewLineAfterLastParagraph,
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
); );
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {

View File

@ -1,10 +1,22 @@
use crate::define_violation;
use crate::violation::Violation;
use ruff_macros::derive_message_formats;
use rustpython_ast::StmtKind; use rustpython_ast::StmtKind;
use crate::ast::types::Range; use crate::ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::docstrings::definition::{DefinitionKind, Docstring}; use crate::docstrings::definition::{DefinitionKind, Docstring};
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violations;
define_violation!(
pub struct NoSignature;
);
impl Violation for NoSignature {
#[derive_message_formats]
fn message(&self) -> String {
format!("First line should not be the function's signature")
}
}
/// D402 /// D402
pub fn no_signature(checker: &mut Checker, docstring: &Docstring) { pub fn no_signature(checker: &mut Checker, docstring: &Docstring) {
@ -28,7 +40,7 @@ pub fn no_signature(checker: &mut Checker, docstring: &Docstring) {
return; return;
}; };
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::NoSignature, NoSignature,
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
)); ));
} }

View File

@ -6,7 +6,24 @@ use crate::fix::Fix;
use crate::message::Location; use crate::message::Location;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::rules::pydocstyle::helpers::leading_quote; use crate::rules::pydocstyle::helpers::leading_quote;
use crate::violations; use crate::violation::AlwaysAutofixableViolation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct NoSurroundingWhitespace;
);
impl AlwaysAutofixableViolation for NoSurroundingWhitespace {
#[derive_message_formats]
fn message(&self) -> String {
format!("No whitespaces allowed surrounding docstring text")
}
fn autofix_title(&self) -> String {
"Trim surrounding whitespace".to_string()
}
}
/// D210 /// D210
pub fn no_surrounding_whitespace(checker: &mut Checker, docstring: &Docstring) { pub fn no_surrounding_whitespace(checker: &mut Checker, docstring: &Docstring) {
@ -24,10 +41,8 @@ pub fn no_surrounding_whitespace(checker: &mut Checker, docstring: &Docstring) {
if line == trimmed { if line == trimmed {
return; return;
} }
let mut diagnostic = Diagnostic::new( let mut diagnostic =
violations::NoSurroundingWhitespace, Diagnostic::new(NoSurroundingWhitespace, Range::from_located(docstring.expr));
Range::from_located(docstring.expr),
);
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
if let Some(pattern) = leading_quote(contents) { if let Some(pattern) = leading_quote(contents) {
// If removing whitespace would lead to an invalid string of quote // If removing whitespace would lead to an invalid string of quote

View File

@ -2,7 +2,20 @@ use crate::ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::docstrings::definition::Docstring; use crate::docstrings::definition::Docstring;
use crate::registry::{Diagnostic, Rule}; use crate::registry::{Diagnostic, Rule};
use crate::violations; use crate::violation::Violation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct NonEmpty;
);
impl Violation for NonEmpty {
#[derive_message_formats]
fn message(&self) -> String {
format!("Docstring is empty")
}
}
/// D419 /// D419
pub fn not_empty(checker: &mut Checker, docstring: &Docstring) -> bool { pub fn not_empty(checker: &mut Checker, docstring: &Docstring) -> bool {
@ -12,7 +25,7 @@ pub fn not_empty(checker: &mut Checker, docstring: &Docstring) -> bool {
if checker.settings.rules.enabled(&Rule::NonEmpty) { if checker.settings.rules.enabled(&Rule::NonEmpty) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::NonEmpty, NonEmpty,
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
)); ));
} }

View File

@ -5,8 +5,91 @@ use crate::checkers::ast::Checker;
use crate::docstrings::definition::{Definition, DefinitionKind}; use crate::docstrings::definition::{Definition, DefinitionKind};
use crate::message::Location; use crate::message::Location;
use crate::registry::{Diagnostic, Rule}; use crate::registry::{Diagnostic, Rule};
use crate::violations; use crate::violation::Violation;
use crate::define_violation;
use crate::visibility::{is_call, is_init, is_magic, is_new, is_overload, is_override, Visibility}; use crate::visibility::{is_call, is_init, is_magic, is_new, is_overload, is_override, Visibility};
use ruff_macros::derive_message_formats;
define_violation!(
pub struct PublicModule;
);
impl Violation for PublicModule {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public module")
}
}
define_violation!(
pub struct PublicClass;
);
impl Violation for PublicClass {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public class")
}
}
define_violation!(
pub struct PublicMethod;
);
impl Violation for PublicMethod {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public method")
}
}
define_violation!(
pub struct PublicFunction;
);
impl Violation for PublicFunction {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public function")
}
}
define_violation!(
pub struct PublicPackage;
);
impl Violation for PublicPackage {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public package")
}
}
define_violation!(
pub struct MagicMethod;
);
impl Violation for MagicMethod {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in magic method")
}
}
define_violation!(
pub struct PublicNestedClass;
);
impl Violation for PublicNestedClass {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public nested class")
}
}
define_violation!(
pub struct PublicInit;
);
impl Violation for PublicInit {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in `__init__`")
}
}
/// D100, D101, D102, D103, D104, D105, D106, D107 /// D100, D101, D102, D103, D104, D105, D106, D107
pub fn not_missing( pub fn not_missing(
@ -22,7 +105,7 @@ pub fn not_missing(
DefinitionKind::Module => { DefinitionKind::Module => {
if checker.settings.rules.enabled(&Rule::PublicModule) { if checker.settings.rules.enabled(&Rule::PublicModule) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::PublicModule, PublicModule,
Range::new(Location::new(1, 0), Location::new(1, 0)), Range::new(Location::new(1, 0), Location::new(1, 0)),
)); ));
} }
@ -31,7 +114,7 @@ pub fn not_missing(
DefinitionKind::Package => { DefinitionKind::Package => {
if checker.settings.rules.enabled(&Rule::PublicPackage) { if checker.settings.rules.enabled(&Rule::PublicPackage) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::PublicPackage, PublicPackage,
Range::new(Location::new(1, 0), Location::new(1, 0)), Range::new(Location::new(1, 0), Location::new(1, 0)),
)); ));
} }
@ -40,7 +123,7 @@ pub fn not_missing(
DefinitionKind::Class(stmt) => { DefinitionKind::Class(stmt) => {
if checker.settings.rules.enabled(&Rule::PublicClass) { if checker.settings.rules.enabled(&Rule::PublicClass) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::PublicClass, PublicClass,
identifier_range(stmt, checker.locator), identifier_range(stmt, checker.locator),
)); ));
} }
@ -49,7 +132,7 @@ pub fn not_missing(
DefinitionKind::NestedClass(stmt) => { DefinitionKind::NestedClass(stmt) => {
if checker.settings.rules.enabled(&Rule::PublicNestedClass) { if checker.settings.rules.enabled(&Rule::PublicNestedClass) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::PublicNestedClass, PublicNestedClass,
identifier_range(stmt, checker.locator), identifier_range(stmt, checker.locator),
)); ));
} }
@ -61,7 +144,7 @@ pub fn not_missing(
} else { } else {
if checker.settings.rules.enabled(&Rule::PublicFunction) { if checker.settings.rules.enabled(&Rule::PublicFunction) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::PublicFunction, PublicFunction,
identifier_range(stmt, checker.locator), identifier_range(stmt, checker.locator),
)); ));
} }
@ -76,7 +159,7 @@ pub fn not_missing(
} else if is_init(cast::name(stmt)) { } else if is_init(cast::name(stmt)) {
if checker.settings.rules.enabled(&Rule::PublicInit) { if checker.settings.rules.enabled(&Rule::PublicInit) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::PublicInit, PublicInit,
identifier_range(stmt, checker.locator), identifier_range(stmt, checker.locator),
)); ));
} }
@ -84,7 +167,7 @@ pub fn not_missing(
} else if is_new(cast::name(stmt)) || is_call(cast::name(stmt)) { } else if is_new(cast::name(stmt)) || is_call(cast::name(stmt)) {
if checker.settings.rules.enabled(&Rule::PublicMethod) { if checker.settings.rules.enabled(&Rule::PublicMethod) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::PublicMethod, PublicMethod,
identifier_range(stmt, checker.locator), identifier_range(stmt, checker.locator),
)); ));
} }
@ -92,7 +175,7 @@ pub fn not_missing(
} else if is_magic(cast::name(stmt)) { } else if is_magic(cast::name(stmt)) {
if checker.settings.rules.enabled(&Rule::MagicMethod) { if checker.settings.rules.enabled(&Rule::MagicMethod) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::MagicMethod, MagicMethod,
identifier_range(stmt, checker.locator), identifier_range(stmt, checker.locator),
)); ));
} }
@ -100,7 +183,7 @@ pub fn not_missing(
} else { } else {
if checker.settings.rules.enabled(&Rule::PublicMethod) { if checker.settings.rules.enabled(&Rule::PublicMethod) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::PublicMethod, PublicMethod,
identifier_range(stmt, checker.locator), identifier_range(stmt, checker.locator),
)); ));
} }

View File

@ -5,7 +5,24 @@ use crate::docstrings::definition::Docstring;
use crate::fix::Fix; use crate::fix::Fix;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::rules::pydocstyle::helpers; use crate::rules::pydocstyle::helpers;
use crate::violations; use crate::violation::AlwaysAutofixableViolation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct FitsOnOneLine;
);
impl AlwaysAutofixableViolation for FitsOnOneLine {
#[derive_message_formats]
fn message(&self) -> String {
format!("One-line docstring should fit on one line")
}
fn autofix_title(&self) -> String {
"Reformat to one line".to_string()
}
}
/// D200 /// D200
pub fn one_liner(checker: &mut Checker, docstring: &Docstring) { pub fn one_liner(checker: &mut Checker, docstring: &Docstring) {
@ -22,10 +39,7 @@ pub fn one_liner(checker: &mut Checker, docstring: &Docstring) {
} }
if non_empty_line_count == 1 && line_count > 1 { if non_empty_line_count == 1 && line_count > 1 {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(FitsOnOneLine, Range::from_located(docstring.expr));
violations::FitsOnOneLine,
Range::from_located(docstring.expr),
);
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
if let (Some(leading), Some(trailing)) = ( if let (Some(leading), Some(trailing)) = (
helpers::leading_quote(docstring.contents), helpers::leading_quote(docstring.contents),

View File

@ -1,6 +1,9 @@
use crate::define_violation;
use crate::violation::{AlwaysAutofixableViolation, Violation};
use itertools::Itertools; use itertools::Itertools;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
use ruff_macros::derive_message_formats;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use rustpython_ast::StmtKind; use rustpython_ast::StmtKind;
@ -15,9 +18,256 @@ use crate::fix::Fix;
use crate::message::Location; use crate::message::Location;
use crate::registry::{Diagnostic, Rule}; use crate::registry::{Diagnostic, Rule};
use crate::rules::pydocstyle::settings::Convention; use crate::rules::pydocstyle::settings::Convention;
use crate::violations;
use crate::visibility::is_staticmethod; use crate::visibility::is_staticmethod;
define_violation!(
pub struct SectionNotOverIndented {
pub name: String,
}
);
impl AlwaysAutofixableViolation for SectionNotOverIndented {
#[derive_message_formats]
fn message(&self) -> String {
let SectionNotOverIndented { name } = self;
format!("Section is over-indented (\"{name}\")")
}
fn autofix_title(&self) -> String {
let SectionNotOverIndented { name } = self;
format!("Remove over-indentation from \"{name}\"")
}
}
define_violation!(
pub struct SectionUnderlineNotOverIndented {
pub name: String,
}
);
impl AlwaysAutofixableViolation for SectionUnderlineNotOverIndented {
#[derive_message_formats]
fn message(&self) -> String {
let SectionUnderlineNotOverIndented { name } = self;
format!("Section underline is over-indented (\"{name}\")")
}
fn autofix_title(&self) -> String {
let SectionUnderlineNotOverIndented { name } = self;
format!("Remove over-indentation from \"{name}\" underline")
}
}
define_violation!(
pub struct CapitalizeSectionName {
pub name: String,
}
);
impl AlwaysAutofixableViolation for CapitalizeSectionName {
#[derive_message_formats]
fn message(&self) -> String {
let CapitalizeSectionName { name } = self;
format!("Section name should be properly capitalized (\"{name}\")")
}
fn autofix_title(&self) -> String {
let CapitalizeSectionName { name } = self;
format!("Capitalize \"{name}\"")
}
}
define_violation!(
pub struct NewLineAfterSectionName {
pub name: String,
}
);
impl AlwaysAutofixableViolation for NewLineAfterSectionName {
#[derive_message_formats]
fn message(&self) -> String {
let NewLineAfterSectionName { name } = self;
format!("Section name should end with a newline (\"{name}\")")
}
fn autofix_title(&self) -> String {
let NewLineAfterSectionName { name } = self;
format!("Add newline after \"{name}\"")
}
}
define_violation!(
pub struct DashedUnderlineAfterSection {
pub name: String,
}
);
impl AlwaysAutofixableViolation for DashedUnderlineAfterSection {
#[derive_message_formats]
fn message(&self) -> String {
let DashedUnderlineAfterSection { name } = self;
format!("Missing dashed underline after section (\"{name}\")")
}
fn autofix_title(&self) -> String {
let DashedUnderlineAfterSection { name } = self;
format!("Add dashed line under \"{name}\"")
}
}
define_violation!(
pub struct SectionUnderlineAfterName {
pub name: String,
}
);
impl AlwaysAutofixableViolation for SectionUnderlineAfterName {
#[derive_message_formats]
fn message(&self) -> String {
let SectionUnderlineAfterName { name } = self;
format!("Section underline should be in the line following the section's name (\"{name}\")")
}
fn autofix_title(&self) -> String {
let SectionUnderlineAfterName { name } = self;
format!("Add underline to \"{name}\"")
}
}
define_violation!(
pub struct SectionUnderlineMatchesSectionLength {
pub name: String,
}
);
impl AlwaysAutofixableViolation for SectionUnderlineMatchesSectionLength {
#[derive_message_formats]
fn message(&self) -> String {
let SectionUnderlineMatchesSectionLength { name } = self;
format!("Section underline should match the length of its name (\"{name}\")")
}
fn autofix_title(&self) -> String {
let SectionUnderlineMatchesSectionLength { name } = self;
format!("Adjust underline length to match \"{name}\"")
}
}
define_violation!(
pub struct BlankLineAfterSection {
pub name: String,
}
);
impl AlwaysAutofixableViolation for BlankLineAfterSection {
#[derive_message_formats]
fn message(&self) -> String {
let BlankLineAfterSection { name } = self;
format!("Missing blank line after section (\"{name}\")")
}
fn autofix_title(&self) -> String {
let BlankLineAfterSection { name } = self;
format!("Add blank line after \"{name}\"")
}
}
define_violation!(
pub struct BlankLineBeforeSection {
pub name: String,
}
);
impl AlwaysAutofixableViolation for BlankLineBeforeSection {
#[derive_message_formats]
fn message(&self) -> String {
let BlankLineBeforeSection { name } = self;
format!("Missing blank line before section (\"{name}\")")
}
fn autofix_title(&self) -> String {
let BlankLineBeforeSection { name } = self;
format!("Add blank line before \"{name}\"")
}
}
define_violation!(
pub struct BlankLineAfterLastSection {
pub name: String,
}
);
impl AlwaysAutofixableViolation for BlankLineAfterLastSection {
#[derive_message_formats]
fn message(&self) -> String {
let BlankLineAfterLastSection { name } = self;
format!("Missing blank line after last section (\"{name}\")")
}
fn autofix_title(&self) -> String {
let BlankLineAfterLastSection { name } = self;
format!("Add blank line after \"{name}\"")
}
}
define_violation!(
pub struct NonEmptySection {
pub name: String,
}
);
impl Violation for NonEmptySection {
#[derive_message_formats]
fn message(&self) -> String {
let NonEmptySection { name } = self;
format!("Section has no content (\"{name}\")")
}
}
define_violation!(
pub struct SectionNameEndsInColon {
pub name: String,
}
);
impl AlwaysAutofixableViolation for SectionNameEndsInColon {
#[derive_message_formats]
fn message(&self) -> String {
let SectionNameEndsInColon { name } = self;
format!("Section name should end with a colon (\"{name}\")")
}
fn autofix_title(&self) -> String {
let SectionNameEndsInColon { name } = self;
format!("Add colon to \"{name}\"")
}
}
define_violation!(
pub struct DocumentAllArguments {
pub names: Vec<String>,
}
);
impl Violation for DocumentAllArguments {
#[derive_message_formats]
fn message(&self) -> String {
let DocumentAllArguments { names } = self;
if names.len() == 1 {
let name = &names[0];
format!("Missing argument description in the docstring: `{name}`")
} else {
let names = names.iter().map(|name| format!("`{name}`")).join(", ");
format!("Missing argument descriptions in the docstring: {names}")
}
}
}
define_violation!(
pub struct NoBlankLinesBetweenHeaderAndContent {
pub name: String,
}
);
impl AlwaysAutofixableViolation for NoBlankLinesBetweenHeaderAndContent {
#[derive_message_formats]
fn message(&self) -> String {
let NoBlankLinesBetweenHeaderAndContent { name } = self;
format!("No blank lines allowed between a section header and its content (\"{name}\")")
}
fn autofix_title(&self) -> String {
"Remove blank line(s)".to_string()
}
}
/// D212, D214, D215, D405, D406, D407, D408, D409, D410, D411, D412, D413, /// D212, D214, D215, D405, D406, D407, D408, D409, D410, D411, D412, D413,
/// D414, D416, D417 /// D414, D416, D417
pub fn sections(checker: &mut Checker, docstring: &Docstring, convention: Option<&Convention>) { pub fn sections(checker: &mut Checker, docstring: &Docstring, convention: Option<&Convention>) {
@ -78,7 +328,7 @@ fn blanks_and_section_underline(
.enabled(&Rule::DashedUnderlineAfterSection) .enabled(&Rule::DashedUnderlineAfterSection)
{ {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::DashedUnderlineAfterSection { DashedUnderlineAfterSection {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -103,7 +353,7 @@ fn blanks_and_section_underline(
} }
if checker.settings.rules.enabled(&Rule::NonEmptySection) { if checker.settings.rules.enabled(&Rule::NonEmptySection) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::NonEmptySection { NonEmptySection {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -125,7 +375,7 @@ fn blanks_and_section_underline(
.enabled(&Rule::SectionUnderlineAfterName) .enabled(&Rule::SectionUnderlineAfterName)
{ {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::SectionUnderlineAfterName { SectionUnderlineAfterName {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -163,7 +413,7 @@ fn blanks_and_section_underline(
.enabled(&Rule::SectionUnderlineMatchesSectionLength) .enabled(&Rule::SectionUnderlineMatchesSectionLength)
{ {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::SectionUnderlineMatchesSectionLength { SectionUnderlineMatchesSectionLength {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -207,7 +457,7 @@ fn blanks_and_section_underline(
let leading_space = whitespace::leading_space(non_empty_line); let leading_space = whitespace::leading_space(non_empty_line);
if leading_space.len() > docstring.indentation.len() { if leading_space.len() > docstring.indentation.len() {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::SectionUnderlineNotOverIndented { SectionUnderlineNotOverIndented {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -249,7 +499,7 @@ fn blanks_and_section_underline(
if blank_lines_after_dashes == rest_of_lines.len() { if blank_lines_after_dashes == rest_of_lines.len() {
if checker.settings.rules.enabled(&Rule::NonEmptySection) { if checker.settings.rules.enabled(&Rule::NonEmptySection) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::NonEmptySection { NonEmptySection {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -262,7 +512,7 @@ fn blanks_and_section_underline(
.enabled(&Rule::NoBlankLinesBetweenHeaderAndContent) .enabled(&Rule::NoBlankLinesBetweenHeaderAndContent)
{ {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::NoBlankLinesBetweenHeaderAndContent { NoBlankLinesBetweenHeaderAndContent {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -294,7 +544,7 @@ fn blanks_and_section_underline(
} else { } else {
if checker.settings.rules.enabled(&Rule::NonEmptySection) { if checker.settings.rules.enabled(&Rule::NonEmptySection) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::NonEmptySection { NonEmptySection {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -308,7 +558,7 @@ fn blanks_and_section_underline(
.enabled(&Rule::DashedUnderlineAfterSection) .enabled(&Rule::DashedUnderlineAfterSection)
{ {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::DashedUnderlineAfterSection { DashedUnderlineAfterSection {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -338,7 +588,7 @@ fn blanks_and_section_underline(
.enabled(&Rule::NoBlankLinesBetweenHeaderAndContent) .enabled(&Rule::NoBlankLinesBetweenHeaderAndContent)
{ {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::NoBlankLinesBetweenHeaderAndContent { NoBlankLinesBetweenHeaderAndContent {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -379,7 +629,7 @@ fn common_section(
.contains(capitalized_section_name.as_str()) .contains(capitalized_section_name.as_str())
{ {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::CapitalizeSectionName { CapitalizeSectionName {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -417,7 +667,7 @@ fn common_section(
let leading_space = whitespace::leading_space(context.line); let leading_space = whitespace::leading_space(context.line);
if leading_space.len() > docstring.indentation.len() { if leading_space.len() > docstring.indentation.len() {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::SectionNotOverIndented { SectionNotOverIndented {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -450,7 +700,7 @@ fn common_section(
.enabled(&Rule::BlankLineAfterLastSection) .enabled(&Rule::BlankLineAfterLastSection)
{ {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::BlankLineAfterLastSection { BlankLineAfterLastSection {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -473,7 +723,7 @@ fn common_section(
} else { } else {
if checker.settings.rules.enabled(&Rule::BlankLineAfterSection) { if checker.settings.rules.enabled(&Rule::BlankLineAfterSection) {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::BlankLineAfterSection { BlankLineAfterSection {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -503,7 +753,7 @@ fn common_section(
{ {
if !context.previous_line.is_empty() { if !context.previous_line.is_empty() {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::BlankLineBeforeSection { BlankLineBeforeSection {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -588,7 +838,7 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: &
if !missing_arg_names.is_empty() { if !missing_arg_names.is_empty() {
let names = missing_arg_names.into_iter().sorted().collect(); let names = missing_arg_names.into_iter().sorted().collect();
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::DocumentAllArguments { names }, DocumentAllArguments { names },
Range::from_located(parent), Range::from_located(parent),
)); ));
} }
@ -698,7 +948,7 @@ fn numpy_section(checker: &mut Checker, docstring: &Docstring, context: &Section
.unwrap(); .unwrap();
if !suffix.is_empty() { if !suffix.is_empty() {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::NewLineAfterSectionName { NewLineAfterSectionName {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
@ -750,7 +1000,7 @@ fn google_section(checker: &mut Checker, docstring: &Docstring, context: &Sectio
.unwrap(); .unwrap();
if suffix != ":" { if suffix != ":" {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
violations::SectionNameEndsInColon { SectionNameEndsInColon {
name: context.section_name.to_string(), name: context.section_name.to_string(),
}, },
Range::from_located(docstring.expr), Range::from_located(docstring.expr),

View File

@ -3,7 +3,20 @@ use crate::checkers::ast::Checker;
use crate::docstrings::definition::Docstring; use crate::docstrings::definition::Docstring;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::rules::pydocstyle::helpers::normalize_word; use crate::rules::pydocstyle::helpers::normalize_word;
use crate::violations; use crate::violation::Violation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct NoThisPrefix;
);
impl Violation for NoThisPrefix {
#[derive_message_formats]
fn message(&self) -> String {
format!(r#"First word of the docstring should not be "This""#)
}
}
/// D404 /// D404
pub fn starts_with_this(checker: &mut Checker, docstring: &Docstring) { pub fn starts_with_this(checker: &mut Checker, docstring: &Docstring) {
@ -21,7 +34,7 @@ pub fn starts_with_this(checker: &mut Checker, docstring: &Docstring) {
return; return;
} }
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::NoThisPrefix, NoThisPrefix,
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
)); ));
} }

View File

@ -2,7 +2,20 @@ use crate::ast::types::Range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::docstrings::definition::Docstring; use crate::docstrings::definition::Docstring;
use crate::registry::Diagnostic; use crate::registry::Diagnostic;
use crate::violations; use crate::violation::Violation;
use crate::define_violation;
use ruff_macros::derive_message_formats;
define_violation!(
pub struct UsesTripleQuotes;
);
impl Violation for UsesTripleQuotes {
#[derive_message_formats]
fn message(&self) -> String {
format!(r#"Use """triple double quotes""""#)
}
}
/// D300 /// D300
pub fn triple_quotes(checker: &mut Checker, docstring: &Docstring) { pub fn triple_quotes(checker: &mut Checker, docstring: &Docstring) {
@ -29,7 +42,7 @@ pub fn triple_quotes(checker: &mut Checker, docstring: &Docstring) {
}; };
if !starts_with_triple { if !starts_with_triple {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
violations::UsesTripleQuotes, UsesTripleQuotes,
Range::from_located(docstring.expr), Range::from_located(docstring.expr),
)); ));
} }

View File

@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
use crate::define_violation; use crate::define_violation;
use crate::violation::{AlwaysAutofixableViolation, AutofixKind, Availability, Violation}; use crate::violation::{AlwaysAutofixableViolation, Violation};
// mccabe // mccabe
@ -193,655 +193,6 @@ impl Violation for SysVersionSlice1Referenced {
} }
} }
// pydocstyle
define_violation!(
pub struct PublicModule;
);
impl Violation for PublicModule {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public module")
}
}
define_violation!(
pub struct PublicClass;
);
impl Violation for PublicClass {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public class")
}
}
define_violation!(
pub struct PublicMethod;
);
impl Violation for PublicMethod {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public method")
}
}
define_violation!(
pub struct PublicFunction;
);
impl Violation for PublicFunction {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public function")
}
}
define_violation!(
pub struct PublicPackage;
);
impl Violation for PublicPackage {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public package")
}
}
define_violation!(
pub struct MagicMethod;
);
impl Violation for MagicMethod {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in magic method")
}
}
define_violation!(
pub struct PublicNestedClass;
);
impl Violation for PublicNestedClass {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in public nested class")
}
}
define_violation!(
pub struct PublicInit;
);
impl Violation for PublicInit {
#[derive_message_formats]
fn message(&self) -> String {
format!("Missing docstring in `__init__`")
}
}
define_violation!(
pub struct FitsOnOneLine;
);
impl AlwaysAutofixableViolation for FitsOnOneLine {
#[derive_message_formats]
fn message(&self) -> String {
format!("One-line docstring should fit on one line")
}
fn autofix_title(&self) -> String {
"Reformat to one line".to_string()
}
}
define_violation!(
pub struct NoBlankLineBeforeFunction {
pub num_lines: usize,
}
);
impl AlwaysAutofixableViolation for NoBlankLineBeforeFunction {
#[derive_message_formats]
fn message(&self) -> String {
let NoBlankLineBeforeFunction { num_lines } = self;
format!("No blank lines allowed before function docstring (found {num_lines})")
}
fn autofix_title(&self) -> String {
"Remove blank line(s) before function docstring".to_string()
}
}
define_violation!(
pub struct NoBlankLineAfterFunction {
pub num_lines: usize,
}
);
impl AlwaysAutofixableViolation for NoBlankLineAfterFunction {
#[derive_message_formats]
fn message(&self) -> String {
let NoBlankLineAfterFunction { num_lines } = self;
format!("No blank lines allowed after function docstring (found {num_lines})")
}
fn autofix_title(&self) -> String {
"Remove blank line(s) after function docstring".to_string()
}
}
define_violation!(
pub struct OneBlankLineBeforeClass {
pub lines: usize,
}
);
impl AlwaysAutofixableViolation for OneBlankLineBeforeClass {
#[derive_message_formats]
fn message(&self) -> String {
format!("1 blank line required before class docstring")
}
fn autofix_title(&self) -> String {
"Insert 1 blank line before class docstring".to_string()
}
}
define_violation!(
pub struct OneBlankLineAfterClass {
pub lines: usize,
}
);
impl AlwaysAutofixableViolation for OneBlankLineAfterClass {
#[derive_message_formats]
fn message(&self) -> String {
format!("1 blank line required after class docstring")
}
fn autofix_title(&self) -> String {
"Insert 1 blank line after class docstring".to_string()
}
}
define_violation!(
pub struct BlankLineAfterSummary {
pub num_lines: usize,
}
);
fn fmt_blank_line_after_summary_autofix_msg(_: &BlankLineAfterSummary) -> String {
"Insert single blank line".to_string()
}
impl Violation for BlankLineAfterSummary {
const AUTOFIX: Option<AutofixKind> = Some(AutofixKind::new(Availability::Always));
#[derive_message_formats]
fn message(&self) -> String {
let BlankLineAfterSummary { num_lines } = self;
if *num_lines == 0 {
format!("1 blank line required between summary line and description")
} else {
format!(
"1 blank line required between summary line and description (found {num_lines})"
)
}
}
fn autofix_title_formatter(&self) -> Option<fn(&Self) -> String> {
let BlankLineAfterSummary { num_lines } = self;
if *num_lines > 0 {
return Some(fmt_blank_line_after_summary_autofix_msg);
}
None
}
}
define_violation!(
pub struct IndentWithSpaces;
);
impl Violation for IndentWithSpaces {
#[derive_message_formats]
fn message(&self) -> String {
format!("Docstring should be indented with spaces, not tabs")
}
}
define_violation!(
pub struct NoUnderIndentation;
);
impl AlwaysAutofixableViolation for NoUnderIndentation {
#[derive_message_formats]
fn message(&self) -> String {
format!("Docstring is under-indented")
}
fn autofix_title(&self) -> String {
"Increase indentation".to_string()
}
}
define_violation!(
pub struct NoOverIndentation;
);
impl AlwaysAutofixableViolation for NoOverIndentation {
#[derive_message_formats]
fn message(&self) -> String {
format!("Docstring is over-indented")
}
fn autofix_title(&self) -> String {
"Remove over-indentation".to_string()
}
}
define_violation!(
pub struct NewLineAfterLastParagraph;
);
impl AlwaysAutofixableViolation for NewLineAfterLastParagraph {
#[derive_message_formats]
fn message(&self) -> String {
format!("Multi-line docstring closing quotes should be on a separate line")
}
fn autofix_title(&self) -> String {
"Move closing quotes to new line".to_string()
}
}
define_violation!(
pub struct NoSurroundingWhitespace;
);
impl AlwaysAutofixableViolation for NoSurroundingWhitespace {
#[derive_message_formats]
fn message(&self) -> String {
format!("No whitespaces allowed surrounding docstring text")
}
fn autofix_title(&self) -> String {
"Trim surrounding whitespace".to_string()
}
}
define_violation!(
pub struct NoBlankLineBeforeClass {
pub lines: usize,
}
);
impl AlwaysAutofixableViolation for NoBlankLineBeforeClass {
#[derive_message_formats]
fn message(&self) -> String {
format!("No blank lines allowed before class docstring")
}
fn autofix_title(&self) -> String {
"Remove blank line(s) before class docstring".to_string()
}
}
define_violation!(
pub struct MultiLineSummaryFirstLine;
);
impl AlwaysAutofixableViolation for MultiLineSummaryFirstLine {
#[derive_message_formats]
fn message(&self) -> String {
format!("Multi-line docstring summary should start at the first line")
}
fn autofix_title(&self) -> String {
"Remove whitespace after opening quotes".to_string()
}
}
define_violation!(
pub struct MultiLineSummarySecondLine;
);
impl AlwaysAutofixableViolation for MultiLineSummarySecondLine {
#[derive_message_formats]
fn message(&self) -> String {
format!("Multi-line docstring summary should start at the second line")
}
fn autofix_title(&self) -> String {
"Insert line break and indentation after opening quotes".to_string()
}
}
define_violation!(
pub struct SectionNotOverIndented {
pub name: String,
}
);
impl AlwaysAutofixableViolation for SectionNotOverIndented {
#[derive_message_formats]
fn message(&self) -> String {
let SectionNotOverIndented { name } = self;
format!("Section is over-indented (\"{name}\")")
}
fn autofix_title(&self) -> String {
let SectionNotOverIndented { name } = self;
format!("Remove over-indentation from \"{name}\"")
}
}
define_violation!(
pub struct SectionUnderlineNotOverIndented {
pub name: String,
}
);
impl AlwaysAutofixableViolation for SectionUnderlineNotOverIndented {
#[derive_message_formats]
fn message(&self) -> String {
let SectionUnderlineNotOverIndented { name } = self;
format!("Section underline is over-indented (\"{name}\")")
}
fn autofix_title(&self) -> String {
let SectionUnderlineNotOverIndented { name } = self;
format!("Remove over-indentation from \"{name}\" underline")
}
}
define_violation!(
pub struct UsesTripleQuotes;
);
impl Violation for UsesTripleQuotes {
#[derive_message_formats]
fn message(&self) -> String {
format!(r#"Use """triple double quotes""""#)
}
}
define_violation!(
pub struct UsesRPrefixForBackslashedContent;
);
impl Violation for UsesRPrefixForBackslashedContent {
#[derive_message_formats]
fn message(&self) -> String {
format!(r#"Use r""" if any backslashes in a docstring"#)
}
}
define_violation!(
pub struct EndsInPeriod;
);
impl AlwaysAutofixableViolation for EndsInPeriod {
#[derive_message_formats]
fn message(&self) -> String {
format!("First line should end with a period")
}
fn autofix_title(&self) -> String {
"Add period".to_string()
}
}
define_violation!(
pub struct NoSignature;
);
impl Violation for NoSignature {
#[derive_message_formats]
fn message(&self) -> String {
format!("First line should not be the function's signature")
}
}
define_violation!(
pub struct FirstLineCapitalized;
);
impl Violation for FirstLineCapitalized {
#[derive_message_formats]
fn message(&self) -> String {
format!("First word of the first line should be properly capitalized")
}
}
define_violation!(
pub struct NoThisPrefix;
);
impl Violation for NoThisPrefix {
#[derive_message_formats]
fn message(&self) -> String {
format!(r#"First word of the docstring should not be "This""#)
}
}
define_violation!(
pub struct CapitalizeSectionName {
pub name: String,
}
);
impl AlwaysAutofixableViolation for CapitalizeSectionName {
#[derive_message_formats]
fn message(&self) -> String {
let CapitalizeSectionName { name } = self;
format!("Section name should be properly capitalized (\"{name}\")")
}
fn autofix_title(&self) -> String {
let CapitalizeSectionName { name } = self;
format!("Capitalize \"{name}\"")
}
}
define_violation!(
pub struct NewLineAfterSectionName {
pub name: String,
}
);
impl AlwaysAutofixableViolation for NewLineAfterSectionName {
#[derive_message_formats]
fn message(&self) -> String {
let NewLineAfterSectionName { name } = self;
format!("Section name should end with a newline (\"{name}\")")
}
fn autofix_title(&self) -> String {
let NewLineAfterSectionName { name } = self;
format!("Add newline after \"{name}\"")
}
}
define_violation!(
pub struct DashedUnderlineAfterSection {
pub name: String,
}
);
impl AlwaysAutofixableViolation for DashedUnderlineAfterSection {
#[derive_message_formats]
fn message(&self) -> String {
let DashedUnderlineAfterSection { name } = self;
format!("Missing dashed underline after section (\"{name}\")")
}
fn autofix_title(&self) -> String {
let DashedUnderlineAfterSection { name } = self;
format!("Add dashed line under \"{name}\"")
}
}
define_violation!(
pub struct SectionUnderlineAfterName {
pub name: String,
}
);
impl AlwaysAutofixableViolation for SectionUnderlineAfterName {
#[derive_message_formats]
fn message(&self) -> String {
let SectionUnderlineAfterName { name } = self;
format!("Section underline should be in the line following the section's name (\"{name}\")")
}
fn autofix_title(&self) -> String {
let SectionUnderlineAfterName { name } = self;
format!("Add underline to \"{name}\"")
}
}
define_violation!(
pub struct SectionUnderlineMatchesSectionLength {
pub name: String,
}
);
impl AlwaysAutofixableViolation for SectionUnderlineMatchesSectionLength {
#[derive_message_formats]
fn message(&self) -> String {
let SectionUnderlineMatchesSectionLength { name } = self;
format!("Section underline should match the length of its name (\"{name}\")")
}
fn autofix_title(&self) -> String {
let SectionUnderlineMatchesSectionLength { name } = self;
format!("Adjust underline length to match \"{name}\"")
}
}
define_violation!(
pub struct BlankLineAfterSection {
pub name: String,
}
);
impl AlwaysAutofixableViolation for BlankLineAfterSection {
#[derive_message_formats]
fn message(&self) -> String {
let BlankLineAfterSection { name } = self;
format!("Missing blank line after section (\"{name}\")")
}
fn autofix_title(&self) -> String {
let BlankLineAfterSection { name } = self;
format!("Add blank line after \"{name}\"")
}
}
define_violation!(
pub struct BlankLineBeforeSection {
pub name: String,
}
);
impl AlwaysAutofixableViolation for BlankLineBeforeSection {
#[derive_message_formats]
fn message(&self) -> String {
let BlankLineBeforeSection { name } = self;
format!("Missing blank line before section (\"{name}\")")
}
fn autofix_title(&self) -> String {
let BlankLineBeforeSection { name } = self;
format!("Add blank line before \"{name}\"")
}
}
define_violation!(
pub struct NoBlankLinesBetweenHeaderAndContent {
pub name: String,
}
);
impl AlwaysAutofixableViolation for NoBlankLinesBetweenHeaderAndContent {
#[derive_message_formats]
fn message(&self) -> String {
let NoBlankLinesBetweenHeaderAndContent { name } = self;
format!("No blank lines allowed between a section header and its content (\"{name}\")")
}
fn autofix_title(&self) -> String {
"Remove blank line(s)".to_string()
}
}
define_violation!(
pub struct BlankLineAfterLastSection {
pub name: String,
}
);
impl AlwaysAutofixableViolation for BlankLineAfterLastSection {
#[derive_message_formats]
fn message(&self) -> String {
let BlankLineAfterLastSection { name } = self;
format!("Missing blank line after last section (\"{name}\")")
}
fn autofix_title(&self) -> String {
let BlankLineAfterLastSection { name } = self;
format!("Add blank line after \"{name}\"")
}
}
define_violation!(
pub struct NonEmptySection {
pub name: String,
}
);
impl Violation for NonEmptySection {
#[derive_message_formats]
fn message(&self) -> String {
let NonEmptySection { name } = self;
format!("Section has no content (\"{name}\")")
}
}
define_violation!(
pub struct EndsInPunctuation;
);
impl AlwaysAutofixableViolation for EndsInPunctuation {
#[derive_message_formats]
fn message(&self) -> String {
format!("First line should end with a period, question mark, or exclamation point")
}
fn autofix_title(&self) -> String {
"Add closing punctuation".to_string()
}
}
define_violation!(
pub struct SectionNameEndsInColon {
pub name: String,
}
);
impl AlwaysAutofixableViolation for SectionNameEndsInColon {
#[derive_message_formats]
fn message(&self) -> String {
let SectionNameEndsInColon { name } = self;
format!("Section name should end with a colon (\"{name}\")")
}
fn autofix_title(&self) -> String {
let SectionNameEndsInColon { name } = self;
format!("Add colon to \"{name}\"")
}
}
define_violation!(
pub struct DocumentAllArguments {
pub names: Vec<String>,
}
);
impl Violation for DocumentAllArguments {
#[derive_message_formats]
fn message(&self) -> String {
let DocumentAllArguments { names } = self;
if names.len() == 1 {
let name = &names[0];
format!("Missing argument description in the docstring: `{name}`")
} else {
let names = names.iter().map(|name| format!("`{name}`")).join(", ");
format!("Missing argument descriptions in the docstring: {names}")
}
}
}
define_violation!(
pub struct SkipDocstring;
);
impl Violation for SkipDocstring {
#[derive_message_formats]
fn message(&self) -> String {
format!("Function decorated with `@overload` shouldn't contain a docstring")
}
}
define_violation!(
pub struct NonEmpty;
);
impl Violation for NonEmpty {
#[derive_message_formats]
fn message(&self) -> String {
format!("Docstring is empty")
}
}
// pep8-naming // pep8-naming
define_violation!( define_violation!(