mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 14:52:01 +00:00
Add another check
This commit is contained in:
parent
6257dd00c7
commit
211849901c
7 changed files with 120 additions and 54 deletions
11
README.md
11
README.md
|
@ -1,7 +1,16 @@
|
||||||
# rust-python-linter
|
# rust-python-linter
|
||||||
|
|
||||||
|
A [Pyflakes](https://github.com/PyCQA/pyflakes)-inspired Python linter, written in Rust.
|
||||||
|
|
||||||
|
Supports:
|
||||||
|
|
||||||
|
- Python 3.10
|
||||||
|
- True parallelism
|
||||||
|
- [ESLint](https://eslint.org/docs/latest/user-guide/command-line-interface#caching)-inspired
|
||||||
|
caching
|
||||||
|
|
||||||
```
|
```
|
||||||
cargo fmt
|
cargo fmt
|
||||||
cargo clippy
|
cargo clippy
|
||||||
cargo run test_sources
|
cargo run resources/test/src
|
||||||
```
|
```
|
||||||
|
|
8
resources/test/src/bar.py
Normal file
8
resources/test/src/bar.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
if (1, 2):
|
||||||
|
pass
|
||||||
|
|
||||||
|
for _ in range(5):
|
||||||
|
if True:
|
||||||
|
pass
|
||||||
|
elif (1, 2):
|
||||||
|
pass
|
127
src/check.rs
127
src/check.rs
|
@ -1,57 +1,94 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use rustpython_parser::ast::{Located, StmtKind, Suite};
|
use rustpython_parser::ast::{ExprKind, Stmt, StmtKind, Suite};
|
||||||
|
|
||||||
use crate::message::Message;
|
use crate::message::Message;
|
||||||
|
|
||||||
pub fn check_ast(path: &Path, python_ast: &Suite) -> Vec<Message> {
|
fn check_statement(path: &Path, stmt: &Stmt) -> Vec<Message> {
|
||||||
let mut messages: Vec<Message> = vec![];
|
let mut messages: Vec<Message> = vec![];
|
||||||
for statement in python_ast {
|
match &stmt.node {
|
||||||
let Located {
|
StmtKind::FunctionDef { body, .. } => {
|
||||||
location,
|
messages.extend(body.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
custom: _,
|
}
|
||||||
node,
|
StmtKind::AsyncFunctionDef { body, .. } => {
|
||||||
} = statement;
|
messages.extend(body.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
match node {
|
}
|
||||||
StmtKind::FunctionDef { .. } => {}
|
StmtKind::ClassDef { body, .. } => {
|
||||||
StmtKind::AsyncFunctionDef { .. } => {}
|
messages.extend(body.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
StmtKind::ClassDef { .. } => {}
|
}
|
||||||
StmtKind::Return { .. } => {}
|
StmtKind::Return { .. } => {}
|
||||||
StmtKind::Delete { .. } => {}
|
StmtKind::Delete { .. } => {}
|
||||||
StmtKind::Assign { .. } => {}
|
StmtKind::Assign { .. } => {}
|
||||||
StmtKind::AugAssign { .. } => {}
|
StmtKind::AugAssign { .. } => {}
|
||||||
StmtKind::AnnAssign { .. } => {}
|
StmtKind::AnnAssign { .. } => {}
|
||||||
StmtKind::For { .. } => {}
|
StmtKind::For { body, orelse, .. } => {
|
||||||
StmtKind::AsyncFor { .. } => {}
|
messages.extend(body.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
StmtKind::While { .. } => {}
|
messages.extend(orelse.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
StmtKind::If { .. } => {}
|
}
|
||||||
StmtKind::With { .. } => {}
|
StmtKind::AsyncFor { body, orelse, .. } => {
|
||||||
StmtKind::AsyncWith { .. } => {}
|
messages.extend(body.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
StmtKind::Raise { .. } => {}
|
messages.extend(orelse.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
StmtKind::Try { .. } => {}
|
}
|
||||||
StmtKind::Assert { .. } => {}
|
StmtKind::While { body, orelse, .. } => {
|
||||||
StmtKind::Import { .. } => {}
|
messages.extend(body.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
StmtKind::ImportFrom {
|
messages.extend(orelse.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
level: _,
|
}
|
||||||
module: _,
|
StmtKind::If { test, body, orelse } => {
|
||||||
names,
|
if let ExprKind::Tuple { .. } = test.node {
|
||||||
} => {
|
messages.push(Message::IfTuple {
|
||||||
for alias in names {
|
filename: path.to_path_buf(),
|
||||||
if alias.name == "*" {
|
location: stmt.location,
|
||||||
messages.push(Message::ImportStarUsage {
|
});
|
||||||
filename: path.to_path_buf(),
|
}
|
||||||
location: *location,
|
messages.extend(body.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
});
|
messages.extend(orelse.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
}
|
}
|
||||||
|
StmtKind::With { body, .. } => {
|
||||||
|
messages.extend(body.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
|
}
|
||||||
|
StmtKind::AsyncWith { body, .. } => {
|
||||||
|
messages.extend(body.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
|
}
|
||||||
|
StmtKind::Raise { .. } => {}
|
||||||
|
StmtKind::Try {
|
||||||
|
body,
|
||||||
|
orelse,
|
||||||
|
finalbody,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
messages.extend(body.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
|
messages.extend(orelse.iter().flat_map(|stmt| check_statement(path, stmt)));
|
||||||
|
messages.extend(
|
||||||
|
finalbody
|
||||||
|
.iter()
|
||||||
|
.flat_map(|stmt| check_statement(path, stmt)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
StmtKind::Assert { .. } => {}
|
||||||
|
StmtKind::Import { .. } => {}
|
||||||
|
StmtKind::ImportFrom { names, .. } => {
|
||||||
|
for alias in names {
|
||||||
|
if alias.name == "*" {
|
||||||
|
messages.push(Message::ImportStarUsage {
|
||||||
|
filename: path.to_path_buf(),
|
||||||
|
location: stmt.location,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Global { .. } => {}
|
|
||||||
StmtKind::Nonlocal { .. } => {}
|
|
||||||
StmtKind::Expr { .. } => {}
|
|
||||||
StmtKind::Pass => {}
|
|
||||||
StmtKind::Break => {}
|
|
||||||
StmtKind::Continue => {}
|
|
||||||
}
|
}
|
||||||
|
StmtKind::Global { .. } => {}
|
||||||
|
StmtKind::Nonlocal { .. } => {}
|
||||||
|
StmtKind::Expr { .. } => {}
|
||||||
|
StmtKind::Pass => {}
|
||||||
|
StmtKind::Break => {}
|
||||||
|
StmtKind::Continue => {}
|
||||||
}
|
}
|
||||||
messages
|
messages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_ast(path: &Path, python_ast: &Suite) -> Vec<Message> {
|
||||||
|
python_ast
|
||||||
|
.iter()
|
||||||
|
.flat_map(|stmt| check_statement(path, stmt))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
|
@ -27,26 +27,27 @@ pub enum Message {
|
||||||
#[serde(with = "LocationDef")]
|
#[serde(with = "LocationDef")]
|
||||||
location: Location,
|
location: Location,
|
||||||
},
|
},
|
||||||
|
IfTuple {
|
||||||
|
filename: PathBuf,
|
||||||
|
#[serde(with = "LocationDef")]
|
||||||
|
location: Location,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Message {
|
impl Message {
|
||||||
/// A four-letter shorthand code for the message.
|
/// A four-letter shorthand code for the message.
|
||||||
pub fn code(&self) -> &'static str {
|
pub fn code(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Message::ImportStarUsage {
|
Message::ImportStarUsage { .. } => "F403",
|
||||||
filename: _,
|
Message::IfTuple { .. } => "F634",
|
||||||
location: _,
|
|
||||||
} => "F403",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The body text for the message.
|
/// The body text for the message.
|
||||||
pub fn body(&self) -> &'static str {
|
pub fn body(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Message::ImportStarUsage {
|
Message::ImportStarUsage { .. } => "Unable to detect undefined names",
|
||||||
filename: _,
|
Message::IfTuple { .. } => "If test is a tuple, which is always `True`",
|
||||||
location: _,
|
|
||||||
} => "Unable to detect undefined names",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +66,17 @@ impl fmt::Display for Message {
|
||||||
self.code().red().bold(),
|
self.code().red().bold(),
|
||||||
self.body()
|
self.body()
|
||||||
),
|
),
|
||||||
|
Message::IfTuple { filename, location } => write!(
|
||||||
|
f,
|
||||||
|
"{}{}{}{}{}\t{}\t{}",
|
||||||
|
filename.to_string_lossy().white().bold(),
|
||||||
|
":".cyan(),
|
||||||
|
location.column(),
|
||||||
|
":".cyan(),
|
||||||
|
location.row(),
|
||||||
|
self.code().red().bold(),
|
||||||
|
self.body()
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue