about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/utils/author.rs18
-rw-r--r--tests/ui/author/macro_in_closure.rs5
-rw-r--r--tests/ui/author/macro_in_closure.stdout39
-rw-r--r--tests/ui/author/macro_in_loop.rs8
-rw-r--r--tests/ui/author/macro_in_loop.stdout48
5 files changed, 110 insertions, 8 deletions
diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs
index f02c33cc674..aecb0c6dbfa 100644
--- a/clippy_lints/src/utils/author.rs
+++ b/clippy_lints/src/utils/author.rs
@@ -268,8 +268,8 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
     fn qpath(&self, qpath: &Binding<&QPath<'_>>) {
         if let QPath::LangItem(lang_item, ..) = *qpath.value {
             chain!(self, "matches!({qpath}, QPath::LangItem(LangItem::{lang_item:?}, _))");
-        } else {
-            chain!(self, "match_qpath({qpath}, &[{}])", path_to_string(qpath.value));
+        } else if let Ok(path) = path_to_string(qpath.value) {
+            chain!(self, "match_qpath({qpath}, &[{}])", path);
         }
     }
 
@@ -738,8 +738,8 @@ fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
     get_attr(cx.sess(), attrs, "author").count() > 0
 }
 
-fn path_to_string(path: &QPath<'_>) -> String {
-    fn inner(s: &mut String, path: &QPath<'_>) {
+fn path_to_string(path: &QPath<'_>) -> Result<String, ()> {
+    fn inner(s: &mut String, path: &QPath<'_>) -> Result<(), ()> {
         match *path {
             QPath::Resolved(_, path) => {
                 for (i, segment) in path.segments.iter().enumerate() {
@@ -751,16 +751,18 @@ fn path_to_string(path: &QPath<'_>) -> String {
             },
             QPath::TypeRelative(ty, segment) => match &ty.kind {
                 hir::TyKind::Path(inner_path) => {
-                    inner(s, inner_path);
+                    inner(s, inner_path)?;
                     *s += ", ";
                     write!(s, "{:?}", segment.ident.as_str()).unwrap();
                 },
                 other => write!(s, "/* unimplemented: {other:?}*/").unwrap(),
             },
-            QPath::LangItem(..) => panic!("path_to_string: called for lang item qpath"),
+            QPath::LangItem(..) => return Err(()),
         }
+
+        Ok(())
     }
     let mut s = String::new();
-    inner(&mut s, path);
-    s
+    inner(&mut s, path)?;
+    Ok(s)
 }
diff --git a/tests/ui/author/macro_in_closure.rs b/tests/ui/author/macro_in_closure.rs
new file mode 100644
index 00000000000..444e6a12165
--- /dev/null
+++ b/tests/ui/author/macro_in_closure.rs
@@ -0,0 +1,5 @@
+fn main() {
+    #[clippy::author]
+    let print_text = |x| println!("{}", x);
+    print_text("hello");
+}
diff --git a/tests/ui/author/macro_in_closure.stdout b/tests/ui/author/macro_in_closure.stdout
new file mode 100644
index 00000000000..9ab71986f40
--- /dev/null
+++ b/tests/ui/author/macro_in_closure.stdout
@@ -0,0 +1,39 @@
+if let StmtKind::Local(local) = stmt.kind
+    && let Some(init) = local.init
+    && let ExprKind::Closure(CaptureBy::Ref, fn_decl, body_id, _, None) = init.kind
+    && let FnRetTy::DefaultReturn(_) = fn_decl.output
+    && expr = &cx.tcx.hir().body(body_id).value
+    && let ExprKind::Block(block, None) = expr.kind
+    && block.stmts.len() == 1
+    && let StmtKind::Semi(e) = block.stmts[0].kind
+    && let ExprKind::Call(func, args) = e.kind
+    && let ExprKind::Path(ref qpath) = func.kind
+    && match_qpath(qpath, &["$crate", "io", "_print"])
+    && args.len() == 1
+    && let ExprKind::Call(func1, args1) = args[0].kind
+    && let ExprKind::Path(ref qpath1) = func1.kind
+    && args1.len() == 2
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = args1[0].kind
+    && let ExprKind::Array(elements) = inner.kind
+    && elements.len() == 2
+    && let ExprKind::Lit(ref lit) = elements[0].kind
+    && let LitKind::Str(s, _) = lit.node
+    && s.as_str() == ""
+    && let ExprKind::Lit(ref lit1) = elements[1].kind
+    && let LitKind::Str(s1, _) = lit1.node
+    && s1.as_str() == "\n"
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args1[1].kind
+    && let ExprKind::Array(elements1) = inner1.kind
+    && elements1.len() == 1
+    && let ExprKind::Call(func2, args2) = elements1[0].kind
+    && let ExprKind::Path(ref qpath2) = func2.kind
+    && args2.len() == 1
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[0].kind
+    && let ExprKind::Path(ref qpath3) = inner2.kind
+    && match_qpath(qpath3, &["x"])
+    && block.expr.is_none()
+    && let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind
+    && name.as_str() == "print_text"
+{
+    // report your lint here
+}
diff --git a/tests/ui/author/macro_in_loop.rs b/tests/ui/author/macro_in_loop.rs
new file mode 100644
index 00000000000..8a520501f8d
--- /dev/null
+++ b/tests/ui/author/macro_in_loop.rs
@@ -0,0 +1,8 @@
+#![feature(stmt_expr_attributes)]
+
+fn main() {
+    #[clippy::author]
+    for i in 0..1 {
+        println!("{}", i);
+    }
+}
diff --git a/tests/ui/author/macro_in_loop.stdout b/tests/ui/author/macro_in_loop.stdout
new file mode 100644
index 00000000000..bd054b6abc4
--- /dev/null
+++ b/tests/ui/author/macro_in_loop.stdout
@@ -0,0 +1,48 @@
+if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr)
+    && let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = pat.kind
+    && name.as_str() == "i"
+    && let ExprKind::Struct(qpath, fields, None) = arg.kind
+    && matches!(qpath, QPath::LangItem(LangItem::Range, _))
+    && fields.len() == 2
+    && fields[0].ident.as_str() == "start"
+    && let ExprKind::Lit(ref lit) = fields[0].expr.kind
+    && let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node
+    && fields[1].ident.as_str() == "end"
+    && let ExprKind::Lit(ref lit1) = fields[1].expr.kind
+    && let LitKind::Int(1, LitIntType::Unsuffixed) = lit1.node
+    && let ExprKind::Block(block, None) = body.kind
+    && block.stmts.len() == 1
+    && let StmtKind::Semi(e) = block.stmts[0].kind
+    && let ExprKind::Block(block1, None) = e.kind
+    && block1.stmts.len() == 1
+    && let StmtKind::Semi(e1) = block1.stmts[0].kind
+    && let ExprKind::Call(func, args) = e1.kind
+    && let ExprKind::Path(ref qpath1) = func.kind
+    && match_qpath(qpath1, &["$crate", "io", "_print"])
+    && args.len() == 1
+    && let ExprKind::Call(func1, args1) = args[0].kind
+    && let ExprKind::Path(ref qpath2) = func1.kind
+    && args1.len() == 2
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = args1[0].kind
+    && let ExprKind::Array(elements) = inner.kind
+    && elements.len() == 2
+    && let ExprKind::Lit(ref lit2) = elements[0].kind
+    && let LitKind::Str(s, _) = lit2.node
+    && s.as_str() == ""
+    && let ExprKind::Lit(ref lit3) = elements[1].kind
+    && let LitKind::Str(s1, _) = lit3.node
+    && s1.as_str() == "\n"
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args1[1].kind
+    && let ExprKind::Array(elements1) = inner1.kind
+    && elements1.len() == 1
+    && let ExprKind::Call(func2, args2) = elements1[0].kind
+    && let ExprKind::Path(ref qpath3) = func2.kind
+    && args2.len() == 1
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[0].kind
+    && let ExprKind::Path(ref qpath4) = inner2.kind
+    && match_qpath(qpath4, &["i"])
+    && block1.expr.is_none()
+    && block.expr.is_none()
+{
+    // report your lint here
+}