Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71802f8861 | ||
|
|
5b6fb8cefa | ||
|
|
2ff964107c | ||
|
|
141132d5be | ||
|
|
8ba872ece4 | ||
|
|
209dce2033 | ||
|
|
90d88dfb10 |
71
Cargo.lock
generated
71
Cargo.lock
generated
@@ -64,6 +64,20 @@ dependencies = [
|
||||
"term",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "assert_cmd"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93ae1ddd39efd67689deb1979d80bad3bf7f2b09c6e6117c8d1f2443b5e2f83e"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"doc-comment",
|
||||
"predicates",
|
||||
"predicates-core",
|
||||
"predicates-tree",
|
||||
"wait-timeout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "1.7.1"
|
||||
@@ -580,6 +594,12 @@ version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "difflib"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.8.1"
|
||||
@@ -658,6 +678,12 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "doc-comment"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.0"
|
||||
@@ -1685,6 +1711,33 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "predicates"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c"
|
||||
dependencies = [
|
||||
"difflib",
|
||||
"itertools",
|
||||
"predicates-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "predicates-core"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb"
|
||||
|
||||
[[package]]
|
||||
name = "predicates-tree"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032"
|
||||
dependencies = [
|
||||
"predicates-core",
|
||||
"termtree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
@@ -1907,9 +1960,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.68"
|
||||
version = "0.0.69"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
"bincode",
|
||||
"cacache",
|
||||
"chrono",
|
||||
@@ -2345,6 +2399,12 @@ dependencies = [
|
||||
"phf_codegen 0.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termtree"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.37"
|
||||
@@ -2593,6 +2653,15 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8e76fae08f03f96e166d2dfda232190638c10e0383841252416f9cfe2ae60e6"
|
||||
|
||||
[[package]]
|
||||
name = "wait-timeout"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "waker-fn"
|
||||
version = "1.1.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.68"
|
||||
version = "0.0.69"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
@@ -40,6 +40,7 @@ strum_macros = "0.24.3"
|
||||
num-bigint = "0.4.3"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "2.0.4"
|
||||
insta = { version = "1.19.1", features = ["yaml"] }
|
||||
|
||||
[features]
|
||||
|
||||
19
README.md
19
README.md
@@ -217,8 +217,8 @@ ruff also implements some of the most popular Flake8 plugins natively, including
|
||||
- [`flake8-print`](https://pypi.org/project/flake8-print/)
|
||||
- [`flake8-comprehensions`](https://pypi.org/project/flake8-comprehensions/) (11/16)
|
||||
- [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) (3/32)
|
||||
- [`flake8-docstrings`](https://pypi.org/project/flake8-docstrings/) (6/47)
|
||||
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (partial)
|
||||
- [`flake8-docstrings`](https://pypi.org/project/flake8-docstrings/) (11/47)
|
||||
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (8/34)
|
||||
|
||||
Beyond rule-set parity, ruff suffers from the following limitations vis-à-vis Flake8:
|
||||
|
||||
@@ -281,7 +281,7 @@ The 🛠 emoji indicates that a rule is automatically fixable by the `--fix` com
|
||||
| A002 | BuiltinArgumentShadowing | Argument `...` is shadowing a python builtin | | |
|
||||
| A003 | BuiltinAttributeShadowing | Class attribute `...` is shadowing a python builtin | | |
|
||||
| B011 | DoNotAssertFalse | Do not `assert False` (`python -O` removes these calls), raise `AssertionError()` | | 🛠 |
|
||||
| B014 | DuplicateHandlerException | Exception handler with duplicate exception: `ValueError | | 🛠 |
|
||||
| B014 | DuplicateHandlerException | Exception handler with duplicate exception: `ValueError` | | 🛠 |
|
||||
| B025 | DuplicateTryBlockException | try-except block with duplicate exception `Exception` | | |
|
||||
| C400 | UnnecessaryGeneratorList | Unnecessary generator - rewrite as a list comprehension | | |
|
||||
| C401 | UnnecessaryGeneratorSet | Unnecessary generator - rewrite as a set comprehension | | |
|
||||
@@ -304,12 +304,17 @@ The 🛠 emoji indicates that a rule is automatically fixable by the `--fix` com
|
||||
| U006 | UsePEP585Annotation | Use `list` instead of `List` for type annotations | | 🛠 |
|
||||
| U007 | UsePEP604Annotation | Use `X \| Y` for type annotations | | 🛠 |
|
||||
| U008 | SuperCallWithParameters | Use `super()` instead of `super(__class__, self)` | | 🛠 |
|
||||
| D200 | OneLinerDocstring | One-line docstring should fit on one line | | |
|
||||
| D205 | BlankLineAfterSummary | 1 blank line required between summary line and description | | |
|
||||
| D200 | FitsOnOneLine | One-line docstring should fit on one line | | |
|
||||
| D205 | NoBlankLineAfterSummary | 1 blank line required between summary line and description | | |
|
||||
| D209 | NewLineAfterLastParagraph | Multi-line docstring closing quotes should be on a separate line | | |
|
||||
| D210 | NoSurroundingWhitespace | No whitespaces allowed surrounding docstring text | | |
|
||||
| D400 | DocstringEndsInNonPeriod | First line should end with a period | | |
|
||||
| D419 | EmptyDocstring | Docstring is empty | | |
|
||||
| D212 | MultiLineSummaryFirstLine | Multi-line docstring summary should start at the first line | | |
|
||||
| D213 | MultiLineSummarySecondLine | Multi-line docstring summary should start at the second line | | |
|
||||
| D300 | UsesTripleQuotes | Use """triple double quotes""" | | |
|
||||
| D400 | EndsInPeriod | First line should end with a period | | |
|
||||
| D403 | FirstLineCapitalized | First word of the first line should be properly capitalized | | |
|
||||
| D415 | EndsInPunctuation | First line should end with a period, question mark, or exclamation point | | |
|
||||
| D419 | NonEmpty | Docstring is empty | | |
|
||||
| M001 | UnusedNOQA | Unused `noqa` directive | | 🛠 |
|
||||
|
||||
## Integrations
|
||||
|
||||
23
setup.py
Normal file
23
setup.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import sys
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
sys.stderr.write(
|
||||
"""
|
||||
===============================
|
||||
Unsupported installation method
|
||||
===============================
|
||||
ruff no longer supports installation with `python setup.py install`.
|
||||
Please use `python -m pip install .` instead.
|
||||
"""
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# The below code will never execute, however GitHub is particularly
|
||||
# picky about where it finds Python packaging metadata.
|
||||
# See: https://github.com/github/feedback/discussions/6456
|
||||
#
|
||||
# To be removed once GitHub catches up.
|
||||
|
||||
setup(name="ruff", install_requires=[])
|
||||
@@ -1890,6 +1890,9 @@ impl<'a> Checker<'a> {
|
||||
|
||||
fn check_docstrings(&mut self) {
|
||||
while let Some(docstring) = self.docstrings.pop() {
|
||||
if !docstrings::not_empty(self, &docstring) {
|
||||
continue;
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::D200) {
|
||||
docstrings::one_liner(self, &docstring);
|
||||
}
|
||||
@@ -1902,11 +1905,22 @@ impl<'a> Checker<'a> {
|
||||
if self.settings.enabled.contains(&CheckCode::D210) {
|
||||
docstrings::no_surrounding_whitespace(self, &docstring);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::D212)
|
||||
|| self.settings.enabled.contains(&CheckCode::D213)
|
||||
{
|
||||
docstrings::multi_line_summary_start(self, &docstring);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::D300) {
|
||||
docstrings::triple_quotes(self, &docstring);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::D400) {
|
||||
docstrings::ends_with_period(self, &docstring);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::D419) {
|
||||
docstrings::not_empty(self, &docstring);
|
||||
if self.settings.enabled.contains(&CheckCode::D403) {
|
||||
docstrings::capitalized(self, &docstring);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::D415) {
|
||||
docstrings::ends_with_punctuation(self, &docstring);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,12 @@ pub enum CheckCode {
|
||||
D205,
|
||||
D209,
|
||||
D210,
|
||||
D212,
|
||||
D213,
|
||||
D300,
|
||||
D400,
|
||||
D403,
|
||||
D415,
|
||||
D419,
|
||||
// Meta
|
||||
M001,
|
||||
@@ -254,12 +259,17 @@ pub enum CheckKind {
|
||||
UsePEP604Annotation,
|
||||
SuperCallWithParameters,
|
||||
// pydocstyle
|
||||
OneLinerDocstring,
|
||||
BlankLineAfterSummary,
|
||||
EndsInPeriod,
|
||||
EndsInPunctuation,
|
||||
FirstLineCapitalized,
|
||||
FitsOnOneLine,
|
||||
MultiLineSummaryFirstLine,
|
||||
MultiLineSummarySecondLine,
|
||||
NewLineAfterLastParagraph,
|
||||
NoBlankLineAfterSummary,
|
||||
NoSurroundingWhitespace,
|
||||
EmptyDocstring,
|
||||
DocstringEndsInNonPeriod,
|
||||
NonEmpty,
|
||||
UsesTripleQuotes,
|
||||
// Meta
|
||||
UnusedNOQA(Option<Vec<String>>),
|
||||
}
|
||||
@@ -369,12 +379,17 @@ impl CheckCode {
|
||||
CheckCode::U007 => CheckKind::UsePEP604Annotation,
|
||||
CheckCode::U008 => CheckKind::SuperCallWithParameters,
|
||||
// pydocstyle
|
||||
CheckCode::D200 => CheckKind::OneLinerDocstring,
|
||||
CheckCode::D205 => CheckKind::BlankLineAfterSummary,
|
||||
CheckCode::D200 => CheckKind::FitsOnOneLine,
|
||||
CheckCode::D205 => CheckKind::NoBlankLineAfterSummary,
|
||||
CheckCode::D209 => CheckKind::NewLineAfterLastParagraph,
|
||||
CheckCode::D210 => CheckKind::NoSurroundingWhitespace,
|
||||
CheckCode::D400 => CheckKind::DocstringEndsInNonPeriod,
|
||||
CheckCode::D419 => CheckKind::EmptyDocstring,
|
||||
CheckCode::D400 => CheckKind::EndsInPeriod,
|
||||
CheckCode::D419 => CheckKind::NonEmpty,
|
||||
CheckCode::D212 => CheckKind::MultiLineSummaryFirstLine,
|
||||
CheckCode::D213 => CheckKind::MultiLineSummarySecondLine,
|
||||
CheckCode::D300 => CheckKind::UsesTripleQuotes,
|
||||
CheckCode::D403 => CheckKind::FirstLineCapitalized,
|
||||
CheckCode::D415 => CheckKind::EndsInPunctuation,
|
||||
// Meta
|
||||
CheckCode::M001 => CheckKind::UnusedNOQA(None),
|
||||
}
|
||||
@@ -463,12 +478,17 @@ impl CheckKind {
|
||||
CheckKind::UselessObjectInheritance(_) => &CheckCode::U004,
|
||||
CheckKind::SuperCallWithParameters => &CheckCode::U008,
|
||||
// pydocstyle
|
||||
CheckKind::OneLinerDocstring => &CheckCode::D200,
|
||||
CheckKind::BlankLineAfterSummary => &CheckCode::D205,
|
||||
CheckKind::FitsOnOneLine => &CheckCode::D200,
|
||||
CheckKind::NoBlankLineAfterSummary => &CheckCode::D205,
|
||||
CheckKind::NewLineAfterLastParagraph => &CheckCode::D209,
|
||||
CheckKind::NoSurroundingWhitespace => &CheckCode::D210,
|
||||
CheckKind::DocstringEndsInNonPeriod => &CheckCode::D400,
|
||||
CheckKind::EmptyDocstring => &CheckCode::D419,
|
||||
CheckKind::EndsInPeriod => &CheckCode::D400,
|
||||
CheckKind::NonEmpty => &CheckCode::D419,
|
||||
CheckKind::MultiLineSummaryFirstLine => &CheckCode::D212,
|
||||
CheckKind::MultiLineSummarySecondLine => &CheckCode::D213,
|
||||
CheckKind::UsesTripleQuotes => &CheckCode::D300,
|
||||
CheckKind::FirstLineCapitalized => &CheckCode::D403,
|
||||
CheckKind::EndsInPunctuation => &CheckCode::D415,
|
||||
// Meta
|
||||
CheckKind::UnusedNOQA(_) => &CheckCode::M001,
|
||||
}
|
||||
@@ -625,7 +645,7 @@ impl CheckKind {
|
||||
CheckKind::DuplicateHandlerException(names) => {
|
||||
if names.len() == 1 {
|
||||
let name = &names[0];
|
||||
format!("Exception handler with duplicate exception: `{name}")
|
||||
format!("Exception handler with duplicate exception: `{name}`")
|
||||
} else {
|
||||
let names = names.iter().map(|name| format!("`{name}`")).join(", ");
|
||||
format!("Exception handler with duplicate exceptions: {names}")
|
||||
@@ -713,8 +733,8 @@ impl CheckKind {
|
||||
"Use `super()` instead of `super(__class__, self)`".to_string()
|
||||
}
|
||||
// pydocstyle
|
||||
CheckKind::OneLinerDocstring => "One-line docstring should fit on one line".to_string(),
|
||||
CheckKind::BlankLineAfterSummary => {
|
||||
CheckKind::FitsOnOneLine => "One-line docstring should fit on one line".to_string(),
|
||||
CheckKind::NoBlankLineAfterSummary => {
|
||||
"1 blank line required between summary line and description".to_string()
|
||||
}
|
||||
CheckKind::NewLineAfterLastParagraph => {
|
||||
@@ -723,10 +743,22 @@ impl CheckKind {
|
||||
CheckKind::NoSurroundingWhitespace => {
|
||||
"No whitespaces allowed surrounding docstring text".to_string()
|
||||
}
|
||||
CheckKind::DocstringEndsInNonPeriod => {
|
||||
"First line should end with a period".to_string()
|
||||
CheckKind::EndsInPeriod => "First line should end with a period".to_string(),
|
||||
CheckKind::NonEmpty => "Docstring is empty".to_string(),
|
||||
CheckKind::EndsInPunctuation => {
|
||||
"First line should end with a period, question mark, or exclamation point"
|
||||
.to_string()
|
||||
}
|
||||
CheckKind::FirstLineCapitalized => {
|
||||
"First word of the first line should be properly capitalized".to_string()
|
||||
}
|
||||
CheckKind::UsesTripleQuotes => r#"Use """triple double quotes""""#.to_string(),
|
||||
CheckKind::MultiLineSummaryFirstLine => {
|
||||
"Multi-line docstring summary should start at the first line".to_string()
|
||||
}
|
||||
CheckKind::MultiLineSummarySecondLine => {
|
||||
"Multi-line docstring summary should start at the second line".to_string()
|
||||
}
|
||||
CheckKind::EmptyDocstring => "Docstring is empty".to_string(),
|
||||
// Meta
|
||||
CheckKind::UnusedNOQA(codes) => match codes {
|
||||
None => "Unused `noqa` directive".to_string(),
|
||||
|
||||
@@ -78,6 +78,9 @@ pub struct Cli {
|
||||
// TODO(charlie): This should be a sub-command.
|
||||
#[arg(long, hide = true)]
|
||||
pub autoformat: bool,
|
||||
/// The name of the file when passing it through stdin.
|
||||
#[arg(long)]
|
||||
pub stdin_filename: Option<String>,
|
||||
}
|
||||
|
||||
pub enum Warnable {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use rustpython_ast::{Constant, Expr, ExprKind, Location, Stmt, StmtKind};
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::check_ast::Checker;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
use rustpython_ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
|
||||
use crate::checks::{Check, CheckCode, CheckKind};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DocstringKind {
|
||||
@@ -17,7 +18,7 @@ pub struct Docstring<'a> {
|
||||
pub expr: &'a Expr,
|
||||
}
|
||||
|
||||
/// Extract a docstring from an expression.
|
||||
/// Extract a `Docstring` from an `Expr`.
|
||||
pub fn extract<'a, 'b>(
|
||||
checker: &'a Checker,
|
||||
stmt: &'b Stmt,
|
||||
@@ -27,7 +28,6 @@ pub fn extract<'a, 'b>(
|
||||
.binding_context()
|
||||
.defined_in
|
||||
.map(|index| checker.parents[index]);
|
||||
|
||||
match defined_in {
|
||||
None => {
|
||||
if checker.initial {
|
||||
@@ -61,6 +61,19 @@ pub fn extract<'a, 'b>(
|
||||
None
|
||||
}
|
||||
|
||||
/// Extract the source code range for a `Docstring`.
|
||||
fn range_for(docstring: &Docstring) -> Range {
|
||||
// RustPython currently omits the first quotation mark in a string, so offset the location.
|
||||
Range {
|
||||
location: Location::new(
|
||||
docstring.expr.location.row(),
|
||||
docstring.expr.location.column() - 1,
|
||||
),
|
||||
end_location: docstring.expr.end_location,
|
||||
}
|
||||
}
|
||||
|
||||
/// D200
|
||||
pub fn one_liner(checker: &mut Checker, docstring: &Docstring) {
|
||||
if let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
@@ -80,14 +93,12 @@ pub fn one_liner(checker: &mut Checker, docstring: &Docstring) {
|
||||
}
|
||||
|
||||
if non_empty_line_count == 1 && line_count > 1 {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::OneLinerDocstring,
|
||||
Range::from_located(docstring.expr),
|
||||
));
|
||||
checker.add_check(Check::new(CheckKind::FitsOnOneLine, range_for(docstring)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// D205
|
||||
pub fn blank_after_summary(checker: &mut Checker, docstring: &Docstring) {
|
||||
if let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
@@ -106,13 +117,14 @@ pub fn blank_after_summary(checker: &mut Checker, docstring: &Docstring) {
|
||||
}
|
||||
if lines_count > 1 && blanks_count != 1 {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::BlankLineAfterSummary,
|
||||
Range::from_located(docstring.expr),
|
||||
CheckKind::NoBlankLineAfterSummary,
|
||||
range_for(docstring),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// D209
|
||||
pub fn newline_after_last_paragraph(checker: &mut Checker, docstring: &Docstring) {
|
||||
if let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
@@ -127,13 +139,13 @@ pub fn newline_after_last_paragraph(checker: &mut Checker, docstring: &Docstring
|
||||
if line_count > 1 {
|
||||
let content = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring.expr));
|
||||
.slice_source_code_range(&range_for(docstring));
|
||||
if let Some(line) = content.lines().last() {
|
||||
let line = line.trim();
|
||||
if line != "\"\"\"" && line != "'''" {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::NewLineAfterLastParagraph,
|
||||
Range::from_located(docstring.expr),
|
||||
range_for(docstring),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -143,6 +155,7 @@ pub fn newline_after_last_paragraph(checker: &mut Checker, docstring: &Docstring
|
||||
}
|
||||
}
|
||||
|
||||
/// D210
|
||||
pub fn no_surrounding_whitespace(checker: &mut Checker, docstring: &Docstring) {
|
||||
if let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
@@ -154,32 +167,82 @@ pub fn no_surrounding_whitespace(checker: &mut Checker, docstring: &Docstring) {
|
||||
if line.trim().is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if line.starts_with(' ') || (matches!(lines.next(), None) && line.ends_with(' ')) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::NoSurroundingWhitespace,
|
||||
Range::from_located(docstring.expr),
|
||||
range_for(docstring),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn not_empty(checker: &mut Checker, docstring: &Docstring) {
|
||||
/// D212, D213
|
||||
pub fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstring) {
|
||||
if let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.expr.node
|
||||
{
|
||||
if string.trim().is_empty() {
|
||||
if string.lines().nth(1).is_some() {
|
||||
let content = checker
|
||||
.locator
|
||||
.slice_source_code_range(&range_for(docstring));
|
||||
if let Some(first_line) = content.lines().next() {
|
||||
let first_line = first_line.trim();
|
||||
if first_line == "\"\"\""
|
||||
|| first_line == "'''"
|
||||
|| first_line == "u\"\"\""
|
||||
|| first_line == "u'''"
|
||||
|| first_line == "r\"\"\""
|
||||
|| first_line == "r'''"
|
||||
|| first_line == "ur\"\"\""
|
||||
|| first_line == "ur'''"
|
||||
{
|
||||
if checker.settings.enabled.contains(&CheckCode::D212) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::MultiLineSummaryFirstLine,
|
||||
range_for(docstring),
|
||||
));
|
||||
}
|
||||
} else if checker.settings.enabled.contains(&CheckCode::D213) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::MultiLineSummarySecondLine,
|
||||
range_for(docstring),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// D300
|
||||
pub fn triple_quotes(checker: &mut Checker, docstring: &Docstring) {
|
||||
if let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.expr.node
|
||||
{
|
||||
let content = checker
|
||||
.locator
|
||||
.slice_source_code_range(&range_for(docstring));
|
||||
if string.contains("\"\"\"") {
|
||||
if !content.starts_with("'''") {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::UsesTripleQuotes,
|
||||
range_for(docstring),
|
||||
));
|
||||
}
|
||||
} else if !content.starts_with("\"\"\"") {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::EmptyDocstring,
|
||||
Range::from_located(docstring.expr),
|
||||
CheckKind::UsesTripleQuotes,
|
||||
range_for(docstring),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// D400
|
||||
pub fn ends_with_period(checker: &mut Checker, docstring: &Docstring) {
|
||||
if let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
@@ -188,11 +251,75 @@ pub fn ends_with_period(checker: &mut Checker, docstring: &Docstring) {
|
||||
{
|
||||
if let Some(string) = string.lines().next() {
|
||||
if !string.ends_with('.') {
|
||||
checker.add_check(Check::new(CheckKind::EndsInPeriod, range_for(docstring)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// D403
|
||||
pub fn capitalized(checker: &mut Checker, docstring: &Docstring) {
|
||||
if !matches!(docstring.kind, DocstringKind::Function) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.expr.node
|
||||
{
|
||||
if let Some(first_word) = string.split(' ').next() {
|
||||
if first_word == first_word.to_uppercase() {
|
||||
return;
|
||||
}
|
||||
for char in first_word.chars() {
|
||||
if !char.is_ascii_alphabetic() && char != '\'' {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if let Some(first_char) = first_word.chars().next() {
|
||||
if !first_char.is_uppercase() {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::FirstLineCapitalized,
|
||||
range_for(docstring),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// D415
|
||||
pub fn ends_with_punctuation(checker: &mut Checker, docstring: &Docstring) {
|
||||
if let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.expr.node
|
||||
{
|
||||
if let Some(string) = string.lines().next() {
|
||||
if !(string.ends_with('.') || string.ends_with('!') || string.ends_with('?')) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::DocstringEndsInNonPeriod,
|
||||
Range::from_located(docstring.expr),
|
||||
CheckKind::EndsInPunctuation,
|
||||
range_for(docstring),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// D419
|
||||
pub fn not_empty(checker: &mut Checker, docstring: &Docstring) -> bool {
|
||||
if let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.expr.node
|
||||
{
|
||||
if string.trim().is_empty() {
|
||||
if checker.settings.enabled.contains(&CheckCode::D419) {
|
||||
checker.add_check(Check::new(CheckKind::NonEmpty, range_for(docstring)));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
@@ -83,6 +83,36 @@ pub(crate) fn check_path(
|
||||
Ok(checks)
|
||||
}
|
||||
|
||||
pub fn lint_stdin(path: &Path, stdin: &str, settings: &Settings) -> Result<Vec<Message>> {
|
||||
// Tokenize once.
|
||||
let tokens: Vec<LexResult> = tokenize(stdin);
|
||||
|
||||
// Determine the noqa line for every line in the source.
|
||||
let noqa_line_for = noqa::extract_noqa_line_for(&tokens);
|
||||
|
||||
// Generate checks.
|
||||
let checks = check_path(
|
||||
path,
|
||||
stdin,
|
||||
tokens,
|
||||
&noqa_line_for,
|
||||
settings,
|
||||
&fixer::Mode::None,
|
||||
)?;
|
||||
|
||||
// Convert to messages.
|
||||
Ok(checks
|
||||
.into_iter()
|
||||
.map(|check| Message {
|
||||
kind: check.kind,
|
||||
fixed: check.fix.map(|fix| fix.applied).unwrap_or_default(),
|
||||
location: check.location,
|
||||
end_location: check.end_location,
|
||||
filename: path.to_string_lossy().to_string(),
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn lint_path(
|
||||
path: &Path,
|
||||
settings: &Settings,
|
||||
@@ -1026,6 +1056,42 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn d212() -> Result<()> {
|
||||
let mut checks = check_path(
|
||||
Path::new("./resources/test/fixtures/D.py"),
|
||||
&settings::Settings::for_rule(CheckCode::D212),
|
||||
&fixer::Mode::Generate,
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn d213() -> Result<()> {
|
||||
let mut checks = check_path(
|
||||
Path::new("./resources/test/fixtures/D.py"),
|
||||
&settings::Settings::for_rule(CheckCode::D213),
|
||||
&fixer::Mode::Generate,
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn d300() -> Result<()> {
|
||||
let mut checks = check_path(
|
||||
Path::new("./resources/test/fixtures/D.py"),
|
||||
&settings::Settings::for_rule(CheckCode::D300),
|
||||
&fixer::Mode::Generate,
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn d400() -> Result<()> {
|
||||
let mut checks = check_path(
|
||||
@@ -1038,6 +1104,30 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn d403() -> Result<()> {
|
||||
let mut checks = check_path(
|
||||
Path::new("./resources/test/fixtures/D.py"),
|
||||
&settings::Settings::for_rule(CheckCode::D403),
|
||||
&fixer::Mode::Generate,
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn d415() -> Result<()> {
|
||||
let mut checks = check_path(
|
||||
Path::new("./resources/test/fixtures/D.py"),
|
||||
&settings::Settings::for_rule(CheckCode::D415),
|
||||
&fixer::Mode::Generate,
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn d419() -> Result<()> {
|
||||
let mut checks = check_path(
|
||||
|
||||
29
src/main.rs
29
src/main.rs
@@ -1,4 +1,4 @@
|
||||
use std::io;
|
||||
use std::io::{self, Read};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::ExitCode;
|
||||
use std::sync::mpsc::channel;
|
||||
@@ -19,7 +19,7 @@ use ruff::cli::{warn_on, Cli, Warnable};
|
||||
use ruff::fs::iter_python_files;
|
||||
use ruff::linter::add_noqa_to_path;
|
||||
use ruff::linter::autoformat_path;
|
||||
use ruff::linter::lint_path;
|
||||
use ruff::linter::{lint_path, lint_stdin};
|
||||
use ruff::logging::set_up_logging;
|
||||
use ruff::message::Message;
|
||||
use ruff::printer::{Printer, SerializationFormat};
|
||||
@@ -75,6 +75,19 @@ fn show_files(files: &[PathBuf], settings: &Settings) {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_from_stdin() -> Result<String> {
|
||||
let mut buffer = String::new();
|
||||
io::stdin().lock().read_to_string(&mut buffer)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
fn run_once_stdin(settings: &Settings, filename: &Path) -> Result<Vec<Message>> {
|
||||
let stdin = read_from_stdin()?;
|
||||
let mut messages = lint_stdin(filename, &stdin, settings)?;
|
||||
messages.sort_unstable();
|
||||
Ok(messages)
|
||||
}
|
||||
|
||||
fn run_once(
|
||||
files: &[PathBuf],
|
||||
settings: &Settings,
|
||||
@@ -352,7 +365,17 @@ fn inner_main() -> Result<ExitCode> {
|
||||
println!("Formatted {modifications} files.");
|
||||
}
|
||||
} else {
|
||||
let messages = run_once(&cli.files, &settings, !cli.no_cache, cli.fix)?;
|
||||
let messages = if cli.files == vec![PathBuf::from("-")] {
|
||||
if cli.fix {
|
||||
eprintln!("Warning: --fix is not enabled when reading from stdin.");
|
||||
}
|
||||
|
||||
let filename = cli.stdin_filename.unwrap_or_else(|| "-".to_string());
|
||||
let path = Path::new(&filename);
|
||||
run_once_stdin(&settings, path)?
|
||||
} else {
|
||||
run_once(&cli.files, &settings, !cli.no_cache, cli.fix)?
|
||||
};
|
||||
if !cli.quiet {
|
||||
printer.write_once(&messages)?;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
source: src/linter.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: OneLinerDocstring
|
||||
- kind: FitsOnOneLine
|
||||
location:
|
||||
row: 124
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 126
|
||||
column: 8
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
source: src/linter.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: BlankLineAfterSummary
|
||||
- kind: NoBlankLineAfterSummary
|
||||
location:
|
||||
row: 195
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 198
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: BlankLineAfterSummary
|
||||
- kind: NoBlankLineAfterSummary
|
||||
location:
|
||||
row: 205
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 210
|
||||
column: 8
|
||||
|
||||
@@ -5,7 +5,7 @@ expression: checks
|
||||
- kind: NewLineAfterLastParagraph
|
||||
location:
|
||||
row: 276
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 278
|
||||
column: 20
|
||||
|
||||
@@ -5,7 +5,7 @@ expression: checks
|
||||
- kind: NoSurroundingWhitespace
|
||||
location:
|
||||
row: 283
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 283
|
||||
column: 34
|
||||
@@ -13,7 +13,7 @@ expression: checks
|
||||
- kind: NoSurroundingWhitespace
|
||||
location:
|
||||
row: 288
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 288
|
||||
column: 38
|
||||
@@ -21,7 +21,7 @@ expression: checks
|
||||
- kind: NoSurroundingWhitespace
|
||||
location:
|
||||
row: 294
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 297
|
||||
column: 8
|
||||
|
||||
13
src/snapshots/ruff__linter__tests__d212.snap
Normal file
13
src/snapshots/ruff__linter__tests__d212.snap
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
source: src/linter.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: MultiLineSummaryFirstLine
|
||||
location:
|
||||
row: 124
|
||||
column: 5
|
||||
end_location:
|
||||
row: 126
|
||||
column: 8
|
||||
fix: ~
|
||||
|
||||
133
src/snapshots/ruff__linter__tests__d213.snap
Normal file
133
src/snapshots/ruff__linter__tests__d213.snap
Normal file
@@ -0,0 +1,133 @@
|
||||
---
|
||||
source: src/linter.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 195
|
||||
column: 5
|
||||
end_location:
|
||||
row: 198
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 205
|
||||
column: 5
|
||||
end_location:
|
||||
row: 210
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 215
|
||||
column: 5
|
||||
end_location:
|
||||
row: 219
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 225
|
||||
column: 5
|
||||
end_location:
|
||||
row: 229
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 235
|
||||
column: 5
|
||||
end_location:
|
||||
row: 239
|
||||
column: 4
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 245
|
||||
column: 5
|
||||
end_location:
|
||||
row: 249
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 255
|
||||
column: 5
|
||||
end_location:
|
||||
row: 259
|
||||
column: 12
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 265
|
||||
column: 5
|
||||
end_location:
|
||||
row: 269
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 276
|
||||
column: 5
|
||||
end_location:
|
||||
row: 278
|
||||
column: 20
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 294
|
||||
column: 5
|
||||
end_location:
|
||||
row: 297
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 338
|
||||
column: 5
|
||||
end_location:
|
||||
row: 343
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 378
|
||||
column: 5
|
||||
end_location:
|
||||
row: 381
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 387
|
||||
column: 5
|
||||
end_location:
|
||||
row: 391
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 433
|
||||
column: 37
|
||||
end_location:
|
||||
row: 436
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 445
|
||||
column: 5
|
||||
end_location:
|
||||
row: 449
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: MultiLineSummarySecondLine
|
||||
location:
|
||||
row: 521
|
||||
column: 5
|
||||
end_location:
|
||||
row: 527
|
||||
column: 8
|
||||
fix: ~
|
||||
|
||||
45
src/snapshots/ruff__linter__tests__d300.snap
Normal file
45
src/snapshots/ruff__linter__tests__d300.snap
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
source: src/linter.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: UsesTripleQuotes
|
||||
location:
|
||||
row: 302
|
||||
column: 6
|
||||
end_location:
|
||||
row: 302
|
||||
column: 20
|
||||
fix: ~
|
||||
- kind: UsesTripleQuotes
|
||||
location:
|
||||
row: 307
|
||||
column: 6
|
||||
end_location:
|
||||
row: 307
|
||||
column: 20
|
||||
fix: ~
|
||||
- kind: UsesTripleQuotes
|
||||
location:
|
||||
row: 312
|
||||
column: 6
|
||||
end_location:
|
||||
row: 312
|
||||
column: 16
|
||||
fix: ~
|
||||
- kind: UsesTripleQuotes
|
||||
location:
|
||||
row: 317
|
||||
column: 6
|
||||
end_location:
|
||||
row: 317
|
||||
column: 16
|
||||
fix: ~
|
||||
- kind: UsesTripleQuotes
|
||||
location:
|
||||
row: 323
|
||||
column: 6
|
||||
end_location:
|
||||
row: 323
|
||||
column: 17
|
||||
fix: ~
|
||||
|
||||
@@ -2,138 +2,130 @@
|
||||
source: src/linter.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
location:
|
||||
row: 69
|
||||
column: 6
|
||||
end_location:
|
||||
row: 69
|
||||
column: 12
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 124
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 126
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 283
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 283
|
||||
column: 34
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 288
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 288
|
||||
column: 38
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 350
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 350
|
||||
column: 18
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 401
|
||||
column: 26
|
||||
column: 25
|
||||
end_location:
|
||||
row: 401
|
||||
column: 40
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 405
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 405
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 411
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 411
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 417
|
||||
column: 36
|
||||
column: 35
|
||||
end_location:
|
||||
row: 417
|
||||
column: 50
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 424
|
||||
column: 50
|
||||
column: 49
|
||||
end_location:
|
||||
row: 424
|
||||
column: 64
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 465
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 465
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 470
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 470
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 475
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 475
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 482
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 482
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 504
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 504
|
||||
column: 35
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 509
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 509
|
||||
column: 34
|
||||
fix: ~
|
||||
- kind: DocstringEndsInNonPeriod
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 515
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 515
|
||||
column: 33
|
||||
|
||||
6
src/snapshots/ruff__linter__tests__d403.snap
Normal file
6
src/snapshots/ruff__linter__tests__d403.snap
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
source: src/linter.rs
|
||||
expression: checks
|
||||
---
|
||||
[]
|
||||
|
||||
125
src/snapshots/ruff__linter__tests__d415.snap
Normal file
125
src/snapshots/ruff__linter__tests__d415.snap
Normal file
@@ -0,0 +1,125 @@
|
||||
---
|
||||
source: src/linter.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 124
|
||||
column: 5
|
||||
end_location:
|
||||
row: 126
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 283
|
||||
column: 5
|
||||
end_location:
|
||||
row: 283
|
||||
column: 34
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 288
|
||||
column: 5
|
||||
end_location:
|
||||
row: 288
|
||||
column: 38
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 350
|
||||
column: 5
|
||||
end_location:
|
||||
row: 350
|
||||
column: 18
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 401
|
||||
column: 25
|
||||
end_location:
|
||||
row: 401
|
||||
column: 40
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 405
|
||||
column: 5
|
||||
end_location:
|
||||
row: 405
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 411
|
||||
column: 5
|
||||
end_location:
|
||||
row: 411
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 417
|
||||
column: 35
|
||||
end_location:
|
||||
row: 417
|
||||
column: 50
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 424
|
||||
column: 49
|
||||
end_location:
|
||||
row: 424
|
||||
column: 64
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 465
|
||||
column: 5
|
||||
end_location:
|
||||
row: 465
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 470
|
||||
column: 5
|
||||
end_location:
|
||||
row: 470
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 475
|
||||
column: 5
|
||||
end_location:
|
||||
row: 475
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 482
|
||||
column: 5
|
||||
end_location:
|
||||
row: 482
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 504
|
||||
column: 5
|
||||
end_location:
|
||||
row: 504
|
||||
column: 35
|
||||
fix: ~
|
||||
- kind: EndsInPunctuation
|
||||
location:
|
||||
row: 515
|
||||
column: 5
|
||||
end_location:
|
||||
row: 515
|
||||
column: 33
|
||||
fix: ~
|
||||
|
||||
@@ -2,26 +2,26 @@
|
||||
source: src/linter.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: EmptyDocstring
|
||||
- kind: NonEmpty
|
||||
location:
|
||||
row: 19
|
||||
column: 10
|
||||
column: 9
|
||||
end_location:
|
||||
row: 19
|
||||
column: 15
|
||||
fix: ~
|
||||
- kind: EmptyDocstring
|
||||
- kind: NonEmpty
|
||||
location:
|
||||
row: 69
|
||||
column: 6
|
||||
column: 5
|
||||
end_location:
|
||||
row: 69
|
||||
column: 12
|
||||
fix: ~
|
||||
- kind: EmptyDocstring
|
||||
- kind: NonEmpty
|
||||
location:
|
||||
row: 75
|
||||
column: 10
|
||||
column: 9
|
||||
end_location:
|
||||
row: 75
|
||||
column: 11
|
||||
|
||||
47
tests/integration_test.rs
Normal file
47
tests/integration_test.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
use std::str;
|
||||
|
||||
use anyhow::Result;
|
||||
use assert_cmd::{crate_name, Command};
|
||||
|
||||
#[test]
|
||||
fn test_stdin_success() -> Result<()> {
|
||||
let mut cmd = Command::cargo_bin(crate_name!())?;
|
||||
cmd.args(&["-"]).write_stdin("").assert().success();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdin_error() -> Result<()> {
|
||||
let mut cmd = Command::cargo_bin(crate_name!())?;
|
||||
let output = cmd
|
||||
.args(&["-"])
|
||||
.write_stdin("import os\n")
|
||||
.assert()
|
||||
.failure();
|
||||
assert!(str::from_utf8(&output.get_output().stdout)?.contains("-:1:1: F401"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdin_filename() -> Result<()> {
|
||||
let mut cmd = Command::cargo_bin(crate_name!())?;
|
||||
let output = cmd
|
||||
.args(&["-", "--stdin-filename", "F401.py"])
|
||||
.write_stdin("import os\n")
|
||||
.assert()
|
||||
.failure();
|
||||
assert!(str::from_utf8(&output.get_output().stdout)?.contains("F401.py:1:1: F401"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdin_autofix() -> Result<()> {
|
||||
let mut cmd = Command::cargo_bin(crate_name!())?;
|
||||
let output = cmd
|
||||
.args(&["-", "--fix"])
|
||||
.write_stdin("import os\n")
|
||||
.assert()
|
||||
.failure();
|
||||
assert!(str::from_utf8(&output.get_output().stdout)?.contains("-:1:1: F401"));
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user