Add duplicate arguments check (#8)

This commit is contained in:
Charlie Marsh 2022-08-13 14:20:19 -04:00 committed by GitHub
parent d5d9dec5ff
commit 290b0091c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 6 deletions

2
Cargo.lock generated
View File

@ -1493,7 +1493,7 @@ dependencies = [
[[package]] [[package]]
name = "rust-python-linter" name = "rust-python-linter"
version = "0.0.7" version = "0.0.8"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "rust-python-linter" name = "rust-python-linter"
version = "0.0.7" version = "0.0.8"
edition = "2021" edition = "2021"
[lib] [lib]

View File

@ -1 +1,5 @@
from bar import * from bar import *
def baz(x: int, x: int) -> None:
pass

View File

@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub enum CheckKind { pub enum CheckKind {
DuplicateArgumentName,
ImportStarUsage, ImportStarUsage,
IfTuple, IfTuple,
} }
@ -11,16 +12,18 @@ impl CheckKind {
/// A four-letter shorthand code for the check. /// A four-letter shorthand code for the check.
pub fn code(&self) -> &'static str { pub fn code(&self) -> &'static str {
match self { match self {
CheckKind::ImportStarUsage => "F403", CheckKind::DuplicateArgumentName => "F831",
CheckKind::IfTuple => "F634", CheckKind::IfTuple => "F634",
CheckKind::ImportStarUsage => "F403",
} }
} }
/// The body text for the check. /// The body text for the check.
pub fn body(&self) -> &'static str { pub fn body(&self) -> &'static str {
match self { match self {
CheckKind::ImportStarUsage => "Unable to detect undefined names", CheckKind::DuplicateArgumentName => "Duplicate argument name in function definition",
CheckKind::IfTuple => "If test is a tuple, which is always `True`", CheckKind::IfTuple => "If test is a tuple, which is always `True`",
CheckKind::ImportStarUsage => "Unable to detect undefined names",
} }
} }
} }

View File

@ -1,7 +1,9 @@
use rustpython_parser::ast::{ExprKind, Stmt, StmtKind, Suite}; use std::collections::HashSet;
use rustpython_parser::ast::{Arg, Arguments, ExprKind, Stmt, StmtKind, Suite};
use crate::check::{Check, CheckKind}; use crate::check::{Check, CheckKind};
use crate::visitor::{walk_stmt, Visitor}; use crate::visitor::{walk_arguments, walk_stmt, Visitor};
struct Checker { struct Checker {
checks: Vec<Check>, checks: Vec<Check>,
@ -32,6 +34,38 @@ impl Visitor for Checker {
} }
walk_stmt(self, stmt); walk_stmt(self, stmt);
} }
fn visit_arguments(&mut self, arguments: &Arguments) {
// Collect all the arguments into a single vector.
let mut all_arguments: Vec<&Arg> = arguments
.posonlyargs
.iter()
.chain(arguments.kwonlyargs.iter())
.chain(arguments.args.iter())
.collect();
if let Some(arg) = &arguments.vararg {
all_arguments.push(arg);
}
if let Some(arg) = &arguments.kwarg {
all_arguments.push(arg);
}
// Search for duplicates.
let mut idents: HashSet<String> = HashSet::new();
for arg in all_arguments {
let ident = &arg.node.arg;
if idents.contains(ident) {
self.checks.push(Check {
kind: CheckKind::DuplicateArgumentName,
location: arg.location,
});
break;
}
idents.insert(ident.clone());
}
walk_arguments(self, arguments);
}
} }
pub fn check_ast(python_ast: &Suite) -> Vec<Check> { pub fn check_ast(python_ast: &Suite) -> Vec<Check> {