diff options
Diffstat (limited to 'crates/ra_analysis/src/imp.rs')
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 975afc145..03d17de0d 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -27,6 +27,7 @@ use crate::{ | |||
27 | symbol_index::{SymbolIndex, SymbolsDatabase}, | 27 | symbol_index::{SymbolIndex, SymbolsDatabase}, |
28 | AnalysisChange, Cancelable, CrateId, Diagnostic, FileId, | 28 | AnalysisChange, Cancelable, CrateId, Diagnostic, FileId, |
29 | FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit, | 29 | FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit, |
30 | ReferenceResolution, | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | #[derive(Debug, Default)] | 33 | #[derive(Debug, Default)] |
@@ -144,7 +145,7 @@ impl AnalysisImpl { | |||
144 | } else { | 145 | } else { |
145 | let files = &self.db.source_root(WORKSPACE).files; | 146 | let files = &self.db.source_root(WORKSPACE).files; |
146 | 147 | ||
147 | /// Need to wrap Snapshot to provide `Clon` impl for `map_with` | 148 | /// Need to wrap Snapshot to provide `Clone` impl for `map_with` |
148 | struct Snap(salsa::Snapshot<db::RootDatabase>); | 149 | struct Snap(salsa::Snapshot<db::RootDatabase>); |
149 | impl Clone for Snap { | 150 | impl Clone for Snap { |
150 | fn clone(&self) -> Snap { | 151 | fn clone(&self) -> Snap { |
@@ -164,7 +165,7 @@ impl AnalysisImpl { | |||
164 | .sweep(salsa::SweepStrategy::default().discard_values()); | 165 | .sweep(salsa::SweepStrategy::default().discard_values()); |
165 | Ok(query.search(&buf)) | 166 | Ok(query.search(&buf)) |
166 | } | 167 | } |
167 | /// This return `Vec`: a module may be included from several places. We | 168 | /// This returns `Vec` because a module may be included from several places. We |
168 | /// don't handle this case yet though, so the Vec has length at most one. | 169 | /// don't handle this case yet though, so the Vec has length at most one. |
169 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 170 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
170 | let descr = match source_binder::module_from_position(&*self.db, position)? { | 171 | let descr = match source_binder::module_from_position(&*self.db, position)? { |
@@ -206,10 +207,11 @@ impl AnalysisImpl { | |||
206 | pub fn approximately_resolve_symbol( | 207 | pub fn approximately_resolve_symbol( |
207 | &self, | 208 | &self, |
208 | position: FilePosition, | 209 | position: FilePosition, |
209 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 210 | ) -> Cancelable<Option<ReferenceResolution>> { |
210 | let file = self.db.source_file(position.file_id); | 211 | let file = self.db.source_file(position.file_id); |
211 | let syntax = file.syntax(); | 212 | let syntax = file.syntax(); |
212 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { | 213 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { |
214 | let mut rr = ReferenceResolution::new(name_ref.syntax().range()); | ||
213 | if let Some(fn_descr) = source_binder::function_from_child_node( | 215 | if let Some(fn_descr) = source_binder::function_from_child_node( |
214 | &*self.db, | 216 | &*self.db, |
215 | position.file_id, | 217 | position.file_id, |
@@ -218,22 +220,25 @@ impl AnalysisImpl { | |||
218 | let scope = fn_descr.scope(&*self.db); | 220 | let scope = fn_descr.scope(&*self.db); |
219 | // First try to resolve the symbol locally | 221 | // First try to resolve the symbol locally |
220 | if let Some(entry) = scope.resolve_local_name(name_ref) { | 222 | if let Some(entry) = scope.resolve_local_name(name_ref) { |
221 | let mut vec = vec![]; | 223 | rr.add_resolution( |
222 | vec.push(( | ||
223 | position.file_id, | 224 | position.file_id, |
224 | FileSymbol { | 225 | FileSymbol { |
225 | name: entry.name().clone(), | 226 | name: entry.name().clone(), |
226 | node_range: entry.ptr().range(), | 227 | node_range: entry.ptr().range(), |
227 | kind: NAME, | 228 | kind: NAME, |
228 | }, | 229 | }, |
229 | )); | 230 | ); |
230 | return Ok(vec); | 231 | return Ok(Some(rr)); |
231 | }; | 232 | }; |
232 | } | 233 | } |
233 | // If that fails try the index based approach. | 234 | // If that fails try the index based approach. |
234 | return self.index_resolve(name_ref); | 235 | for (file_id, symbol) in self.index_resolve(name_ref)? { |
236 | rr.add_resolution(file_id, symbol); | ||
237 | } | ||
238 | return Ok(Some(rr)); | ||
235 | } | 239 | } |
236 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { | 240 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { |
241 | let mut rr = ReferenceResolution::new(name.syntax().range()); | ||
237 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { | 242 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { |
238 | if module.has_semi() { | 243 | if module.has_semi() { |
239 | let parent_module = | 244 | let parent_module = |
@@ -248,7 +253,8 @@ impl AnalysisImpl { | |||
248 | node_range: TextRange::offset_len(0.into(), 0.into()), | 253 | node_range: TextRange::offset_len(0.into(), 0.into()), |
249 | kind: MODULE, | 254 | kind: MODULE, |
250 | }; | 255 | }; |
251 | return Ok(vec![(file_id, symbol)]); | 256 | rr.add_resolution(file_id, symbol); |
257 | return Ok(Some(rr)); | ||
252 | } | 258 | } |
253 | } | 259 | } |
254 | _ => (), | 260 | _ => (), |
@@ -256,7 +262,7 @@ impl AnalysisImpl { | |||
256 | } | 262 | } |
257 | } | 263 | } |
258 | } | 264 | } |
259 | Ok(vec![]) | 265 | Ok(None) |
260 | } | 266 | } |
261 | 267 | ||
262 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { | 268 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { |
@@ -318,6 +324,19 @@ impl AnalysisImpl { | |||
318 | 324 | ||
319 | Ok(symbol.docs(&file)) | 325 | Ok(symbol.docs(&file)) |
320 | } | 326 | } |
327 | pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable<Option<String>> { | ||
328 | let file = self.db.source_file(file_id); | ||
329 | let result = match (symbol.description(&file), symbol.docs(&file)) { | ||
330 | (Some(desc), Some(docs)) => { | ||
331 | Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs) | ||
332 | } | ||
333 | (Some(desc), None) => Some("```rust\n".to_string() + &*desc + "\n```"), | ||
334 | (None, Some(docs)) => Some(docs), | ||
335 | _ => None, | ||
336 | }; | ||
337 | |||
338 | Ok(result) | ||
339 | } | ||
321 | 340 | ||
322 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { | 341 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { |
323 | let syntax = self.db.source_file(file_id); | 342 | let syntax = self.db.source_file(file_id); |