aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/fn_references.rs80
1 files changed, 77 insertions, 3 deletions
diff --git a/crates/ide/src/fn_references.rs b/crates/ide/src/fn_references.rs
index ca91b98cf..1989a562b 100644
--- a/crates/ide/src/fn_references.rs
+++ b/crates/ide/src/fn_references.rs
@@ -1,3 +1,6 @@
1//! This module implements a methods and free functions search in the specified file.
2//! We have to skip tests, so cannot reuse file_structure module.
3
1use hir::Semantics; 4use hir::Semantics;
2use ide_db::RootDatabase; 5use ide_db::RootDatabase;
3use syntax::{ast, ast::NameOwner, AstNode, SyntaxNode}; 6use syntax::{ast, ast::NameOwner, AstNode, SyntaxNode};
@@ -10,12 +13,83 @@ pub(crate) fn find_all_methods(db: &RootDatabase, file_id: FileId) -> Vec<FileRa
10 source_file.syntax().descendants().filter_map(|it| method_range(it, file_id)).collect() 13 source_file.syntax().descendants().filter_map(|it| method_range(it, file_id)).collect()
11} 14}
12 15
13pub(crate) fn method_range(item: SyntaxNode, file_id: FileId) -> Option<FileRange> { 16fn method_range(item: SyntaxNode, file_id: FileId) -> Option<FileRange> {
14 ast::Fn::cast(item).and_then(|fn_def|{ 17 ast::Fn::cast(item).and_then(|fn_def| {
15 if has_test_related_attribute(&fn_def) { 18 if has_test_related_attribute(&fn_def) {
16 None 19 None
17 } else { 20 } else {
18 fn_def.name().map(|name| FileRange{ file_id, range: name.syntax().text_range() }) 21 fn_def.name().map(|name| FileRange { file_id, range: name.syntax().text_range() })
19 } 22 }
20 }) 23 })
21} 24}
25
26#[cfg(test)]
27mod tests {
28 use crate::mock_analysis::analysis_and_position;
29 use crate::{FileRange, TextSize};
30 use std::ops::RangeInclusive;
31
32 #[test]
33 fn test_find_all_methods() {
34 let (analysis, pos) = analysis_and_position(
35 r#"
36 //- /lib.rs
37 fn private_fn() {<|>}
38
39 pub fn pub_fn() {}
40
41 pub fn generic_fn<T>(arg: T) {}
42 "#,
43 );
44
45 let refs = analysis.find_all_methods(pos.file_id).unwrap();
46 check_result(&refs, &[3..=13, 27..=33, 47..=57]);
47 }
48
49 #[test]
50 fn test_find_trait_methods() {
51 let (analysis, pos) = analysis_and_position(
52 r#"
53 //- /lib.rs
54 trait Foo {
55 fn bar() {<|>}
56 fn baz() {}
57 }
58 "#,
59 );
60
61 let refs = analysis.find_all_methods(pos.file_id).unwrap();
62 check_result(&refs, &[19..=22, 35..=38]);
63 }
64
65 #[test]
66 fn test_skip_tests() {
67 let (analysis, pos) = analysis_and_position(
68 r#"
69 //- /lib.rs
70 #[test]
71 fn foo() {<|>}
72
73 pub fn pub_fn() {}
74
75 mod tests {
76 #[test]
77 fn bar() {}
78 }
79 "#,
80 );
81
82 let refs = analysis.find_all_methods(pos.file_id).unwrap();
83 check_result(&refs, &[28..=34]);
84 }
85
86 fn check_result(refs: &[FileRange], expected: &[RangeInclusive<u32>]) {
87 assert_eq!(refs.len(), expected.len());
88
89 for (i, item) in refs.iter().enumerate() {
90 let range = &expected[i];
91 assert_eq!(TextSize::from(*range.start()), item.range.start());
92 assert_eq!(TextSize::from(*range.end()), item.range.end());
93 }
94 }
95}