aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/display/navigation_target.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/display/navigation_target.rs')
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs134
1 files changed, 66 insertions, 68 deletions
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs
index 5da28edd2..8bf2428ed 100644
--- a/crates/ra_ide/src/display/navigation_target.rs
+++ b/crates/ra_ide/src/display/navigation_target.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
11 TextRange, 11 TextRange,
12}; 12};
13 13
14use crate::{FileRange, FileSymbol}; 14use crate::FileSymbol;
15 15
16use super::short_label::ShortLabel; 16use super::short_label::ShortLabel;
17 17
@@ -47,6 +47,19 @@ impl NavigationTarget {
47 pub fn range(&self) -> TextRange { 47 pub fn range(&self) -> TextRange {
48 self.focus_range.unwrap_or(self.full_range) 48 self.focus_range.unwrap_or(self.full_range)
49 } 49 }
50 /// A "most interesting" range withing the `full_range`.
51 ///
52 /// Typically, `full_range` is the whole syntax node,
53 /// including doc comments, and `focus_range` is the range of the identifier.
54 pub fn focus_range(&self) -> Option<TextRange> {
55 self.focus_range
56 }
57 pub fn full_range(&self) -> TextRange {
58 self.full_range
59 }
60 pub fn file_id(&self) -> FileId {
61 self.file_id
62 }
50 63
51 pub fn name(&self) -> &SmolStr { 64 pub fn name(&self) -> &SmolStr {
52 &self.name 65 &self.name
@@ -60,18 +73,6 @@ impl NavigationTarget {
60 self.kind 73 self.kind
61 } 74 }
62 75
63 pub fn file_id(&self) -> FileId {
64 self.file_id
65 }
66
67 pub fn file_range(&self) -> FileRange {
68 FileRange { file_id: self.file_id, range: self.full_range }
69 }
70
71 pub fn full_range(&self) -> TextRange {
72 self.full_range
73 }
74
75 pub fn docs(&self) -> Option<&str> { 76 pub fn docs(&self) -> Option<&str> {
76 self.docs.as_deref() 77 self.docs.as_deref()
77 } 78 }
@@ -80,27 +81,20 @@ impl NavigationTarget {
80 self.description.as_deref() 81 self.description.as_deref()
81 } 82 }
82 83
83 /// A "most interesting" range withing the `full_range`.
84 ///
85 /// Typically, `full_range` is the whole syntax node,
86 /// including doc comments, and `focus_range` is the range of the identifier.
87 pub fn focus_range(&self) -> Option<TextRange> {
88 self.focus_range
89 }
90
91 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { 84 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
92 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); 85 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
93 if let Some(src) = module.declaration_source(db) { 86 if let Some(src) = module.declaration_source(db) {
94 let frange = original_range(db, src.as_ref().map(|it| it.syntax())); 87 let frange = original_range(db, src.as_ref().map(|it| it.syntax()));
95 return NavigationTarget::from_syntax( 88 let mut res = NavigationTarget::from_syntax(
96 frange.file_id, 89 frange.file_id,
97 name, 90 name,
98 None, 91 None,
99 frange.range, 92 frange.range,
100 src.value.syntax().kind(), 93 src.value.syntax().kind(),
101 src.value.doc_comment_text(),
102 src.value.short_label(),
103 ); 94 );
95 res.docs = src.value.doc_comment_text();
96 res.description = src.value.short_label();
97 return res;
104 } 98 }
105 module.to_nav(db) 99 module.to_nav(db)
106 } 100 }
@@ -130,14 +124,12 @@ impl NavigationTarget {
130 } 124 }
131 125
132 /// Allows `NavigationTarget` to be created from a `NameOwner` 126 /// Allows `NavigationTarget` to be created from a `NameOwner`
133 fn from_named( 127 pub(crate) fn from_named(
134 db: &RootDatabase, 128 db: &RootDatabase,
135 node: InFile<&dyn ast::NameOwner>, 129 node: InFile<&dyn ast::NameOwner>,
136 docs: Option<String>,
137 description: Option<String>,
138 ) -> NavigationTarget { 130 ) -> NavigationTarget {
139 //FIXME: use `_` instead of empty string 131 let name =
140 let name = node.value.name().map(|it| it.text().clone()).unwrap_or_default(); 132 node.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_"));
141 let focus_range = 133 let focus_range =
142 node.value.name().map(|it| original_range(db, node.with_value(it.syntax())).range); 134 node.value.name().map(|it| original_range(db, node.with_value(it.syntax())).range);
143 let frange = original_range(db, node.map(|it| it.syntax())); 135 let frange = original_range(db, node.map(|it| it.syntax()));
@@ -148,8 +140,25 @@ impl NavigationTarget {
148 focus_range, 140 focus_range,
149 frange.range, 141 frange.range,
150 node.value.syntax().kind(), 142 node.value.syntax().kind(),
151 docs, 143 )
152 description, 144 }
145
146 /// Allows `NavigationTarget` to be created from a `DocCommentsOwner` and a `NameOwner`
147 pub(crate) fn from_doc_commented(
148 db: &RootDatabase,
149 named: InFile<&dyn ast::NameOwner>,
150 node: InFile<&dyn ast::DocCommentsOwner>,
151 ) -> NavigationTarget {
152 let name =
153 named.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_"));
154 let frange = original_range(db, node.map(|it| it.syntax()));
155
156 NavigationTarget::from_syntax(
157 frange.file_id,
158 name,
159 None,
160 frange.range,
161 node.value.syntax().kind(),
153 ) 162 )
154 } 163 }
155 164
@@ -159,8 +168,6 @@ impl NavigationTarget {
159 focus_range: Option<TextRange>, 168 focus_range: Option<TextRange>,
160 full_range: TextRange, 169 full_range: TextRange,
161 kind: SyntaxKind, 170 kind: SyntaxKind,
162 docs: Option<String>,
163 description: Option<String>,
164 ) -> NavigationTarget { 171 ) -> NavigationTarget {
165 NavigationTarget { 172 NavigationTarget {
166 file_id, 173 file_id,
@@ -169,8 +176,8 @@ impl NavigationTarget {
169 full_range, 176 full_range,
170 focus_range, 177 focus_range,
171 container_name: None, 178 container_name: None,
172 description, 179 description: None,
173 docs, 180 docs: None,
174 } 181 }
175 } 182 }
176} 183}
@@ -238,12 +245,11 @@ where
238{ 245{
239 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 246 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
240 let src = self.source(db); 247 let src = self.source(db);
241 NavigationTarget::from_named( 248 let mut res =
242 db, 249 NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner));
243 src.as_ref().map(|it| it as &dyn ast::NameOwner), 250 res.docs = src.value.doc_comment_text();
244 src.value.doc_comment_text(), 251 res.description = src.value.short_label();
245 src.value.short_label(), 252 res
246 )
247 } 253 }
248} 254}
249 255
@@ -258,35 +264,31 @@ impl ToNav for hir::Module {
258 } 264 }
259 }; 265 };
260 let frange = original_range(db, src.with_value(syntax)); 266 let frange = original_range(db, src.with_value(syntax));
261 NavigationTarget::from_syntax( 267 NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, syntax.kind())
262 frange.file_id,
263 name,
264 focus,
265 frange.range,
266 syntax.kind(),
267 None,
268 None,
269 )
270 } 268 }
271} 269}
272 270
273impl ToNav for hir::ImplDef { 271impl ToNav for hir::ImplDef {
274 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 272 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
275 let src = self.source(db); 273 let src = self.source(db);
276 let frange = if let Some(item) = self.is_builtin_derive(db) { 274 let derive_attr = self.is_builtin_derive(db);
275 let frange = if let Some(item) = &derive_attr {
277 original_range(db, item.syntax()) 276 original_range(db, item.syntax())
278 } else { 277 } else {
279 original_range(db, src.as_ref().map(|it| it.syntax())) 278 original_range(db, src.as_ref().map(|it| it.syntax()))
280 }; 279 };
280 let focus_range = if derive_attr.is_some() {
281 None
282 } else {
283 src.value.target_type().map(|ty| original_range(db, src.with_value(ty.syntax())).range)
284 };
281 285
282 NavigationTarget::from_syntax( 286 NavigationTarget::from_syntax(
283 frange.file_id, 287 frange.file_id,
284 "impl".into(), 288 "impl".into(),
285 None, 289 focus_range,
286 frange.range, 290 frange.range,
287 src.value.syntax().kind(), 291 src.value.syntax().kind(),
288 None,
289 None,
290 ) 292 )
291 } 293 }
292} 294}
@@ -296,12 +298,12 @@ impl ToNav for hir::Field {
296 let src = self.source(db); 298 let src = self.source(db);
297 299
298 match &src.value { 300 match &src.value {
299 FieldSource::Named(it) => NavigationTarget::from_named( 301 FieldSource::Named(it) => {
300 db, 302 let mut res = NavigationTarget::from_named(db, src.with_value(it));
301 src.with_value(it), 303 res.docs = it.doc_comment_text();
302 it.doc_comment_text(), 304 res.description = it.short_label();
303 it.short_label(), 305 res
304 ), 306 }
305 FieldSource::Pos(it) => { 307 FieldSource::Pos(it) => {
306 let frange = original_range(db, src.with_value(it.syntax())); 308 let frange = original_range(db, src.with_value(it.syntax()));
307 NavigationTarget::from_syntax( 309 NavigationTarget::from_syntax(
@@ -310,8 +312,6 @@ impl ToNav for hir::Field {
310 None, 312 None,
311 frange.range, 313 frange.range,
312 it.syntax().kind(), 314 it.syntax().kind(),
313 None,
314 None,
315 ) 315 )
316 } 316 }
317 } 317 }
@@ -322,12 +322,10 @@ impl ToNav for hir::MacroDef {
322 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 322 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
323 let src = self.source(db); 323 let src = self.source(db);
324 log::debug!("nav target {:#?}", src.value.syntax()); 324 log::debug!("nav target {:#?}", src.value.syntax());
325 NavigationTarget::from_named( 325 let mut res =
326 db, 326 NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner));
327 src.as_ref().map(|it| it as &dyn ast::NameOwner), 327 res.docs = src.value.doc_comment_text();
328 src.value.doc_comment_text(), 328 res
329 None,
330 )
331 } 329 }
332} 330}
333 331