mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 14:21:24 +00:00
Enforce max-doc-length for multi-line docstrings (#4347)
This commit is contained in:
parent
ddbe5a1243
commit
5f64d2346f
5 changed files with 57 additions and 12 deletions
|
@ -2,7 +2,7 @@
|
|||
"""Here's a top-level docstring that's over the limit."""
|
||||
|
||||
|
||||
def f():
|
||||
def f1():
|
||||
"""Here's a docstring that's also over the limit."""
|
||||
|
||||
x = 1 # Here's a comment that's over the limit, but it's not standalone.
|
||||
|
@ -16,3 +16,16 @@ def f():
|
|||
|
||||
|
||||
"This is also considered a docstring, and is over the limit."
|
||||
|
||||
|
||||
def f2():
|
||||
"""Here's a multi-line docstring.
|
||||
|
||||
It's over the limit on this line, which isn't the first line in the docstring.
|
||||
"""
|
||||
|
||||
|
||||
def f3():
|
||||
"""Here's a multi-line docstring.
|
||||
|
||||
It's over the limit on this line, which isn't the first line in the docstring."""
|
||||
|
|
|
@ -118,7 +118,7 @@ pub fn check_physical_lines(
|
|||
}
|
||||
|
||||
while doc_lines_iter
|
||||
.next_if(|doc_line_start| line.range().contains(**doc_line_start))
|
||||
.next_if(|doc_line_start| line.range().contains_inclusive(**doc_line_start))
|
||||
.is_some()
|
||||
{
|
||||
if enforce_doc_line_too_long {
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
//! Doc line extraction. In this context, a doc line is a line consisting of a
|
||||
//! standalone comment or a constant string statement.
|
||||
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
use std::iter::FusedIterator;
|
||||
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
use rustpython_parser::ast::{Constant, ExprKind, Stmt, StmtKind, Suite};
|
||||
use rustpython_parser::lexer::LexResult;
|
||||
use rustpython_parser::Tok;
|
||||
|
||||
use ruff_python_ast::newlines::UniversalNewlineIterator;
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
use ruff_python_ast::visitor;
|
||||
use ruff_python_ast::visitor::Visitor;
|
||||
|
||||
|
@ -69,12 +70,12 @@ impl Iterator for DocLines<'_> {
|
|||
|
||||
impl FusedIterator for DocLines<'_> {}
|
||||
|
||||
#[derive(Default)]
|
||||
struct StringLinesVisitor {
|
||||
struct StringLinesVisitor<'a> {
|
||||
string_lines: Vec<TextSize>,
|
||||
locator: &'a Locator<'a>,
|
||||
}
|
||||
|
||||
impl Visitor<'_> for StringLinesVisitor {
|
||||
impl Visitor<'_> for StringLinesVisitor<'_> {
|
||||
fn visit_stmt(&mut self, stmt: &Stmt) {
|
||||
if let StmtKind::Expr { value } = &stmt.node {
|
||||
if let ExprKind::Constant {
|
||||
|
@ -82,16 +83,30 @@ impl Visitor<'_> for StringLinesVisitor {
|
|||
..
|
||||
} = &value.node
|
||||
{
|
||||
self.string_lines.push(value.start());
|
||||
for line in UniversalNewlineIterator::with_offset(
|
||||
self.locator.slice(value.range()),
|
||||
value.start(),
|
||||
) {
|
||||
self.string_lines.push(line.start());
|
||||
}
|
||||
}
|
||||
}
|
||||
visitor::walk_stmt(self, stmt);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> StringLinesVisitor<'a> {
|
||||
fn new(locator: &'a Locator<'a>) -> Self {
|
||||
Self {
|
||||
string_lines: Vec::new(),
|
||||
locator,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract doc lines (standalone strings) start positions from an AST.
|
||||
pub fn doc_lines_from_ast(python_ast: &Suite) -> Vec<TextSize> {
|
||||
let mut visitor = StringLinesVisitor::default();
|
||||
pub fn doc_lines_from_ast(python_ast: &Suite, locator: &Locator) -> Vec<TextSize> {
|
||||
let mut visitor = StringLinesVisitor::new(locator);
|
||||
visitor.visit_body(python_ast);
|
||||
visitor.string_lines
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ pub fn check_path(
|
|||
diagnostics.extend(import_diagnostics);
|
||||
}
|
||||
if use_doc_lines {
|
||||
doc_lines.extend(doc_lines_from_ast(&python_ast));
|
||||
doc_lines.extend(doc_lines_from_ast(&python_ast, locator));
|
||||
}
|
||||
}
|
||||
Err(parse_error) => {
|
||||
|
|
|
@ -10,7 +10,7 @@ W505.py:2:51: W505 Doc line too long (57 > 50 characters)
|
|||
|
||||
W505.py:6:51: W505 Doc line too long (56 > 50 characters)
|
||||
|
|
||||
6 | def f():
|
||||
6 | def f1():
|
||||
7 | """Here's a docstring that's also over the limit."""
|
||||
| ^^^^^^ W505
|
||||
8 |
|
||||
|
@ -42,4 +42,21 @@ W505.py:18:51: W505 Doc line too long (61 > 50 characters)
|
|||
| ^^^^^^^^^^^ W505
|
||||
|
|
||||
|
||||
W505.py:24:51: W505 Doc line too long (82 > 50 characters)
|
||||
|
|
||||
24 | """Here's a multi-line docstring.
|
||||
25 |
|
||||
26 | It's over the limit on this line, which isn't the first line in the docstring.
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ W505
|
||||
27 | """
|
||||
|
|
||||
|
||||
W505.py:31:51: W505 Doc line too long (85 > 50 characters)
|
||||
|
|
||||
31 | """Here's a multi-line docstring.
|
||||
32 |
|
||||
33 | It's over the limit on this line, which isn't the first line in the docstring."""
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ W505
|
||||
|
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue