From 2aa125251ebd74c0e2a119b351caec27a9e1da46 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 11 Jan 2019 13:01:35 +0300 Subject: move nav to a separate file --- crates/ra_ide_api/src/navigation_target.rs | 86 ++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 crates/ra_ide_api/src/navigation_target.rs (limited to 'crates/ra_ide_api/src/navigation_target.rs') diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs new file mode 100644 index 000000000..bacb7329f --- /dev/null +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -0,0 +1,86 @@ +use ra_db::{FileId, LocalSyntaxPtr, Cancelable}; +use ra_syntax::{SyntaxNode, AstNode}; +use hir::{Name, Def, ModuleSource}; + +use crate::{ + NavigationTarget, + FileSymbol, + db::RootDatabase, +}; + +impl NavigationTarget { + pub(crate) fn from_symbol(symbol: FileSymbol) -> NavigationTarget { + NavigationTarget { + file_id: symbol.file_id, + name: symbol.name.clone(), + kind: symbol.ptr.kind(), + range: symbol.ptr.range(), + ptr: Some(symbol.ptr.clone()), + } + } + + pub(crate) fn from_syntax( + name: Option, + file_id: FileId, + node: &SyntaxNode, + ) -> NavigationTarget { + NavigationTarget { + file_id, + name: name.map(|n| n.to_string().into()).unwrap_or("".into()), + kind: node.kind(), + range: node.range(), + ptr: Some(LocalSyntaxPtr::new(node)), + } + } + // TODO once Def::Item is gone, this should be able to always return a NavigationTarget + pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Cancelable> { + Ok(match def { + Def::Struct(s) => { + let (file_id, node) = s.source(db)?; + Some(NavigationTarget::from_syntax( + s.name(db)?, + file_id.original_file(db), + node.syntax(), + )) + } + Def::Enum(e) => { + let (file_id, node) = e.source(db)?; + Some(NavigationTarget::from_syntax( + e.name(db)?, + file_id.original_file(db), + node.syntax(), + )) + } + Def::EnumVariant(ev) => { + let (file_id, node) = ev.source(db)?; + Some(NavigationTarget::from_syntax( + ev.name(db)?, + file_id.original_file(db), + node.syntax(), + )) + } + Def::Function(f) => { + let (file_id, node) = f.source(db)?; + let name = f.signature(db).name().clone(); + Some(NavigationTarget::from_syntax( + Some(name), + file_id.original_file(db), + node.syntax(), + )) + } + Def::Module(m) => { + let (file_id, source) = m.definition_source(db)?; + let name = m.name(db)?; + match source { + ModuleSource::SourceFile(node) => { + Some(NavigationTarget::from_syntax(name, file_id, node.syntax())) + } + ModuleSource::Module(node) => { + Some(NavigationTarget::from_syntax(name, file_id, node.syntax())) + } + } + } + Def::Item => None, + }) + } +} -- cgit v1.2.3 From df6bbc6e420e869c4a3a6effb21170c952727d04 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 11 Jan 2019 13:05:45 +0300 Subject: Make from_syntax private --- crates/ra_ide_api/src/navigation_target.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'crates/ra_ide_api/src/navigation_target.rs') diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index bacb7329f..eaf46fd01 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -19,19 +19,6 @@ impl NavigationTarget { } } - pub(crate) fn from_syntax( - name: Option, - file_id: FileId, - node: &SyntaxNode, - ) -> NavigationTarget { - NavigationTarget { - file_id, - name: name.map(|n| n.to_string().into()).unwrap_or("".into()), - kind: node.kind(), - range: node.range(), - ptr: Some(LocalSyntaxPtr::new(node)), - } - } // TODO once Def::Item is gone, this should be able to always return a NavigationTarget pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Cancelable> { Ok(match def { @@ -83,4 +70,14 @@ impl NavigationTarget { Def::Item => None, }) } + + fn from_syntax(name: Option, file_id: FileId, node: &SyntaxNode) -> NavigationTarget { + NavigationTarget { + file_id, + name: name.map(|n| n.to_string().into()).unwrap_or("".into()), + kind: node.kind(), + range: node.range(), + ptr: Some(LocalSyntaxPtr::new(node)), + } + } } -- cgit v1.2.3 From 7b143779653ac6dfe094f7cf0c9967e1c0a81318 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 11 Jan 2019 13:28:59 +0300 Subject: refactor nav target --- crates/ra_ide_api/src/navigation_target.rs | 49 ++++++++++++++++++------------ 1 file changed, 29 insertions(+), 20 deletions(-) (limited to 'crates/ra_ide_api/src/navigation_target.rs') diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index eaf46fd01..cff11eeab 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -1,6 +1,9 @@ use ra_db::{FileId, LocalSyntaxPtr, Cancelable}; -use ra_syntax::{SyntaxNode, AstNode}; -use hir::{Name, Def, ModuleSource}; +use ra_syntax::{ + SyntaxNode, AstNode, SmolStr, + ast +}; +use hir::{Def, ModuleSource}; use crate::{ NavigationTarget, @@ -24,46 +27,44 @@ impl NavigationTarget { Ok(match def { Def::Struct(s) => { let (file_id, node) = s.source(db)?; - Some(NavigationTarget::from_syntax( - s.name(db)?, + Some(NavigationTarget::from_named( file_id.original_file(db), - node.syntax(), + &*node, )) } Def::Enum(e) => { let (file_id, node) = e.source(db)?; - Some(NavigationTarget::from_syntax( - e.name(db)?, + Some(NavigationTarget::from_named( file_id.original_file(db), - node.syntax(), + &*node, )) } Def::EnumVariant(ev) => { let (file_id, node) = ev.source(db)?; - Some(NavigationTarget::from_syntax( - ev.name(db)?, + Some(NavigationTarget::from_named( file_id.original_file(db), - node.syntax(), + &*node, )) } Def::Function(f) => { let (file_id, node) = f.source(db)?; - let name = f.signature(db).name().clone(); - Some(NavigationTarget::from_syntax( - Some(name), + Some(NavigationTarget::from_named( file_id.original_file(db), - node.syntax(), + &*node, )) } Def::Module(m) => { let (file_id, source) = m.definition_source(db)?; - let name = m.name(db)?; + let name = m + .name(db)? + .map(|it| it.to_string().into()) + .unwrap_or_else(|| SmolStr::new("")); match source { ModuleSource::SourceFile(node) => { - Some(NavigationTarget::from_syntax(name, file_id, node.syntax())) + Some(NavigationTarget::from_syntax(file_id, name, node.syntax())) } ModuleSource::Module(node) => { - Some(NavigationTarget::from_syntax(name, file_id, node.syntax())) + Some(NavigationTarget::from_syntax(file_id, name, node.syntax())) } } } @@ -71,10 +72,18 @@ impl NavigationTarget { }) } - fn from_syntax(name: Option, file_id: FileId, node: &SyntaxNode) -> NavigationTarget { + fn from_named(file_id: FileId, node: &impl ast::NameOwner) -> NavigationTarget { + let name = node + .name() + .map(|it| it.text().clone()) + .unwrap_or_else(|| SmolStr::new("")); + NavigationTarget::from_syntax(file_id, name, node.syntax()) + } + + fn from_syntax(file_id: FileId, name: SmolStr, node: &SyntaxNode) -> NavigationTarget { NavigationTarget { file_id, - name: name.map(|n| n.to_string().into()).unwrap_or("".into()), + name, kind: node.kind(), range: node.range(), ptr: Some(LocalSyntaxPtr::new(node)), -- cgit v1.2.3 From a5dd04078e6be1e3a874a2c9017d824f5a067315 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 11 Jan 2019 13:29:53 +0300 Subject: reshuffle nones --- crates/ra_ide_api/src/navigation_target.rs | 31 ++++++++++-------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'crates/ra_ide_api/src/navigation_target.rs') diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index cff11eeab..b2a53e9aa 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -24,34 +24,22 @@ impl NavigationTarget { // TODO once Def::Item is gone, this should be able to always return a NavigationTarget pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Cancelable> { - Ok(match def { + let res = match def { Def::Struct(s) => { let (file_id, node) = s.source(db)?; - Some(NavigationTarget::from_named( - file_id.original_file(db), - &*node, - )) + NavigationTarget::from_named(file_id.original_file(db), &*node) } Def::Enum(e) => { let (file_id, node) = e.source(db)?; - Some(NavigationTarget::from_named( - file_id.original_file(db), - &*node, - )) + NavigationTarget::from_named(file_id.original_file(db), &*node) } Def::EnumVariant(ev) => { let (file_id, node) = ev.source(db)?; - Some(NavigationTarget::from_named( - file_id.original_file(db), - &*node, - )) + NavigationTarget::from_named(file_id.original_file(db), &*node) } Def::Function(f) => { let (file_id, node) = f.source(db)?; - Some(NavigationTarget::from_named( - file_id.original_file(db), - &*node, - )) + NavigationTarget::from_named(file_id.original_file(db), &*node) } Def::Module(m) => { let (file_id, source) = m.definition_source(db)?; @@ -61,15 +49,16 @@ impl NavigationTarget { .unwrap_or_else(|| SmolStr::new("")); match source { ModuleSource::SourceFile(node) => { - Some(NavigationTarget::from_syntax(file_id, name, node.syntax())) + NavigationTarget::from_syntax(file_id, name, node.syntax()) } ModuleSource::Module(node) => { - Some(NavigationTarget::from_syntax(file_id, name, node.syntax())) + NavigationTarget::from_syntax(file_id, name, node.syntax()) } } } - Def::Item => None, - }) + Def::Item => return Ok(None), + }; + Ok(Some(res)) } fn from_named(file_id: FileId, node: &impl ast::NameOwner) -> NavigationTarget { -- cgit v1.2.3 From 1d3d05d5d70943d8b1356a7e2c8d8b63a1ec470d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 11 Jan 2019 13:31:21 +0300 Subject: simplify --- crates/ra_ide_api/src/navigation_target.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'crates/ra_ide_api/src/navigation_target.rs') diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index b2a53e9aa..09a723d68 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -46,7 +46,7 @@ impl NavigationTarget { let name = m .name(db)? .map(|it| it.to_string().into()) - .unwrap_or_else(|| SmolStr::new("")); + .unwrap_or_default(); match source { ModuleSource::SourceFile(node) => { NavigationTarget::from_syntax(file_id, name, node.syntax()) @@ -62,10 +62,7 @@ impl NavigationTarget { } fn from_named(file_id: FileId, node: &impl ast::NameOwner) -> NavigationTarget { - let name = node - .name() - .map(|it| it.text().clone()) - .unwrap_or_else(|| SmolStr::new("")); + let name = node.name().map(|it| it.text().clone()).unwrap_or_default(); NavigationTarget::from_syntax(file_id, name, node.syntax()) } -- cgit v1.2.3 From f9ed8d4d23cd210f24ca303c72b436bfbe84741f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 11 Jan 2019 14:00:54 +0300 Subject: envapsulate navigation target better --- crates/ra_ide_api/src/navigation_target.rs | 112 ++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 24 deletions(-) (limited to 'crates/ra_ide_api/src/navigation_target.rs') diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 09a723d68..943e62eb8 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -1,27 +1,98 @@ use ra_db::{FileId, LocalSyntaxPtr, Cancelable}; use ra_syntax::{ - SyntaxNode, AstNode, SmolStr, - ast + SyntaxNode, AstNode, SmolStr, TextRange, ast, + SyntaxKind::{self, NAME}, }; use hir::{Def, ModuleSource}; -use crate::{ - NavigationTarget, - FileSymbol, - db::RootDatabase, -}; +use crate::{FileSymbol, db::RootDatabase}; + +/// `NavigationTarget` represents and element in the editor's UI which you can +/// click on to navigate to a particular piece of code. +/// +/// Typically, a `NavigationTarget` corresponds to some element in the source +/// code, like a function or a struct, but this is not strictly required. +#[derive(Debug, Clone)] +pub struct NavigationTarget { + file_id: FileId, + name: SmolStr, + kind: SyntaxKind, + range: TextRange, + focus_range: Option, + // Should be DefId ideally + ptr: Option, +} impl NavigationTarget { + pub fn name(&self) -> &SmolStr { + &self.name + } + + pub fn kind(&self) -> SyntaxKind { + self.kind + } + + pub fn file_id(&self) -> FileId { + self.file_id + } + + pub fn range(&self) -> TextRange { + self.range + } + + /// A "most interesting" range withing the `range`. + /// + /// Typically, `range` is the whole syntax node, including doc comments, and + /// `focus_range` is the range of the identifier. + pub fn focus_range(&self) -> Option { + self.focus_range + } + pub(crate) fn from_symbol(symbol: FileSymbol) -> NavigationTarget { NavigationTarget { file_id: symbol.file_id, name: symbol.name.clone(), kind: symbol.ptr.kind(), range: symbol.ptr.range(), + focus_range: None, ptr: Some(symbol.ptr.clone()), } } + pub(crate) fn from_scope_entry( + file_id: FileId, + entry: &hir::ScopeEntryWithSyntax, + ) -> NavigationTarget { + NavigationTarget { + file_id, + name: entry.name().to_string().into(), + range: entry.ptr().range(), + focus_range: None, + kind: NAME, + ptr: None, + } + } + + pub(crate) fn from_module( + db: &RootDatabase, + module: hir::Module, + ) -> Cancelable { + let (file_id, source) = module.definition_source(db)?; + let name = module + .name(db)? + .map(|it| it.to_string().into()) + .unwrap_or_default(); + let res = match source { + ModuleSource::SourceFile(node) => { + NavigationTarget::from_syntax(file_id, name, None, node.syntax()) + } + ModuleSource::Module(node) => { + NavigationTarget::from_syntax(file_id, name, None, node.syntax()) + } + }; + Ok(res) + } + // TODO once Def::Item is gone, this should be able to always return a NavigationTarget pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Cancelable> { let res = match def { @@ -41,21 +112,7 @@ impl NavigationTarget { let (file_id, node) = f.source(db)?; NavigationTarget::from_named(file_id.original_file(db), &*node) } - Def::Module(m) => { - let (file_id, source) = m.definition_source(db)?; - let name = m - .name(db)? - .map(|it| it.to_string().into()) - .unwrap_or_default(); - match source { - ModuleSource::SourceFile(node) => { - NavigationTarget::from_syntax(file_id, name, node.syntax()) - } - ModuleSource::Module(node) => { - NavigationTarget::from_syntax(file_id, name, node.syntax()) - } - } - } + Def::Module(m) => NavigationTarget::from_module(db, m)?, Def::Item => return Ok(None), }; Ok(Some(res)) @@ -63,15 +120,22 @@ impl NavigationTarget { fn from_named(file_id: FileId, node: &impl ast::NameOwner) -> NavigationTarget { let name = node.name().map(|it| it.text().clone()).unwrap_or_default(); - NavigationTarget::from_syntax(file_id, name, node.syntax()) + let focus_range = node.name().map(|it| it.syntax().range()); + NavigationTarget::from_syntax(file_id, name, focus_range, node.syntax()) } - fn from_syntax(file_id: FileId, name: SmolStr, node: &SyntaxNode) -> NavigationTarget { + fn from_syntax( + file_id: FileId, + name: SmolStr, + focus_range: Option, + node: &SyntaxNode, + ) -> NavigationTarget { NavigationTarget { file_id, name, kind: node.kind(), range: node.range(), + focus_range, ptr: Some(LocalSyntaxPtr::new(node)), } } -- cgit v1.2.3 From dda916bc4d51383fcf84f736bd12c7a77c445fb0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 11 Jan 2019 18:17:20 +0300 Subject: fix tests --- crates/ra_ide_api/src/navigation_target.rs | 35 ++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'crates/ra_ide_api/src/navigation_target.rs') diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 943e62eb8..8b29c3a97 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -17,7 +17,7 @@ pub struct NavigationTarget { file_id: FileId, name: SmolStr, kind: SyntaxKind, - range: TextRange, + full_range: TextRange, focus_range: Option, // Should be DefId ideally ptr: Option, @@ -36,11 +36,11 @@ impl NavigationTarget { self.file_id } - pub fn range(&self) -> TextRange { - self.range + pub fn full_range(&self) -> TextRange { + self.full_range } - /// A "most interesting" range withing the `range`. + /// A "most interesting" range withing the `range_full`. /// /// Typically, `range` is the whole syntax node, including doc comments, and /// `focus_range` is the range of the identifier. @@ -53,7 +53,7 @@ impl NavigationTarget { file_id: symbol.file_id, name: symbol.name.clone(), kind: symbol.ptr.kind(), - range: symbol.ptr.range(), + full_range: symbol.ptr.range(), focus_range: None, ptr: Some(symbol.ptr.clone()), } @@ -66,7 +66,7 @@ impl NavigationTarget { NavigationTarget { file_id, name: entry.name().to_string().into(), - range: entry.ptr().range(), + full_range: entry.ptr().range(), focus_range: None, kind: NAME, ptr: None, @@ -118,6 +118,27 @@ impl NavigationTarget { Ok(Some(res)) } + #[cfg(test)] + pub(crate) fn assert_match(&self, expected: &str) { + let actual = self.debug_render(); + test_utils::assert_eq_text!(expected.trim(), actual.trim(),); + } + + #[cfg(test)] + pub(crate) fn debug_render(&self) -> String { + let mut buf = format!( + "{} {:?} {:?} {:?}", + self.name(), + self.kind(), + self.file_id(), + self.full_range() + ); + if let Some(focus_range) = self.focus_range() { + buf.push_str(&format!(" {:?}", focus_range)) + } + buf + } + fn from_named(file_id: FileId, node: &impl ast::NameOwner) -> NavigationTarget { let name = node.name().map(|it| it.text().clone()).unwrap_or_default(); let focus_range = node.name().map(|it| it.syntax().range()); @@ -134,7 +155,7 @@ impl NavigationTarget { file_id, name, kind: node.kind(), - range: node.range(), + full_range: node.range(), focus_range, ptr: Some(LocalSyntaxPtr::new(node)), } -- cgit v1.2.3 From f23a13bfa7bae7e34070bfd14d22b70a82315022 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 11 Jan 2019 18:35:04 +0300 Subject: kill NavTarget ptr --- crates/ra_ide_api/src/navigation_target.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'crates/ra_ide_api/src/navigation_target.rs') diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 8b29c3a97..b955bbe42 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -1,4 +1,4 @@ -use ra_db::{FileId, LocalSyntaxPtr, Cancelable}; +use ra_db::{FileId, Cancelable}; use ra_syntax::{ SyntaxNode, AstNode, SmolStr, TextRange, ast, SyntaxKind::{self, NAME}, @@ -19,8 +19,6 @@ pub struct NavigationTarget { kind: SyntaxKind, full_range: TextRange, focus_range: Option, - // Should be DefId ideally - ptr: Option, } impl NavigationTarget { @@ -55,7 +53,6 @@ impl NavigationTarget { kind: symbol.ptr.kind(), full_range: symbol.ptr.range(), focus_range: None, - ptr: Some(symbol.ptr.clone()), } } @@ -69,7 +66,6 @@ impl NavigationTarget { full_range: entry.ptr().range(), focus_range: None, kind: NAME, - ptr: None, } } @@ -157,7 +153,7 @@ impl NavigationTarget { kind: node.kind(), full_range: node.range(), focus_range, - ptr: Some(LocalSyntaxPtr::new(node)), + // ptr: Some(LocalSyntaxPtr::new(node)), } } } -- cgit v1.2.3