use ra_db::FileId;
use ra_syntax::{
- SyntaxNode, AstNode, SmolStr, TextRange, ast,
+ SyntaxNode, SyntaxNodePtr, AstNode, SmolStr, TextRange, ast,
SyntaxKind::{self, NAME},
};
-use hir::{ModuleSource, FieldSource};
+use hir::{ModuleSource, FieldSource, Name, ImplItem};
use crate::{FileSymbol, db::RootDatabase};
kind: SyntaxKind,
full_range: TextRange,
focus_range: Option<TextRange>,
+ container_name: Option<SmolStr>,
}
impl NavigationTarget {
+ /// When `focus_range` is specified, returns it. otherwise
+ /// returns `full_range`
+ pub fn range(&self) -> TextRange {
+ self.focus_range.unwrap_or(self.full_range)
+ }
+
pub fn name(&self) -> &SmolStr {
&self.name
}
+ pub fn container_name(&self) -> Option<&SmolStr> {
+ self.container_name.as_ref()
+ }
+
pub fn kind(&self) -> SyntaxKind {
self.kind
}
self.full_range
}
- /// A "most interesting" range withing the `range_full`.
+ /// A "most interesting" range withing the `full_range`.
///
- /// Typically, `range` is the whole syntax node, including doc comments, and
- /// `focus_range` is the range of the identifier.
+ /// Typically, `full_range` is the whole syntax node,
+ /// including doc comments, and `focus_range` is the range of the identifier.
pub fn focus_range(&self) -> Option<TextRange> {
self.focus_range
}
+ pub(crate) fn from_bind_pat(file_id: FileId, pat: &ast::BindPat) -> NavigationTarget {
+ NavigationTarget::from_named(file_id, pat)
+ }
+
pub(crate) fn from_symbol(symbol: FileSymbol) -> NavigationTarget {
NavigationTarget {
file_id: symbol.file_id,
name: symbol.name.clone(),
kind: symbol.ptr.kind(),
full_range: symbol.ptr.range(),
- focus_range: None,
+ focus_range: symbol.name_range,
+ container_name: symbol.container_name.clone(),
}
}
pub(crate) fn from_scope_entry(
file_id: FileId,
- entry: &hir::ScopeEntryWithSyntax,
+ name: Name,
+ ptr: SyntaxNodePtr,
) -> NavigationTarget {
NavigationTarget {
file_id,
- name: entry.name().to_string().into(),
- full_range: entry.ptr().range(),
+ name: name.to_string().into(),
+ full_range: ptr.range(),
focus_range: None,
kind: NAME,
+ container_name: None,
}
}
pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
let (file_id, source) = module.definition_source(db);
- let name = module
- .name(db)
- .map(|it| it.to_string().into())
- .unwrap_or_default();
+ let file_id = file_id.as_original_file();
+ let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
match source {
ModuleSource::SourceFile(node) => {
NavigationTarget::from_syntax(file_id, name, None, node.syntax())
}
pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
- let name = module
- .name(db)
- .map(|it| it.to_string().into())
- .unwrap_or_default();
+ let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
if let Some((file_id, source)) = module.declaration_source(db) {
+ let file_id = file_id.as_original_file();
return NavigationTarget::from_syntax(file_id, name, None, source.syntax());
}
NavigationTarget::from_module(db, module)
let (file_id, node) = e.source(db);
NavigationTarget::from_named(file_id.original_file(db), &*node)
}
- hir::ModuleDef::Type(e) => {
+ hir::ModuleDef::TypeAlias(e) => {
let (file_id, node) = e.source(db);
NavigationTarget::from_named(file_id.original_file(db), &*node)
}
}
}
+ pub(crate) fn from_impl_block(
+ db: &RootDatabase,
+ impl_block: hir::ImplBlock,
+ ) -> NavigationTarget {
+ let (file_id, node) = impl_block.source(db);
+ NavigationTarget::from_syntax(
+ file_id.as_original_file(),
+ "impl".into(),
+ None,
+ node.syntax(),
+ )
+ }
+
+ pub(crate) fn from_impl_item(db: &RootDatabase, impl_item: hir::ImplItem) -> NavigationTarget {
+ match impl_item {
+ ImplItem::Method(f) => NavigationTarget::from_function(db, f),
+ ImplItem::Const(c) => {
+ let (file_id, node) = c.source(db);
+ NavigationTarget::from_named(file_id.original_file(db), &*node)
+ }
+ ImplItem::TypeAlias(a) => {
+ let (file_id, node) = a.source(db);
+ NavigationTarget::from_named(file_id.original_file(db), &*node)
+ }
+ }
+ }
+
#[cfg(test)]
pub(crate) fn assert_match(&self, expected: &str) {
let actual = self.debug_render();
if let Some(focus_range) = self.focus_range() {
buf.push_str(&format!(" {:?}", focus_range))
}
+ if let Some(container_name) = self.container_name() {
+ buf.push_str(&format!(" {}", container_name))
+ }
buf
}
- fn from_named(file_id: FileId, node: &impl ast::NameOwner) -> NavigationTarget {
+ /// Allows `NavigationTarget` to be created from a `NameOwner`
+ pub(crate) 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());
NavigationTarget::from_syntax(file_id, name, focus_range, node.syntax())
full_range: node.range(),
focus_range,
// ptr: Some(LocalSyntaxPtr::new(node)),
+ container_name: None,
}
}
}