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 ++++++++++++++++- crates/ra_editor/src/lib.rs | 4 +- crates/ra_editor/src/structure.rs | 129 +++++++++++++++++ crates/ra_editor/src/symbols.rs | 246 --------------------------------- 6 files changed, 255 insertions(+), 256 deletions(-) create mode 100644 crates/ra_editor/src/structure.rs delete mode 100644 crates/ra_editor/src/symbols.rs (limited to 'crates') 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)? +} diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs index b03f9ea54..bfc745e58 100644 --- a/crates/ra_editor/src/lib.rs +++ b/crates/ra_editor/src/lib.rs @@ -3,7 +3,7 @@ mod extend_selection; mod folding_ranges; mod line_index; mod line_index_utils; -mod symbols; +mod structure; #[cfg(test)] mod test_utils; mod typing; @@ -15,7 +15,7 @@ pub use self::{ folding_ranges::{folding_ranges, Fold, FoldKind}, line_index::{LineCol, LineIndex}, line_index_utils::translate_offset_with_edit, - symbols::{file_structure, file_symbols, FileSymbol, StructureNode}, + structure::{file_structure, StructureNode}, typing::{join_lines, on_enter, on_eq_typed}, diagnostics::diagnostics }; diff --git a/crates/ra_editor/src/structure.rs b/crates/ra_editor/src/structure.rs new file mode 100644 index 000000000..2292b1ddf --- /dev/null +++ b/crates/ra_editor/src/structure.rs @@ -0,0 +1,129 @@ +use crate::TextRange; + +use ra_syntax::{ + algo::visit::{visitor, Visitor}, + ast::{self, NameOwner}, + AstNode, SourceFileNode, SyntaxKind, SyntaxNodeRef, WalkEvent, +}; + +#[derive(Debug, Clone)] +pub struct StructureNode { + pub parent: Option, + pub label: String, + pub navigation_range: TextRange, + pub node_range: TextRange, + pub kind: SyntaxKind, +} + +pub fn file_structure(file: &SourceFileNode) -> Vec { + let mut res = Vec::new(); + let mut stack = Vec::new(); + + for event in file.syntax().preorder() { + match event { + WalkEvent::Enter(node) => { + if let Some(mut symbol) = structure_node(node) { + symbol.parent = stack.last().map(|&n| n); + stack.push(res.len()); + res.push(symbol); + } + } + WalkEvent::Leave(node) => { + if structure_node(node).is_some() { + stack.pop().unwrap(); + } + } + } + } + res +} + +fn structure_node(node: SyntaxNodeRef) -> Option { + fn decl<'a, N: NameOwner<'a>>(node: N) -> Option { + let name = node.name()?; + Some(StructureNode { + parent: None, + label: name.text().to_string(), + navigation_range: name.syntax().range(), + 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::) + .visit(decl::) + .visit(|im: ast::ImplItem| { + let target_type = im.target_type()?; + let target_trait = im.target_trait(); + let label = match target_trait { + None => format!("impl {}", target_type.syntax().text()), + Some(t) => format!( + "impl {} for {}", + t.syntax().text(), + target_type.syntax().text(), + ), + }; + + let node = StructureNode { + parent: None, + label, + navigation_range: target_type.syntax().range(), + node_range: im.syntax().range(), + kind: im.syntax().kind(), + }; + Some(node) + }) + .accept(node)? +} + +#[cfg(test)] +mod tests { + use super::*; + use test_utils::assert_eq_dbg; + + #[test] + fn test_file_structure() { + let file = SourceFileNode::parse( + r#" +struct Foo { + x: i32 +} + +mod m { + fn bar() {} +} + +enum E { X, Y(i32) } +type T = (); +static S: i32 = 92; +const C: i32 = 92; + +impl E {} + +impl fmt::Debug for E {} +"#, + ); + let structure = file_structure(&file); + assert_eq_dbg( + r#"[StructureNode { parent: None, label: "Foo", navigation_range: [8; 11), node_range: [1; 26), kind: STRUCT_DEF }, + StructureNode { parent: Some(0), label: "x", navigation_range: [18; 19), node_range: [18; 24), kind: NAMED_FIELD_DEF }, + StructureNode { parent: None, label: "m", navigation_range: [32; 33), node_range: [28; 53), kind: MODULE }, + StructureNode { parent: Some(2), label: "bar", navigation_range: [43; 46), node_range: [40; 51), kind: FN_DEF }, + StructureNode { parent: None, label: "E", navigation_range: [60; 61), node_range: [55; 75), kind: ENUM_DEF }, + StructureNode { parent: None, label: "T", navigation_range: [81; 82), node_range: [76; 88), kind: TYPE_DEF }, + StructureNode { parent: None, label: "S", navigation_range: [96; 97), node_range: [89; 108), kind: STATIC_DEF }, + StructureNode { parent: None, label: "C", navigation_range: [115; 116), node_range: [109; 127), kind: CONST_DEF }, + StructureNode { parent: None, label: "impl E", navigation_range: [134; 135), node_range: [129; 138), kind: IMPL_ITEM }, + StructureNode { parent: None, label: "impl fmt::Debug for E", navigation_range: [160; 161), node_range: [140; 164), kind: IMPL_ITEM }]"#, + &structure, + ) + } +} diff --git a/crates/ra_editor/src/symbols.rs b/crates/ra_editor/src/symbols.rs deleted file mode 100644 index 9e25decfb..000000000 --- a/crates/ra_editor/src/symbols.rs +++ /dev/null @@ -1,246 +0,0 @@ -use crate::TextRange; - -use ra_syntax::{ - algo::visit::{visitor, Visitor}, - ast::{self, DocCommentsOwner, NameOwner}, - AstNode, SourceFileNode, SmolStr, SyntaxKind, SyntaxNodeRef, WalkEvent, -}; - -#[derive(Debug, Clone)] -pub struct StructureNode { - pub parent: Option, - pub label: String, - pub navigation_range: TextRange, - pub node_range: TextRange, - pub kind: SyntaxKind, -} - -#[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) - } -} - -pub fn file_symbols(file: &SourceFileNode) -> Vec { - file.syntax().descendants().filter_map(to_symbol).collect() -} - -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)? -} - -pub fn file_structure(file: &SourceFileNode) -> Vec { - let mut res = Vec::new(); - let mut stack = Vec::new(); - - for event in file.syntax().preorder() { - match event { - WalkEvent::Enter(node) => { - if let Some(mut symbol) = structure_node(node) { - symbol.parent = stack.last().map(|&n| n); - stack.push(res.len()); - res.push(symbol); - } - } - WalkEvent::Leave(node) => { - if structure_node(node).is_some() { - stack.pop().unwrap(); - } - } - } - } - res -} - -fn structure_node(node: SyntaxNodeRef) -> Option { - fn decl<'a, N: NameOwner<'a>>(node: N) -> Option { - let name = node.name()?; - Some(StructureNode { - parent: None, - label: name.text().to_string(), - navigation_range: name.syntax().range(), - 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::) - .visit(decl::) - .visit(|im: ast::ImplItem| { - let target_type = im.target_type()?; - let target_trait = im.target_trait(); - let label = match target_trait { - None => format!("impl {}", target_type.syntax().text()), - Some(t) => format!( - "impl {} for {}", - t.syntax().text(), - target_type.syntax().text(), - ), - }; - - let node = StructureNode { - parent: None, - label, - navigation_range: target_type.syntax().range(), - node_range: im.syntax().range(), - kind: im.syntax().kind(), - }; - Some(node) - }) - .accept(node)? -} - -#[cfg(test)] -mod tests { - use super::*; - use test_utils::assert_eq_dbg; - - #[test] - fn test_file_structure() { - let file = SourceFileNode::parse( - r#" -struct Foo { - x: i32 -} - -mod m { - fn bar() {} -} - -enum E { X, Y(i32) } -type T = (); -static S: i32 = 92; -const C: i32 = 92; - -impl E {} - -impl fmt::Debug for E {} -"#, - ); - let symbols = file_structure(&file); - assert_eq_dbg( - r#"[StructureNode { parent: None, label: "Foo", navigation_range: [8; 11), node_range: [1; 26), kind: STRUCT_DEF }, - StructureNode { parent: Some(0), label: "x", navigation_range: [18; 19), node_range: [18; 24), kind: NAMED_FIELD_DEF }, - StructureNode { parent: None, label: "m", navigation_range: [32; 33), node_range: [28; 53), kind: MODULE }, - StructureNode { parent: Some(2), label: "bar", navigation_range: [43; 46), node_range: [40; 51), kind: FN_DEF }, - StructureNode { parent: None, label: "E", navigation_range: [60; 61), node_range: [55; 75), kind: ENUM_DEF }, - StructureNode { parent: None, label: "T", navigation_range: [81; 82), node_range: [76; 88), kind: TYPE_DEF }, - StructureNode { parent: None, label: "S", navigation_range: [96; 97), node_range: [89; 108), kind: STATIC_DEF }, - StructureNode { parent: None, label: "C", navigation_range: [115; 116), node_range: [109; 127), kind: CONST_DEF }, - StructureNode { parent: None, label: "impl E", navigation_range: [134; 135), node_range: [129; 138), kind: IMPL_ITEM }, - StructureNode { parent: None, label: "impl fmt::Debug for E", navigation_range: [160; 161), node_range: [140; 164), kind: IMPL_ITEM }]"#, - &symbols, - ) - } -} -- 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 +++++++++++++++++++---- crates/ra_lsp_server/src/main_loop/handlers.rs | 10 +++++----- 3 files changed, 28 insertions(+), 13 deletions(-) (limited to 'crates') 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) diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 11825d74e..5ff6219f9 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -213,9 +213,9 @@ pub fn handle_goto_definition( Some(it) => it, }; let mut res = Vec::new(); - for (file_id, symbol) in rr.resolves_to { - let line_index = world.analysis().file_line_index(file_id); - let location = to_location(file_id, symbol.node_range, &world, &line_index)?; + for nav in rr.resolves_to { + let line_index = world.analysis().file_line_index(nav.file_id()); + let location = to_location(nav.file_id(), nav.range(), &world, &line_index)?; res.push(location) } Ok(Some(req::GotoDefinitionResponse::Array(res))) @@ -517,8 +517,8 @@ pub fn handle_hover( Some(it) => it, }; let mut result = Vec::new(); - for (file_id, symbol) in rr.resolves_to { - if let Some(docs) = world.analysis().doc_text_for(file_id, symbol)? { + for nav in rr.resolves_to { + if let Some(docs) = world.analysis().doc_text_for(nav)? { result.push(docs); } } -- 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 ++++++++++++---- crates/ra_lsp_server/src/conv.rs | 11 ++++++++- crates/ra_lsp_server/src/main_loop/handlers.rs | 33 ++++++++++++-------------- 4 files changed, 44 insertions(+), 26 deletions(-) (limited to 'crates') 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> { diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 618486250..1107ffc8b 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs @@ -2,7 +2,7 @@ use languageserver_types::{ self, Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, InsertTextFormat, }; -use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileEdit, FilePosition,FileRange, CompletionItem, CompletionItemKind, InsertText}; +use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileEdit, FilePosition,FileRange, CompletionItem, CompletionItemKind, InsertText, NavigationTarget}; use ra_editor::{LineCol, LineIndex, translate_offset_with_edit}; use ra_text_edit::{AtomTextEdit, TextEdit}; use ra_syntax::{SyntaxKind, TextRange, TextUnit}; @@ -322,6 +322,15 @@ impl TryConvWith for FileSystemEdit { } } +impl TryConvWith for &NavigationTarget { + type Ctx = ServerWorld; + type Output = Location; + fn try_conv_with(self, world: &ServerWorld) -> Result { + let line_index = world.analysis().file_line_index(self.file_id()); + to_location(self.file_id(), self.range(), &world, &line_index) + } +} + pub fn to_location( file_id: FileId, range: TextRange, diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 5ff6219f9..26b6c7d8a 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -188,12 +188,11 @@ pub fn handle_workspace_symbol( fn exec_query(world: &ServerWorld, query: Query) -> Result> { let mut res = Vec::new(); - for (file_id, symbol) in world.analysis().symbol_search(query)? { - let line_index = world.analysis().file_line_index(file_id); + for nav in world.analysis().symbol_search(query)? { let info = SymbolInformation { - name: symbol.name.to_string(), - kind: symbol.kind.conv(), - location: to_location(file_id, symbol.node_range, world, &line_index)?, + name: nav.name().into(), + kind: nav.kind().conv(), + location: nav.try_conv_with(world)?, container_name: None, deprecated: None, }; @@ -212,12 +211,11 @@ pub fn handle_goto_definition( None => return Ok(None), Some(it) => it, }; - let mut res = Vec::new(); - for nav in rr.resolves_to { - let line_index = world.analysis().file_line_index(nav.file_id()); - let location = to_location(nav.file_id(), nav.range(), &world, &line_index)?; - res.push(location) - } + let res = rr + .resolves_to + .into_iter() + .map(|nav| nav.try_conv_with(&world)) + .collect::>>()?; Ok(Some(req::GotoDefinitionResponse::Array(res))) } @@ -226,13 +224,12 @@ pub fn handle_parent_module( params: req::TextDocumentPositionParams, ) -> Result> { let position = params.try_conv_with(&world)?; - let mut res = Vec::new(); - for (file_id, symbol) in world.analysis().parent_module(position)? { - let line_index = world.analysis().file_line_index(file_id); - let location = to_location(file_id, symbol.node_range, &world, &line_index)?; - res.push(location); - } - Ok(res) + world + .analysis() + .parent_module(position)? + .into_iter() + .map(|nav| nav.try_conv_with(&world)) + .collect::>>() } pub fn handle_runnables( -- 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') 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') 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