mirror of
https://github.com/astral-sh/ruff
synced 2026-01-21 13:30:49 -05:00
This PR implements `W505` (`DocLineTooLong`), which is similar to `E501` (`LineTooLong`) but confined to doc lines. I based the "doc line" definition on pycodestyle, which defines a doc line as a standalone comment or string statement. Our definition is a bit more liberal, since we consider any string statement a doc line (even if it's part of a multi-line statement) -- but that seems fine to me. Note that, unusually, this rule requires custom extraction from both the token stream (to find standalone comments) and the AST (to find string statements). Closes #1784.
59 lines
1.8 KiB
Rust
59 lines
1.8 KiB
Rust
//! Doc line extraction. In this context, a doc line is a line consisting of a
|
|
//! standalone comment or a constant string statement.
|
|
|
|
use rustpython_ast::{Constant, ExprKind, Stmt, StmtKind, Suite};
|
|
use rustpython_parser::lexer::{LexResult, Tok};
|
|
|
|
use crate::ast::visitor;
|
|
use crate::ast::visitor::Visitor;
|
|
|
|
/// Extract doc lines (standalone comments) from a token sequence.
|
|
pub fn doc_lines_from_tokens(lxr: &[LexResult]) -> Vec<usize> {
|
|
let mut doc_lines: Vec<usize> = Vec::default();
|
|
let mut prev: Option<usize> = None;
|
|
for (start, tok, end) in lxr.iter().flatten() {
|
|
if matches!(tok, Tok::Indent | Tok::Dedent | Tok::Newline) {
|
|
continue;
|
|
}
|
|
if matches!(tok, Tok::Comment(..)) {
|
|
if let Some(prev) = prev {
|
|
if start.row() > prev {
|
|
doc_lines.push(start.row());
|
|
}
|
|
} else {
|
|
doc_lines.push(start.row());
|
|
}
|
|
}
|
|
prev = Some(end.row());
|
|
}
|
|
doc_lines
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct StringLinesVisitor {
|
|
string_lines: Vec<usize>,
|
|
}
|
|
|
|
impl Visitor<'_> for StringLinesVisitor {
|
|
fn visit_stmt(&mut self, stmt: &Stmt) {
|
|
if let StmtKind::Expr { value } = &stmt.node {
|
|
if let ExprKind::Constant {
|
|
value: Constant::Str(..),
|
|
..
|
|
} = &value.node
|
|
{
|
|
self.string_lines
|
|
.extend(value.location.row()..=value.end_location.unwrap().row());
|
|
}
|
|
}
|
|
visitor::walk_stmt(self, stmt);
|
|
}
|
|
}
|
|
|
|
/// Extract doc lines (standalone strings) from an AST.
|
|
pub fn doc_lines_from_ast(python_ast: &Suite) -> Vec<usize> {
|
|
let mut visitor = StringLinesVisitor::default();
|
|
visitor.visit_body(python_ast);
|
|
visitor.string_lines
|
|
}
|