diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 124 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 25 | ||||
-rw-r--r-- | crates/ra_analysis/src/symbol_index.rs | 91 |
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::{ | |||
8 | use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase}; | 8 | use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase}; |
9 | use ra_editor::{self, find_node_at_offset, LocalEdit, Severity}; | 9 | use ra_editor::{self, find_node_at_offset, LocalEdit, Severity}; |
10 | use ra_syntax::{ | 10 | use 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 | ||
18 | use crate::{ | 18 | use 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 | |||
513 | impl 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)] |
223 | pub struct NavigationTarget { | 223 | pub 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 | ||
228 | impl NavigationTarget { | 230 | impl 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 | ||
6 | use fst::{self, Streamer}; | 6 | use fst::{self, Streamer}; |
7 | use ra_syntax::{ | 7 | use 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 | }; |
13 | use ra_db::{SyntaxDatabase, SourceRootId, FilesDatabase}; | 13 | use ra_db::{SyntaxDatabase, SourceRootId, FilesDatabase}; |
14 | use salsa::ParallelDatabase; | 14 | use 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 | |||
170 | impl 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 | ||
255 | fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> { | 171 | fn 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() |