diff --git a/crates/ra_analysis/src/completion/complete_dot.rs b/crates/ra_analysis/src/completion/complete_dot.rs
index fa62da21052..93d65757681 100644
--- a/crates/ra_analysis/src/completion/complete_dot.rs
+++ b/crates/ra_analysis/src/completion/complete_dot.rs
@@ -33,9 +33,9 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) -> Ca
     Ok(())
 }
 
-fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, ty: Ty) -> Cancelable<()> {
+fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) -> Cancelable<()> {
     // TODO: autoderef etc.
-    match ty {
+    match receiver {
         Ty::Adt { def_id, .. } => {
             match def_id.resolve(ctx.db)? {
                 Def::Struct(s) => {
diff --git a/crates/ra_analysis/src/completion/completion_context.rs b/crates/ra_analysis/src/completion/completion_context.rs
index 12e98e870cd..978772fd447 100644
--- a/crates/ra_analysis/src/completion/completion_context.rs
+++ b/crates/ra_analysis/src/completion/completion_context.rs
@@ -1,12 +1,13 @@
 use ra_editor::find_node_at_offset;
 use ra_text_edit::AtomTextEdit;
 use ra_syntax::{
-    algo::find_leaf_at_offset,
+    algo::{find_leaf_at_offset, find_covering_node},
     ast,
     AstNode,
     SyntaxNodeRef,
     SourceFileNode,
     TextUnit,
+    TextRange,
     SyntaxKind::*,
 };
 use hir::source_binder;
@@ -65,7 +66,7 @@ impl<'a> CompletionContext<'a> {
         Ok(Some(ctx))
     }
 
-    fn fill(&mut self, original_file: &SourceFileNode, offset: TextUnit) {
+    fn fill(&mut self, original_file: &'a SourceFileNode, offset: TextUnit) {
         // Insert a fake ident to get a valid parse tree. We will use this file
         // to determine context, though the original_file will be used for
         // actual completion.
@@ -82,7 +83,7 @@ impl<'a> CompletionContext<'a> {
                 self.is_param = true;
                 return;
             }
-            self.classify_name_ref(&file, name_ref);
+            self.classify_name_ref(original_file, name_ref);
         }
 
         // Otherwise, see if this is a declaration. We can use heuristics to
@@ -94,7 +95,7 @@ impl<'a> CompletionContext<'a> {
             }
         }
     }
-    fn classify_name_ref(&mut self, file: &SourceFileNode, name_ref: ast::NameRef) {
+    fn classify_name_ref(&mut self, original_file: &'a SourceFileNode, name_ref: ast::NameRef) {
         let name_range = name_ref.syntax().range();
         let top_node = name_ref
             .syntax()
@@ -144,7 +145,9 @@ impl<'a> CompletionContext<'a> {
                 };
 
                 if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) {
-                    if let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) {
+                    if let Some(if_expr) =
+                        find_node_at_offset::<ast::IfExpr>(original_file.syntax(), off)
+                    {
                         if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
                             self.after_if = true;
                         }
@@ -152,26 +155,33 @@ impl<'a> CompletionContext<'a> {
                 }
             }
         }
-        if let Some(_field_expr) = ast::FieldExpr::cast(parent) {
-            self.dot_receiver = self
-                .leaf
-                .ancestors()
-                .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
-                .find_map(ast::FieldExpr::cast)
-                .and_then(ast::FieldExpr::expr);
+        if let Some(field_expr) = ast::FieldExpr::cast(parent) {
+            // The receiver comes before the point of insertion of the fake
+            // ident, so it should have the same range in the non-modified file
+            self.dot_receiver = field_expr
+                .expr()
+                .map(|e| e.syntax().range())
+                .and_then(|r| find_node_with_range(original_file.syntax(), r));
         }
-        if let Some(_method_call_expr) = ast::MethodCallExpr::cast(parent) {
-            self.dot_receiver = self
-                .leaf
-                .ancestors()
-                .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
-                .find_map(ast::MethodCallExpr::cast)
-                .and_then(ast::MethodCallExpr::expr);
+        if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) {
+            // As above
+            self.dot_receiver = method_call_expr
+                .expr()
+                .map(|e| e.syntax().range())
+                .and_then(|r| find_node_with_range(original_file.syntax(), r));
             self.is_method_call = true;
         }
     }
 }
 
+fn find_node_with_range<'a, N: AstNode<'a>>(
+    syntax: SyntaxNodeRef<'a>,
+    range: TextRange,
+) -> Option<N> {
+    let node = find_covering_node(syntax, range);
+    node.ancestors().find_map(N::cast)
+}
+
 fn is_node<'a, N: AstNode<'a>>(node: SyntaxNodeRef<'a>) -> bool {
     match node.ancestors().filter_map(N::cast).next() {
         None => false,