Implemented majority of from_str_radix_10

This commit is contained in:
boolean_coercion 2021-02-11 02:30:37 +02:00
parent b80ac2af9c
commit 64729390a1
3 changed files with 86 additions and 6 deletions

View File

@ -1,6 +1,10 @@
use rustc_lint::{EarlyLintPass, EarlyContext};
use rustc_lint::{LateLintPass, LateContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_ast::ast::*;
use rustc_hir::*;
use rustc_errors::Applicability;
use if_chain::if_chain;
use crate::utils::span_lint_and_sugg;
declare_clippy_lint! {
/// **What it does:**
@ -26,9 +30,56 @@
/// ```
pub FROM_STR_RADIX_10,
style,
"default lint description"
"from_str_radix with radix 10"
}
declare_lint_pass!(FromStrRadix10 => [FROM_STR_RADIX_10]);
impl EarlyLintPass for FromStrRadix10 {}
impl LateLintPass<'tcx> for FromStrRadix10 {
fn check_expr(&mut self, cx: &LateContext<'tcx>, exp: &Expr<'tcx>) {
if_chain! {
if let ExprKind::Call(maybe_path, arguments) = &exp.kind;
if let ExprKind::Path(qpath) = &maybe_path.kind;
if let QPath::TypeRelative(ty, pathseg) = &qpath;
// check if the first part of the path is some integer primitive
if let TyKind::Path(ty_qpath) = &ty.kind;
let ty_res = cx.qpath_res(ty_qpath, ty.hir_id);
if let def::Res::PrimTy(prim_ty) = ty_res;
if is_primitive_integer_ty(prim_ty);
// check if the second part of the path indeed calls the associated
// function `from_str_radix`
if pathseg.ident.name.as_str() == "from_str_radix";
// check if the second argument resolves to a constant `10`
if arguments.len() == 2;
if is_constant_10(&arguments[1]);
then {
span_lint_and_sugg(
cx,
FROM_STR_RADIX_10,
exp.span,
"This call to `from_str_radix` can be shortened to a call to str::parse",
"try",
format!("TODO"),
Applicability::MachineApplicable
);
}
}
}
}
fn is_primitive_integer_ty(ty: PrimTy) -> bool {
match ty {
PrimTy::Int(_) => true,
PrimTy::Uint(_) => true,
_ => false
}
}
fn is_constant_10<'tcx>(expr: &Expr<'tcx>) -> bool {
// TODO
true
}

View File

@ -1258,6 +1258,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(move || box types::PtrAsPtr::new(msrv));
store.register_late_pass(|| box case_sensitive_file_extension_comparisons::CaseSensitiveFileExtensionComparisons);
store.register_late_pass(|| box redundant_slicing::RedundantSlicing);
store.register_late_pass(|| box from_str_radix_10::FromStrRadix10);
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
LintId::of(&arithmetic::FLOAT_ARITHMETIC),

View File

@ -1,5 +1,33 @@
#![warn(clippy::from_str_radix_10)]
fn main() {
// test code goes here
mod some_mod {
// fake function that shouldn't trigger the lint
pub fn from_str_radix(_: &str, _: u32) -> Result<(), std::num::ParseIntError> {
unimplemented!()
}
}
// fake function that shouldn't trigger the lint
fn from_str_radix(_: &str, _: u32) -> Result<(), std::num::ParseIntError> {
unimplemented!()
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// all of these should trigger the lint
u32::from_str_radix("30", 10)?;
i64::from_str_radix("24", 10)?;
isize::from_str_radix("100", 10)?;
u8::from_str_radix("7", 10)?;
// none of these should trigger the lint
u16::from_str_radix("20", 3)?;
i32::from_str_radix("45", 12)?;
usize::from_str_radix("10", 16)?;
i128::from_str_radix("10", 13)?;
some_mod::from_str_radix("50", 10)?;
some_mod::from_str_radix("50", 6)?;
from_str_radix("50", 10)?;
from_str_radix("50", 6)?;
Ok(())
}