diff options
Diffstat (limited to 'crates/ra_ide/src/expand.rs')
-rw-r--r-- | crates/ra_ide/src/expand.rs | 53 |
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 | ||
4 | use hir::InFile; | 4 | use hir::InFile; |
5 | use ra_db::FileId; | 5 | use ra_db::FileId; |
6 | use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken}; | 6 | use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange}; |
7 | 7 | ||
8 | use crate::{db::RootDatabase, FileRange}; | 8 | use 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 | ||