diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index d6b5ac9ad7c..55c78d305ca 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -584,6 +584,42 @@ mod tests {
         kind: Function,
         detail: "fn foo()",
     },
+]"###
+        );
+    }
+
+    #[test]
+    fn completes_quantified_macros() {
+        assert_debug_snapshot!(
+            do_reference_completion(
+                "
+                #[macro_export]
+                macro_rules! foo {
+                    () => {}
+                }
+
+                fn main() {
+                    let _ = crate::<|>
+                }
+                "
+            ),
+            @r###"[
+    CompletionItem {
+        label: "foo",
+        source_range: [179; 179),
+        delete: [179; 179),
+        insert: "foo!",
+        kind: Macro,
+        detail: "#[macro_export]\nmacro_rules! foo",
+    },
+    CompletionItem {
+        label: "main",
+        source_range: [179; 179),
+        delete: [179; 179),
+        insert: "main()$0",
+        kind: Function,
+        detail: "fn main()",
+    },
 ]"###
         );
     }
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index 67fb7ba4ef2..e2e1d7872ae 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -6,6 +6,15 @@ use rustc_hash::FxHashMap;
 use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions};
 
 pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
+    // Show only macros in top level.
+    if ctx.is_new_item {
+        for (name, res) in ctx.analyzer.all_names(ctx.db) {
+            if res.get_macros().is_some() {
+                acc.add_resolution(ctx, name.to_string(), &res.only_macros());
+            }
+        }
+    }
+
     if !ctx.is_trivial_path {
         return;
     }
@@ -532,4 +541,224 @@ mod tests {
 ]"#
         );
     }
+
+    #[test]
+    fn completes_macros_as_value() {
+        assert_debug_snapshot!(
+            do_reference_completion(
+                "
+                //- /main.rs
+                macro_rules! foo {
+                    () => {}
+                }
+
+                #[macro_use]
+                mod m1 {
+                    macro_rules! bar {
+                        () => {}
+                    }
+                }
+
+                mod m2 {
+                    macro_rules! nope {
+                        () => {}
+                    }
+
+                    #[macro_export]
+                    macro_rules! baz {
+                        () => {}
+                    }
+                }
+
+                fn main() {
+                    let v = <|>
+                }
+                "
+            ),
+            @r##"[
+    CompletionItem {
+        label: "bar",
+        source_range: [252; 252),
+        delete: [252; 252),
+        insert: "bar!",
+        kind: Macro,
+        detail: "macro_rules! bar",
+    },
+    CompletionItem {
+        label: "baz",
+        source_range: [252; 252),
+        delete: [252; 252),
+        insert: "baz!",
+        kind: Macro,
+        detail: "#[macro_export]\nmacro_rules! baz",
+    },
+    CompletionItem {
+        label: "foo",
+        source_range: [252; 252),
+        delete: [252; 252),
+        insert: "foo!",
+        kind: Macro,
+        detail: "macro_rules! foo",
+    },
+    CompletionItem {
+        label: "m1",
+        source_range: [252; 252),
+        delete: [252; 252),
+        insert: "m1",
+        kind: Module,
+    },
+    CompletionItem {
+        label: "m2",
+        source_range: [252; 252),
+        delete: [252; 252),
+        insert: "m2",
+        kind: Module,
+    },
+    CompletionItem {
+        label: "main",
+        source_range: [252; 252),
+        delete: [252; 252),
+        insert: "main()$0",
+        kind: Function,
+        detail: "fn main()",
+    },
+]"##
+        );
+    }
+
+    #[test]
+    fn completes_both_macro_and_value() {
+        assert_debug_snapshot!(
+            do_reference_completion(
+                "
+                //- /main.rs
+                macro_rules! foo {
+                    () => {}
+                }
+
+                fn foo() {
+                    <|>
+                }
+                "
+            ),
+            @r##"[
+    CompletionItem {
+        label: "foo",
+        source_range: [49; 49),
+        delete: [49; 49),
+        insert: "foo!",
+        kind: Macro,
+        detail: "macro_rules! foo",
+    },
+    CompletionItem {
+        label: "foo",
+        source_range: [49; 49),
+        delete: [49; 49),
+        insert: "foo()$0",
+        kind: Function,
+        detail: "fn foo()",
+    },
+]"##
+        );
+    }
+
+    #[test]
+    fn completes_macros_as_type() {
+        assert_debug_snapshot!(
+            do_reference_completion(
+                "
+                //- /main.rs
+                macro_rules! foo {
+                    () => {}
+                }
+
+                fn main() {
+                    let x: <|>
+                }
+                "
+            ),
+            @r##"[
+    CompletionItem {
+        label: "foo",
+        source_range: [57; 57),
+        delete: [57; 57),
+        insert: "foo!",
+        kind: Macro,
+        detail: "macro_rules! foo",
+    },
+    CompletionItem {
+        label: "main",
+        source_range: [57; 57),
+        delete: [57; 57),
+        insert: "main()$0",
+        kind: Function,
+        detail: "fn main()",
+    },
+]"##
+        );
+    }
+
+    #[test]
+    fn completes_macros_as_stmt() {
+        assert_debug_snapshot!(
+            do_reference_completion(
+                "
+                //- /main.rs
+                macro_rules! foo {
+                    () => {}
+                }
+
+                fn main() {
+                    <|>
+                }
+                "
+            ),
+            @r##"[
+    CompletionItem {
+        label: "foo",
+        source_range: [50; 50),
+        delete: [50; 50),
+        insert: "foo!",
+        kind: Macro,
+        detail: "macro_rules! foo",
+    },
+    CompletionItem {
+        label: "main",
+        source_range: [50; 50),
+        delete: [50; 50),
+        insert: "main()$0",
+        kind: Function,
+        detail: "fn main()",
+    },
+]"##
+        );
+    }
+
+    #[test]
+    fn completes_macros_as_item() {
+        assert_debug_snapshot!(
+            do_reference_completion(
+                "
+                //- /main.rs
+                macro_rules! foo {
+                    () => {}
+                }
+
+                fn foo() {}
+
+                <|>
+                "
+            ),
+            @r##"[
+    CompletionItem {
+        label: "foo",
+        source_range: [46; 46),
+        delete: [46; 46),
+        insert: "foo!",
+        kind: Macro,
+        detail: "macro_rules! foo",
+    },
+]"##
+        );
+    }
 }
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index db7e8348e1e..1b706bb131d 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -8,7 +8,7 @@ use crate::completion::{
     CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
 };
 
-use crate::display::{const_label, function_label, type_label};
+use crate::display::{const_label, function_label, macro_label, type_label};
 
 impl Completions {
     pub(crate) fn add_field(
@@ -43,8 +43,14 @@ impl Completions {
     ) {
         use hir::ModuleDef::*;
 
+        if let Some(macro_) = resolution.get_macros() {
+            self.add_macro(ctx, Some(local_name.clone()), macro_);
+        }
+
         let def = resolution.as_ref().take_types().or_else(|| resolution.as_ref().take_values());
         let def = match def {
+            // Only insert once if it is just a macro name
+            None if resolution.get_macros().is_some() => return,
             None => {
                 self.add(CompletionItem::new(
                     CompletionKind::Reference,
@@ -98,6 +104,22 @@ impl Completions {
         self.add_function_with_name(ctx, None, func)
     }
 
+    fn add_macro(&mut self, ctx: &CompletionContext, name: Option<String>, macro_: hir::MacroDef) {
+        let ast_node = macro_.source(ctx.db).ast;
+        if let Some(name) = name {
+            let detail = macro_label(&ast_node);
+
+            let builder =
+                CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone())
+                    .kind(CompletionItemKind::Macro)
+                    .set_documentation(macro_.docs(ctx.db))
+                    .detail(detail)
+                    .insert_snippet(format!("{}!", name));
+
+            self.add(builder);
+        }
+    }
+
     fn add_function_with_name(
         &mut self,
         ctx: &CompletionContext,
diff --git a/crates/ra_ide_api/src/display.rs b/crates/ra_ide_api/src/display.rs
index cc59e99d881..a980c56bc05 100644
--- a/crates/ra_ide_api/src/display.rs
+++ b/crates/ra_ide_api/src/display.rs
@@ -7,7 +7,7 @@ mod structure;
 mod short_label;
 
 use ra_syntax::{
-    ast::{self, AstNode, TypeParamsOwner},
+    ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner},
     SyntaxKind::{ATTR, COMMENT},
 };
 
@@ -61,6 +61,12 @@ pub(crate) fn where_predicates<N: TypeParamsOwner>(node: &N) -> Vec<String> {
     res
 }
 
+pub(crate) fn macro_label(node: &ast::MacroCall) -> String {
+    let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default();
+    let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" };
+    format!("{}macro_rules! {}", vis, name)
+}
+
 pub(crate) fn rust_code_markup<CODE: AsRef<str>>(val: CODE) -> String {
     rust_code_markup_with_doc::<_, &str>(val, None)
 }