aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src')
-rw-r--r--crates/ra_analysis/src/completion.rs (renamed from crates/ra_analysis/src/completion/mod.rs)0
-rw-r--r--crates/ra_analysis/src/imp.rs39
-rw-r--r--crates/ra_analysis/src/lib.rs29
3 files changed, 57 insertions, 11 deletions
diff --git a/crates/ra_analysis/src/completion/mod.rs b/crates/ra_analysis/src/completion.rs
index 0f154112a..0f154112a 100644
--- a/crates/ra_analysis/src/completion/mod.rs
+++ b/crates/ra_analysis/src/completion.rs
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);
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index 4b8b10816..eaf24cb36 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -178,6 +178,30 @@ impl Query {
178 } 178 }
179} 179}
180 180
181/// Result of "goto def" query.
182#[derive(Debug)]
183pub struct ReferenceResolution {
184 /// The range of the reference itself. Client does not know what constitutes
185 /// a reference, it handles us only the offset. It's helpful to tell the
186 /// client where the reference was.
187 pub reference_range: TextRange,
188 /// What this reference resolves to.
189 pub resolves_to: Vec<(FileId, FileSymbol)>,
190}
191
192impl ReferenceResolution {
193 fn new(reference_range: TextRange) -> ReferenceResolution {
194 ReferenceResolution {
195 reference_range,
196 resolves_to: Vec::new(),
197 }
198 }
199
200 fn add_resolution(&mut self, file_id: FileId, symbol: FileSymbol) {
201 self.resolves_to.push((file_id, symbol))
202 }
203}
204
181/// Analysis is a snapshot of a world state at a moment in time. It is the main 205/// Analysis is a snapshot of a world state at a moment in time. It is the main
182/// entry point for asking semantic information about the world. When the world 206/// entry point for asking semantic information about the world. When the world
183/// state is advanced using `AnalysisHost::apply_change` method, all existing 207/// state is advanced using `AnalysisHost::apply_change` method, all existing
@@ -236,7 +260,7 @@ impl Analysis {
236 pub fn approximately_resolve_symbol( 260 pub fn approximately_resolve_symbol(
237 &self, 261 &self,
238 position: FilePosition, 262 position: FilePosition,
239 ) -> Cancelable<Vec<(FileId, FileSymbol)>> { 263 ) -> Cancelable<Option<ReferenceResolution>> {
240 self.imp.approximately_resolve_symbol(position) 264 self.imp.approximately_resolve_symbol(position)
241 } 265 }
242 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { 266 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
@@ -249,6 +273,9 @@ impl Analysis {
249 ) -> Cancelable<Option<String>> { 273 ) -> Cancelable<Option<String>> {
250 self.imp.doc_comment_for(file_id, symbol) 274 self.imp.doc_comment_for(file_id, symbol)
251 } 275 }
276 pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable<Option<String>> {
277 self.imp.doc_text_for(file_id, symbol)
278 }
252 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { 279 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> {
253 self.imp.parent_module(position) 280 self.imp.parent_module(position)
254 } 281 }