about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/ide-completion/src/completions.rs122
-rw-r--r--crates/ide-completion/src/completions/attribute.rs14
-rw-r--r--crates/ide-completion/src/completions/attribute/derive.rs12
-rw-r--r--crates/ide-completion/src/completions/dot.rs23
-rw-r--r--crates/ide-completion/src/completions/expr.rs36
-rw-r--r--crates/ide-completion/src/completions/field.rs16
-rw-r--r--crates/ide-completion/src/completions/item_list.rs39
-rw-r--r--crates/ide-completion/src/completions/item_list/trait_impl.rs23
-rw-r--r--crates/ide-completion/src/completions/keyword.rs4
-rw-r--r--crates/ide-completion/src/completions/pattern.rs9
-rw-r--r--crates/ide-completion/src/completions/record.rs15
-rw-r--r--crates/ide-completion/src/completions/snippet.rs57
-rw-r--r--crates/ide-completion/src/completions/type.rs27
-rw-r--r--crates/ide-completion/src/completions/use_.rs11
-rw-r--r--crates/ide-completion/src/completions/vis.rs12
-rw-r--r--crates/ide-completion/src/context.rs5
-rw-r--r--crates/ide-completion/src/lib.rs94
17 files changed, 263 insertions, 256 deletions
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index 284372f7fc5..c925d242a42 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -27,7 +27,10 @@ use ide_db::SymbolKind;
 use syntax::ast;
 
 use crate::{
-    context::Visible,
+    context::{
+        ItemListKind, NameContext, NameKind, NameRefContext, NameRefKind, PathKind, PatternContext,
+        TypeLocation, Visible,
+    },
     item::Builder,
     render::{
         const_::render_const,
@@ -437,3 +440,120 @@ fn enum_variants_with_paths(
         }
     }
 }
+
+pub(super) fn complete_name(
+    acc: &mut Completions,
+    ctx: &CompletionContext,
+    NameContext { name, kind }: &NameContext,
+) {
+    match kind {
+        NameKind::Const => {
+            item_list::trait_impl::complete_trait_impl_const(acc, ctx, name);
+        }
+        NameKind::Function => {
+            item_list::trait_impl::complete_trait_impl_fn(acc, ctx, name);
+        }
+        NameKind::IdentPat(pattern_ctx) => complete_patterns(acc, ctx, pattern_ctx),
+        NameKind::Module(mod_under_caret) => {
+            mod_::complete_mod(acc, ctx, mod_under_caret);
+        }
+        NameKind::TypeAlias => {
+            item_list::trait_impl::complete_trait_impl_type_alias(acc, ctx, name);
+        }
+        NameKind::RecordField => {
+            field::complete_field_list_record_variant(acc, ctx);
+        }
+        NameKind::ConstParam
+        | NameKind::Enum
+        | NameKind::MacroDef
+        | NameKind::MacroRules
+        | NameKind::Rename
+        | NameKind::SelfParam
+        | NameKind::Static
+        | NameKind::Struct
+        | NameKind::Trait
+        | NameKind::TypeParam
+        | NameKind::Union
+        | NameKind::Variant => (),
+    }
+}
+
+pub(super) fn complete_name_ref(
+    acc: &mut Completions,
+    ctx: &CompletionContext,
+    NameRefContext { nameref, kind }: &NameRefContext,
+) {
+    match kind {
+        NameRefKind::Path(path_ctx) => {
+            flyimport::import_on_the_fly_path(acc, ctx, path_ctx);
+            match &path_ctx.kind {
+                PathKind::Expr { expr_ctx } => {
+                    dot::complete_undotted_self(acc, ctx, path_ctx, expr_ctx);
+                    expr::complete_expr_path(acc, ctx, path_ctx, expr_ctx);
+                    item_list::complete_item_list_in_expr(acc, ctx, path_ctx, expr_ctx);
+                    record::complete_record_expr_func_update(acc, ctx, path_ctx, expr_ctx);
+                    snippet::complete_expr_snippet(acc, ctx, path_ctx, expr_ctx);
+                }
+                PathKind::Type { location } => {
+                    r#type::complete_type_path(acc, ctx, path_ctx, location);
+                    match location {
+                        TypeLocation::TupleField => {
+                            field::complete_field_list_tuple_variant(acc, ctx, path_ctx);
+                        }
+                        TypeLocation::TypeAscription(ascription) => {
+                            r#type::complete_ascribed_type(acc, ctx, path_ctx, ascription);
+                        }
+                        TypeLocation::GenericArgList(_)
+                        | TypeLocation::TypeBound
+                        | TypeLocation::ImplTarget
+                        | TypeLocation::ImplTrait
+                        | TypeLocation::Other => (),
+                    }
+                }
+                PathKind::Attr { attr_ctx } => {
+                    attribute::complete_attribute(acc, ctx, path_ctx, attr_ctx);
+                }
+                PathKind::Derive { existing_derives } => {
+                    attribute::complete_derive(acc, ctx, path_ctx, existing_derives);
+                }
+                PathKind::Item { kind } => {
+                    item_list::complete_item_list(acc, ctx, path_ctx, kind);
+                    snippet::complete_item_snippet(acc, ctx, path_ctx, kind);
+                    if let ItemListKind::TraitImpl(impl_) = kind {
+                        item_list::trait_impl::complete_trait_impl_item_by_name(
+                            acc, ctx, path_ctx, nameref, impl_,
+                        );
+                    }
+                }
+                PathKind::Pat { .. } => {
+                    pattern::complete_pattern_path(acc, ctx, path_ctx);
+                }
+                PathKind::Vis { has_in_token } => {
+                    vis::complete_vis_path(acc, ctx, path_ctx, has_in_token);
+                }
+                PathKind::Use => {
+                    use_::complete_use_tree(acc, ctx, path_ctx, nameref);
+                }
+            }
+        }
+        NameRefKind::DotAccess(dot_access) => {
+            flyimport::import_on_the_fly_dot(acc, ctx, dot_access);
+            dot::complete_dot(acc, ctx, dot_access);
+            postfix::complete_postfix(acc, ctx, dot_access);
+        }
+        NameRefKind::Keyword(item) => {
+            keyword::complete_for_and_where(acc, ctx, item);
+        }
+        NameRefKind::RecordExpr(record_expr) => {
+            record::complete_record_expr_fields(acc, ctx, record_expr);
+        }
+        NameRefKind::Pattern(pattern_ctx) => complete_patterns(acc, ctx, pattern_ctx),
+    }
+}
+
+fn complete_patterns(acc: &mut Completions, ctx: &CompletionContext, pattern_ctx: &PatternContext) {
+    flyimport::import_on_the_fly_pat(acc, ctx, pattern_ctx);
+    fn_param::complete_fn_param(acc, ctx, pattern_ctx);
+    pattern::complete_pattern(acc, ctx, pattern_ctx);
+    record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
+}
diff --git a/crates/ide-completion/src/completions/attribute.rs b/crates/ide-completion/src/completions/attribute.rs
index a82ebbdd918..712163d81d2 100644
--- a/crates/ide-completion/src/completions/attribute.rs
+++ b/crates/ide-completion/src/completions/attribute.rs
@@ -18,7 +18,7 @@ use syntax::{
 
 use crate::{
     completions::module_or_attr,
-    context::{AttrCtx, CompletionContext, PathCompletionCtx, PathKind, Qualified},
+    context::{AttrCtx, CompletionContext, PathCompletionCtx, Qualified},
     item::CompletionItem,
     Completions,
 };
@@ -72,16 +72,10 @@ pub(crate) fn complete_known_attribute_input(
 pub(crate) fn complete_attribute(
     acc: &mut Completions,
     ctx: &CompletionContext,
-    path_ctx: &PathCompletionCtx,
+    PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
+    &AttrCtx { kind, annotated_item_kind }: &AttrCtx,
 ) {
-    let (qualified, is_inner, annotated_item_kind) = match path_ctx {
-        &PathCompletionCtx {
-            kind: PathKind::Attr { attr_ctx: AttrCtx { kind, annotated_item_kind } },
-            ref qualified,
-            ..
-        } => (qualified, kind == AttrKind::Inner, annotated_item_kind),
-        _ => return,
-    };
+    let is_inner = kind == AttrKind::Inner;
 
     match qualified {
         Qualified::With {
diff --git a/crates/ide-completion/src/completions/attribute/derive.rs b/crates/ide-completion/src/completions/attribute/derive.rs
index 0927d2f7643..5dee4d79568 100644
--- a/crates/ide-completion/src/completions/attribute/derive.rs
+++ b/crates/ide-completion/src/completions/attribute/derive.rs
@@ -5,7 +5,7 @@ use itertools::Itertools;
 use syntax::SmolStr;
 
 use crate::{
-    context::{CompletionContext, PathCompletionCtx, PathKind, Qualified},
+    context::{CompletionContext, ExistingDerives, PathCompletionCtx, Qualified},
     item::CompletionItem,
     Completions,
 };
@@ -13,15 +13,9 @@ use crate::{
 pub(crate) fn complete_derive(
     acc: &mut Completions,
     ctx: &CompletionContext,
-    path_ctx: &PathCompletionCtx,
+    PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
+    existing_derives: &ExistingDerives,
 ) {
-    let (qualified, existing_derives) = match path_ctx {
-        PathCompletionCtx { kind: PathKind::Derive { existing_derives }, qualified, .. } => {
-            (qualified, existing_derives)
-        }
-        _ => return,
-    };
-
     let core = ctx.famous_defs().core();
 
     match qualified {
diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs
index fea4fbf4d50..a8a57c0c7dd 100644
--- a/crates/ide-completion/src/completions/dot.rs
+++ b/crates/ide-completion/src/completions/dot.rs
@@ -3,10 +3,7 @@
 use ide_db::FxHashSet;
 
 use crate::{
-    context::{
-        CompletionContext, DotAccess, DotAccessKind, ExprCtx, PathCompletionCtx, PathKind,
-        Qualified,
-    },
+    context::{CompletionContext, DotAccess, DotAccessKind, ExprCtx, PathCompletionCtx, Qualified},
     CompletionItem, CompletionItemKind, Completions,
 };
 
@@ -43,16 +40,22 @@ pub(crate) fn complete_undotted_self(
     acc: &mut Completions,
     ctx: &CompletionContext,
     path_ctx: &PathCompletionCtx,
+    expr_ctx: &ExprCtx,
 ) {
     if !ctx.config.enable_self_on_the_fly {
         return;
     }
-    let self_param = match path_ctx {
-        PathCompletionCtx {
-            qualified: Qualified::No,
-            kind: PathKind::Expr { expr_ctx: ExprCtx { self_param: Some(self_param), .. } },
-            ..
-        } if path_ctx.is_trivial_path() && ctx.qualifier_ctx.none() => self_param,
+    if !path_ctx.is_trivial_path() {
+        return;
+    }
+    if !ctx.qualifier_ctx.none() {
+        return;
+    }
+    if !matches!(path_ctx.qualified, Qualified::No) {
+        return;
+    }
+    let self_param = match expr_ctx {
+        ExprCtx { self_param: Some(self_param), .. } => self_param,
         _ => return,
     };
 
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
index 6bc453a514c..84ae596a8d0 100644
--- a/crates/ide-completion/src/completions/expr.rs
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -4,39 +4,31 @@ use hir::ScopeDef;
 use ide_db::FxHashSet;
 
 use crate::{
-    context::{ExprCtx, PathCompletionCtx, PathKind, Qualified},
+    context::{ExprCtx, PathCompletionCtx, Qualified},
     CompletionContext, Completions,
 };
 
 pub(crate) fn complete_expr_path(
     acc: &mut Completions,
     ctx: &CompletionContext,
-    path_ctx: &PathCompletionCtx,
+    PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
+    &ExprCtx {
+        in_block_expr,
+        in_loop_body,
+        after_if_expr,
+        in_condition,
+        incomplete_let,
+        ref ref_expr_parent,
+        ref is_func_update,
+        ref innermost_ret_ty,
+        ref impl_,
+        ..
+    }: &ExprCtx,
 ) {
     let _p = profile::span("complete_expr_path");
     if !ctx.qualifier_ctx.none() {
         return;
     }
-    let (
-        qualified,
-        &ExprCtx {
-            in_block_expr,
-            in_loop_body,
-            after_if_expr,
-            in_condition,
-            incomplete_let,
-            ref ref_expr_parent,
-            ref is_func_update,
-            ref innermost_ret_ty,
-            ref impl_,
-            ..
-        },
-    ) = match path_ctx {
-        PathCompletionCtx { kind: PathKind::Expr { expr_ctx }, qualified, .. } => {
-            (qualified, expr_ctx)
-        }
-        _ => return,
-    };
 
     let wants_mut_token =
         ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false);
diff --git a/crates/ide-completion/src/completions/field.rs b/crates/ide-completion/src/completions/field.rs
index 505f5f1edff..738c24574c9 100644
--- a/crates/ide-completion/src/completions/field.rs
+++ b/crates/ide-completion/src/completions/field.rs
@@ -1,7 +1,7 @@
 //! Completion of field list position.
 
 use crate::{
-    context::{PathCompletionCtx, PathKind, Qualified, TypeLocation},
+    context::{PathCompletionCtx, Qualified},
     CompletionContext, Completions,
 };
 
@@ -10,21 +10,21 @@ pub(crate) fn complete_field_list_tuple_variant(
     ctx: &CompletionContext,
     path_ctx: &PathCompletionCtx,
 ) {
+    if ctx.qualifier_ctx.vis_node.is_some() {
+        return;
+    }
     match path_ctx {
         PathCompletionCtx {
             has_macro_bang: false,
             qualified: Qualified::No,
             parent: None,
-            kind: PathKind::Type { location: TypeLocation::TupleField },
             has_type_args: false,
             ..
         } => {
-            if ctx.qualifier_ctx.vis_node.is_none() {
-                let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
-                add_keyword("pub(crate)", "pub(crate)");
-                add_keyword("pub(super)", "pub(super)");
-                add_keyword("pub", "pub");
-            }
+            let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
+            add_keyword("pub(crate)", "pub(crate)");
+            add_keyword("pub(super)", "pub(super)");
+            add_keyword("pub", "pub");
         }
         _ => (),
     }
diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs
index 8ced01da679..33130028dbc 100644
--- a/crates/ide-completion/src/completions/item_list.rs
+++ b/crates/ide-completion/src/completions/item_list.rs
@@ -2,34 +2,37 @@
 
 use crate::{
     completions::module_or_fn_macro,
-    context::{ExprCtx, ItemListKind, PathCompletionCtx, PathKind, Qualified},
+    context::{ExprCtx, ItemListKind, PathCompletionCtx, Qualified},
     CompletionContext, Completions,
 };
 
 pub(crate) mod trait_impl;
 
-pub(crate) fn complete_item_list(
+pub(crate) fn complete_item_list_in_expr(
     acc: &mut Completions,
     ctx: &CompletionContext,
     path_ctx: &PathCompletionCtx,
+    expr_ctx: &ExprCtx,
+) {
+    if !expr_ctx.in_block_expr {
+        return;
+    }
+    if !path_ctx.is_trivial_path() {
+        return;
+    }
+    add_keywords(acc, ctx, None);
+}
+
+pub(crate) fn complete_item_list(
+    acc: &mut Completions,
+    ctx: &CompletionContext,
+    path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
+    kind: &ItemListKind,
 ) {
     let _p = profile::span("complete_item_list");
-    let qualified = match path_ctx {
-        PathCompletionCtx { kind: PathKind::Item { kind }, qualified, .. } => {
-            if path_ctx.is_trivial_path() {
-                add_keywords(acc, ctx, Some(kind));
-            }
-            qualified
-        }
-        PathCompletionCtx {
-            kind: PathKind::Expr { expr_ctx: ExprCtx { in_block_expr: true, .. } },
-            ..
-        } if path_ctx.is_trivial_path() => {
-            add_keywords(acc, ctx, None);
-            return;
-        }
-        _ => return,
-    };
+    if path_ctx.is_trivial_path() {
+        add_keywords(acc, ctx, Some(kind));
+    }
 
     match qualified {
         Qualified::With {
diff --git a/crates/ide-completion/src/completions/item_list/trait_impl.rs b/crates/ide-completion/src/completions/item_list/trait_impl.rs
index 83d78e1093b..972a7d2f211 100644
--- a/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -43,8 +43,8 @@ use syntax::{
 use text_edit::TextEdit;
 
 use crate::{
-    context::{ItemListKind, PathCompletionCtx, PathKind},
-    CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
+    context::PathCompletionCtx, CompletionContext, CompletionItem, CompletionItemKind,
+    CompletionRelevance, Completions,
 };
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -102,17 +102,18 @@ fn complete_trait_impl_name(
     Some(())
 }
 
-pub(crate) fn complete_trait_impl_name_ref(
+pub(crate) fn complete_trait_impl_item_by_name(
     acc: &mut Completions,
     ctx: &CompletionContext,
     path_ctx: &PathCompletionCtx,
     name_ref: &Option<ast::NameRef>,
-) -> Option<()> {
-    match path_ctx {
-        PathCompletionCtx {
-            kind: PathKind::Item { kind: ItemListKind::TraitImpl(Some(impl_)) },
-            ..
-        } if path_ctx.is_trivial_path() => complete_trait_impl(
+    impl_: &Option<ast::Impl>,
+) {
+    if !path_ctx.is_trivial_path() {
+        return;
+    }
+    if let Some(impl_) = impl_ {
+        complete_trait_impl(
             acc,
             ctx,
             ImplCompletionKind::All,
@@ -121,10 +122,8 @@ pub(crate) fn complete_trait_impl_name_ref(
                 None => ctx.source_range(),
             },
             impl_,
-        ),
-        _ => (),
+        );
     }
-    Some(())
 }
 
 fn complete_trait_impl(
diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs
index 57d545ab8fe..7d8d3a9636d 100644
--- a/crates/ide-completion/src/completions/keyword.rs
+++ b/crates/ide-completion/src/completions/keyword.rs
@@ -4,7 +4,7 @@ use syntax::ast::{self, Item};
 
 use crate::{CompletionContext, Completions};
 
-pub(crate) fn complete_special_keywords(
+pub(crate) fn complete_for_and_where(
     acc: &mut Completions,
     ctx: &CompletionContext,
     keyword_item: &ast::Item,
@@ -60,8 +60,6 @@ mod tests {
                 kw fn
                 kw impl
                 kw trait
-                sn pd
-                sn ppd
             "#]],
         );
     }
diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs
index 149acb3c1be..e2e8d3f205a 100644
--- a/crates/ide-completion/src/completions/pattern.rs
+++ b/crates/ide-completion/src/completions/pattern.rs
@@ -5,7 +5,7 @@ use ide_db::FxHashSet;
 use syntax::ast::Pat;
 
 use crate::{
-    context::{PathCompletionCtx, PathKind, PatternContext, PatternRefutability, Qualified},
+    context::{PathCompletionCtx, PatternContext, PatternRefutability, Qualified},
     CompletionContext, Completions,
 };
 
@@ -108,14 +108,11 @@ pub(crate) fn complete_pattern(
     });
 }
 
-pub(crate) fn pattern_path_completion(
+pub(crate) fn complete_pattern_path(
     acc: &mut Completions,
     ctx: &CompletionContext,
-    PathCompletionCtx { qualified, kind, .. }: &PathCompletionCtx,
+    PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
 ) {
-    if !matches!(kind, PathKind::Pat { .. }) {
-        return;
-    }
     match qualified {
         Qualified::With { resolution: Some(resolution), is_super_chain, .. } => {
             if *is_super_chain {
diff --git a/crates/ide-completion/src/completions/record.rs b/crates/ide-completion/src/completions/record.rs
index 18115241067..12c449bf352 100644
--- a/crates/ide-completion/src/completions/record.rs
+++ b/crates/ide-completion/src/completions/record.rs
@@ -6,7 +6,7 @@ use syntax::{
 };
 
 use crate::{
-    context::{ExprCtx, PathCompletionCtx, PathKind, PatternContext, Qualified},
+    context::{ExprCtx, PathCompletionCtx, PatternContext, Qualified},
     CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
     CompletionRelevancePostfixMatch, Completions,
 };
@@ -20,7 +20,7 @@ pub(crate) fn complete_record_pattern_fields(
         complete_fields(acc, ctx, ctx.sema.record_pattern_missing_fields(record_pat));
     }
 }
-pub(crate) fn complete_record_expr_fields_record_expr(
+pub(crate) fn complete_record_expr_fields(
     acc: &mut Completions,
     ctx: &CompletionContext,
     record_expr: &ast::RecordExpr,
@@ -85,13 +85,12 @@ pub(crate) fn complete_record_expr_func_update(
     acc: &mut Completions,
     ctx: &CompletionContext,
     path_ctx: &PathCompletionCtx,
+    expr_ctx: &ExprCtx,
 ) {
-    if let PathCompletionCtx {
-        kind: PathKind::Expr { expr_ctx: ExprCtx { is_func_update: Some(record_expr), .. } },
-        qualified: Qualified::No,
-        ..
-    } = path_ctx
-    {
+    if !matches!(path_ctx.qualified, Qualified::No) {
+        return;
+    }
+    if let ExprCtx { is_func_update: Some(record_expr), .. } = expr_ctx {
         let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_expr.clone()));
 
         match ty.as_ref().and_then(|t| t.original.as_adt()) {
diff --git a/crates/ide-completion/src/completions/snippet.rs b/crates/ide-completion/src/completions/snippet.rs
index af315616fad..9992a81fe07 100644
--- a/crates/ide-completion/src/completions/snippet.rs
+++ b/crates/ide-completion/src/completions/snippet.rs
@@ -4,7 +4,7 @@ use hir::Documentation;
 use ide_db::{imports::insert_use::ImportScope, SnippetCap};
 
 use crate::{
-    context::{ExprCtx, ItemListKind, PathCompletionCtx, PathKind, Qualified},
+    context::{ExprCtx, ItemListKind, PathCompletionCtx, Qualified},
     item::Builder,
     CompletionContext, CompletionItem, CompletionItemKind, Completions, SnippetScope,
 };
@@ -19,15 +19,14 @@ pub(crate) fn complete_expr_snippet(
     acc: &mut Completions,
     ctx: &CompletionContext,
     path_ctx: &PathCompletionCtx,
+    &ExprCtx { in_block_expr, .. }: &ExprCtx,
 ) {
-    let &can_be_stmt = match path_ctx {
-        PathCompletionCtx {
-            qualified: Qualified::No,
-            kind: PathKind::Expr { expr_ctx: ExprCtx { in_block_expr, .. } },
-            ..
-        } => in_block_expr,
-        _ => return,
-    };
+    if !matches!(path_ctx.qualified, Qualified::No) {
+        return;
+    }
+    if !ctx.qualifier_ctx.none() {
+        return;
+    }
 
     let cap = match ctx.config.snippet_cap {
         Some(it) => it,
@@ -38,9 +37,21 @@ pub(crate) fn complete_expr_snippet(
         add_custom_completions(acc, ctx, cap, SnippetScope::Expr);
     }
 
-    if can_be_stmt {
+    if in_block_expr {
         snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
         snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
+        let item = snippet(
+            ctx,
+            cap,
+            "macro_rules",
+            "\
+macro_rules! $1 {
+    ($2) => {
+        $0
+    };
+}",
+        );
+        item.add_to(acc);
     }
 }
 
@@ -48,23 +59,13 @@ pub(crate) fn complete_item_snippet(
     acc: &mut Completions,
     ctx: &CompletionContext,
     path_ctx: &PathCompletionCtx,
+    kind: &ItemListKind,
 ) {
-    let path_kind = match path_ctx {
-        PathCompletionCtx {
-            qualified: Qualified::No,
-            kind:
-                kind @ (PathKind::Item { .. }
-                | PathKind::Expr { expr_ctx: ExprCtx { in_block_expr: true, .. }, .. }),
-            ..
-        } => kind,
-        _ => return,
-    };
-    if !ctx.qualifier_ctx.none() {
+    if !matches!(path_ctx.qualified, Qualified::No) {
         return;
     }
-    if ctx.qualifier_ctx.vis_node.is_some() {
-        return; // technically we could do some of these snippet completions if we were to put the
-                // attributes before the vis node.
+    if !ctx.qualifier_ctx.none() {
+        return;
     }
     let cap = match ctx.config.snippet_cap {
         Some(it) => it,
@@ -76,8 +77,7 @@ pub(crate) fn complete_item_snippet(
     }
 
     // Test-related snippets shouldn't be shown in blocks.
-    if let PathKind::Item { kind: ItemListKind::SourceFile | ItemListKind::Module, .. } = path_kind
-    {
+    if let ItemListKind::SourceFile | ItemListKind::Module = kind {
         let mut item = snippet(
             ctx,
             cap,
@@ -108,10 +108,7 @@ fn ${1:feature}() {
         );
         item.lookup_by("tfn");
         item.add_to(acc);
-    }
-    if let PathKind::Item { kind: ItemListKind::SourceFile | ItemListKind::Module, .. }
-    | PathKind::Expr { .. } = path_kind
-    {
+
         let item = snippet(
             ctx,
             cap,
diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs
index b8d172696d7..0f7ca758681 100644
--- a/crates/ide-completion/src/completions/type.rs
+++ b/crates/ide-completion/src/completions/type.rs
@@ -5,7 +5,7 @@ use ide_db::FxHashSet;
 use syntax::{ast, AstNode};
 
 use crate::{
-    context::{PathCompletionCtx, PathKind, Qualified, TypeAscriptionTarget, TypeLocation},
+    context::{PathCompletionCtx, Qualified, TypeAscriptionTarget, TypeLocation},
     render::render_type_inference,
     CompletionContext, Completions,
 };
@@ -13,17 +13,11 @@ use crate::{
 pub(crate) fn complete_type_path(
     acc: &mut Completions,
     ctx: &CompletionContext,
-    path_ctx: &PathCompletionCtx,
+    PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
+    location: &TypeLocation,
 ) {
     let _p = profile::span("complete_type_path");
 
-    let (location, qualified) = match path_ctx {
-        PathCompletionCtx { kind: PathKind::Type { location }, qualified, .. } => {
-            (location, qualified)
-        }
-        _ => return,
-    };
-
     let scope_def_applicable = |def| {
         use hir::{GenericParam::*, ModuleDef::*};
         match def {
@@ -191,19 +185,16 @@ pub(crate) fn complete_type_path(
     }
 }
 
-pub(crate) fn complete_inferred_type(
+pub(crate) fn complete_ascribed_type(
     acc: &mut Completions,
     ctx: &CompletionContext,
     path_ctx: &PathCompletionCtx,
+    ascription: &TypeAscriptionTarget,
 ) -> Option<()> {
-    let pat = match path_ctx {
-        PathCompletionCtx {
-            kind: PathKind::Type { location: TypeLocation::TypeAscription(ascription), .. },
-            ..
-        } if path_ctx.is_trivial_path() => ascription,
-        _ => return None,
-    };
-    let x = match pat {
+    if !path_ctx.is_trivial_path() {
+        return None;
+    }
+    let x = match ascription {
         TypeAscriptionTarget::Let(pat) | TypeAscriptionTarget::FnParam(pat) => {
             ctx.sema.type_of_pat(pat.as_ref()?)
         }
diff --git a/crates/ide-completion/src/completions/use_.rs b/crates/ide-completion/src/completions/use_.rs
index e12acc34e7b..9ebbc8ab9dc 100644
--- a/crates/ide-completion/src/completions/use_.rs
+++ b/crates/ide-completion/src/completions/use_.rs
@@ -5,7 +5,7 @@ use ide_db::{FxHashSet, SymbolKind};
 use syntax::{ast, AstNode};
 
 use crate::{
-    context::{CompletionContext, PathCompletionCtx, PathKind, Qualified},
+    context::{CompletionContext, PathCompletionCtx, Qualified},
     item::Builder,
     CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
 };
@@ -13,16 +13,9 @@ use crate::{
 pub(crate) fn complete_use_tree(
     acc: &mut Completions,
     ctx: &CompletionContext,
-    path_ctx: &PathCompletionCtx,
+    PathCompletionCtx { qualified, use_tree_parent, .. }: &PathCompletionCtx,
     name_ref: &Option<ast::NameRef>,
 ) {
-    let (qualified, name_ref, use_tree_parent) = match path_ctx {
-        PathCompletionCtx { kind: PathKind::Use, qualified, use_tree_parent, .. } => {
-            (qualified, name_ref, use_tree_parent)
-        }
-        _ => return,
-    };
-
     match qualified {
         Qualified::With { path, resolution: Some(resolution), is_super_chain } => {
             if *is_super_chain {
diff --git a/crates/ide-completion/src/completions/vis.rs b/crates/ide-completion/src/completions/vis.rs
index 18513039e67..86ffe32ff3d 100644
--- a/crates/ide-completion/src/completions/vis.rs
+++ b/crates/ide-completion/src/completions/vis.rs
@@ -3,22 +3,16 @@
 use hir::ScopeDef;
 
 use crate::{
-    context::{CompletionContext, PathCompletionCtx, PathKind, Qualified},
+    context::{CompletionContext, PathCompletionCtx, Qualified},
     Completions,
 };
 
 pub(crate) fn complete_vis_path(
     acc: &mut Completions,
     ctx: &CompletionContext,
-    path_ctx: &PathCompletionCtx,
+    PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
+    &has_in_token: &bool,
 ) {
-    let (qualified, &has_in_token) = match path_ctx {
-        PathCompletionCtx { kind: PathKind::Vis { has_in_token }, qualified, .. } => {
-            (qualified, has_in_token)
-        }
-        _ => return,
-    };
-
     match qualified {
         Qualified::With {
             resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index c212b5b9b9d..8c73709f4ce 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -97,7 +97,7 @@ pub(super) enum PathKind {
         attr_ctx: AttrCtx,
     },
     Derive {
-        existing_derives: FxHashSet<hir::Macro>,
+        existing_derives: ExistingDerives,
     },
     /// Path in item position, that is inside an (Assoc)ItemList
     Item {
@@ -111,6 +111,9 @@ pub(super) enum PathKind {
     },
     Use,
 }
+
+pub(crate) type ExistingDerives = FxHashSet<hir::Macro>;
+
 #[derive(Debug, PartialEq, Eq)]
 pub(crate) struct AttrCtx {
     pub(crate) kind: AttrKind,
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index 5a3ddeea25e..90e2628439f 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -25,7 +25,7 @@ use text_edit::TextEdit;
 use crate::{
     completions::Completions,
     context::{
-        CompletionContext, IdentContext, NameContext, NameKind, NameRefContext, NameRefKind,
+        CompletionContext, IdentContext, NameRefContext, NameRefKind, PathCompletionCtx, PathKind,
     },
 };
 
@@ -153,10 +153,13 @@ pub fn completions(
 
     // prevent `(` from triggering unwanted completion noise
     if trigger_character == Some('(') {
-        if let IdentContext::NameRef(NameRefContext { kind: NameRefKind::Path(path_ctx), .. }) =
-            &ctx.ident_ctx
-        {
-            completions::vis::complete_vis_path(&mut completions, ctx, path_ctx);
+        if let IdentContext::NameRef(NameRefContext { kind, .. }) = &ctx.ident_ctx {
+            if let NameRefKind::Path(
+                path_ctx @ PathCompletionCtx { kind: PathKind::Vis { has_in_token }, .. },
+            ) = kind
+            {
+                completions::vis::complete_vis_path(&mut completions, ctx, path_ctx, has_in_token);
+            }
         }
         // prevent `(` from triggering unwanted completion noise
         return Some(completions);
@@ -165,84 +168,11 @@ pub fn completions(
     {
         let acc = &mut completions;
 
-        let mut complete_patterns = |pattern_ctx| {
-            completions::flyimport::import_on_the_fly_pat(acc, ctx, pattern_ctx);
-            completions::fn_param::complete_fn_param(acc, ctx, pattern_ctx);
-            completions::pattern::complete_pattern(acc, ctx, pattern_ctx);
-            completions::record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
-        };
-
         match &ctx.ident_ctx {
-            IdentContext::Name(NameContext { name, kind }) => match kind {
-                NameKind::Const => {
-                    completions::item_list::trait_impl::complete_trait_impl_const(acc, ctx, name);
-                }
-                NameKind::Function => {
-                    completions::item_list::trait_impl::complete_trait_impl_fn(acc, ctx, name);
-                }
-                NameKind::IdentPat(pattern_ctx) => complete_patterns(pattern_ctx),
-                NameKind::Module(mod_under_caret) => {
-                    completions::mod_::complete_mod(acc, ctx, mod_under_caret);
-                }
-                NameKind::TypeAlias => {
-                    completions::item_list::trait_impl::complete_trait_impl_type_alias(
-                        acc, ctx, name,
-                    );
-                }
-                NameKind::RecordField => {
-                    completions::field::complete_field_list_record_variant(acc, ctx);
-                }
-                NameKind::ConstParam
-                | NameKind::Enum
-                | NameKind::MacroDef
-                | NameKind::MacroRules
-                | NameKind::Rename
-                | NameKind::SelfParam
-                | NameKind::Static
-                | NameKind::Struct
-                | NameKind::Trait
-                | NameKind::TypeParam
-                | NameKind::Union
-                | NameKind::Variant => (),
-            },
-            IdentContext::NameRef(NameRefContext { kind, nameref }) => match kind {
-                NameRefKind::Path(path_ctx) => {
-                    completions::attribute::complete_attribute(acc, ctx, path_ctx);
-                    completions::attribute::complete_derive(acc, ctx, path_ctx);
-                    completions::dot::complete_undotted_self(acc, ctx, path_ctx);
-                    completions::expr::complete_expr_path(acc, ctx, path_ctx);
-                    completions::field::complete_field_list_tuple_variant(acc, ctx, path_ctx);
-                    completions::flyimport::import_on_the_fly_path(acc, ctx, path_ctx);
-                    completions::item_list::complete_item_list(acc, ctx, path_ctx);
-                    completions::item_list::trait_impl::complete_trait_impl_name_ref(
-                        acc, ctx, path_ctx, nameref,
-                    );
-                    completions::pattern::pattern_path_completion(acc, ctx, path_ctx);
-                    completions::r#type::complete_inferred_type(acc, ctx, path_ctx);
-                    completions::r#type::complete_type_path(acc, ctx, path_ctx);
-                    completions::record::complete_record_expr_func_update(acc, ctx, path_ctx);
-                    completions::snippet::complete_expr_snippet(acc, ctx, path_ctx);
-                    completions::snippet::complete_item_snippet(acc, ctx, path_ctx);
-                    completions::use_::complete_use_tree(acc, ctx, path_ctx, nameref);
-                    completions::vis::complete_vis_path(acc, ctx, path_ctx);
-                }
-                NameRefKind::DotAccess(dot_access) => {
-                    completions::flyimport::import_on_the_fly_dot(acc, ctx, dot_access);
-                    completions::dot::complete_dot(acc, ctx, dot_access);
-                    completions::postfix::complete_postfix(acc, ctx, dot_access);
-                }
-                NameRefKind::Keyword(item) => {
-                    completions::keyword::complete_special_keywords(acc, ctx, item);
-                }
-                NameRefKind::RecordExpr(record_expr) => {
-                    completions::record::complete_record_expr_fields_record_expr(
-                        acc,
-                        ctx,
-                        record_expr,
-                    );
-                }
-                NameRefKind::Pattern(pattern_ctx) => complete_patterns(pattern_ctx),
-            },
+            IdentContext::Name(name_ctx) => completions::complete_name(acc, ctx, name_ctx),
+            IdentContext::NameRef(name_ref_ctx) => {
+                completions::complete_name_ref(acc, ctx, name_ref_ctx)
+            }
             IdentContext::Lifetime(lifetime_ctx) => {
                 completions::lifetime::complete_label(acc, ctx, lifetime_ctx);
                 completions::lifetime::complete_lifetime(acc, ctx, lifetime_ctx);