aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_analysis/src/imp.rs124
-rw-r--r--crates/ra_analysis/src/lib.rs25
-rw-r--r--crates/ra_analysis/src/symbol_index.rs91
3 files changed, 127 insertions, 113 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index ff13247de..5f67c95f6 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -8,11 +8,11 @@ use hir::{
8use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase}; 8use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase};
9use ra_editor::{self, find_node_at_offset, LocalEdit, Severity}; 9use ra_editor::{self, find_node_at_offset, LocalEdit, Severity};
10use ra_syntax::{ 10use ra_syntax::{
11 algo::find_covering_node, 11 algo::{find_covering_node, visit::{visitor, Visitor}},
12 ast::{self, ArgListOwner, Expr, FnDef, NameOwner}, 12 ast::{self, ArgListOwner, Expr, FnDef, NameOwner},
13 AstNode, SourceFileNode, 13 AstNode, SourceFileNode,
14 SyntaxKind::*, 14 SyntaxKind::*,
15 SyntaxNodeRef, TextRange, TextUnit, 15 SyntaxNode, SyntaxNodeRef, TextRange, TextUnit,
16}; 16};
17 17
18use crate::{ 18use crate::{
@@ -116,12 +116,12 @@ impl db::RootDatabase {
116 }; 116 };
117 let decl = decl.borrowed(); 117 let decl = decl.borrowed();
118 let decl_name = decl.name().unwrap(); 118 let decl_name = decl.name().unwrap();
119 let symbol = FileSymbol { 119 Ok(vec![NavigationTarget {
120 file_id,
120 name: decl_name.text(), 121 name: decl_name.text(),
121 node_range: decl_name.syntax().range(), 122 range: decl_name.syntax().range(),
122 kind: MODULE, 123 kind: MODULE,
123 }; 124 }])
124 Ok(vec![NavigationTarget { file_id, symbol }])
125 } 125 }
126 /// Returns `Vec` for the same reason as `parent_module` 126 /// Returns `Vec` for the same reason as `parent_module`
127 pub(crate) fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { 127 pub(crate) fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
@@ -153,14 +153,12 @@ impl db::RootDatabase {
153 let scope = fn_descr.scopes(self); 153 let scope = fn_descr.scopes(self);
154 // First try to resolve the symbol locally 154 // First try to resolve the symbol locally
155 if let Some(entry) = scope.resolve_local_name(name_ref) { 155 if let Some(entry) = scope.resolve_local_name(name_ref) {
156 rr.add_resolution( 156 rr.resolves_to.push(NavigationTarget {
157 position.file_id, 157 file_id: position.file_id,
158 FileSymbol { 158 name: entry.name().to_string().into(),
159 name: entry.name().to_string().into(), 159 range: entry.ptr().range(),
160 node_range: entry.ptr().range(), 160 kind: NAME,
161 kind: NAME, 161 });
162 },
163 );
164 return Ok(Some(rr)); 162 return Ok(Some(rr));
165 }; 163 };
166 } 164 }
@@ -182,12 +180,13 @@ impl db::RootDatabase {
182 Some(name) => name.to_string().into(), 180 Some(name) => name.to_string().into(),
183 None => "".into(), 181 None => "".into(),
184 }; 182 };
185 let symbol = FileSymbol { 183 let symbol = NavigationTarget {
184 file_id,
186 name, 185 name,
187 node_range: TextRange::offset_len(0.into(), 0.into()), 186 range: TextRange::offset_len(0.into(), 0.into()),
188 kind: MODULE, 187 kind: MODULE,
189 }; 188 };
190 rr.add_resolution(file_id, symbol); 189 rr.resolves_to.push(symbol);
191 return Ok(Some(rr)); 190 return Ok(Some(rr));
192 } 191 }
193 } 192 }
@@ -253,8 +252,7 @@ impl db::RootDatabase {
253 } 252 }
254 } 253 }
255 pub(crate) fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> { 254 pub(crate) fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> {
256 let file = self.source_file(nav.file_id); 255 let result = match (nav.description(self), nav.docs(self)) {
257 let result = match (nav.symbol.description(&file), nav.symbol.docs(&file)) {
258 (Some(desc), Some(docs)) => { 256 (Some(desc), Some(docs)) => {
259 Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs) 257 Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs)
260 } 258 }
@@ -511,3 +509,91 @@ impl<'a> FnCallNode<'a> {
511 } 509 }
512 } 510 }
513} 511}
512
513impl NavigationTarget {
514 fn node(&self, db: &db::RootDatabase) -> Option<SyntaxNode> {
515 let source_file = db.source_file(self.file_id);
516 let source_file = source_file.syntax();
517 let node = source_file
518 .descendants()
519 .find(|node| node.kind() == self.kind && node.range() == self.range)?
520 .owned();
521 Some(node)
522 }
523
524 fn docs(&self, db: &db::RootDatabase) -> Option<String> {
525 let node = self.node(db)?;
526 let node = node.borrowed();
527 fn doc_comments<'a, N: ast::DocCommentsOwner<'a>>(node: N) -> Option<String> {
528 let comments = node.doc_comment_text();
529 if comments.is_empty() {
530 None
531 } else {
532 Some(comments)
533 }
534 }
535
536 visitor()
537 .visit(doc_comments::<ast::FnDef>)
538 .visit(doc_comments::<ast::StructDef>)
539 .visit(doc_comments::<ast::EnumDef>)
540 .visit(doc_comments::<ast::TraitDef>)
541 .visit(doc_comments::<ast::Module>)
542 .visit(doc_comments::<ast::TypeDef>)
543 .visit(doc_comments::<ast::ConstDef>)
544 .visit(doc_comments::<ast::StaticDef>)
545 .accept(node)?
546 }
547
548 /// Get a description of this node.
549 ///
550 /// e.g. `struct Name`, `enum Name`, `fn Name`
551 fn description(&self, db: &db::RootDatabase) -> Option<String> {
552 // TODO: After type inference is done, add type information to improve the output
553 let node = self.node(db)?;
554 let node = node.borrowed();
555 // TODO: Refactor to be have less repetition
556 visitor()
557 .visit(|node: ast::FnDef| {
558 let mut string = "fn ".to_string();
559 node.name()?.syntax().text().push_to(&mut string);
560 Some(string)
561 })
562 .visit(|node: ast::StructDef| {
563 let mut string = "struct ".to_string();
564 node.name()?.syntax().text().push_to(&mut string);
565 Some(string)
566 })
567 .visit(|node: ast::EnumDef| {
568 let mut string = "enum ".to_string();
569 node.name()?.syntax().text().push_to(&mut string);
570 Some(string)
571 })
572 .visit(|node: ast::TraitDef| {
573 let mut string = "trait ".to_string();
574 node.name()?.syntax().text().push_to(&mut string);
575 Some(string)
576 })
577 .visit(|node: ast::Module| {
578 let mut string = "mod ".to_string();
579 node.name()?.syntax().text().push_to(&mut string);
580 Some(string)
581 })
582 .visit(|node: ast::TypeDef| {
583 let mut string = "type ".to_string();
584 node.name()?.syntax().text().push_to(&mut string);
585 Some(string)
586 })
587 .visit(|node: ast::ConstDef| {
588 let mut string = "const ".to_string();
589 node.name()?.syntax().text().push_to(&mut string);
590 Some(string)
591 })
592 .visit(|node: ast::StaticDef| {
593 let mut string = "static ".to_string();
594 node.name()?.syntax().text().push_to(&mut string);
595 Some(string)
596 })
597 .accept(node)?
598 }
599}
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index a01febf4e..8247914c0 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -222,21 +222,31 @@ impl Query {
222#[derive(Debug)] 222#[derive(Debug)]
223pub struct NavigationTarget { 223pub struct NavigationTarget {
224 file_id: FileId, 224 file_id: FileId,
225 symbol: FileSymbol, 225 name: SmolStr,
226 kind: SyntaxKind,
227 range: TextRange,
226} 228}
227 229
228impl NavigationTarget { 230impl NavigationTarget {
229 pub fn name(&self) -> SmolStr { 231 fn from_symbol(file_id: FileId, symbol: FileSymbol) -> NavigationTarget {
230 self.symbol.name.clone() 232 NavigationTarget {
233 name: symbol.name.clone(),
234 kind: symbol.kind.clone(),
235 file_id,
236 range: symbol.node_range.clone(),
237 }
238 }
239 pub fn name(&self) -> &SmolStr {
240 &self.name
231 } 241 }
232 pub fn kind(&self) -> SyntaxKind { 242 pub fn kind(&self) -> SyntaxKind {
233 self.symbol.kind 243 self.kind
234 } 244 }
235 pub fn file_id(&self) -> FileId { 245 pub fn file_id(&self) -> FileId {
236 self.file_id 246 self.file_id
237 } 247 }
238 pub fn range(&self) -> TextRange { 248 pub fn range(&self) -> TextRange {
239 self.symbol.node_range 249 self.range
240 } 250 }
241} 251}
242 252
@@ -260,7 +270,8 @@ impl ReferenceResolution {
260 } 270 }
261 271
262 fn add_resolution(&mut self, file_id: FileId, symbol: FileSymbol) { 272 fn add_resolution(&mut self, file_id: FileId, symbol: FileSymbol) {
263 self.resolves_to.push(NavigationTarget { file_id, symbol }) 273 self.resolves_to
274 .push(NavigationTarget::from_symbol(file_id, symbol))
264 } 275 }
265} 276}
266 277
@@ -359,7 +370,7 @@ impl Analysis {
359 pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> { 370 pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> {
360 let res = symbol_index::world_symbols(&*self.db, query)? 371 let res = symbol_index::world_symbols(&*self.db, query)?
361 .into_iter() 372 .into_iter()
362 .map(|(file_id, symbol)| NavigationTarget { file_id, symbol }) 373 .map(|(file_id, symbol)| NavigationTarget::from_symbol(file_id, symbol))
363 .collect(); 374 .collect();
364 Ok(res) 375 Ok(res)
365 } 376 }
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs
index ddcf3d052..65abaec2e 100644
--- a/crates/ra_analysis/src/symbol_index.rs
+++ b/crates/ra_analysis/src/symbol_index.rs
@@ -5,10 +5,10 @@ use std::{
5 5
6use fst::{self, Streamer}; 6use fst::{self, Streamer};
7use ra_syntax::{ 7use ra_syntax::{
8 AstNode, SyntaxNodeRef, SourceFileNode, SmolStr, TextRange, 8 SyntaxNodeRef, SourceFileNode, SmolStr, TextRange,
9 algo::visit::{visitor, Visitor}, 9 algo::visit::{visitor, Visitor},
10 SyntaxKind::{self, *}, 10 SyntaxKind::{self, *},
11 ast::{self, NameOwner, DocCommentsOwner}, 11 ast::{self, NameOwner},
12}; 12};
13use ra_db::{SyntaxDatabase, SourceRootId, FilesDatabase}; 13use ra_db::{SyntaxDatabase, SourceRootId, FilesDatabase};
14use salsa::ParallelDatabase; 14use salsa::ParallelDatabase;
@@ -165,91 +165,7 @@ pub(crate) struct FileSymbol {
165 pub(crate) name: SmolStr, 165 pub(crate) name: SmolStr,
166 pub(crate) node_range: TextRange, 166 pub(crate) node_range: TextRange,
167 pub(crate) kind: SyntaxKind, 167 pub(crate) kind: SyntaxKind,
168} 168 _x: (),
169
170impl FileSymbol {
171 pub(crate) fn docs(&self, file: &SourceFileNode) -> Option<String> {
172 file.syntax()
173 .descendants()
174 .filter(|node| node.kind() == self.kind && node.range() == self.node_range)
175 .filter_map(|node: SyntaxNodeRef| {
176 fn doc_comments<'a, N: DocCommentsOwner<'a>>(node: N) -> Option<String> {
177 let comments = node.doc_comment_text();
178 if comments.is_empty() {
179 None
180 } else {
181 Some(comments)
182 }
183 }
184
185 visitor()
186 .visit(doc_comments::<ast::FnDef>)
187 .visit(doc_comments::<ast::StructDef>)
188 .visit(doc_comments::<ast::EnumDef>)
189 .visit(doc_comments::<ast::TraitDef>)
190 .visit(doc_comments::<ast::Module>)
191 .visit(doc_comments::<ast::TypeDef>)
192 .visit(doc_comments::<ast::ConstDef>)
193 .visit(doc_comments::<ast::StaticDef>)
194 .accept(node)?
195 })
196 .nth(0)
197 }
198 /// Get a description of this node.
199 ///
200 /// e.g. `struct Name`, `enum Name`, `fn Name`
201 pub(crate) fn description(&self, file: &SourceFileNode) -> Option<String> {
202 // TODO: After type inference is done, add type information to improve the output
203 file.syntax()
204 .descendants()
205 .filter(|node| node.kind() == self.kind && node.range() == self.node_range)
206 .filter_map(|node: SyntaxNodeRef| {
207 // TODO: Refactor to be have less repetition
208 visitor()
209 .visit(|node: ast::FnDef| {
210 let mut string = "fn ".to_string();
211 node.name()?.syntax().text().push_to(&mut string);
212 Some(string)
213 })
214 .visit(|node: ast::StructDef| {
215 let mut string = "struct ".to_string();
216 node.name()?.syntax().text().push_to(&mut string);
217 Some(string)
218 })
219 .visit(|node: ast::EnumDef| {
220 let mut string = "enum ".to_string();
221 node.name()?.syntax().text().push_to(&mut string);
222 Some(string)
223 })
224 .visit(|node: ast::TraitDef| {
225 let mut string = "trait ".to_string();
226 node.name()?.syntax().text().push_to(&mut string);
227 Some(string)
228 })
229 .visit(|node: ast::Module| {
230 let mut string = "mod ".to_string();
231 node.name()?.syntax().text().push_to(&mut string);
232 Some(string)
233 })
234 .visit(|node: ast::TypeDef| {
235 let mut string = "type ".to_string();
236 node.name()?.syntax().text().push_to(&mut string);
237 Some(string)
238 })
239 .visit(|node: ast::ConstDef| {
240 let mut string = "const ".to_string();
241 node.name()?.syntax().text().push_to(&mut string);
242 Some(string)
243 })
244 .visit(|node: ast::StaticDef| {
245 let mut string = "static ".to_string();
246 node.name()?.syntax().text().push_to(&mut string);
247 Some(string)
248 })
249 .accept(node)?
250 })
251 .nth(0)
252 }
253} 169}
254 170
255fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> { 171fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> {
@@ -259,6 +175,7 @@ fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> {
259 name: name.text(), 175 name: name.text(),
260 node_range: node.syntax().range(), 176 node_range: node.syntax().range(),
261 kind: node.syntax().kind(), 177 kind: node.syntax().kind(),
178 _x: (),
262 }) 179 })
263 } 180 }
264 visitor() 181 visitor()