aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-01-11 11:00:54 +0000
committerAleksey Kladov <[email protected]>2019-01-11 13:01:57 +0000
commitf9ed8d4d23cd210f24ca303c72b436bfbe84741f (patch)
tree0fc1e57980421ff42e68f5ee8dc699a38dc0fbb4 /crates/ra_ide_api
parent1d3d05d5d70943d8b1356a7e2c8d8b63a1ec470d (diff)
envapsulate navigation target better
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs23
-rw-r--r--crates/ra_ide_api/src/hover.rs4
-rw-r--r--crates/ra_ide_api/src/imp.rs15
-rw-r--r--crates/ra_ide_api/src/lib.rs38
-rw-r--r--crates/ra_ide_api/src/navigation_target.rs112
5 files changed, 98 insertions, 94 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index eaddd5083..4706dc733 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -1,6 +1,6 @@
1use ra_db::{FileId, Cancelable, SyntaxDatabase}; 1use ra_db::{FileId, Cancelable, SyntaxDatabase};
2use ra_syntax::{ 2use ra_syntax::{
3 TextRange, AstNode, ast, SyntaxKind::{NAME, MODULE}, 3 AstNode, ast,
4 algo::find_node_at_offset, 4 algo::find_node_at_offset,
5}; 5};
6 6
@@ -32,13 +32,7 @@ pub(crate) fn reference_definition(
32 let scope = fn_descr.scopes(db)?; 32 let scope = fn_descr.scopes(db)?;
33 // First try to resolve the symbol locally 33 // First try to resolve the symbol locally
34 if let Some(entry) = scope.resolve_local_name(name_ref) { 34 if let Some(entry) = scope.resolve_local_name(name_ref) {
35 let nav = NavigationTarget { 35 let nav = NavigationTarget::from_scope_entry(file_id, &entry);
36 file_id,
37 name: entry.name().to_string().into(),
38 range: entry.ptr().range(),
39 kind: NAME,
40 ptr: None,
41 };
42 return Ok(vec![nav]); 36 return Ok(vec![nav]);
43 }; 37 };
44 } 38 }
@@ -79,18 +73,7 @@ fn name_definition(
79 if let Some(child_module) = 73 if let Some(child_module) =
80 hir::source_binder::module_from_declaration(db, file_id, module)? 74 hir::source_binder::module_from_declaration(db, file_id, module)?
81 { 75 {
82 let (file_id, _) = child_module.definition_source(db)?; 76 let nav = NavigationTarget::from_module(db, child_module)?;
83 let name = match child_module.name(db)? {
84 Some(name) => name.to_string().into(),
85 None => "".into(),
86 };
87 let nav = NavigationTarget {
88 file_id,
89 name,
90 range: TextRange::offset_len(0.into(), 0.into()),
91 kind: MODULE,
92 ptr: None,
93 };
94 return Ok(Some(vec![nav])); 77 return Ok(Some(vec![nav]));
95 } 78 }
96 } 79 }
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index 41309e756..9b06a0e58 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -88,11 +88,11 @@ fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Cancelable<Option<S
88 88
89impl NavigationTarget { 89impl NavigationTarget {
90 fn node(&self, db: &RootDatabase) -> Option<TreePtr<SyntaxNode>> { 90 fn node(&self, db: &RootDatabase) -> Option<TreePtr<SyntaxNode>> {
91 let source_file = db.source_file(self.file_id); 91 let source_file = db.source_file(self.file_id());
92 let source_file = source_file.syntax(); 92 let source_file = source_file.syntax();
93 let node = source_file 93 let node = source_file
94 .descendants() 94 .descendants()
95 .find(|node| node.kind() == self.kind && node.range() == self.range)? 95 .find(|node| node.kind() == self.kind() && node.range() == self.range())?
96 .to_owned(); 96 .to_owned();
97 Some(node) 97 Some(node)
98 } 98 }
diff --git a/crates/ra_ide_api/src/imp.rs b/crates/ra_ide_api/src/imp.rs
index 7c60ab7d6..12bfe1761 100644
--- a/crates/ra_ide_api/src/imp.rs
+++ b/crates/ra_ide_api/src/imp.rs
@@ -11,7 +11,6 @@ use ra_syntax::{
11 TextRange, AstNode, SourceFile, 11 TextRange, AstNode, SourceFile,
12 ast::{self, NameOwner}, 12 ast::{self, NameOwner},
13 algo::find_node_at_offset, 13 algo::find_node_at_offset,
14 SyntaxKind::*,
15}; 14};
16 15
17use crate::{ 16use crate::{
@@ -109,18 +108,8 @@ impl db::RootDatabase {
109 None => return Ok(Vec::new()), 108 None => return Ok(Vec::new()),
110 Some(it) => it, 109 Some(it) => it,
111 }; 110 };
112 let (file_id, ast_module) = match module.declaration_source(self)? { 111 let nav = NavigationTarget::from_module(self, module)?;
113 None => return Ok(Vec::new()), 112 Ok(vec![nav])
114 Some(it) => it,
115 };
116 let name = ast_module.name().unwrap();
117 Ok(vec![NavigationTarget {
118 file_id,
119 name: name.text().clone(),
120 range: name.syntax().range(),
121 kind: MODULE,
122 ptr: None,
123 }])
124 } 113 }
125 /// Returns `Vec` for the same reason as `parent_module` 114 /// Returns `Vec` for the same reason as `parent_module`
126 pub(crate) fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { 115 pub(crate) fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 9c5a82187..2873bab36 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -34,9 +34,9 @@ mod syntax_highlighting;
34 34
35use std::{fmt, sync::Arc}; 35use std::{fmt, sync::Arc};
36 36
37use ra_syntax::{SmolStr, SourceFile, TreePtr, SyntaxKind, TextRange, TextUnit}; 37use ra_syntax::{SourceFile, TreePtr, TextRange, TextUnit};
38use ra_text_edit::TextEdit; 38use ra_text_edit::TextEdit;
39use ra_db::{SyntaxDatabase, FilesDatabase, LocalSyntaxPtr, BaseDatabase}; 39use ra_db::{SyntaxDatabase, FilesDatabase, BaseDatabase};
40use rayon::prelude::*; 40use rayon::prelude::*;
41use relative_path::RelativePathBuf; 41use relative_path::RelativePathBuf;
42use rustc_hash::FxHashMap; 42use rustc_hash::FxHashMap;
@@ -50,6 +50,7 @@ use crate::{
50pub use crate::{ 50pub use crate::{
51 completion::{CompletionItem, CompletionItemKind, InsertText}, 51 completion::{CompletionItem, CompletionItemKind, InsertText},
52 runnables::{Runnable, RunnableKind}, 52 runnables::{Runnable, RunnableKind},
53 navigation_target::NavigationTarget,
53}; 54};
54pub use ra_ide_api_light::{ 55pub use ra_ide_api_light::{
55 Fold, FoldKind, HighlightedRange, Severity, StructureNode, 56 Fold, FoldKind, HighlightedRange, Severity, StructureNode,
@@ -243,39 +244,6 @@ impl Query {
243 } 244 }
244} 245}
245 246
246/// `NavigationTarget` represents and element in the editor's UI which you can
247/// click on to navigate to a particular piece of code.
248///
249/// Typically, a `NavigationTarget` corresponds to some element in the source
250/// code, like a function or a struct, but this is not strictly required.
251#[derive(Debug, Clone)]
252pub struct NavigationTarget {
253 file_id: FileId,
254 name: SmolStr,
255 kind: SyntaxKind,
256 range: TextRange,
257 // Should be DefId ideally
258 ptr: Option<LocalSyntaxPtr>,
259}
260
261impl NavigationTarget {
262 pub fn name(&self) -> &SmolStr {
263 &self.name
264 }
265
266 pub fn kind(&self) -> SyntaxKind {
267 self.kind
268 }
269
270 pub fn file_id(&self) -> FileId {
271 self.file_id
272 }
273
274 pub fn range(&self) -> TextRange {
275 self.range
276 }
277}
278
279#[derive(Debug)] 247#[derive(Debug)]
280pub struct RangeInfo<T> { 248pub struct RangeInfo<T> {
281 pub range: TextRange, 249 pub range: TextRange,
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 @@
1use ra_db::{FileId, LocalSyntaxPtr, Cancelable}; 1use ra_db::{FileId, LocalSyntaxPtr, Cancelable};
2use ra_syntax::{ 2use ra_syntax::{
3 SyntaxNode, AstNode, SmolStr, 3 SyntaxNode, AstNode, SmolStr, TextRange, ast,
4 ast 4 SyntaxKind::{self, NAME},
5}; 5};
6use hir::{Def, ModuleSource}; 6use hir::{Def, ModuleSource};
7 7
8use crate::{ 8use crate::{FileSymbol, db::RootDatabase};
9 NavigationTarget, 9
10 FileSymbol, 10/// `NavigationTarget` represents and element in the editor's UI which you can
11 db::RootDatabase, 11/// click on to navigate to a particular piece of code.
12}; 12///
13/// Typically, a `NavigationTarget` corresponds to some element in the source
14/// code, like a function or a struct, but this is not strictly required.
15#[derive(Debug, Clone)]
16pub struct NavigationTarget {
17 file_id: FileId,
18 name: SmolStr,
19 kind: SyntaxKind,
20 range: TextRange,
21 focus_range: Option<TextRange>,
22 // Should be DefId ideally
23 ptr: Option<LocalSyntaxPtr>,
24}
13 25
14impl NavigationTarget { 26impl NavigationTarget {
27 pub fn name(&self) -> &SmolStr {
28 &self.name
29 }
30
31 pub fn kind(&self) -> SyntaxKind {
32 self.kind
33 }
34
35 pub fn file_id(&self) -> FileId {
36 self.file_id
37 }
38
39 pub fn range(&self) -> TextRange {
40 self.range
41 }
42
43 /// A "most interesting" range withing the `range`.
44 ///
45 /// Typically, `range` is the whole syntax node, including doc comments, and
46 /// `focus_range` is the range of the identifier.
47 pub fn focus_range(&self) -> Option<TextRange> {
48 self.focus_range
49 }
50
15 pub(crate) fn from_symbol(symbol: FileSymbol) -> NavigationTarget { 51 pub(crate) fn from_symbol(symbol: FileSymbol) -> NavigationTarget {
16 NavigationTarget { 52 NavigationTarget {
17 file_id: symbol.file_id, 53 file_id: symbol.file_id,
18 name: symbol.name.clone(), 54 name: symbol.name.clone(),
19 kind: symbol.ptr.kind(), 55 kind: symbol.ptr.kind(),
20 range: symbol.ptr.range(), 56 range: symbol.ptr.range(),
57 focus_range: None,
21 ptr: Some(symbol.ptr.clone()), 58 ptr: Some(symbol.ptr.clone()),
22 } 59 }
23 } 60 }
24 61
62 pub(crate) fn from_scope_entry(
63 file_id: FileId,
64 entry: &hir::ScopeEntryWithSyntax,
65 ) -> NavigationTarget {
66 NavigationTarget {
67 file_id,
68 name: entry.name().to_string().into(),
69 range: entry.ptr().range(),
70 focus_range: None,
71 kind: NAME,
72 ptr: None,
73 }
74 }
75
76 pub(crate) fn from_module(
77 db: &RootDatabase,
78 module: hir::Module,
79 ) -> Cancelable<NavigationTarget> {
80 let (file_id, source) = module.definition_source(db)?;
81 let name = module
82 .name(db)?
83 .map(|it| it.to_string().into())
84 .unwrap_or_default();
85 let res = match source {
86 ModuleSource::SourceFile(node) => {
87 NavigationTarget::from_syntax(file_id, name, None, node.syntax())
88 }
89 ModuleSource::Module(node) => {
90 NavigationTarget::from_syntax(file_id, name, None, node.syntax())
91 }
92 };
93 Ok(res)
94 }
95
25 // TODO once Def::Item is gone, this should be able to always return a NavigationTarget 96 // TODO once Def::Item is gone, this should be able to always return a NavigationTarget
26 pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Cancelable<Option<NavigationTarget>> { 97 pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Cancelable<Option<NavigationTarget>> {
27 let res = match def { 98 let res = match def {
@@ -41,21 +112,7 @@ impl NavigationTarget {
41 let (file_id, node) = f.source(db)?; 112 let (file_id, node) = f.source(db)?;
42 NavigationTarget::from_named(file_id.original_file(db), &*node) 113 NavigationTarget::from_named(file_id.original_file(db), &*node)
43 } 114 }
44 Def::Module(m) => { 115 Def::Module(m) => NavigationTarget::from_module(db, m)?,
45 let (file_id, source) = m.definition_source(db)?;
46 let name = m
47 .name(db)?
48 .map(|it| it.to_string().into())
49 .unwrap_or_default();
50 match source {
51 ModuleSource::SourceFile(node) => {
52 NavigationTarget::from_syntax(file_id, name, node.syntax())
53 }
54 ModuleSource::Module(node) => {
55 NavigationTarget::from_syntax(file_id, name, node.syntax())
56 }
57 }
58 }
59 Def::Item => return Ok(None), 116 Def::Item => return Ok(None),
60 }; 117 };
61 Ok(Some(res)) 118 Ok(Some(res))
@@ -63,15 +120,22 @@ impl NavigationTarget {
63 120
64 fn from_named(file_id: FileId, node: &impl ast::NameOwner) -> NavigationTarget { 121 fn from_named(file_id: FileId, node: &impl ast::NameOwner) -> NavigationTarget {
65 let name = node.name().map(|it| it.text().clone()).unwrap_or_default(); 122 let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
66 NavigationTarget::from_syntax(file_id, name, node.syntax()) 123 let focus_range = node.name().map(|it| it.syntax().range());
124 NavigationTarget::from_syntax(file_id, name, focus_range, node.syntax())
67 } 125 }
68 126
69 fn from_syntax(file_id: FileId, name: SmolStr, node: &SyntaxNode) -> NavigationTarget { 127 fn from_syntax(
128 file_id: FileId,
129 name: SmolStr,
130 focus_range: Option<TextRange>,
131 node: &SyntaxNode,
132 ) -> NavigationTarget {
70 NavigationTarget { 133 NavigationTarget {
71 file_id, 134 file_id,
72 name, 135 name,
73 kind: node.kind(), 136 kind: node.kind(),
74 range: node.range(), 137 range: node.range(),
138 focus_range,
75 ptr: Some(LocalSyntaxPtr::new(node)), 139 ptr: Some(LocalSyntaxPtr::new(node)),
76 } 140 }
77 } 141 }