]> git.lizzy.rs Git - rust.git/commitdiff
envapsulate navigation target better
authorAleksey Kladov <aleksey.kladov@gmail.com>
Fri, 11 Jan 2019 11:00:54 +0000 (14:00 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Fri, 11 Jan 2019 13:01:57 +0000 (16:01 +0300)
crates/ra_hir/src/code_model_api.rs
crates/ra_hir/src/code_model_impl/function.rs
crates/ra_hir/src/lib.rs
crates/ra_ide_api/src/goto_definition.rs
crates/ra_ide_api/src/hover.rs
crates/ra_ide_api/src/imp.rs
crates/ra_ide_api/src/lib.rs
crates/ra_ide_api/src/navigation_target.rs

index e69f546ffec318e5b3843bb5d7f1b6cbe86e6ef6..8ec6b9b2b025599c024fe22341eba033bc3289dd 100644 (file)
@@ -274,6 +274,8 @@ pub struct Function {
     pub(crate) def_id: DefId,
 }
 
+pub use crate::code_model_impl::function::ScopeEntryWithSyntax;
+
 /// The declared signature of a function.
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct FnSignature {
index 1bd4cc8022a2004db22fb0f9fc0fe351b730f186..009175bab96315dd2cc1fb76e610fd6940b9aed3 100644 (file)
@@ -15,7 +15,7 @@
     impl_block::ImplBlock,
 };
 
-pub use self::scope::{FnScopes, ScopesWithSyntaxMapping};
+pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
 
 impl Function {
     pub(crate) fn new(def_id: DefId) -> Function {
index 1aca2f06717bcc646dcc0b5d92bc32899c2954c4..fe8be570072b67f545a9aba8813834f1655b1df4 100644 (file)
@@ -59,5 +59,5 @@ macro_rules! ctry {
     Def,
     Module, ModuleSource, Problem,
     Struct, Enum, EnumVariant,
-    Function, FnSignature,
+    Function, FnSignature, ScopeEntryWithSyntax,
 };
index eaddd50835ffc4073f8080d9848445cd967594b6..4706dc7331e66afd7194bdc07faf1a3bfdb83859 100644 (file)
@@ -1,6 +1,6 @@
 use ra_db::{FileId, Cancelable, SyntaxDatabase};
 use ra_syntax::{
-    TextRange, AstNode, ast, SyntaxKind::{NAME, MODULE},
+    AstNode, ast,
     algo::find_node_at_offset,
 };
 
@@ -32,13 +32,7 @@ pub(crate) fn reference_definition(
         let scope = fn_descr.scopes(db)?;
         // First try to resolve the symbol locally
         if let Some(entry) = scope.resolve_local_name(name_ref) {
-            let nav = NavigationTarget {
-                file_id,
-                name: entry.name().to_string().into(),
-                range: entry.ptr().range(),
-                kind: NAME,
-                ptr: None,
-            };
+            let nav = NavigationTarget::from_scope_entry(file_id, &entry);
             return Ok(vec![nav]);
         };
     }
@@ -79,18 +73,7 @@ fn name_definition(
             if let Some(child_module) =
                 hir::source_binder::module_from_declaration(db, file_id, module)?
             {
-                let (file_id, _) = child_module.definition_source(db)?;
-                let name = match child_module.name(db)? {
-                    Some(name) => name.to_string().into(),
-                    None => "".into(),
-                };
-                let nav = NavigationTarget {
-                    file_id,
-                    name,
-                    range: TextRange::offset_len(0.into(), 0.into()),
-                    kind: MODULE,
-                    ptr: None,
-                };
+                let nav = NavigationTarget::from_module(db, child_module)?;
                 return Ok(Some(vec![nav]));
             }
         }
index 41309e7562ffa640b89bafcfcf90e495509271b4..9b06a0e58fcb15539d1df92f0b4a83cfe8d081f5 100644 (file)
@@ -88,11 +88,11 @@ fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Cancelable<Option<S
 
 impl NavigationTarget {
     fn node(&self, db: &RootDatabase) -> Option<TreePtr<SyntaxNode>> {
-        let source_file = db.source_file(self.file_id);
+        let source_file = db.source_file(self.file_id());
         let source_file = source_file.syntax();
         let node = source_file
             .descendants()
-            .find(|node| node.kind() == self.kind && node.range() == self.range)?
+            .find(|node| node.kind() == self.kind() && node.range() == self.range())?
             .to_owned();
         Some(node)
     }
index 7c60ab7d6f4ec1b0c65df96a08bb22440b8cd967..12bfe17613a7c969ed70d7338a9a34ed23132011 100644 (file)
@@ -11,7 +11,6 @@
     TextRange, AstNode, SourceFile,
     ast::{self, NameOwner},
     algo::find_node_at_offset,
-    SyntaxKind::*,
 };
 
 use crate::{
@@ -109,18 +108,8 @@ pub(crate) fn parent_module(
             None => return Ok(Vec::new()),
             Some(it) => it,
         };
-        let (file_id, ast_module) = match module.declaration_source(self)? {
-            None => return Ok(Vec::new()),
-            Some(it) => it,
-        };
-        let name = ast_module.name().unwrap();
-        Ok(vec![NavigationTarget {
-            file_id,
-            name: name.text().clone(),
-            range: name.syntax().range(),
-            kind: MODULE,
-            ptr: None,
-        }])
+        let nav = NavigationTarget::from_module(self, module)?;
+        Ok(vec![nav])
     }
     /// Returns `Vec` for the same reason as `parent_module`
     pub(crate) fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
index 9c5a82187387827ae3c5674d5b30032854992f2d..2873bab36a3ae8f9f573e77271ff698e4e5c73d3 100644 (file)
@@ -34,9 +34,9 @@ macro_rules! ctry {
 
 use std::{fmt, sync::Arc};
 
-use ra_syntax::{SmolStr, SourceFile, TreePtr, SyntaxKind, TextRange, TextUnit};
+use ra_syntax::{SourceFile, TreePtr, TextRange, TextUnit};
 use ra_text_edit::TextEdit;
-use ra_db::{SyntaxDatabase, FilesDatabase, LocalSyntaxPtr, BaseDatabase};
+use ra_db::{SyntaxDatabase, FilesDatabase, BaseDatabase};
 use rayon::prelude::*;
 use relative_path::RelativePathBuf;
 use rustc_hash::FxHashMap;
@@ -50,6 +50,7 @@ macro_rules! ctry {
 pub use crate::{
     completion::{CompletionItem, CompletionItemKind, InsertText},
     runnables::{Runnable, RunnableKind},
+    navigation_target::NavigationTarget,
 };
 pub use ra_ide_api_light::{
     Fold, FoldKind, HighlightedRange, Severity, StructureNode,
@@ -243,39 +244,6 @@ pub fn limit(&mut self, limit: usize) {
     }
 }
 
-/// `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,
-    // Should be DefId ideally
-    ptr: Option<LocalSyntaxPtr>,
-}
-
-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
-    }
-}
-
 #[derive(Debug)]
 pub struct RangeInfo<T> {
     pub range: TextRange,
index 09a723d683698e01710481c5419477562cf832c1..943e62eb8b475e1cb38d4b4d4e0fd2e9c285d780 100644 (file)
@@ -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<TextRange>,
+    // Should be DefId ideally
+    ptr: Option<LocalSyntaxPtr>,
+}
 
 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<TextRange> {
+        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<NavigationTarget> {
+        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<Option<NavigationTarget>> {
         let res = match def {
@@ -41,21 +112,7 @@ pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Cancelable<Option<Navigat
                 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 @@ pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Cancelable<Option<Navigat
 
     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<TextRange>,
+        node: &SyntaxNode,
+    ) -> NavigationTarget {
         NavigationTarget {
             file_id,
             name,
             kind: node.kind(),
             range: node.range(),
+            focus_range,
             ptr: Some(LocalSyntaxPtr::new(node)),
         }
     }