diff --git a/doc/adding_lints.md b/doc/adding_lints.md
index b3f5a62d553..8092be277cc 100644
--- a/doc/adding_lints.md
+++ b/doc/adding_lints.md
@@ -465,6 +465,7 @@ Here are some pointers to things you are likely going to need for every lint:
 * [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro]
 * [`Span`][span]
 * [`Applicability`][applicability]
+* [Common tools for writing lints](common_tools_writing_lints.md) helps with common operations
 * [The rustc-dev-guide][rustc-dev-guide] explains a lot of internal compiler concepts
 * [The nightly rustc docs][nightly_docs] which has been linked to throughout
   this guide
diff --git a/doc/common_tools_writing_lints.md b/doc/common_tools_writing_lints.md
new file mode 100644
index 00000000000..ed33b37c6bd
--- /dev/null
+++ b/doc/common_tools_writing_lints.md
@@ -0,0 +1,152 @@
+# Common tools for writing lints
+
+You may need following tooltips to catch up with common operations.
+
+- [Common tools for writing lints](#common-tools-for-writing-lints)
+  - [Retrieving the type of an expression](#retrieving-the-type-of-an-expression)
+  - [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait)
+  - [Dealing with macros](#dealing-with-macros)
+
+Useful Rustc dev guide links:
+- [Stages of compilation](https://rustc-dev-guide.rust-lang.org/compiler-src.html#the-main-stages-of-compilation)
+- [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
+- [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
+
+# Retrieving the type of an expression
+
+Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for example to answer following questions:
+
+- which type does this expression correspond to (using its [`TyKind`][TyKind])?
+- is it a sized type? 
+- is it a primitive type?
+- does it implement a trait?
+
+This operation is performed using the [`expr_ty()`][expr_ty] method from the [`TypeckTables`][TypeckTables] struct, 
+that gives you access to the underlying structure [`TyS`][TyS].
+
+Example of use:
+```rust
+impl LateLintPass<'_, '_> for MyStructLint {
+    fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
+        // Get type of `expr`
+        let ty = cx.tables.expr_ty(expr);
+        // Match its kind to enter its type
+        match ty.kind {
+            ty::Adt(adt_def, _) if adt_def.is_struct() => println!("Our `expr` is a struct!"),
+            _ => ()
+        }
+    }
+}
+```
+
+Similarly in [`TypeckTables`][TypeckTables] methods, you have the [`pat_ty()`][pat_ty] method 
+to retrieve a type from a pattern.
+
+Two noticeable items here:
+- `cx` is the lint context [`LateContext`][LateContext]. 
+  The two most useful data structures in this context are `tcx` and `tables`, 
+  allowing us to jump to type definitions and other compilation stages such as HIR.
+- `tables` is [`TypeckTables`][TypeckTables] and is created by type checking step, 
+  it includes useful information such as types of expressions, ways to resolve methods and so on.
+
+# Checking if a type implements a specific trait
+
+There are two ways to do this, depending if the target trait is part of lang items.
+
+```rust
+use crate::utils::{implements_trait, match_trait_method, paths};
+
+impl LateLintPass<'_, '_> for MyStructLint {
+    fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
+        // 1. Using expression and Clippy's convenient method
+        // we use `match_trait_method` function from Clippy's toolbox
+        if match_trait_method(cx, expr, &paths::INTO) {
+            // `expr` implements `Into` trait
+        }
+
+        // 2. Using type context `TyCtxt`
+        let ty = cx.tables.expr_ty(expr);
+        if cx.tcx.lang_items()
+            // we are looking for the `DefId` of `Drop` trait in lang items
+            .drop_trait()
+            // then we use it with our type `ty` by calling `implements_trait` from Clippy's utils
+            .map_or(false, |id| implements_trait(cx, ty, id, &[])) {
+                // `expr` implements `Drop` trait
+            }
+    }
+}
+```
+
+> Prefer using lang items, if the target trait is available there.
+
+A list of defined paths for Clippy can be found in [paths.rs][paths]
+
+We access lang items through the type context `tcx`. `tcx` is of type [`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate.
+
+# Dealing with macros
+
+There are several helpers in Clippy's utils to deal with macros:
+
+- `in_macro()`: detect if the given span is expanded by a macro
+
+You may want to use this for example to not start linting in any macro.
+
+```rust
+macro_rules! foo {
+    ($param:expr) => {
+        match $param {
+            "bar" => println!("whatever"),
+            _ => ()
+        }
+    };
+}
+
+foo!("bar");
+
+// if we lint the `match` of `foo` call and test its span
+assert_eq!(in_macro(match_span), true);
+```
+
+- `in_external_macro()`: detect if the given span is from an external macro, defined in a foreign crate
+
+You may want to use it for example to not start linting in macros from other crates
+
+```rust
+#[macro_use]
+extern crate a_crate_with_macros;
+
+// `foo` is defined in `a_crate_with_macros`
+foo!("bar");
+
+// if we lint the `match` of `foo` call and test its span
+assert_eq!(in_external_macro(cx.sess(), match_span), true);
+```
+
+- `differing_macro_contexts()`: returns true if the two given spans are not from the same context
+
+```rust
+macro_rules! m {
+    ($a:expr, $b:expr) => {
+        if $a.is_some() {
+            $b;
+        }
+    }
+}
+
+let x: Option<u32> = Some(42);
+m!(x, x.unwrap());
+
+// These spans are not from the same context
+// x.is_some() is from inside the macro
+// x.unwrap() is from outside the macro
+assert_eq!(differing_macro_contexts(x_is_some_span, x_unwrap_span), true);
+```
+
+[TyS]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyS.html
+[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html
+[TypeckTables]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckTables.html
+[expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckTables.html#method.expr_ty
+[LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html
+[TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html
+[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckTables.html#method.pat_ty
+[paths]: ../clippy_lints/src/utils/paths.rs