about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2022-05-07 13:46:43 +0200
committerLukas Wirth <lukastw97@gmail.com>2022-05-07 13:46:43 +0200
commit6a045c70296043ce2d00a8c0d7b0ee9264ff4aba (patch)
tree18bc32ec828d392bec7172eef6bc1d03bf2948e1
parent1dc83f5a90248c53fca38eaee7392a5485a375a3 (diff)
downloadrust-6a045c70296043ce2d00a8c0d7b0ee9264ff4aba.tar.gz
rust-6a045c70296043ce2d00a8c0d7b0ee9264ff4aba.zip
Introduce NameRefContext
-rw-r--r--crates/ide-completion/src/completions/attribute.rs4
-rw-r--r--crates/ide-completion/src/completions/attribute/derive.rs9
-rw-r--r--crates/ide-completion/src/completions/dot.rs10
-rw-r--r--crates/ide-completion/src/completions/expr.rs2
-rw-r--r--crates/ide-completion/src/completions/flyimport.rs2
-rw-r--r--crates/ide-completion/src/completions/item_list.rs2
-rw-r--r--crates/ide-completion/src/completions/keyword.rs4
-rw-r--r--crates/ide-completion/src/completions/pattern.rs2
-rw-r--r--crates/ide-completion/src/completions/postfix.rs17
-rw-r--r--crates/ide-completion/src/completions/snippet.rs4
-rw-r--r--crates/ide-completion/src/completions/type.rs2
-rw-r--r--crates/ide-completion/src/completions/use_.rs2
-rw-r--r--crates/ide-completion/src/completions/vis.rs2
-rw-r--r--crates/ide-completion/src/context.rs139
-rw-r--r--crates/ide-completion/src/patterns.rs31
-rw-r--r--crates/ide-completion/src/render.rs2
-rw-r--r--crates/ide-completion/src/render/function.rs9
-rw-r--r--crates/ide-completion/src/render/literal.rs2
-rw-r--r--crates/ide-completion/src/render/macro_.rs4
-rw-r--r--crates/ide-completion/src/render/pattern.rs2
20 files changed, 145 insertions, 106 deletions
diff --git a/crates/ide-completion/src/completions/attribute.rs b/crates/ide-completion/src/completions/attribute.rs
index fef177d2dd0..ec95021ec02 100644
--- a/crates/ide-completion/src/completions/attribute.rs
+++ b/crates/ide-completion/src/completions/attribute.rs
@@ -69,8 +69,8 @@ pub(crate) fn complete_known_attribute_input(
 }
 
 pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) {
-    let (is_absolute_path, qualifier, is_inner, annotated_item_kind) = match ctx.path_context {
-        Some(PathCompletionCtx {
+    let (is_absolute_path, qualifier, is_inner, annotated_item_kind) = match ctx.path_context() {
+        Some(&PathCompletionCtx {
             kind: PathKind::Attr { kind, annotated_item_kind },
             is_absolute_path,
             ref qualifier,
diff --git a/crates/ide-completion/src/completions/attribute/derive.rs b/crates/ide-completion/src/completions/attribute/derive.rs
index d827d781a32..19414e4b315 100644
--- a/crates/ide-completion/src/completions/attribute/derive.rs
+++ b/crates/ide-completion/src/completions/attribute/derive.rs
@@ -11,9 +11,12 @@ use crate::{
 };
 
 pub(crate) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext) {
-    let (qualifier, is_absolute_path) = match ctx.path_context {
-        Some(PathCompletionCtx {
-            kind: PathKind::Derive, ref qualifier, is_absolute_path, ..
+    let (qualifier, is_absolute_path) = match ctx.path_context() {
+        Some(&PathCompletionCtx {
+            kind: PathKind::Derive,
+            ref qualifier,
+            is_absolute_path,
+            ..
         }) => (qualifier, is_absolute_path),
         _ => return,
     };
diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs
index 33af76c7100..af0f38a3d8d 100644
--- a/crates/ide-completion/src/completions/dot.rs
+++ b/crates/ide-completion/src/completions/dot.rs
@@ -3,8 +3,7 @@
 use ide_db::FxHashSet;
 
 use crate::{
-    context::{CompletionContext, PathCompletionCtx, PathKind},
-    patterns::ImmediateLocation,
+    context::{CompletionContext, DotAccess, NameRefContext, PathCompletionCtx, PathKind},
     Completions,
 };
 
@@ -20,7 +19,10 @@ pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
         _ => return,
     };
 
-    if matches!(ctx.completion_location, Some(ImmediateLocation::MethodCall { .. })) {
+    if matches!(
+        ctx.nameref_ctx,
+        Some(NameRefContext { dot_access: Some(DotAccess::Method { .. }), .. }),
+    ) {
         cov_mark::hit!(test_no_struct_field_completion_for_method_call);
     } else {
         complete_fields(
@@ -38,7 +40,7 @@ fn complete_undotted_self(acc: &mut Completions, ctx: &CompletionContext) {
     if !ctx.config.enable_self_on_the_fly {
         return;
     }
-    match ctx.path_context {
+    match ctx.path_context() {
         Some(PathCompletionCtx {
             is_absolute_path: false,
             qualifier: None,
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
index b7e2b886574..a2a17d92185 100644
--- a/crates/ide-completion/src/completions/expr.rs
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -14,7 +14,7 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
         return;
     }
 
-    let (&is_absolute_path, qualifier) = match &ctx.path_context {
+    let (&is_absolute_path, qualifier) = match ctx.path_context() {
         Some(PathCompletionCtx {
             kind: PathKind::Expr { .. },
             is_absolute_path,
diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs
index 7a90126916f..bfa4c06f922 100644
--- a/crates/ide-completion/src/completions/flyimport.rs
+++ b/crates/ide-completion/src/completions/flyimport.rs
@@ -119,7 +119,7 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
         return None;
     }
     // FIXME: This should be encoded in a different way
-    if ctx.pattern_ctx.is_none() && ctx.path_context.is_none() && !ctx.has_dot_receiver() {
+    if ctx.pattern_ctx.is_none() && ctx.path_context().is_none() && !ctx.has_dot_receiver() {
         // completion inside `ast::Name` of a item declaration
         return None;
     }
diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs
index df03120dfe1..ebbc33c2da0 100644
--- a/crates/ide-completion/src/completions/item_list.rs
+++ b/crates/ide-completion/src/completions/item_list.rs
@@ -12,7 +12,7 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext)
         return;
     }
 
-    let (&is_absolute_path, qualifier) = match &ctx.path_context {
+    let (&is_absolute_path, qualifier) = match ctx.path_context() {
         Some(PathCompletionCtx {
             kind: PathKind::Item { .. },
             is_absolute_path,
diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs
index 557992d14a9..766ab4fcd7d 100644
--- a/crates/ide-completion/src/completions/keyword.rs
+++ b/crates/ide-completion/src/completions/keyword.rs
@@ -124,8 +124,8 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
         add_keyword("mut", "mut ");
     }
 
-    let (can_be_stmt, in_loop_body) = match ctx.path_context {
-        Some(PathCompletionCtx {
+    let (can_be_stmt, in_loop_body) = match ctx.path_context() {
+        Some(&PathCompletionCtx {
             is_absolute_path: false,
             kind: PathKind::Expr { in_block_expr, in_loop_body, .. },
             ..
diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs
index 963ee309590..211ca4e531b 100644
--- a/crates/ide-completion/src/completions/pattern.rs
+++ b/crates/ide-completion/src/completions/pattern.rs
@@ -17,7 +17,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
     };
     let refutable = patctx.refutability == PatternRefutability::Refutable;
 
-    if let Some(path_ctx) = &ctx.path_context {
+    if let Some(path_ctx) = ctx.path_context() {
         pattern_path_completion(acc, ctx, path_ctx);
         return;
     }
diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs
index cc2a4437000..ef765a345a5 100644
--- a/crates/ide-completion/src/completions/postfix.rs
+++ b/crates/ide-completion/src/completions/postfix.rs
@@ -13,9 +13,8 @@ use text_edit::TextEdit;
 
 use crate::{
     completions::postfix::format_like::add_format_like_completions,
-    context::CompletionContext,
+    context::{CompletionContext, DotAccess, NameRefContext},
     item::{Builder, CompletionRelevancePostfixMatch},
-    patterns::ImmediateLocation,
     CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope,
 };
 
@@ -24,11 +23,15 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
         return;
     }
 
-    let (dot_receiver, receiver_is_ambiguous_float_literal) = match &ctx.completion_location {
-        Some(ImmediateLocation::MethodCall { receiver: Some(it), .. }) => (it, false),
-        Some(ImmediateLocation::FieldAccess {
-            receiver: Some(it),
-            receiver_is_ambiguous_float_literal,
+    let (dot_receiver, receiver_is_ambiguous_float_literal) = match &ctx.nameref_ctx {
+        Some(NameRefContext {
+            dot_access: Some(DotAccess::Method { receiver: Some(it), .. }),
+            ..
+        }) => (it, false),
+        Some(NameRefContext {
+            dot_access:
+                Some(DotAccess::Field { receiver: Some(it), receiver_is_ambiguous_float_literal }),
+            ..
         }) => (it, *receiver_is_ambiguous_float_literal),
         _ => return,
     };
diff --git a/crates/ide-completion/src/completions/snippet.rs b/crates/ide-completion/src/completions/snippet.rs
index 38136db4a9f..2bae19c84fd 100644
--- a/crates/ide-completion/src/completions/snippet.rs
+++ b/crates/ide-completion/src/completions/snippet.rs
@@ -17,7 +17,7 @@ fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str)
 }
 
 pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) {
-    let can_be_stmt = match ctx.path_context {
+    let &can_be_stmt = match ctx.path_context() {
         Some(PathCompletionCtx {
             is_absolute_path: false,
             qualifier: None,
@@ -43,7 +43,7 @@ pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionConte
 }
 
 pub(crate) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) {
-    let path_kind = match ctx.path_context {
+    let path_kind = match ctx.path_context() {
         Some(PathCompletionCtx {
             is_absolute_path: false,
             qualifier: None,
diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs
index a8d71fd8688..9381548e5ed 100644
--- a/crates/ide-completion/src/completions/type.rs
+++ b/crates/ide-completion/src/completions/type.rs
@@ -17,7 +17,7 @@ pub(crate) fn complete_type_path(acc: &mut Completions, ctx: &CompletionContext)
         return;
     }
 
-    let (&is_absolute_path, qualifier) = match &ctx.path_context {
+    let (&is_absolute_path, qualifier) = match ctx.path_context() {
         Some(PathCompletionCtx { kind: PathKind::Type, is_absolute_path, qualifier, .. }) => {
             (is_absolute_path, qualifier)
         }
diff --git a/crates/ide-completion/src/completions/use_.rs b/crates/ide-completion/src/completions/use_.rs
index a8d301da17f..d52a348eb87 100644
--- a/crates/ide-completion/src/completions/use_.rs
+++ b/crates/ide-completion/src/completions/use_.rs
@@ -11,7 +11,7 @@ use crate::{
 };
 
 pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext) {
-    let (&is_absolute_path, qualifier) = match &ctx.path_context {
+    let (&is_absolute_path, qualifier) = match ctx.path_context() {
         Some(PathCompletionCtx { kind: PathKind::Use, is_absolute_path, qualifier, .. }) => {
             (is_absolute_path, qualifier)
         }
diff --git a/crates/ide-completion/src/completions/vis.rs b/crates/ide-completion/src/completions/vis.rs
index 50560c99923..b5e86b62d1a 100644
--- a/crates/ide-completion/src/completions/vis.rs
+++ b/crates/ide-completion/src/completions/vis.rs
@@ -8,7 +8,7 @@ use crate::{
 };
 
 pub(crate) fn complete_vis(acc: &mut Completions, ctx: &CompletionContext) {
-    let (&is_absolute_path, qualifier, &has_in_token) = match &ctx.path_context {
+    let (&is_absolute_path, qualifier, &has_in_token) = match ctx.path_context() {
         Some(PathCompletionCtx {
             kind: PathKind::Vis { has_in_token },
             is_absolute_path,
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 802e48f23a6..e6b41ffbd45 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -14,7 +14,7 @@ use ide_db::{
 };
 use syntax::{
     algo::{find_node_at_offset, non_trivia_sibling},
-    ast::{self, AttrKind, HasName, NameOrNameRef},
+    ast::{self, AttrKind, HasArgList, HasName, NameOrNameRef},
     match_ast, AstNode, NodeOrToken,
     SyntaxKind::{self, *},
     SyntaxNode, SyntaxToken, TextRange, TextSize, T,
@@ -148,6 +148,26 @@ pub(super) enum NameContext {
     Variant,
 }
 
+#[derive(Debug)]
+pub(super) struct NameRefContext {
+    pub(super) dot_access: Option<DotAccess>,
+    pub(super) path_ctx: Option<PathCompletionCtx>,
+}
+
+#[derive(Debug)]
+pub(super) enum DotAccess {
+    Field {
+        receiver: Option<ast::Expr>,
+        /// True if the receiver is an integer and there is no ident in the original file after it yet
+        /// like `0.$0`
+        receiver_is_ambiguous_float_literal: bool,
+    },
+    Method {
+        receiver: Option<ast::Expr>,
+        has_parens: bool,
+    },
+}
+
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub(crate) enum ParamKind {
     Function(ast::Fn),
@@ -195,8 +215,8 @@ pub(crate) struct CompletionContext<'a> {
 
     pub(super) name_ctx: Option<NameContext>,
     pub(super) lifetime_ctx: Option<LifetimeContext>,
+    pub(super) nameref_ctx: Option<NameRefContext>,
     pub(super) pattern_ctx: Option<PatternContext>,
-    pub(super) path_context: Option<PathCompletionCtx>,
 
     pub(super) existing_derives: FxHashSet<hir::Macro>,
 
@@ -237,21 +257,18 @@ impl<'a> CompletionContext<'a> {
     }
 
     pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> {
-        match &self.completion_location {
-            Some(
-                ImmediateLocation::MethodCall { receiver, .. }
-                | ImmediateLocation::FieldAccess { receiver, .. },
-            ) => receiver.as_ref(),
+        match &self.nameref_ctx {
+            Some(NameRefContext {
+                dot_access:
+                    Some(DotAccess::Method { receiver, .. } | DotAccess::Field { receiver, .. }),
+                ..
+            }) => receiver.as_ref(),
             _ => None,
         }
     }
 
     pub(crate) fn has_dot_receiver(&self) -> bool {
-        matches!(
-            &self.completion_location,
-            Some(ImmediateLocation::FieldAccess { receiver, .. } | ImmediateLocation::MethodCall { receiver,.. })
-                if receiver.is_some()
-        )
+        self.dot_receiver().is_some()
     }
 
     pub(crate) fn expects_assoc_item(&self) -> bool {
@@ -324,21 +341,25 @@ impl<'a> CompletionContext<'a> {
             || matches!(self.name_ctx, Some(NameContext::Module(_) | NameContext::Rename))
     }
 
+    pub(crate) fn path_context(&self) -> Option<&PathCompletionCtx> {
+        self.nameref_ctx.as_ref().and_then(|ctx| ctx.path_ctx.as_ref())
+    }
+
     pub(crate) fn expects_expression(&self) -> bool {
-        matches!(self.path_context, Some(PathCompletionCtx { kind: PathKind::Expr { .. }, .. }))
+        matches!(self.path_context(), Some(PathCompletionCtx { kind: PathKind::Expr { .. }, .. }))
     }
 
     pub(crate) fn expects_type(&self) -> bool {
-        matches!(self.path_context, Some(PathCompletionCtx { kind: PathKind::Type, .. }))
+        matches!(self.path_context(), Some(PathCompletionCtx { kind: PathKind::Type, .. }))
     }
 
     pub(crate) fn path_is_call(&self) -> bool {
-        self.path_context.as_ref().map_or(false, |it| it.has_call_parens)
+        self.path_context().map_or(false, |it| it.has_call_parens)
     }
 
     pub(crate) fn is_non_trivial_path(&self) -> bool {
         matches!(
-            self.path_context,
+            self.path_context(),
             Some(
                 PathCompletionCtx { is_absolute_path: true, .. }
                     | PathCompletionCtx { qualifier: Some(_), .. }
@@ -347,11 +368,11 @@ impl<'a> CompletionContext<'a> {
     }
 
     pub(crate) fn path_qual(&self) -> Option<&ast::Path> {
-        self.path_context.as_ref().and_then(|it| it.qualifier.as_ref().map(|it| &it.path))
+        self.path_context().and_then(|it| it.qualifier.as_ref().map(|it| &it.path))
     }
 
     pub(crate) fn path_kind(&self) -> Option<PathKind> {
-        self.path_context.as_ref().map(|it| it.kind)
+        self.path_context().map(|it| it.kind)
     }
 
     pub(crate) fn is_immediately_after_macro_bang(&self) -> bool {
@@ -498,17 +519,17 @@ impl<'a> CompletionContext<'a> {
             function_def: None,
             impl_def: None,
             name_syntax: None,
-            lifetime_ctx: None,
-            pattern_ctx: None,
-            name_ctx: None,
+            incomplete_let: false,
             completion_location: None,
             prev_sibling: None,
             fake_attribute_under_caret: None,
             previous_token: None,
-            path_context: None,
-            locals,
-            incomplete_let: false,
+            name_ctx: None,
+            lifetime_ctx: None,
+            nameref_ctx: None,
+            pattern_ctx: None,
             existing_derives: Default::default(),
+            locals,
         };
         ctx.expand_and_fill(
             original_file.syntax().clone(),
@@ -843,11 +864,13 @@ impl<'a> CompletionContext<'a> {
             {
                 self.name_syntax =
                     find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
-                if let Some((path_ctx, _)) =
+                if let Some((mut nameref_ctx, _)) =
                     Self::classify_name_ref(&self.sema, &original_file, name_ref)
                 {
-                    self.path_context =
-                        Some(PathCompletionCtx { kind: PathKind::Derive, ..path_ctx });
+                    if let Some(path_ctx) = &mut nameref_ctx.path_ctx {
+                        path_ctx.kind = PathKind::Derive;
+                    }
+                    self.nameref_ctx = Some(nameref_ctx);
                 }
             }
             return;
@@ -878,10 +901,10 @@ impl<'a> CompletionContext<'a> {
                 self.lifetime_ctx = Self::classify_lifetime(&self.sema, original_file, lifetime);
             }
             ast::NameLike::NameRef(name_ref) => {
-                if let Some((path_ctx, pat_ctx)) =
+                if let Some((nameref_ctx, pat_ctx)) =
                     Self::classify_name_ref(&self.sema, original_file, name_ref)
                 {
-                    self.path_context = Some(path_ctx);
+                    self.nameref_ctx = Some(nameref_ctx);
                     self.pattern_ctx = pat_ctx;
                 }
             }
@@ -968,11 +991,53 @@ impl<'a> CompletionContext<'a> {
         sema: &Semantics<RootDatabase>,
         original_file: &SyntaxNode,
         name_ref: ast::NameRef,
-    ) -> Option<(PathCompletionCtx, Option<PatternContext>)> {
+    ) -> Option<(NameRefContext, Option<PatternContext>)> {
         let parent = name_ref.syntax().parent()?;
-        let segment = ast::PathSegment::cast(parent)?;
-        let path = segment.parent_path();
 
+        let mut nameref_ctx = NameRefContext { dot_access: None, path_ctx: None };
+
+        fn find_in_original_file<N: AstNode>(
+            x: Option<N>,
+            original_file: &SyntaxNode,
+        ) -> Option<N> {
+            fn find_node_with_range<N: AstNode>(
+                syntax: &SyntaxNode,
+                range: TextRange,
+            ) -> Option<N> {
+                let range = syntax.text_range().intersect(range)?;
+                syntax.covering_element(range).ancestors().find_map(N::cast)
+            }
+            x.map(|e| e.syntax().text_range()).and_then(|r| find_node_with_range(original_file, r))
+        }
+        let segment = match_ast! {
+            match parent {
+                ast::PathSegment(segment) => segment,
+                ast::FieldExpr(field) => {
+                    let receiver = find_in_original_file(field.expr(), original_file);
+                    let receiver_is_ambiguous_float_literal = match &receiver {
+                        Some(ast::Expr::Literal(l)) => matches! {
+                            l.kind(),
+                            ast::LiteralKind::FloatNumber { .. } if l.syntax().last_token().map_or(false, |it| it.kind() == T![.])
+                        },
+                        _ => false,
+                    };
+                    nameref_ctx.dot_access = Some(DotAccess::Field { receiver, receiver_is_ambiguous_float_literal });
+                    return Some((nameref_ctx, None));
+                },
+                ast::MethodCallExpr(method) => {
+                    nameref_ctx.dot_access = Some(
+                        DotAccess::Method {
+                            receiver: find_in_original_file(method.receiver(), original_file),
+                            has_parens: method.arg_list().map_or(false, |it| it.l_paren_token().is_some())
+                        }
+                    );
+                    return Some((nameref_ctx, None));
+                },
+                _ => return None,
+            }
+        };
+
+        let path = segment.parent_path();
         let mut path_ctx = PathCompletionCtx {
             has_call_parens: false,
             has_macro_bang: false,
@@ -1109,17 +1174,13 @@ impl<'a> CompletionContext<'a> {
                     is_infer_qualifier,
                 }
             });
-            return Some((path_ctx, pat_ctx));
-        }
-
-        if let Some(segment) = path.segment() {
+        } else if let Some(segment) = path.segment() {
             if segment.coloncolon_token().is_some() {
                 path_ctx.is_absolute_path = true;
-                return Some((path_ctx, pat_ctx));
             }
         }
-
-        Some((path_ctx, pat_ctx))
+        nameref_ctx.path_ctx = Some(path_ctx);
+        Some((nameref_ctx, pat_ctx))
     }
 }
 
diff --git a/crates/ide-completion/src/patterns.rs b/crates/ide-completion/src/patterns.rs
index c1db8ce4a6c..07b2ac4297f 100644
--- a/crates/ide-completion/src/patterns.rs
+++ b/crates/ide-completion/src/patterns.rs
@@ -8,7 +8,7 @@ use hir::Semantics;
 use ide_db::RootDatabase;
 use syntax::{
     algo::non_trivia_sibling,
-    ast::{self, HasArgList, HasLoopBody, HasName},
+    ast::{self, HasLoopBody, HasName},
     match_ast, AstNode, Direction, SyntaxElement,
     SyntaxKind::*,
     SyntaxNode, SyntaxToken, TextRange, TextSize,
@@ -51,16 +51,6 @@ pub(crate) enum ImmediateLocation {
     TypeBound,
     /// Original file ast node
     TypeAnnotation(TypeAnnotation),
-    /// Original file ast node
-    MethodCall {
-        receiver: Option<ast::Expr>,
-        has_parens: bool,
-    },
-    /// Original file ast node
-    FieldAccess {
-        receiver: Option<ast::Expr>,
-        receiver_is_ambiguous_float_literal: bool,
-    },
     // Only set from a type arg
     /// Original file ast node
     GenericArgList(ast::GenericArgList),
@@ -226,25 +216,6 @@ pub(crate) fn determine_location(
             ast::GenericArgList(_) => sema
                 .find_node_at_offset_with_macros(original_file, offset)
                 .map(ImmediateLocation::GenericArgList)?,
-            ast::FieldExpr(it) => {
-                let receiver = find_in_original_file(it.expr(), original_file);
-                let receiver_is_ambiguous_float_literal = if let Some(ast::Expr::Literal(l)) = &receiver {
-                    match l.kind() {
-                        ast::LiteralKind::FloatNumber { .. } => l.to_string().ends_with('.'),
-                        _ => false,
-                    }
-                } else {
-                    false
-                };
-                ImmediateLocation::FieldAccess {
-                    receiver,
-                    receiver_is_ambiguous_float_literal,
-                }
-            },
-            ast::MethodCallExpr(it) => ImmediateLocation::MethodCall {
-                receiver: find_in_original_file(it.receiver(), original_file),
-                has_parens: it.arg_list().map_or(false, |it| it.l_paren_token().is_some())
-            },
             ast::Const(it) => {
                 if !it.ty().map_or(false, |x| x.syntax().text_range().contains(offset)) {
                     return None;
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index a59c8e8ee2f..01c9bfdb85c 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -272,7 +272,7 @@ fn render_resolution_simple_(
 
     // Add `<>` for generic types
     let type_path_no_ty_args = matches!(
-        ctx.completion.path_context,
+        ctx.completion.path_context(),
         Some(PathCompletionCtx { kind: PathKind::Type, has_type_args: false, .. })
     ) && ctx.completion.config.add_call_parenthesis;
     if type_path_no_ty_args {
diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index 0117d869ea4..93c64eec6f8 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/crates/ide-completion/src/render/function.rs
@@ -7,9 +7,8 @@ use stdx::{format_to, to_lower_snake_case};
 use syntax::SmolStr;
 
 use crate::{
-    context::{CompletionContext, PathCompletionCtx, PathKind},
+    context::{CompletionContext, DotAccess, NameRefContext, PathCompletionCtx, PathKind},
     item::{Builder, CompletionItem, CompletionItemKind, CompletionRelevance},
-    patterns::ImmediateLocation,
     render::{compute_exact_name_match, compute_ref_match, compute_type_match, RenderContext},
 };
 
@@ -196,7 +195,7 @@ fn should_add_parens(ctx: &CompletionContext) -> bool {
         return false;
     }
 
-    match ctx.path_context {
+    match ctx.path_context() {
         Some(PathCompletionCtx { kind: PathKind::Expr { .. }, has_call_parens: true, .. }) => {
             return false
         }
@@ -208,8 +207,8 @@ fn should_add_parens(ctx: &CompletionContext) -> bool {
     };
 
     if matches!(
-        ctx.completion_location,
-        Some(ImmediateLocation::MethodCall { has_parens: true, .. })
+        ctx.nameref_ctx,
+        Some(NameRefContext { dot_access: Some(DotAccess::Method { has_parens: true, .. }), .. })
     ) {
         return false;
     }
diff --git a/crates/ide-completion/src/render/literal.rs b/crates/ide-completion/src/render/literal.rs
index f1773137fed..e6540e6ac53 100644
--- a/crates/ide-completion/src/render/literal.rs
+++ b/crates/ide-completion/src/render/literal.rs
@@ -52,7 +52,7 @@ fn render(
     let db = completion.db;
     let kind = thing.kind(db);
     let has_call_parens =
-        matches!(completion.path_context, Some(PathCompletionCtx { has_call_parens: true, .. }));
+        matches!(completion.path_context(), Some(PathCompletionCtx { has_call_parens: true, .. }));
 
     let fields = thing.fields(completion)?;
     let (qualified_name, short_qualified_name, qualified) = match path {
diff --git a/crates/ide-completion/src/render/macro_.rs b/crates/ide-completion/src/render/macro_.rs
index 22df7132f0e..9c51a6311a4 100644
--- a/crates/ide-completion/src/render/macro_.rs
+++ b/crates/ide-completion/src/render/macro_.rs
@@ -33,8 +33,8 @@ fn render(
     let is_fn_like = macro_.is_fn_like(completion.db);
     let (bra, ket) = if is_fn_like { guess_macro_braces(&name, docs_str) } else { ("", "") };
 
-    let needs_bang = match completion.path_context {
-        Some(PathCompletionCtx { kind, has_macro_bang, .. }) => {
+    let needs_bang = match completion.path_context() {
+        Some(&PathCompletionCtx { kind, has_macro_bang, .. }) => {
             is_fn_like && kind != PathKind::Use && !has_macro_bang
         }
         _ => is_fn_like,
diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs
index ff61bf61c54..5b403ae8ccc 100644
--- a/crates/ide-completion/src/render/pattern.rs
+++ b/crates/ide-completion/src/render/pattern.rs
@@ -78,7 +78,7 @@ fn render_pat(
     fields_omitted: bool,
 ) -> Option<String> {
     let has_call_parens = matches!(
-        ctx.completion.path_context,
+        ctx.completion.path_context(),
         Some(PathCompletionCtx { has_call_parens: true, .. })
     );
     let mut pat = match kind {