Confine type-of-primitive checks to builtin type calls (#1962)

Closes #1958.
This commit is contained in:
Charlie Marsh
2023-01-18 10:53:50 -05:00
committed by GitHub
parent 83346de6e0
commit b1f10c8339
4 changed files with 37 additions and 42 deletions

View File

@@ -1,5 +1,12 @@
type('')
type(b'')
type("")
type(b"")
type(0)
type(0.)
type(0.0)
type(0j)
# OK
y = x.dtype.type(0.0)
# OK
type = lambda *args, **kwargs: None
type("")

View File

@@ -4,48 +4,36 @@ use super::super::types::Primitive;
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
use crate::fix::Fix;
use crate::registry::{Diagnostic, DiagnosticKind};
use crate::registry::Diagnostic;
use crate::violations;
fn rule(func: &Expr, args: &[Expr], location: Range) -> Option<Diagnostic> {
// Validate the arguments.
if args.len() != 1 {
return None;
}
let (ExprKind::Attribute { attr: id, .. } | ExprKind::Name { id, .. }) = &func.node else {
return None;
};
if id != "type" {
return None;
}
let ExprKind::Constant { value, .. } = &args[0].node else {
return None;
};
let primitive = Primitive::from_constant(value)?;
Some(Diagnostic::new(
violations::TypeOfPrimitive(primitive),
location,
))
}
/// UP003
pub fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
let Some(mut diagnostic) = rule(func, args, Range::from_located(expr)) else {
if args.len() != 1 {
return;
}
if !checker
.resolve_call_path(func)
.map_or(false, |call_path| call_path == ["", "type"])
{
return;
}
let ExprKind::Constant { value, .. } = &args[0].node else {
return;
};
let Some(primitive) = Primitive::from_constant(value) else {
return;
};
let mut diagnostic = Diagnostic::new(
violations::TypeOfPrimitive(primitive),
Range::from_located(expr),
);
if checker.patch(diagnostic.kind.code()) {
if let DiagnosticKind::TypeOfPrimitive(violations::TypeOfPrimitive(primitive)) =
&diagnostic.kind
{
diagnostic.amend(Fix::replacement(
primitive.builtin(),
expr.location,
expr.end_location.unwrap(),
));
}
diagnostic.amend(Fix::replacement(
primitive.builtin(),
expr.location,
expr.end_location.unwrap(),
));
}
checker.diagnostics.push(diagnostic);
}

View File

@@ -60,7 +60,7 @@ expression: diagnostics
column: 0
end_location:
row: 4
column: 8
column: 9
fix:
content: float
location:
@@ -68,7 +68,7 @@ expression: diagnostics
column: 0
end_location:
row: 4
column: 8
column: 9
parent: ~
- kind:
TypeOfPrimitive: Complex

View File

@@ -1,7 +1,7 @@
use rustpython_ast::Constant;
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Primitive {
Bool,
Str,
@@ -24,7 +24,7 @@ impl Primitive {
}
}
pub fn builtin(&self) -> String {
pub fn builtin(self) -> String {
match self {
Primitive::Bool => "bool".to_string(),
Primitive::Str => "str".to_string(),