aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src')
-rw-r--r--crates/ide/src/call_hierarchy.rs8
-rw-r--r--crates/ide/src/diagnostics/fixes.rs9
-rw-r--r--crates/ide/src/display/navigation_target.rs130
-rw-r--r--crates/ide/src/goto_implementation.rs6
-rw-r--r--crates/ide/src/goto_type_definition.rs4
-rw-r--r--crates/ide/src/hover.rs27
-rw-r--r--crates/ide/src/lib.rs5
-rw-r--r--crates/ide/src/view_hir.rs25
8 files changed, 118 insertions, 96 deletions
diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs
index 60e0cd4ad..3c2d39f5d 100644
--- a/crates/ide/src/call_hierarchy.rs
+++ b/crates/ide/src/call_hierarchy.rs
@@ -8,7 +8,7 @@ use ide_db::RootDatabase;
8use syntax::{ast, match_ast, AstNode, TextRange}; 8use syntax::{ast, match_ast, AstNode, TextRange};
9 9
10use crate::{ 10use crate::{
11 display::ToNav, goto_definition, references, FilePosition, NavigationTarget, RangeInfo, 11 display::TryToNav, goto_definition, references, FilePosition, NavigationTarget, RangeInfo,
12}; 12};
13 13
14#[derive(Debug, Clone)] 14#[derive(Debug, Clone)]
@@ -61,7 +61,7 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio
61 match node { 61 match node {
62 ast::Fn(it) => { 62 ast::Fn(it) => {
63 let def = sema.to_def(&it)?; 63 let def = sema.to_def(&it)?;
64 Some(def.to_nav(sema.db)) 64 def.try_to_nav(sema.db)
65 }, 65 },
66 _ => None, 66 _ => None,
67 } 67 }
@@ -99,7 +99,7 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio
99 match callable.kind() { 99 match callable.kind() {
100 hir::CallableKind::Function(it) => { 100 hir::CallableKind::Function(it) => {
101 let fn_def: hir::Function = it.into(); 101 let fn_def: hir::Function = it.into();
102 let nav = fn_def.to_nav(db); 102 let nav = fn_def.try_to_nav(db)?;
103 Some(nav) 103 Some(nav)
104 } 104 }
105 _ => None, 105 _ => None,
@@ -107,7 +107,7 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio
107 } 107 }
108 FnCallNode::MethodCallExpr(expr) => { 108 FnCallNode::MethodCallExpr(expr) => {
109 let function = sema.resolve_method_call(&expr)?; 109 let function = sema.resolve_method_call(&expr)?;
110 Some(function.to_nav(db)) 110 function.try_to_nav(db)
111 } 111 }
112 } { 112 } {
113 Some((func_target, name_ref.syntax().text_range())) 113 Some((func_target, name_ref.syntax().text_range()))
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs
index d79f5c170..ec0f840e9 100644
--- a/crates/ide/src/diagnostics/fixes.rs
+++ b/crates/ide/src/diagnostics/fixes.rs
@@ -156,20 +156,23 @@ fn missing_record_expr_field_fix(
156 let record_fields = match VariantDef::from(def_id) { 156 let record_fields = match VariantDef::from(def_id) {
157 VariantDef::Struct(s) => { 157 VariantDef::Struct(s) => {
158 module = s.module(sema.db); 158 module = s.module(sema.db);
159 let source = s.source(sema.db); 159 #[allow(deprecated)]
160 let source = s.source(sema.db)?;
160 def_file_id = source.file_id; 161 def_file_id = source.file_id;
161 let fields = source.value.field_list()?; 162 let fields = source.value.field_list()?;
162 record_field_list(fields)? 163 record_field_list(fields)?
163 } 164 }
164 VariantDef::Union(u) => { 165 VariantDef::Union(u) => {
165 module = u.module(sema.db); 166 module = u.module(sema.db);
166 let source = u.source(sema.db); 167 #[allow(deprecated)]
168 let source = u.source(sema.db)?;
167 def_file_id = source.file_id; 169 def_file_id = source.file_id;
168 source.value.record_field_list()? 170 source.value.record_field_list()?
169 } 171 }
170 VariantDef::Variant(e) => { 172 VariantDef::Variant(e) => {
171 module = e.module(sema.db); 173 module = e.module(sema.db);
172 let source = e.source(sema.db); 174 #[allow(deprecated)]
175 let source = e.source(sema.db)?;
173 def_file_id = source.file_id; 176 def_file_id = source.file_id;
174 let fields = source.value.field_list()?; 177 let fields = source.value.field_list()?;
175 record_field_list(fields)? 178 record_field_list(fields)?
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index bcde2b6f1..e24c78301 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -210,41 +210,32 @@ impl ToNav for FileSymbol {
210impl TryToNav for Definition { 210impl TryToNav for Definition {
211 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { 211 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
212 match self { 212 match self {
213 Definition::Macro(it) => { 213 Definition::Macro(it) => it.try_to_nav(db),
214 // FIXME: Currently proc-macro do not have ast-node, 214 Definition::Field(it) => it.try_to_nav(db),
215 // such that it does not have source
216 // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
217 if it.is_proc_macro() {
218 return None;
219 }
220 Some(it.to_nav(db))
221 }
222 Definition::Field(it) => Some(it.to_nav(db)),
223 Definition::ModuleDef(it) => it.try_to_nav(db), 215 Definition::ModuleDef(it) => it.try_to_nav(db),
224 Definition::SelfType(it) => Some(it.to_nav(db)), 216 Definition::SelfType(it) => it.try_to_nav(db),
225 Definition::Local(it) => Some(it.to_nav(db)), 217 Definition::Local(it) => Some(it.to_nav(db)),
226 Definition::TypeParam(it) => Some(it.to_nav(db)), 218 Definition::TypeParam(it) => it.try_to_nav(db),
227 Definition::LifetimeParam(it) => Some(it.to_nav(db)), 219 Definition::LifetimeParam(it) => it.try_to_nav(db),
228 Definition::Label(it) => Some(it.to_nav(db)), 220 Definition::Label(it) => Some(it.to_nav(db)),
229 Definition::ConstParam(it) => Some(it.to_nav(db)), 221 Definition::ConstParam(it) => it.try_to_nav(db),
230 } 222 }
231 } 223 }
232} 224}
233 225
234impl TryToNav for hir::ModuleDef { 226impl TryToNav for hir::ModuleDef {
235 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { 227 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
236 let res = match self { 228 match self {
237 hir::ModuleDef::Module(it) => it.to_nav(db), 229 hir::ModuleDef::Module(it) => Some(it.to_nav(db)),
238 hir::ModuleDef::Function(it) => it.to_nav(db), 230 hir::ModuleDef::Function(it) => it.try_to_nav(db),
239 hir::ModuleDef::Adt(it) => it.to_nav(db), 231 hir::ModuleDef::Adt(it) => it.try_to_nav(db),
240 hir::ModuleDef::Variant(it) => it.to_nav(db), 232 hir::ModuleDef::Variant(it) => it.try_to_nav(db),
241 hir::ModuleDef::Const(it) => it.to_nav(db), 233 hir::ModuleDef::Const(it) => it.try_to_nav(db),
242 hir::ModuleDef::Static(it) => it.to_nav(db), 234 hir::ModuleDef::Static(it) => it.try_to_nav(db),
243 hir::ModuleDef::Trait(it) => it.to_nav(db), 235 hir::ModuleDef::Trait(it) => it.try_to_nav(db),
244 hir::ModuleDef::TypeAlias(it) => it.to_nav(db), 236 hir::ModuleDef::TypeAlias(it) => it.try_to_nav(db),
245 hir::ModuleDef::BuiltinType(_) => return None, 237 hir::ModuleDef::BuiltinType(_) => None,
246 }; 238 }
247 Some(res)
248 } 239 }
249} 240}
250 241
@@ -279,13 +270,13 @@ impl ToNavFromAst for hir::Trait {
279 const KIND: SymbolKind = SymbolKind::Trait; 270 const KIND: SymbolKind = SymbolKind::Trait;
280} 271}
281 272
282impl<D> ToNav for D 273impl<D> TryToNav for D
283where 274where
284 D: HasSource + ToNavFromAst + Copy + HasAttrs, 275 D: HasSource + ToNavFromAst + Copy + HasAttrs,
285 D::Ast: ast::NameOwner + ShortLabel, 276 D::Ast: ast::NameOwner + ShortLabel,
286{ 277{
287 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 278 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
288 let src = self.source(db); 279 let src = self.source(db)?;
289 let mut res = NavigationTarget::from_named( 280 let mut res = NavigationTarget::from_named(
290 db, 281 db,
291 src.as_ref().map(|it| it as &dyn ast::NameOwner), 282 src.as_ref().map(|it| it as &dyn ast::NameOwner),
@@ -293,7 +284,7 @@ where
293 ); 284 );
294 res.docs = self.docs(db); 285 res.docs = self.docs(db);
295 res.description = src.value.short_label(); 286 res.description = src.value.short_label();
296 res 287 Some(res)
297 } 288 }
298} 289}
299 290
@@ -312,9 +303,9 @@ impl ToNav for hir::Module {
312 } 303 }
313} 304}
314 305
315impl ToNav for hir::Impl { 306impl TryToNav for hir::Impl {
316 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 307 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
317 let src = self.source(db); 308 let src = self.source(db)?;
318 let derive_attr = self.is_builtin_derive(db); 309 let derive_attr = self.is_builtin_derive(db);
319 let frange = if let Some(item) = &derive_attr { 310 let frange = if let Some(item) = &derive_attr {
320 item.syntax().original_file_range(db) 311 item.syntax().original_file_range(db)
@@ -327,21 +318,21 @@ impl ToNav for hir::Impl {
327 src.value.self_ty().map(|ty| src.with_value(ty.syntax()).original_file_range(db).range) 318 src.value.self_ty().map(|ty| src.with_value(ty.syntax()).original_file_range(db).range)
328 }; 319 };
329 320
330 NavigationTarget::from_syntax( 321 Some(NavigationTarget::from_syntax(
331 frange.file_id, 322 frange.file_id,
332 "impl".into(), 323 "impl".into(),
333 focus_range, 324 focus_range,
334 frange.range, 325 frange.range,
335 SymbolKind::Impl, 326 SymbolKind::Impl,
336 ) 327 ))
337 } 328 }
338} 329}
339 330
340impl ToNav for hir::Field { 331impl TryToNav for hir::Field {
341 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 332 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
342 let src = self.source(db); 333 let src = self.source(db)?;
343 334
344 match &src.value { 335 let field_source = match &src.value {
345 FieldSource::Named(it) => { 336 FieldSource::Named(it) => {
346 let mut res = 337 let mut res =
347 NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field); 338 NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field);
@@ -359,13 +350,14 @@ impl ToNav for hir::Field {
359 SymbolKind::Field, 350 SymbolKind::Field,
360 ) 351 )
361 } 352 }
362 } 353 };
354 Some(field_source)
363 } 355 }
364} 356}
365 357
366impl ToNav for hir::MacroDef { 358impl TryToNav for hir::MacroDef {
367 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 359 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
368 let src = self.source(db); 360 let src = self.source(db)?;
369 log::debug!("nav target {:#?}", src.value.syntax()); 361 log::debug!("nav target {:#?}", src.value.syntax());
370 let mut res = NavigationTarget::from_named( 362 let mut res = NavigationTarget::from_named(
371 db, 363 db,
@@ -373,26 +365,26 @@ impl ToNav for hir::MacroDef {
373 SymbolKind::Macro, 365 SymbolKind::Macro,
374 ); 366 );
375 res.docs = self.docs(db); 367 res.docs = self.docs(db);
376 res 368 Some(res)
377 } 369 }
378} 370}
379 371
380impl ToNav for hir::Adt { 372impl TryToNav for hir::Adt {
381 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 373 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
382 match self { 374 match self {
383 hir::Adt::Struct(it) => it.to_nav(db), 375 hir::Adt::Struct(it) => it.try_to_nav(db),
384 hir::Adt::Union(it) => it.to_nav(db), 376 hir::Adt::Union(it) => it.try_to_nav(db),
385 hir::Adt::Enum(it) => it.to_nav(db), 377 hir::Adt::Enum(it) => it.try_to_nav(db),
386 } 378 }
387 } 379 }
388} 380}
389 381
390impl ToNav for hir::AssocItem { 382impl TryToNav for hir::AssocItem {
391 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 383 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
392 match self { 384 match self {
393 AssocItem::Function(it) => it.to_nav(db), 385 AssocItem::Function(it) => it.try_to_nav(db),
394 AssocItem::Const(it) => it.to_nav(db), 386 AssocItem::Const(it) => it.try_to_nav(db),
395 AssocItem::TypeAlias(it) => it.to_nav(db), 387 AssocItem::TypeAlias(it) => it.try_to_nav(db),
396 } 388 }
397 } 389 }
398} 390}
@@ -446,9 +438,9 @@ impl ToNav for hir::Label {
446 } 438 }
447} 439}
448 440
449impl ToNav for hir::TypeParam { 441impl TryToNav for hir::TypeParam {
450 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 442 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
451 let src = self.source(db); 443 let src = self.source(db)?;
452 let full_range = match &src.value { 444 let full_range = match &src.value {
453 Either::Left(it) => it.syntax().text_range(), 445 Either::Left(it) => it.syntax().text_range(),
454 Either::Right(it) => it.syntax().text_range(), 446 Either::Right(it) => it.syntax().text_range(),
@@ -457,7 +449,7 @@ impl ToNav for hir::TypeParam {
457 Either::Left(_) => None, 449 Either::Left(_) => None,
458 Either::Right(it) => it.name().map(|it| it.syntax().text_range()), 450 Either::Right(it) => it.name().map(|it| it.syntax().text_range()),
459 }; 451 };
460 NavigationTarget { 452 Some(NavigationTarget {
461 file_id: src.file_id.original_file(db), 453 file_id: src.file_id.original_file(db),
462 name: self.name(db).to_string().into(), 454 name: self.name(db).to_string().into(),
463 kind: Some(SymbolKind::TypeParam), 455 kind: Some(SymbolKind::TypeParam),
@@ -466,15 +458,15 @@ impl ToNav for hir::TypeParam {
466 container_name: None, 458 container_name: None,
467 description: None, 459 description: None,
468 docs: None, 460 docs: None,
469 } 461 })
470 } 462 }
471} 463}
472 464
473impl ToNav for hir::LifetimeParam { 465impl TryToNav for hir::LifetimeParam {
474 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 466 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
475 let src = self.source(db); 467 let src = self.source(db)?;
476 let full_range = src.value.syntax().text_range(); 468 let full_range = src.value.syntax().text_range();
477 NavigationTarget { 469 Some(NavigationTarget {
478 file_id: src.file_id.original_file(db), 470 file_id: src.file_id.original_file(db),
479 name: self.name(db).to_string().into(), 471 name: self.name(db).to_string().into(),
480 kind: Some(SymbolKind::LifetimeParam), 472 kind: Some(SymbolKind::LifetimeParam),
@@ -483,15 +475,15 @@ impl ToNav for hir::LifetimeParam {
483 container_name: None, 475 container_name: None,
484 description: None, 476 description: None,
485 docs: None, 477 docs: None,
486 } 478 })
487 } 479 }
488} 480}
489 481
490impl ToNav for hir::ConstParam { 482impl TryToNav for hir::ConstParam {
491 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 483 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
492 let src = self.source(db); 484 let src = self.source(db)?;
493 let full_range = src.value.syntax().text_range(); 485 let full_range = src.value.syntax().text_range();
494 NavigationTarget { 486 Some(NavigationTarget {
495 file_id: src.file_id.original_file(db), 487 file_id: src.file_id.original_file(db),
496 name: self.name(db).to_string().into(), 488 name: self.name(db).to_string().into(),
497 kind: Some(SymbolKind::ConstParam), 489 kind: Some(SymbolKind::ConstParam),
@@ -500,7 +492,7 @@ impl ToNav for hir::ConstParam {
500 container_name: None, 492 container_name: None,
501 description: None, 493 description: None,
502 docs: None, 494 docs: None,
503 } 495 })
504 } 496 }
505} 497}
506 498
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index 6eac39639..da9378a97 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -2,7 +2,7 @@ use hir::{Crate, Impl, Semantics};
2use ide_db::RootDatabase; 2use ide_db::RootDatabase;
3use syntax::{algo::find_node_at_offset, ast, AstNode}; 3use syntax::{algo::find_node_at_offset, ast, AstNode};
4 4
5use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; 5use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};
6 6
7// Feature: Go to Implementation 7// Feature: Go to Implementation
8// 8//
@@ -55,7 +55,7 @@ fn impls_for_def(
55 impls 55 impls
56 .into_iter() 56 .into_iter()
57 .filter(|impl_def| ty.is_equal_for_find_impls(&impl_def.target_ty(sema.db))) 57 .filter(|impl_def| ty.is_equal_for_find_impls(&impl_def.target_ty(sema.db)))
58 .map(|imp| imp.to_nav(sema.db)) 58 .filter_map(|imp| imp.try_to_nav(sema.db))
59 .collect(), 59 .collect(),
60 ) 60 )
61} 61}
@@ -69,7 +69,7 @@ fn impls_for_trait(
69 69
70 let impls = Impl::for_trait(sema.db, krate, tr); 70 let impls = Impl::for_trait(sema.db, krate, tr);
71 71
72 Some(impls.into_iter().map(|imp| imp.to_nav(sema.db)).collect()) 72 Some(impls.into_iter().filter_map(|imp| imp.try_to_nav(sema.db)).collect())
73} 73}
74 74
75#[cfg(test)] 75#[cfg(test)]
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs
index aba6bf5dc..7e84e06be 100644
--- a/crates/ide/src/goto_type_definition.rs
+++ b/crates/ide/src/goto_type_definition.rs
@@ -1,7 +1,7 @@
1use ide_db::RootDatabase; 1use ide_db::RootDatabase;
2use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; 2use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
3 3
4use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; 4use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};
5 5
6// Feature: Go to Type Definition 6// Feature: Go to Type Definition
7// 7//
@@ -37,7 +37,7 @@ pub(crate) fn goto_type_definition(
37 37
38 let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?; 38 let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?;
39 39
40 let nav = adt_def.to_nav(db); 40 let nav = adt_def.try_to_nav(db)?;
41 Some(RangeInfo::new(node.text_range(), vec![nav])) 41 Some(RangeInfo::new(node.text_range(), vec![nav]))
42} 42}
43 43
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 98c7bfbe5..2737c900f 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -13,7 +13,7 @@ use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset,
13use test_utils::mark; 13use test_utils::mark;
14 14
15use crate::{ 15use crate::{
16 display::{macro_label, ShortLabel, ToNav, TryToNav}, 16 display::{macro_label, ShortLabel, TryToNav},
17 doc_links::{remove_links, rewrite_links}, 17 doc_links::{remove_links, rewrite_links},
18 markdown_remove::remove_markdown, 18 markdown_remove::remove_markdown,
19 markup::Markup, 19 markup::Markup,
@@ -183,10 +183,10 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov
183 183
184 match def { 184 match def {
185 Definition::ModuleDef(it) => match it { 185 Definition::ModuleDef(it) => match it {
186 ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.to_nav(db))), 186 ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.try_to_nav(db)?)),
187 ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.to_nav(db))), 187 ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.try_to_nav(db)?)),
188 ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.to_nav(db))), 188 ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.try_to_nav(db)?)),
189 ModuleDef::Trait(it) => Some(to_action(it.to_nav(db))), 189 ModuleDef::Trait(it) => Some(to_action(it.try_to_nav(db)?)),
190 _ => None, 190 _ => None,
191 }, 191 },
192 _ => None, 192 _ => None,
@@ -206,7 +206,8 @@ fn runnable_action(
206 _ => None, 206 _ => None,
207 }, 207 },
208 ModuleDef::Function(it) => { 208 ModuleDef::Function(it) => {
209 let src = it.source(sema.db); 209 #[allow(deprecated)]
210 let src = it.source(sema.db)?;
210 if src.file_id != file_id.into() { 211 if src.file_id != file_id.into() {
211 mark::hit!(hover_macro_generated_struct_fn_doc_comment); 212 mark::hit!(hover_macro_generated_struct_fn_doc_comment);
212 mark::hit!(hover_macro_generated_struct_fn_doc_attr); 213 mark::hit!(hover_macro_generated_struct_fn_doc_attr);
@@ -326,17 +327,12 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
326 let mod_path = definition_mod_path(db, &def); 327 let mod_path = definition_mod_path(db, &def);
327 return match def { 328 return match def {
328 Definition::Macro(it) => { 329 Definition::Macro(it) => {
329 // FIXME: Currently proc-macro do not have ast-node, 330 let label = macro_label(&it.source(db)?.value);
330 // such that it does not have source
331 // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
332 if it.is_proc_macro() {
333 return None;
334 }
335 let label = macro_label(&it.source(db).value);
336 from_def_source_labeled(db, it, Some(label), mod_path) 331 from_def_source_labeled(db, it, Some(label), mod_path)
337 } 332 }
338 Definition::Field(def) => { 333 Definition::Field(def) => {
339 let src = def.source(db).value; 334 #[allow(deprecated)]
335 let src = def.source(db)?.value;
340 if let FieldSource::Named(it) = src { 336 if let FieldSource::Named(it) = src {
341 from_def_source_labeled(db, def, it.short_label(), mod_path) 337 from_def_source_labeled(db, def, it.short_label(), mod_path)
342 } else { 338 } else {
@@ -385,7 +381,8 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
385 D: HasSource<Ast = A> + HasAttrs + Copy, 381 D: HasSource<Ast = A> + HasAttrs + Copy,
386 A: ShortLabel, 382 A: ShortLabel,
387 { 383 {
388 let short_label = def.source(db).value.short_label(); 384 #[allow(deprecated)]
385 let short_label = def.source(db)?.value.short_label();
389 from_def_source_labeled(db, def, short_label, mod_path) 386 from_def_source_labeled(db, def, short_label, mod_path)
390 } 387 }
391 388
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index b3331f03f..a450794f3 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -31,6 +31,7 @@ mod folding_ranges;
31mod goto_definition; 31mod goto_definition;
32mod goto_implementation; 32mod goto_implementation;
33mod goto_type_definition; 33mod goto_type_definition;
34mod view_hir;
34mod hover; 35mod hover;
35mod inlay_hints; 36mod inlay_hints;
36mod join_lines; 37mod join_lines;
@@ -271,6 +272,10 @@ impl Analysis {
271 self.with_db(|db| syntax_tree::syntax_tree(&db, file_id, text_range)) 272 self.with_db(|db| syntax_tree::syntax_tree(&db, file_id, text_range))
272 } 273 }
273 274
275 pub fn view_hir(&self, position: FilePosition) -> Cancelable<String> {
276 self.with_db(|db| view_hir::view_hir(&db, position))
277 }
278
274 pub fn expand_macro(&self, position: FilePosition) -> Cancelable<Option<ExpandedMacro>> { 279 pub fn expand_macro(&self, position: FilePosition) -> Cancelable<Option<ExpandedMacro>> {
275 self.with_db(|db| expand_macro::expand_macro(db, position)) 280 self.with_db(|db| expand_macro::expand_macro(db, position))
276 } 281 }
diff --git a/crates/ide/src/view_hir.rs b/crates/ide/src/view_hir.rs
new file mode 100644
index 000000000..cfcfb7cfb
--- /dev/null
+++ b/crates/ide/src/view_hir.rs
@@ -0,0 +1,25 @@
1use hir::{Function, Semantics};
2use ide_db::base_db::FilePosition;
3use ide_db::RootDatabase;
4use syntax::{algo::find_node_at_offset, ast, AstNode};
5
6// Feature: View Hir
7//
8// |===
9// | Editor | Action Name
10//
11// | VS Code | **Rust Analyzer: View Hir**
12// |===
13pub(crate) fn view_hir(db: &RootDatabase, position: FilePosition) -> String {
14 body_hir(db, position).unwrap_or("Not inside a function body".to_string())
15}
16
17fn body_hir(db: &RootDatabase, position: FilePosition) -> Option<String> {
18 let sema = Semantics::new(db);
19 let source_file = sema.parse(position.file_id);
20
21 let function = find_node_at_offset::<ast::Fn>(source_file.syntax(), position.offset)?;
22
23 let function: Function = sema.to_def(&function)?;
24 Some(function.debug_hir(db))
25}