about summary refs log tree commit diff
diff options
context:
space:
mode:
authorboolean_coercion <booleancoercion@gmail.com>2021-02-11 02:30:37 +0200
committerboolean_coercion <booleancoercion@gmail.com>2021-02-12 11:54:22 +0200
commit64729390a1b2b6b05f8a4407658163ddff4d017e (patch)
treeb6a52ceea6258361675cf3a3b14152db2a2d69cc
parentb80ac2af9c0939428054e7d018f19fc16b920b05 (diff)
downloadrust-64729390a1b2b6b05f8a4407658163ddff4d017e.tar.gz
rust-64729390a1b2b6b05f8a4407658163ddff4d017e.zip
Implemented majority of from_str_radix_10
-rw-r--r--clippy_lints/src/from_str_radix_10.rs59
-rw-r--r--clippy_lints/src/lib.rs1
-rw-r--r--tests/ui/from_str_radix_10.rs32
3 files changed, 86 insertions, 6 deletions
diff --git a/clippy_lints/src/from_str_radix_10.rs b/clippy_lints/src/from_str_radix_10.rs
index ec2a60ec47c..612ea9ae62c 100644
--- a/clippy_lints/src/from_str_radix_10.rs
+++ b/clippy_lints/src/from_str_radix_10.rs
@@ -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 @@ declare_clippy_lint! {
     /// ```
     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
+}
\ No newline at end of file
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 5b84422458f..dae686b1229 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -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),
diff --git a/tests/ui/from_str_radix_10.rs b/tests/ui/from_str_radix_10.rs
index 70eaa8d666c..086616d09ff 100644
--- a/tests/ui/from_str_radix_10.rs
+++ b/tests/ui/from_str_radix_10.rs
@@ -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(())
+}
\ No newline at end of file