aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_ide/src/expand.rs53
1 files changed, 36 insertions, 17 deletions
diff --git a/crates/ra_ide/src/expand.rs b/crates/ra_ide/src/expand.rs
index 216d5cfec..661628ae4 100644
--- a/crates/ra_ide/src/expand.rs
+++ b/crates/ra_ide/src/expand.rs
@@ -3,7 +3,7 @@ use std::iter::successors;
3 3
4use hir::InFile; 4use hir::InFile;
5use ra_db::FileId; 5use ra_db::FileId;
6use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken}; 6use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange};
7 7
8use crate::{db::RootDatabase, FileRange}; 8use crate::{db::RootDatabase, FileRange};
9 9
@@ -17,26 +17,45 @@ pub(crate) fn original_range(db: &RootDatabase, node: InFile<&SyntaxNode>) -> Fi
17 } 17 }
18 Some(it) => it, 18 Some(it) => it,
19 }; 19 };
20 // FIXME: the following completely wrong. 20 // FIXME: We should handle recurside macro expansions
21 // 21
22 // *First*, we should try to map first and last tokens of node, and, if that 22 let range = node.value.descendants_with_tokens().find_map(|it| {
23 // fails, return the range of the overall macro expansions. 23 match it.as_token() {
24 // 24 // FIXME: Remove this branch after all `tt::TokenTree`s have a proper `TokenId`,
25 // *Second*, we should handle recurside macro expansions 25 // and return the range of the overall macro expansions if mapping first and last tokens fails.
26 26 Some(token) => {
27 let token = node 27 let token = expansion.map_token_up(node.with_value(&token))?;
28 .value 28 Some(token.with_value(token.value.text_range()))
29 .descendants_with_tokens() 29 }
30 .filter_map(|it| it.into_token()) 30 None => {
31 .find_map(|it| expansion.map_token_up(node.with_value(&it))); 31 // Try to map first and last tokens of node, and, if success, return the union range of mapped tokens
32 32 let n = it.into_node()?;
33 match token { 33 let first = expansion.map_token_up(node.with_value(&n.first_token()?))?;
34 Some(it) => { 34 let last = expansion.map_token_up(node.with_value(&n.last_token()?))?;
35 FileRange { file_id: it.file_id.original_file(db), range: it.value.text_range() } 35
36 // FIXME: Is is possible ?
37 if first.file_id != last.file_id {
38 return None;
39 }
40
41 // FIXME: Add union method in TextRange
42 let range = union_range(first.value.text_range(), last.value.text_range());
43 Some(first.with_value(range))
44 }
36 } 45 }
46 });
47
48 return match range {
49 Some(it) => FileRange { file_id: it.file_id.original_file(db), range: it.value },
37 None => { 50 None => {
38 FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() } 51 FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() }
39 } 52 }
53 };
54
55 fn union_range(a: TextRange, b: TextRange) -> TextRange {
56 let start = a.start().min(b.start());
57 let end = a.end().max(b.end());
58 TextRange::from_to(start, end)
40 } 59 }
41} 60}
42 61