diff --git a/crates/ra_ide/src/expand.rs b/crates/ra_ide/src/expand.rs
index 216d5cfec71..661628ae466 100644
--- a/crates/ra_ide/src/expand.rs
+++ b/crates/ra_ide/src/expand.rs
@@ -3,7 +3,7 @@ use std::iter::successors;
 
 use hir::InFile;
 use ra_db::FileId;
-use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken};
+use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange};
 
 use crate::{db::RootDatabase, FileRange};
 
@@ -17,26 +17,45 @@ pub(crate) fn original_range(db: &RootDatabase, node: InFile<&SyntaxNode>) -> Fi
         }
         Some(it) => it,
     };
-    // FIXME: the following completely wrong.
-    //
-    // *First*, we should try to map first and last tokens of node, and, if that
-    // fails, return the range of the overall macro expansions.
-    //
-    // *Second*, we should handle recurside macro expansions
+    // FIXME: We should handle recurside macro expansions
 
-    let token = node
-        .value
-        .descendants_with_tokens()
-        .filter_map(|it| it.into_token())
-        .find_map(|it| expansion.map_token_up(node.with_value(&it)));
+    let range = node.value.descendants_with_tokens().find_map(|it| {
+        match it.as_token() {
+            // FIXME: Remove this branch after all `tt::TokenTree`s have a proper `TokenId`,
+            // and return the range of the overall macro expansions if mapping first and last tokens fails.
+            Some(token) => {
+                let token = expansion.map_token_up(node.with_value(&token))?;
+                Some(token.with_value(token.value.text_range()))
+            }
+            None => {
+                // Try to map first and last tokens of node, and, if success, return the union range of mapped tokens
+                let n = it.into_node()?;
+                let first = expansion.map_token_up(node.with_value(&n.first_token()?))?;
+                let last = expansion.map_token_up(node.with_value(&n.last_token()?))?;
 
-    match token {
-        Some(it) => {
-            FileRange { file_id: it.file_id.original_file(db), range: it.value.text_range() }
+                // FIXME: Is is possible ?
+                if first.file_id != last.file_id {
+                    return None;
+                }
+
+                // FIXME: Add union method in TextRange
+                let range = union_range(first.value.text_range(), last.value.text_range());
+                Some(first.with_value(range))
+            }
         }
+    });
+
+    return match range {
+        Some(it) => FileRange { file_id: it.file_id.original_file(db), range: it.value },
         None => {
             FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() }
         }
+    };
+
+    fn union_range(a: TextRange, b: TextRange) -> TextRange {
+        let start = a.start().min(b.start());
+        let end = a.end().max(b.end());
+        TextRange::from_to(start, end)
     }
 }