aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/extend_selection.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/extend_selection.rs')
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs56
1 files changed, 56 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
new file mode 100644
index 000000000..c3c809c9f
--- /dev/null
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -0,0 +1,56 @@
1use ra_db::SyntaxDatabase;
2use ra_syntax::{
3 SyntaxNode, AstNode, SourceFile,
4 ast, algo::find_covering_node,
5};
6
7use crate::{
8 TextRange, FileRange,
9 db::RootDatabase,
10};
11
12pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRange {
13 let source_file = db.source_file(frange.file_id);
14 if let Some(range) = extend_selection_in_macro(db, &source_file, frange) {
15 return range;
16 }
17 ra_ide_api_light::extend_selection(source_file.syntax(), frange.range).unwrap_or(frange.range)
18}
19
20fn extend_selection_in_macro(
21 _db: &RootDatabase,
22 source_file: &SourceFile,
23 frange: FileRange,
24) -> Option<TextRange> {
25 let macro_call = find_macro_call(source_file.syntax(), frange.range)?;
26 let (off, exp) = hir::MacroDef::ast_expand(macro_call)?;
27 let dst_range = exp.map_range_forward(frange.range - off)?;
28 let dst_range = ra_ide_api_light::extend_selection(&exp.syntax(), dst_range)?;
29 let src_range = exp.map_range_back(dst_range)? + off;
30 Some(src_range)
31}
32
33fn find_macro_call(node: &SyntaxNode, range: TextRange) -> Option<&ast::MacroCall> {
34 find_covering_node(node, range)
35 .ancestors()
36 .find_map(ast::MacroCall::cast)
37}
38
39#[cfg(test)]
40mod tests {
41 use crate::mock_analysis::single_file_with_range;
42 use test_utils::assert_eq_dbg;
43
44 #[test]
45 fn extend_selection_inside_macros() {
46 let (analysis, frange) = single_file_with_range(
47 "
48 fn main() {
49 ctry!(foo(|x| <|>x<|>));
50 }
51 ",
52 );
53 let r = analysis.extend_selection(frange);
54 assert_eq_dbg("[51; 56)", &r);
55 }
56}