diff options
Diffstat (limited to 'crates/ra_ide_api/src/search_scope.rs')
-rw-r--r-- | crates/ra_ide_api/src/search_scope.rs | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/search_scope.rs b/crates/ra_ide_api/src/search_scope.rs new file mode 100644 index 000000000..ca1ac2b03 --- /dev/null +++ b/crates/ra_ide_api/src/search_scope.rs | |||
@@ -0,0 +1,186 @@ | |||
1 | pub enum SearchScope { | ||
2 | Function(hir::Function), | ||
3 | Module(hir::Module), | ||
4 | Crate(hir::Crate), | ||
5 | Crates(Vec<hir::Crate>), | ||
6 | } | ||
7 | |||
8 | pub struct SearchScope{ | ||
9 | pub scope: Vec<SyntaxNode> | ||
10 | } | ||
11 | |||
12 | pub fn find_all_refs(db: &RootDatabase, decl: NameKind) -> Vec<ReferenceDescriptor> { | ||
13 | let (module, visibility) = match decl { | ||
14 | FieldAccess(field) => { | ||
15 | let parent = field.parent_def(db); | ||
16 | let module = parent.module(db); | ||
17 | let visibility = match parent { | ||
18 | VariantDef::Struct(s) => s.source(db).ast.visibility(), | ||
19 | VariantDef::EnumVariant(v) => v.parent_enum(db).source(db).ast.visibility(), | ||
20 | }; | ||
21 | (module, visibility) | ||
22 | } | ||
23 | AssocItem(item) => { | ||
24 | let parent = item.parent_trait(db)?; | ||
25 | let module = parent.module(db); | ||
26 | let visibility = parent.source(db).ast.visibility(); | ||
27 | (module, visibility) | ||
28 | } | ||
29 | Def(def) => { | ||
30 | let (module, visibility) = match def { | ||
31 | ModuleDef::Module(m) => (m, ), | ||
32 | ModuleDef::Function(f) => (f.module(db), f.source(db).ast.visibility()), | ||
33 | ModuleDef::Adt::Struct(s) => (s.module(db), s.source(db).ast.visibility()), | ||
34 | ModuleDef::Adt::Union(u) => (u.module(db), u.source(db).ast.visibility()), | ||
35 | ModuleDef::Adt::Enum(e) => (e.module(db), e.source(db).ast.visibility()), | ||
36 | ModuleDef::EnumVariant(v) => (v.module(db), v.source(db).ast.visibility()), | ||
37 | ModuleDef::Const(c) => (c.module(db), c.source(db).ast.visibility()), | ||
38 | ModuleDef::Static(s) => (s.module(db), s.source(db).ast.visibility()), | ||
39 | ModuleDef::Trait(t) => (t.module(db), t.source(db).ast.visibility()), | ||
40 | ModuleDef::TypeAlias(a) => (a.module(db), a.source(db).ast.visibility()), | ||
41 | ModuleDef::BuiltinType(_) => return vec![]; | ||
42 | }; | ||
43 | (module, visibility) | ||
44 | } | ||
45 | // FIXME: add missing kinds | ||
46 | _ => return vec![]; | ||
47 | }; | ||
48 | let scope = scope(db, module, visibility); | ||
49 | } | ||
50 | |||
51 | fn scope(db: &RootDatabase, module: hir::Module, item_vis: Option<ast::Visibility>) -> SearchScope { | ||
52 | if let Some(v) = item_vis { | ||
53 | let krate = module.krate(db)?; | ||
54 | |||
55 | if v.syntax().text() == "pub" { | ||
56 | SearchScope::Crate(krate) | ||
57 | } | ||
58 | if v.syntax().text() == "pub(crate)" { | ||
59 | let crate_graph = db.crate_graph(); | ||
60 | let crates = crate_graph.iter().filter(|id| { | ||
61 | crate_graph.dependencies(id).any(|d| d.crate_id() == krate.crate_id()) | ||
62 | }).map(|id| Crate { id }).collect::<Vec<_>>(); | ||
63 | crates.insert(0, krate); | ||
64 | SearchScope::Crates(crates) | ||
65 | } | ||
66 | // FIXME: "pub(super)", "pub(in path)" | ||
67 | SearchScope::Module(module) | ||
68 | } | ||
69 | SearchScope::Module(module) | ||
70 | } | ||
71 | |||
72 | fn process_one(db, scope: SearchScope, pat) { | ||
73 | match scope { | ||
74 | SearchScope::Crate(krate) => { | ||
75 | let text = db.file_text(position.file_id).as_str(); | ||
76 | let parse = SourceFile::parse(text); | ||
77 | for (offset, name) in text.match_indices(pat) { | ||
78 | if let Some() = find_node_at_offset<ast::NameRef>(parse, offset) { | ||
79 | |||
80 | } | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | |||
86 | #[cfg(test)] | ||
87 | mod tests { | ||
88 | use crate::{ | ||
89 | mock_analysis::analysis_and_position, mock_analysis::single_file_with_position, FileId, | ||
90 | ReferenceSearchResult, | ||
91 | }; | ||
92 | use insta::assert_debug_snapshot; | ||
93 | use test_utils::assert_eq_text; | ||
94 | |||
95 | #[test] | ||
96 | fn test_find_all_refs_for_local() { | ||
97 | let code = r#" | ||
98 | fn main() { | ||
99 | let mut i = 1; | ||
100 | let j = 1; | ||
101 | i = i<|> + j; | ||
102 | |||
103 | { | ||
104 | i = 0; | ||
105 | } | ||
106 | |||
107 | i = 5; | ||
108 | } | ||
109 | "#; | ||
110 | |||
111 | let refs = get_all_refs(code); | ||
112 | assert_eq!(refs.len(), 5); | ||
113 | } | ||
114 | |||
115 | #[test] | ||
116 | fn test_find_all_refs_for_param_inside() { | ||
117 | let code = r#" | ||
118 | fn foo(i : u32) -> u32 { | ||
119 | i<|> | ||
120 | }"#; | ||
121 | |||
122 | let refs = get_all_refs(code); | ||
123 | assert_eq!(refs.len(), 2); | ||
124 | } | ||
125 | |||
126 | #[test] | ||
127 | fn test_find_all_refs_for_fn_param() { | ||
128 | let code = r#" | ||
129 | fn foo(i<|> : u32) -> u32 { | ||
130 | i | ||
131 | }"#; | ||
132 | |||
133 | let refs = get_all_refs(code); | ||
134 | assert_eq!(refs.len(), 2); | ||
135 | } | ||
136 | |||
137 | #[test] | ||
138 | fn test_find_all_refs_field_name() { | ||
139 | let code = r#" | ||
140 | //- /lib.rs | ||
141 | struct Foo { | ||
142 | spam<|>: u32, | ||
143 | } | ||
144 | "#; | ||
145 | |||
146 | let refs = get_all_refs(code); | ||
147 | assert_eq!(refs.len(), 1); | ||
148 | } | ||
149 | |||
150 | #[test] | ||
151 | fn test_find_all_refs_methods() { | ||
152 | let code = r#" | ||
153 | //- /lib.rs | ||
154 | struct Foo; | ||
155 | impl Foo { | ||
156 | pub fn a() { | ||
157 | self.b() | ||
158 | } | ||
159 | fn b(&self) {} | ||
160 | } | ||
161 | "#; | ||
162 | |||
163 | let refs = get_all_refs(code); | ||
164 | assert_eq!(refs.len(), 1); | ||
165 | } | ||
166 | |||
167 | #[test] | ||
168 | fn test_find_all_refs_pub_enum() { | ||
169 | let code = r#" | ||
170 | //- /lib.rs | ||
171 | pub enum Foo { | ||
172 | A, | ||
173 | B<|>, | ||
174 | C, | ||
175 | } | ||
176 | "#; | ||
177 | |||
178 | let refs = get_all_refs(code); | ||
179 | assert_eq!(refs.len(), 1); | ||
180 | } | ||
181 | |||
182 | fn get_all_refs(text: &str) -> ReferenceSearchResult { | ||
183 | let (analysis, position) = single_file_with_position(text); | ||
184 | analysis.find_all_refs(position).unwrap().unwrap() | ||
185 | } | ||
186 | } \ No newline at end of file | ||