diff --git a/crates/ruff/resources/test/fixtures/pydocstyle/D403.py b/crates/ruff/resources/test/fixtures/pydocstyle/D403.py index 3cc63a5af7..d90acb358e 100644 --- a/crates/ruff/resources/test/fixtures/pydocstyle/D403.py +++ b/crates/ruff/resources/test/fixtures/pydocstyle/D403.py @@ -16,3 +16,12 @@ def utf8_function(): def uppercase_char_not_possible(): """'args' is not capitalized.""" + +def non_alphabetic(): + """th!is is not capitalized.""" + +def non_ascii(): + """th•s is not capitalized.""" + +def all_caps(): + """th•s is not capitalized.""" diff --git a/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs b/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs index 28776d97f0..eab3d35ad4 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs @@ -40,36 +40,27 @@ pub fn capitalized(checker: &mut Checker, docstring: &Docstring) { } let body = docstring.body(); - let Some(first_word) = body.split(' ').next() else { return }; - if first_word == first_word.to_uppercase() { - return; - } + + // Like pydocstyle, we only support ASCII for now. for char in first_word.chars() { if !char.is_ascii_alphabetic() && char != '\'' { return; } } + let mut first_word_chars = first_word.chars(); let Some(first_char) = first_word_chars.next() else { return; }; - if first_char.is_uppercase() { - return; - }; - if first_char - .to_uppercase() - .next() - .map_or(false, |uppercase_first_char| { - uppercase_first_char == first_char - }) - { + let uppercase_first_char = first_char.to_ascii_uppercase(); + if first_char == uppercase_first_char { return; } - let capitalized_word = first_char.to_uppercase().to_string() + first_word_chars.as_str(); + let capitalized_word = uppercase_first_char.to_string() + first_word_chars.as_str(); let mut diagnostic = Diagnostic::new( FirstLineCapitalized {