From a4b4fd7dc50575d015b404532ec9dd13e0a01835 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 2 Jan 2019 16:29:08 +0300 Subject: move symbols to ra_analysis --- crates/ra_analysis/src/imp.rs | 4 +- crates/ra_analysis/src/lib.rs | 5 +- crates/ra_analysis/src/symbol_index.rs | 123 +++++++++++++++++++++++++++++++-- 3 files changed, 124 insertions(+), 8 deletions(-) (limited to 'crates/ra_analysis') diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 5669aa94d..f3b513de1 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -10,7 +10,7 @@ use hir::{ self, FnSignatureInfo, Problem, source_binder, }; use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase}; -use ra_editor::{self, FileSymbol, find_node_at_offset, LineIndex, LocalEdit, Severity}; +use ra_editor::{self, find_node_at_offset, LineIndex, LocalEdit, Severity}; use ra_syntax::{ algo::find_covering_node, ast::{self, ArgListOwner, Expr, FnDef, NameOwner}, @@ -25,7 +25,7 @@ use crate::{ completion::{CompletionItem, completions}, CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit, Query, ReferenceResolution, RootChange, SourceChange, SourceFileEdit, - symbol_index::{LibrarySymbolsQuery, SymbolIndex, SymbolsDatabase}, + symbol_index::{LibrarySymbolsQuery, SymbolIndex, SymbolsDatabase, FileSymbol}, }; #[derive(Debug, Default)] diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index e6cfaecc3..ff28271ab 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -36,10 +36,11 @@ use crate::{ pub use crate::{ completion::{CompletionItem, CompletionItemKind, InsertText}, - runnables::{Runnable, RunnableKind} + runnables::{Runnable, RunnableKind}, + symbol_index::FileSymbol, }; pub use ra_editor::{ - FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, StructureNode, Severity + Fold, FoldKind, HighlightedRange, LineIndex, StructureNode, Severity }; pub use hir::FnSignatureInfo; diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs index e5bdf0aa1..edb2268fb 100644 --- a/crates/ra_analysis/src/symbol_index.rs +++ b/crates/ra_analysis/src/symbol_index.rs @@ -4,10 +4,11 @@ use std::{ }; use fst::{self, Streamer}; -use ra_editor::{self, FileSymbol}; use ra_syntax::{ - SourceFileNode, + AstNode, SyntaxNodeRef, SourceFileNode, SmolStr, TextRange, + algo::visit::{visitor, Visitor}, SyntaxKind::{self, *}, + ast::{self, NameOwner, DocCommentsOwner}, }; use ra_db::{SyntaxDatabase, SourceRootId}; use rayon::prelude::*; @@ -65,8 +66,9 @@ impl SymbolIndex { ) -> SymbolIndex { let mut symbols = files .flat_map(|(file_id, file)| { - ra_editor::file_symbols(&file) - .into_iter() + file.syntax() + .descendants() + .filter_map(to_symbol) .map(move |symbol| (symbol.name.as_str().to_lowercase(), (file_id, symbol))) .collect::>() }) @@ -121,3 +123,116 @@ fn is_type(kind: SyntaxKind) -> bool { _ => false, } } + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct FileSymbol { + pub name: SmolStr, + pub node_range: TextRange, + pub kind: SyntaxKind, +} + +impl FileSymbol { + pub fn docs(&self, file: &SourceFileNode) -> Option { + file.syntax() + .descendants() + .filter(|node| node.kind() == self.kind && node.range() == self.node_range) + .filter_map(|node: SyntaxNodeRef| { + fn doc_comments<'a, N: DocCommentsOwner<'a>>(node: N) -> Option { + let comments = node.doc_comment_text(); + if comments.is_empty() { + None + } else { + Some(comments) + } + } + + visitor() + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .accept(node)? + }) + .nth(0) + } + /// Get a description of this node. + /// + /// e.g. `struct Name`, `enum Name`, `fn Name` + pub fn description(&self, file: &SourceFileNode) -> Option { + // TODO: After type inference is done, add type information to improve the output + file.syntax() + .descendants() + .filter(|node| node.kind() == self.kind && node.range() == self.node_range) + .filter_map(|node: SyntaxNodeRef| { + // TODO: Refactor to be have less repetition + visitor() + .visit(|node: ast::FnDef| { + let mut string = "fn ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::StructDef| { + let mut string = "struct ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::EnumDef| { + let mut string = "enum ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::TraitDef| { + let mut string = "trait ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::Module| { + let mut string = "mod ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::TypeDef| { + let mut string = "type ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::ConstDef| { + let mut string = "const ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::StaticDef| { + let mut string = "static ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .accept(node)? + }) + .nth(0) + } +} + +fn to_symbol(node: SyntaxNodeRef) -> Option { + fn decl<'a, N: NameOwner<'a>>(node: N) -> Option { + let name = node.name()?; + Some(FileSymbol { + name: name.text(), + node_range: node.syntax().range(), + kind: node.syntax().kind(), + }) + } + visitor() + .visit(decl::) + .visit(decl::) + .visit(decl::) + .visit(decl::) + .visit(decl::) + .visit(decl::) + .visit(decl::) + .visit(decl::) + .accept(node)? +} -- cgit v1.2.3 From d25c89f7608cb15e8c5ae08a92b6a7a6d6f308b8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 2 Jan 2019 16:53:40 +0300 Subject: introduce navigation target --- crates/ra_analysis/src/imp.rs | 8 ++++---- crates/ra_analysis/src/lib.rs | 23 +++++++++++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) (limited to 'crates/ra_analysis') diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index f3b513de1..836fb89f5 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -21,7 +21,7 @@ use ra_syntax::{ use crate::{ AnalysisChange, - Cancelable, + Cancelable, NavigationTarget, completion::{CompletionItem, completions}, CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit, Query, ReferenceResolution, RootChange, SourceChange, SourceFileEdit, @@ -355,9 +355,9 @@ impl AnalysisImpl { Ok(Some((binding, descr))) } } - pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable> { - let file = self.db.source_file(file_id); - let result = match (symbol.description(&file), symbol.docs(&file)) { + pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable> { + let file = self.db.source_file(nav.file_id); + let result = match (nav.symbol.description(&file), nav.symbol.docs(&file)) { (Some(desc), Some(docs)) => { Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs) } diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index ff28271ab..4d8bdb61b 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -244,6 +244,21 @@ impl Query { } } +#[derive(Debug)] +pub struct NavigationTarget { + file_id: FileId, + symbol: FileSymbol, +} + +impl NavigationTarget { + pub fn file_id(&self) -> FileId { + self.file_id + } + pub fn range(&self) -> TextRange { + self.symbol.node_range + } +} + /// Result of "goto def" query. #[derive(Debug)] pub struct ReferenceResolution { @@ -252,7 +267,7 @@ pub struct ReferenceResolution { /// client where the reference was. pub reference_range: TextRange, /// What this reference resolves to. - pub resolves_to: Vec<(FileId, FileSymbol)>, + pub resolves_to: Vec, } impl ReferenceResolution { @@ -264,7 +279,7 @@ impl ReferenceResolution { } fn add_resolution(&mut self, file_id: FileId, symbol: FileSymbol) { - self.resolves_to.push((file_id, symbol)) + self.resolves_to.push(NavigationTarget { file_id, symbol }) } } @@ -334,8 +349,8 @@ impl Analysis { pub fn find_all_refs(&self, position: FilePosition) -> Cancelable> { self.imp.find_all_refs(position) } - pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable> { - self.imp.doc_text_for(file_id, symbol) + pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable> { + self.imp.doc_text_for(nav) } pub fn parent_module(&self, position: FilePosition) -> Cancelable> { self.imp.parent_module(position) -- cgit v1.2.3 From 830abe0c1b9fdbc20a78771d0b3df37d9eabdc3e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 2 Jan 2019 17:09:39 +0300 Subject: use navigation target in API --- crates/ra_analysis/src/imp.rs | 6 +++--- crates/ra_analysis/src/lib.rs | 20 ++++++++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) (limited to 'crates/ra_analysis') diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 836fb89f5..b513736bb 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -205,7 +205,7 @@ impl AnalysisImpl { /// This returns `Vec` because a module may be included from several places. We /// don't handle this case yet though, so the Vec has length at most one. - pub fn parent_module(&self, position: FilePosition) -> Cancelable> { + pub fn parent_module(&self, position: FilePosition) -> Cancelable> { let descr = match source_binder::module_from_position(&*self.db, position)? { None => return Ok(Vec::new()), Some(it) => it, @@ -216,12 +216,12 @@ impl AnalysisImpl { }; let decl = decl.borrowed(); let decl_name = decl.name().unwrap(); - let sym = FileSymbol { + let symbol = FileSymbol { name: decl_name.text(), node_range: decl_name.syntax().range(), kind: MODULE, }; - Ok(vec![(file_id, sym)]) + Ok(vec![NavigationTarget { file_id, symbol }]) } /// Returns `Vec` for the same reason as `parent_module` pub fn crate_for(&self, file_id: FileId) -> Cancelable> { diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 4d8bdb61b..75867ee86 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -24,7 +24,7 @@ mod macros; use std::{fmt, sync::Arc}; use rustc_hash::FxHashMap; -use ra_syntax::{SourceFileNode, TextRange, TextUnit}; +use ra_syntax::{SourceFileNode, TextRange, TextUnit, SmolStr, SyntaxKind}; use ra_text_edit::TextEdit; use rayon::prelude::*; use relative_path::RelativePathBuf; @@ -251,6 +251,12 @@ pub struct NavigationTarget { } impl NavigationTarget { + pub fn name(&self) -> SmolStr { + self.symbol.name.clone() + } + pub fn kind(&self) -> SyntaxKind { + self.symbol.kind + } pub fn file_id(&self) -> FileId { self.file_id } @@ -337,8 +343,14 @@ impl Analysis { let file = self.imp.file_syntax(file_id); ra_editor::folding_ranges(&file) } - pub fn symbol_search(&self, query: Query) -> Cancelable> { - self.imp.world_symbols(query) + pub fn symbol_search(&self, query: Query) -> Cancelable> { + let res = self + .imp + .world_symbols(query)? + .into_iter() + .map(|(file_id, symbol)| NavigationTarget { file_id, symbol }) + .collect(); + Ok(res) } pub fn approximately_resolve_symbol( &self, @@ -352,7 +364,7 @@ impl Analysis { pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable> { self.imp.doc_text_for(nav) } - pub fn parent_module(&self, position: FilePosition) -> Cancelable> { + pub fn parent_module(&self, position: FilePosition) -> Cancelable> { self.imp.parent_module(position) } pub fn module_path(&self, position: FilePosition) -> Cancelable> { -- cgit v1.2.3 From fb775a293d42787ae7c3a78fc341cbbba5863fcd Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 2 Jan 2019 17:11:04 +0300 Subject: make FileSymbol private --- crates/ra_analysis/src/lib.rs | 3 +-- crates/ra_analysis/src/symbol_index.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'crates/ra_analysis') diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 75867ee86..392437ad9 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -31,13 +31,12 @@ use relative_path::RelativePathBuf; use crate::{ imp::{AnalysisHostImpl, AnalysisImpl}, - symbol_index::SymbolIndex, + symbol_index::{SymbolIndex, FileSymbol}, }; pub use crate::{ completion::{CompletionItem, CompletionItemKind, InsertText}, runnables::{Runnable, RunnableKind}, - symbol_index::FileSymbol, }; pub use ra_editor::{ Fold, FoldKind, HighlightedRange, LineIndex, StructureNode, Severity diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs index edb2268fb..56a84a850 100644 --- a/crates/ra_analysis/src/symbol_index.rs +++ b/crates/ra_analysis/src/symbol_index.rs @@ -125,14 +125,14 @@ fn is_type(kind: SyntaxKind) -> bool { } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct FileSymbol { - pub name: SmolStr, - pub node_range: TextRange, - pub kind: SyntaxKind, +pub(crate) struct FileSymbol { + pub(crate) name: SmolStr, + pub(crate) node_range: TextRange, + pub(crate) kind: SyntaxKind, } impl FileSymbol { - pub fn docs(&self, file: &SourceFileNode) -> Option { + pub(crate) fn docs(&self, file: &SourceFileNode) -> Option { file.syntax() .descendants() .filter(|node| node.kind() == self.kind && node.range() == self.node_range) @@ -162,7 +162,7 @@ impl FileSymbol { /// Get a description of this node. /// /// e.g. `struct Name`, `enum Name`, `fn Name` - pub fn description(&self, file: &SourceFileNode) -> Option { + pub(crate) fn description(&self, file: &SourceFileNode) -> Option { // TODO: After type inference is done, add type information to improve the output file.syntax() .descendants() -- cgit v1.2.3 From 76910639e6930d1d76ec0a5d7c11219e073b73be Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 2 Jan 2019 17:25:28 +0300 Subject: fix tests --- crates/ra_analysis/tests/tests.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'crates/ra_analysis') diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index b61ead752..845fff3c6 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs @@ -25,7 +25,7 @@ fn approximate_resolve_works_in_items() { assert_eq_dbg( r#"ReferenceResolution { reference_range: [23; 26), - resolves_to: [(FileId(1), FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF })] + resolves_to: [NavigationTarget { file_id: FileId(1), symbol: FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF } }] }"#, &symbols, ); @@ -46,7 +46,7 @@ fn test_resolve_module() { assert_eq_dbg( r#"ReferenceResolution { reference_range: [4; 7), - resolves_to: [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })] + resolves_to: [NavigationTarget { file_id: FileId(2), symbol: FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE } }] }"#, &symbols, ); @@ -64,7 +64,7 @@ fn test_resolve_module() { assert_eq_dbg( r#"ReferenceResolution { reference_range: [4; 7), - resolves_to: [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })] + resolves_to: [NavigationTarget { file_id: FileId(2), symbol: FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE } }] }"#, &symbols, ); @@ -107,7 +107,7 @@ fn test_resolve_parent_module() { ); let symbols = analysis.parent_module(pos).unwrap(); assert_eq_dbg( - r#"[(FileId(1), FileSymbol { name: "foo", node_range: [4; 7), kind: MODULE })]"#, + r#"[NavigationTarget { file_id: FileId(1), symbol: FileSymbol { name: "foo", node_range: [4; 7), kind: MODULE } }]"#, &symbols, ); } @@ -126,7 +126,7 @@ fn test_resolve_parent_module_for_inline() { ); let symbols = analysis.parent_module(pos).unwrap(); assert_eq_dbg( - r#"[(FileId(1), FileSymbol { name: "bar", node_range: [18; 21), kind: MODULE })]"#, + r#"[NavigationTarget { file_id: FileId(1), symbol: FileSymbol { name: "bar", node_range: [18; 21), kind: MODULE } }]"#, &symbols, ); } -- cgit v1.2.3