diff options
Diffstat (limited to 'crates/ide')
-rw-r--r-- | crates/ide/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ide/src/call_hierarchy.rs | 8 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/fixes.rs | 9 | ||||
-rw-r--r-- | crates/ide/src/display/navigation_target.rs | 137 | ||||
-rw-r--r-- | crates/ide/src/doc_links.rs | 1 | ||||
-rw-r--r-- | crates/ide/src/goto_implementation.rs | 6 | ||||
-rw-r--r-- | crates/ide/src/goto_type_definition.rs | 4 | ||||
-rw-r--r-- | crates/ide/src/hover.rs | 74 | ||||
-rw-r--r-- | crates/ide/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ide/src/references.rs | 16 | ||||
-rw-r--r-- | crates/ide/src/runnables.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting.rs | 1 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/injection.rs | 13 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/tags.rs | 1 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/test_data/highlighting.html | 4 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/tests.rs | 4 | ||||
-rw-r--r-- | crates/ide/src/view_hir.rs | 25 |
17 files changed, 214 insertions, 98 deletions
diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml index f1544dbe0..bb28cca4d 100644 --- a/crates/ide/Cargo.toml +++ b/crates/ide/Cargo.toml | |||
@@ -36,4 +36,4 @@ completion = { path = "../completion", version = "0.0.0" } | |||
36 | hir = { path = "../hir", version = "0.0.0" } | 36 | hir = { path = "../hir", version = "0.0.0" } |
37 | 37 | ||
38 | [dev-dependencies] | 38 | [dev-dependencies] |
39 | expect-test = "1.0" | 39 | expect-test = "1.1" |
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; | |||
8 | use syntax::{ast, match_ast, AstNode, TextRange}; | 8 | use syntax::{ast, match_ast, AstNode, TextRange}; |
9 | 9 | ||
10 | use crate::{ | 10 | use 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 6431e7d6d..e24c78301 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs | |||
@@ -24,6 +24,7 @@ pub enum SymbolKind { | |||
24 | Impl, | 24 | Impl, |
25 | Field, | 25 | Field, |
26 | TypeParam, | 26 | TypeParam, |
27 | ConstParam, | ||
27 | LifetimeParam, | 28 | LifetimeParam, |
28 | ValueParam, | 29 | ValueParam, |
29 | SelfParam, | 30 | SelfParam, |
@@ -209,40 +210,32 @@ impl ToNav for FileSymbol { | |||
209 | impl TryToNav for Definition { | 210 | impl TryToNav for Definition { |
210 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { | 211 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
211 | match self { | 212 | match self { |
212 | Definition::Macro(it) => { | 213 | Definition::Macro(it) => it.try_to_nav(db), |
213 | // FIXME: Currently proc-macro do not have ast-node, | 214 | Definition::Field(it) => it.try_to_nav(db), |
214 | // such that it does not have source | ||
215 | // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913 | ||
216 | if it.is_proc_macro() { | ||
217 | return None; | ||
218 | } | ||
219 | Some(it.to_nav(db)) | ||
220 | } | ||
221 | Definition::Field(it) => Some(it.to_nav(db)), | ||
222 | Definition::ModuleDef(it) => it.try_to_nav(db), | 215 | Definition::ModuleDef(it) => it.try_to_nav(db), |
223 | Definition::SelfType(it) => Some(it.to_nav(db)), | 216 | Definition::SelfType(it) => it.try_to_nav(db), |
224 | Definition::Local(it) => Some(it.to_nav(db)), | 217 | Definition::Local(it) => Some(it.to_nav(db)), |
225 | Definition::TypeParam(it) => Some(it.to_nav(db)), | 218 | Definition::TypeParam(it) => it.try_to_nav(db), |
226 | Definition::LifetimeParam(it) => Some(it.to_nav(db)), | 219 | Definition::LifetimeParam(it) => it.try_to_nav(db), |
227 | Definition::Label(it) => Some(it.to_nav(db)), | 220 | Definition::Label(it) => Some(it.to_nav(db)), |
221 | Definition::ConstParam(it) => it.try_to_nav(db), | ||
228 | } | 222 | } |
229 | } | 223 | } |
230 | } | 224 | } |
231 | 225 | ||
232 | impl TryToNav for hir::ModuleDef { | 226 | impl TryToNav for hir::ModuleDef { |
233 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { | 227 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
234 | let res = match self { | 228 | match self { |
235 | hir::ModuleDef::Module(it) => it.to_nav(db), | 229 | hir::ModuleDef::Module(it) => Some(it.to_nav(db)), |
236 | hir::ModuleDef::Function(it) => it.to_nav(db), | 230 | hir::ModuleDef::Function(it) => it.try_to_nav(db), |
237 | hir::ModuleDef::Adt(it) => it.to_nav(db), | 231 | hir::ModuleDef::Adt(it) => it.try_to_nav(db), |
238 | hir::ModuleDef::Variant(it) => it.to_nav(db), | 232 | hir::ModuleDef::Variant(it) => it.try_to_nav(db), |
239 | hir::ModuleDef::Const(it) => it.to_nav(db), | 233 | hir::ModuleDef::Const(it) => it.try_to_nav(db), |
240 | hir::ModuleDef::Static(it) => it.to_nav(db), | 234 | hir::ModuleDef::Static(it) => it.try_to_nav(db), |
241 | hir::ModuleDef::Trait(it) => it.to_nav(db), | 235 | hir::ModuleDef::Trait(it) => it.try_to_nav(db), |
242 | hir::ModuleDef::TypeAlias(it) => it.to_nav(db), | 236 | hir::ModuleDef::TypeAlias(it) => it.try_to_nav(db), |
243 | hir::ModuleDef::BuiltinType(_) => return None, | 237 | hir::ModuleDef::BuiltinType(_) => None, |
244 | }; | 238 | } |
245 | Some(res) | ||
246 | } | 239 | } |
247 | } | 240 | } |
248 | 241 | ||
@@ -277,13 +270,13 @@ impl ToNavFromAst for hir::Trait { | |||
277 | const KIND: SymbolKind = SymbolKind::Trait; | 270 | const KIND: SymbolKind = SymbolKind::Trait; |
278 | } | 271 | } |
279 | 272 | ||
280 | impl<D> ToNav for D | 273 | impl<D> TryToNav for D |
281 | where | 274 | where |
282 | D: HasSource + ToNavFromAst + Copy + HasAttrs, | 275 | D: HasSource + ToNavFromAst + Copy + HasAttrs, |
283 | D::Ast: ast::NameOwner + ShortLabel, | 276 | D::Ast: ast::NameOwner + ShortLabel, |
284 | { | 277 | { |
285 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 278 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
286 | let src = self.source(db); | 279 | let src = self.source(db)?; |
287 | let mut res = NavigationTarget::from_named( | 280 | let mut res = NavigationTarget::from_named( |
288 | db, | 281 | db, |
289 | src.as_ref().map(|it| it as &dyn ast::NameOwner), | 282 | src.as_ref().map(|it| it as &dyn ast::NameOwner), |
@@ -291,7 +284,7 @@ where | |||
291 | ); | 284 | ); |
292 | res.docs = self.docs(db); | 285 | res.docs = self.docs(db); |
293 | res.description = src.value.short_label(); | 286 | res.description = src.value.short_label(); |
294 | res | 287 | Some(res) |
295 | } | 288 | } |
296 | } | 289 | } |
297 | 290 | ||
@@ -310,9 +303,9 @@ impl ToNav for hir::Module { | |||
310 | } | 303 | } |
311 | } | 304 | } |
312 | 305 | ||
313 | impl ToNav for hir::Impl { | 306 | impl TryToNav for hir::Impl { |
314 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 307 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
315 | let src = self.source(db); | 308 | let src = self.source(db)?; |
316 | let derive_attr = self.is_builtin_derive(db); | 309 | let derive_attr = self.is_builtin_derive(db); |
317 | let frange = if let Some(item) = &derive_attr { | 310 | let frange = if let Some(item) = &derive_attr { |
318 | item.syntax().original_file_range(db) | 311 | item.syntax().original_file_range(db) |
@@ -325,21 +318,21 @@ impl ToNav for hir::Impl { | |||
325 | 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) |
326 | }; | 319 | }; |
327 | 320 | ||
328 | NavigationTarget::from_syntax( | 321 | Some(NavigationTarget::from_syntax( |
329 | frange.file_id, | 322 | frange.file_id, |
330 | "impl".into(), | 323 | "impl".into(), |
331 | focus_range, | 324 | focus_range, |
332 | frange.range, | 325 | frange.range, |
333 | SymbolKind::Impl, | 326 | SymbolKind::Impl, |
334 | ) | 327 | )) |
335 | } | 328 | } |
336 | } | 329 | } |
337 | 330 | ||
338 | impl ToNav for hir::Field { | 331 | impl TryToNav for hir::Field { |
339 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 332 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
340 | let src = self.source(db); | 333 | let src = self.source(db)?; |
341 | 334 | ||
342 | match &src.value { | 335 | let field_source = match &src.value { |
343 | FieldSource::Named(it) => { | 336 | FieldSource::Named(it) => { |
344 | let mut res = | 337 | let mut res = |
345 | NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field); | 338 | NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field); |
@@ -357,13 +350,14 @@ impl ToNav for hir::Field { | |||
357 | SymbolKind::Field, | 350 | SymbolKind::Field, |
358 | ) | 351 | ) |
359 | } | 352 | } |
360 | } | 353 | }; |
354 | Some(field_source) | ||
361 | } | 355 | } |
362 | } | 356 | } |
363 | 357 | ||
364 | impl ToNav for hir::MacroDef { | 358 | impl TryToNav for hir::MacroDef { |
365 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 359 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
366 | let src = self.source(db); | 360 | let src = self.source(db)?; |
367 | log::debug!("nav target {:#?}", src.value.syntax()); | 361 | log::debug!("nav target {:#?}", src.value.syntax()); |
368 | let mut res = NavigationTarget::from_named( | 362 | let mut res = NavigationTarget::from_named( |
369 | db, | 363 | db, |
@@ -371,26 +365,26 @@ impl ToNav for hir::MacroDef { | |||
371 | SymbolKind::Macro, | 365 | SymbolKind::Macro, |
372 | ); | 366 | ); |
373 | res.docs = self.docs(db); | 367 | res.docs = self.docs(db); |
374 | res | 368 | Some(res) |
375 | } | 369 | } |
376 | } | 370 | } |
377 | 371 | ||
378 | impl ToNav for hir::Adt { | 372 | impl TryToNav for hir::Adt { |
379 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 373 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
380 | match self { | 374 | match self { |
381 | hir::Adt::Struct(it) => it.to_nav(db), | 375 | hir::Adt::Struct(it) => it.try_to_nav(db), |
382 | hir::Adt::Union(it) => it.to_nav(db), | 376 | hir::Adt::Union(it) => it.try_to_nav(db), |
383 | hir::Adt::Enum(it) => it.to_nav(db), | 377 | hir::Adt::Enum(it) => it.try_to_nav(db), |
384 | } | 378 | } |
385 | } | 379 | } |
386 | } | 380 | } |
387 | 381 | ||
388 | impl ToNav for hir::AssocItem { | 382 | impl TryToNav for hir::AssocItem { |
389 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 383 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
390 | match self { | 384 | match self { |
391 | AssocItem::Function(it) => it.to_nav(db), | 385 | AssocItem::Function(it) => it.try_to_nav(db), |
392 | AssocItem::Const(it) => it.to_nav(db), | 386 | AssocItem::Const(it) => it.try_to_nav(db), |
393 | AssocItem::TypeAlias(it) => it.to_nav(db), | 387 | AssocItem::TypeAlias(it) => it.try_to_nav(db), |
394 | } | 388 | } |
395 | } | 389 | } |
396 | } | 390 | } |
@@ -444,9 +438,9 @@ impl ToNav for hir::Label { | |||
444 | } | 438 | } |
445 | } | 439 | } |
446 | 440 | ||
447 | impl ToNav for hir::TypeParam { | 441 | impl TryToNav for hir::TypeParam { |
448 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 442 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
449 | let src = self.source(db); | 443 | let src = self.source(db)?; |
450 | let full_range = match &src.value { | 444 | let full_range = match &src.value { |
451 | Either::Left(it) => it.syntax().text_range(), | 445 | Either::Left(it) => it.syntax().text_range(), |
452 | Either::Right(it) => it.syntax().text_range(), | 446 | Either::Right(it) => it.syntax().text_range(), |
@@ -455,7 +449,7 @@ impl ToNav for hir::TypeParam { | |||
455 | Either::Left(_) => None, | 449 | Either::Left(_) => None, |
456 | Either::Right(it) => it.name().map(|it| it.syntax().text_range()), | 450 | Either::Right(it) => it.name().map(|it| it.syntax().text_range()), |
457 | }; | 451 | }; |
458 | NavigationTarget { | 452 | Some(NavigationTarget { |
459 | file_id: src.file_id.original_file(db), | 453 | file_id: src.file_id.original_file(db), |
460 | name: self.name(db).to_string().into(), | 454 | name: self.name(db).to_string().into(), |
461 | kind: Some(SymbolKind::TypeParam), | 455 | kind: Some(SymbolKind::TypeParam), |
@@ -464,15 +458,15 @@ impl ToNav for hir::TypeParam { | |||
464 | container_name: None, | 458 | container_name: None, |
465 | description: None, | 459 | description: None, |
466 | docs: None, | 460 | docs: None, |
467 | } | 461 | }) |
468 | } | 462 | } |
469 | } | 463 | } |
470 | 464 | ||
471 | impl ToNav for hir::LifetimeParam { | 465 | impl TryToNav for hir::LifetimeParam { |
472 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 466 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
473 | let src = self.source(db); | 467 | let src = self.source(db)?; |
474 | let full_range = src.value.syntax().text_range(); | 468 | let full_range = src.value.syntax().text_range(); |
475 | NavigationTarget { | 469 | Some(NavigationTarget { |
476 | file_id: src.file_id.original_file(db), | 470 | file_id: src.file_id.original_file(db), |
477 | name: self.name(db).to_string().into(), | 471 | name: self.name(db).to_string().into(), |
478 | kind: Some(SymbolKind::LifetimeParam), | 472 | kind: Some(SymbolKind::LifetimeParam), |
@@ -481,7 +475,24 @@ impl ToNav for hir::LifetimeParam { | |||
481 | container_name: None, | 475 | container_name: None, |
482 | description: None, | 476 | description: None, |
483 | docs: None, | 477 | docs: None, |
484 | } | 478 | }) |
479 | } | ||
480 | } | ||
481 | |||
482 | impl TryToNav for hir::ConstParam { | ||
483 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { | ||
484 | let src = self.source(db)?; | ||
485 | let full_range = src.value.syntax().text_range(); | ||
486 | Some(NavigationTarget { | ||
487 | file_id: src.file_id.original_file(db), | ||
488 | name: self.name(db).to_string().into(), | ||
489 | kind: Some(SymbolKind::ConstParam), | ||
490 | full_range, | ||
491 | focus_range: src.value.name().map(|n| n.syntax().text_range()), | ||
492 | container_name: None, | ||
493 | description: None, | ||
494 | docs: None, | ||
495 | }) | ||
485 | } | 496 | } |
486 | } | 497 | } |
487 | 498 | ||
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index e10516f43..367fac05e 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs | |||
@@ -193,6 +193,7 @@ fn rewrite_intra_doc_link( | |||
193 | Definition::SelfType(_) | 193 | Definition::SelfType(_) |
194 | | Definition::Local(_) | 194 | | Definition::Local(_) |
195 | | Definition::TypeParam(_) | 195 | | Definition::TypeParam(_) |
196 | | Definition::ConstParam(_) | ||
196 | | Definition::LifetimeParam(_) | 197 | | Definition::LifetimeParam(_) |
197 | | Definition::Label(_) => return None, | 198 | | Definition::Label(_) => return None, |
198 | }?; | 199 | }?; |
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}; | |||
2 | use ide_db::RootDatabase; | 2 | use ide_db::RootDatabase; |
3 | use syntax::{algo::find_node_at_offset, ast, AstNode}; | 3 | use syntax::{algo::find_node_at_offset, ast, AstNode}; |
4 | 4 | ||
5 | use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; | 5 | use 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 @@ | |||
1 | use ide_db::RootDatabase; | 1 | use ide_db::RootDatabase; |
2 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; | 2 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; |
3 | 3 | ||
4 | use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; | 4 | use 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 73245fbe7..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, | |||
13 | use test_utils::mark; | 13 | use test_utils::mark; |
14 | 14 | ||
15 | use crate::{ | 15 | use 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, |
@@ -109,6 +109,8 @@ pub(crate) fn hover( | |||
109 | match node { | 109 | match node { |
110 | ast::Name(name) => NameClass::classify(&sema, &name).and_then(|d| d.defined(sema.db)), | 110 | ast::Name(name) => NameClass::classify(&sema, &name).and_then(|d| d.defined(sema.db)), |
111 | ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), | 111 | ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), |
112 | ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime) | ||
113 | .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)), | ||
112 | _ => None, | 114 | _ => None, |
113 | } | 115 | } |
114 | }; | 116 | }; |
@@ -181,10 +183,10 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov | |||
181 | 183 | ||
182 | match def { | 184 | match def { |
183 | Definition::ModuleDef(it) => match it { | 185 | Definition::ModuleDef(it) => match it { |
184 | 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)?)), |
185 | 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)?)), |
186 | 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)?)), |
187 | ModuleDef::Trait(it) => Some(to_action(it.to_nav(db))), | 189 | ModuleDef::Trait(it) => Some(to_action(it.try_to_nav(db)?)), |
188 | _ => None, | 190 | _ => None, |
189 | }, | 191 | }, |
190 | _ => None, | 192 | _ => None, |
@@ -204,7 +206,8 @@ fn runnable_action( | |||
204 | _ => None, | 206 | _ => None, |
205 | }, | 207 | }, |
206 | ModuleDef::Function(it) => { | 208 | ModuleDef::Function(it) => { |
207 | let src = it.source(sema.db); | 209 | #[allow(deprecated)] |
210 | let src = it.source(sema.db)?; | ||
208 | if src.file_id != file_id.into() { | 211 | if src.file_id != file_id.into() { |
209 | mark::hit!(hover_macro_generated_struct_fn_doc_comment); | 212 | mark::hit!(hover_macro_generated_struct_fn_doc_comment); |
210 | mark::hit!(hover_macro_generated_struct_fn_doc_attr); | 213 | mark::hit!(hover_macro_generated_struct_fn_doc_attr); |
@@ -324,17 +327,12 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
324 | let mod_path = definition_mod_path(db, &def); | 327 | let mod_path = definition_mod_path(db, &def); |
325 | return match def { | 328 | return match def { |
326 | Definition::Macro(it) => { | 329 | Definition::Macro(it) => { |
327 | // FIXME: Currently proc-macro do not have ast-node, | 330 | let label = macro_label(&it.source(db)?.value); |
328 | // such that it does not have source | ||
329 | // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913 | ||
330 | if it.is_proc_macro() { | ||
331 | return None; | ||
332 | } | ||
333 | let label = macro_label(&it.source(db).value); | ||
334 | from_def_source_labeled(db, it, Some(label), mod_path) | 331 | from_def_source_labeled(db, it, Some(label), mod_path) |
335 | } | 332 | } |
336 | Definition::Field(def) => { | 333 | Definition::Field(def) => { |
337 | let src = def.source(db).value; | 334 | #[allow(deprecated)] |
335 | let src = def.source(db)?.value; | ||
338 | if let FieldSource::Named(it) = src { | 336 | if let FieldSource::Named(it) = src { |
339 | from_def_source_labeled(db, def, it.short_label(), mod_path) | 337 | from_def_source_labeled(db, def, it.short_label(), mod_path) |
340 | } else { | 338 | } else { |
@@ -360,9 +358,9 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
360 | ModuleDef::Static(it) => from_def_source(db, it, mod_path), | 358 | ModuleDef::Static(it) => from_def_source(db, it, mod_path), |
361 | ModuleDef::Trait(it) => from_def_source(db, it, mod_path), | 359 | ModuleDef::Trait(it) => from_def_source(db, it, mod_path), |
362 | ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), | 360 | ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), |
363 | ModuleDef::BuiltinType(it) => return Some(it.to_string().into()), | 361 | ModuleDef::BuiltinType(it) => Some(Markup::fenced_block(&it)), |
364 | }, | 362 | }, |
365 | Definition::Local(it) => return Some(Markup::fenced_block(&it.ty(db).display(db))), | 363 | Definition::Local(it) => Some(Markup::fenced_block(&it.ty(db).display(db))), |
366 | Definition::SelfType(impl_def) => { | 364 | Definition::SelfType(impl_def) => { |
367 | impl_def.target_ty(db).as_adt().and_then(|adt| match adt { | 365 | impl_def.target_ty(db).as_adt().and_then(|adt| match adt { |
368 | Adt::Struct(it) => from_def_source(db, it, mod_path), | 366 | Adt::Struct(it) => from_def_source(db, it, mod_path), |
@@ -370,7 +368,9 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
370 | Adt::Enum(it) => from_def_source(db, it, mod_path), | 368 | Adt::Enum(it) => from_def_source(db, it, mod_path), |
371 | }) | 369 | }) |
372 | } | 370 | } |
373 | Definition::TypeParam(_) | Definition::LifetimeParam(_) | Definition::Label(_) => { | 371 | Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))), |
372 | Definition::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))), | ||
373 | Definition::TypeParam(_) | Definition::ConstParam(_) => { | ||
374 | // FIXME: Hover for generic param | 374 | // FIXME: Hover for generic param |
375 | None | 375 | None |
376 | } | 376 | } |
@@ -381,7 +381,8 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
381 | D: HasSource<Ast = A> + HasAttrs + Copy, | 381 | D: HasSource<Ast = A> + HasAttrs + Copy, |
382 | A: ShortLabel, | 382 | A: ShortLabel, |
383 | { | 383 | { |
384 | let short_label = def.source(db).value.short_label(); | 384 | #[allow(deprecated)] |
385 | let short_label = def.source(db)?.value.short_label(); | ||
385 | from_def_source_labeled(db, def, short_label, mod_path) | 386 | from_def_source_labeled(db, def, short_label, mod_path) |
386 | } | 387 | } |
387 | 388 | ||
@@ -403,7 +404,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | |||
403 | return tokens.max_by_key(priority); | 404 | return tokens.max_by_key(priority); |
404 | fn priority(n: &SyntaxToken) -> usize { | 405 | fn priority(n: &SyntaxToken) -> usize { |
405 | match n.kind() { | 406 | match n.kind() { |
406 | IDENT | INT_NUMBER => 3, | 407 | IDENT | INT_NUMBER | LIFETIME_IDENT => 3, |
407 | T!['('] | T![')'] => 2, | 408 | T!['('] | T![')'] => 2, |
408 | kind if kind.is_trivia() => 0, | 409 | kind if kind.is_trivia() => 0, |
409 | _ => 1, | 410 | _ => 1, |
@@ -1169,7 +1170,10 @@ fn f() { fo<|>o!(); } | |||
1169 | r#"struct TS(String, i32<|>);"#, | 1170 | r#"struct TS(String, i32<|>);"#, |
1170 | expect![[r#" | 1171 | expect![[r#" |
1171 | *i32* | 1172 | *i32* |
1173 | |||
1174 | ```rust | ||
1172 | i32 | 1175 | i32 |
1176 | ``` | ||
1173 | "#]], | 1177 | "#]], |
1174 | ) | 1178 | ) |
1175 | } | 1179 | } |
@@ -3221,4 +3225,36 @@ fn no_hover() { | |||
3221 | "#, | 3225 | "#, |
3222 | ); | 3226 | ); |
3223 | } | 3227 | } |
3228 | |||
3229 | #[test] | ||
3230 | fn hover_label() { | ||
3231 | check( | ||
3232 | r#" | ||
3233 | fn foo() { | ||
3234 | 'label<|>: loop {} | ||
3235 | } | ||
3236 | "#, | ||
3237 | expect![[r#" | ||
3238 | *'label* | ||
3239 | |||
3240 | ```rust | ||
3241 | 'label | ||
3242 | ``` | ||
3243 | "#]], | ||
3244 | ); | ||
3245 | } | ||
3246 | |||
3247 | #[test] | ||
3248 | fn hover_lifetime() { | ||
3249 | check( | ||
3250 | r#"fn foo<'lifetime>(_: &'lifetime<|> ()) {}"#, | ||
3251 | expect![[r#" | ||
3252 | *'lifetime* | ||
3253 | |||
3254 | ```rust | ||
3255 | 'lifetime | ||
3256 | ``` | ||
3257 | "#]], | ||
3258 | ); | ||
3259 | } | ||
3224 | } | 3260 | } |
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; | |||
31 | mod goto_definition; | 31 | mod goto_definition; |
32 | mod goto_implementation; | 32 | mod goto_implementation; |
33 | mod goto_type_definition; | 33 | mod goto_type_definition; |
34 | mod view_hir; | ||
34 | mod hover; | 35 | mod hover; |
35 | mod inlay_hints; | 36 | mod inlay_hints; |
36 | mod join_lines; | 37 | mod 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/references.rs b/crates/ide/src/references.rs index 21b2d7ca1..fa58fc319 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs | |||
@@ -1144,4 +1144,20 @@ fn foo<'a>() -> &'a () { | |||
1144 | "#]], | 1144 | "#]], |
1145 | ); | 1145 | ); |
1146 | } | 1146 | } |
1147 | |||
1148 | #[test] | ||
1149 | fn test_find_const_param() { | ||
1150 | check( | ||
1151 | r#" | ||
1152 | fn foo<const FOO<|>: usize>() -> usize { | ||
1153 | FOO | ||
1154 | } | ||
1155 | "#, | ||
1156 | expect![[r#" | ||
1157 | FOO ConstParam FileId(0) 7..23 13..16 Other | ||
1158 | |||
1159 | FileId(0) 42..45 Other | ||
1160 | "#]], | ||
1161 | ); | ||
1162 | } | ||
1147 | } | 1163 | } |
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 891183266..c893afc7c 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs | |||
@@ -230,7 +230,7 @@ impl TestAttr { | |||
230 | 230 | ||
231 | const RUSTDOC_FENCE: &str = "```"; | 231 | const RUSTDOC_FENCE: &str = "```"; |
232 | const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] = | 232 | const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] = |
233 | &["", "rust", "should_panic", "edition2015", "edition2018"]; | 233 | &["", "rust", "should_panic", "edition2015", "edition2018", "edition2021"]; |
234 | 234 | ||
235 | fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool { | 235 | fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool { |
236 | attrs.docs().map_or(false, |doc| { | 236 | attrs.docs().map_or(false, |doc| { |
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 5ad96581b..ba0085244 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs | |||
@@ -819,6 +819,7 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
819 | }, | 819 | }, |
820 | Definition::SelfType(_) => HighlightTag::Symbol(SymbolKind::Impl), | 820 | Definition::SelfType(_) => HighlightTag::Symbol(SymbolKind::Impl), |
821 | Definition::TypeParam(_) => HighlightTag::Symbol(SymbolKind::TypeParam), | 821 | Definition::TypeParam(_) => HighlightTag::Symbol(SymbolKind::TypeParam), |
822 | Definition::ConstParam(_) => HighlightTag::Symbol(SymbolKind::ConstParam), | ||
822 | Definition::Local(local) => { | 823 | Definition::Local(local) => { |
823 | let tag = if local.is_param(db) { | 824 | let tag = if local.is_param(db) { |
824 | HighlightTag::Symbol(SymbolKind::ValueParam) | 825 | HighlightTag::Symbol(SymbolKind::ValueParam) |
diff --git a/crates/ide/src/syntax_highlighting/injection.rs b/crates/ide/src/syntax_highlighting/injection.rs index 9eb184c74..6cbd683c6 100644 --- a/crates/ide/src/syntax_highlighting/injection.rs +++ b/crates/ide/src/syntax_highlighting/injection.rs | |||
@@ -54,8 +54,17 @@ pub(super) fn highlight_injection( | |||
54 | type RangesMap = BTreeMap<TextSize, TextSize>; | 54 | type RangesMap = BTreeMap<TextSize, TextSize>; |
55 | 55 | ||
56 | const RUSTDOC_FENCE: &'static str = "```"; | 56 | const RUSTDOC_FENCE: &'static str = "```"; |
57 | const RUSTDOC_FENCE_TOKENS: &[&'static str] = | 57 | const RUSTDOC_FENCE_TOKENS: &[&'static str] = &[ |
58 | &["", "rust", "should_panic", "ignore", "no_run", "compile_fail", "edition2015", "edition2018"]; | 58 | "", |
59 | "rust", | ||
60 | "should_panic", | ||
61 | "ignore", | ||
62 | "no_run", | ||
63 | "compile_fail", | ||
64 | "edition2015", | ||
65 | "edition2018", | ||
66 | "edition2021", | ||
67 | ]; | ||
59 | 68 | ||
60 | /// Extracts Rust code from documentation comments as well as a mapping from | 69 | /// Extracts Rust code from documentation comments as well as a mapping from |
61 | /// the extracted source code back to the original source ranges. | 70 | /// the extracted source code back to the original source ranges. |
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index 2a6cc0cab..8b8867079 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs | |||
@@ -77,6 +77,7 @@ impl HighlightTag { | |||
77 | SymbolKind::Function => "function", | 77 | SymbolKind::Function => "function", |
78 | SymbolKind::TypeAlias => "type_alias", | 78 | SymbolKind::TypeAlias => "type_alias", |
79 | SymbolKind::TypeParam => "type_param", | 79 | SymbolKind::TypeParam => "type_param", |
80 | SymbolKind::ConstParam => "const_param", | ||
80 | SymbolKind::LifetimeParam => "lifetime", | 81 | SymbolKind::LifetimeParam => "lifetime", |
81 | SymbolKind::Macro => "macro", | 82 | SymbolKind::Macro => "macro", |
82 | SymbolKind::Local => "variable", | 83 | SymbolKind::Local => "variable", |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 72ff9dd40..02270b077 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html | |||
@@ -118,6 +118,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
118 | <span class="keyword control">loop</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 118 | <span class="keyword control">loop</span> <span class="punctuation">{</span><span class="punctuation">}</span> |
119 | <span class="punctuation">}</span> | 119 | <span class="punctuation">}</span> |
120 | 120 | ||
121 | <span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="punctuation"><</span><span class="keyword">const</span> <span class="const_param declaration">FOO</span><span class="punctuation">:</span> <span class="builtin_type">usize</span><span class="punctuation">></span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">usize</span> <span class="punctuation">{</span> | ||
122 | <span class="const_param">FOO</span> | ||
123 | <span class="punctuation">}</span> | ||
124 | |||
121 | <span class="keyword">use</span> <span class="module">ops</span><span class="operator">::</span><span class="trait">Fn</span><span class="punctuation">;</span> | 125 | <span class="keyword">use</span> <span class="module">ops</span><span class="operator">::</span><span class="trait">Fn</span><span class="punctuation">;</span> |
122 | <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation"><</span><span class="type_param declaration">F</span><span class="punctuation">:</span> <span class="trait">Fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">></span><span class="punctuation">(</span><span class="value_param declaration callable">f</span><span class="punctuation">:</span> <span class="type_param">F</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 126 | <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation"><</span><span class="type_param declaration">F</span><span class="punctuation">:</span> <span class="trait">Fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">></span><span class="punctuation">(</span><span class="value_param declaration callable">f</span><span class="punctuation">:</span> <span class="type_param">F</span><span class="punctuation">)</span> <span class="punctuation">{</span> |
123 | <span class="value_param callable">f</span><span class="punctuation">(</span><span class="punctuation">)</span> | 127 | <span class="value_param callable">f</span><span class="punctuation">(</span><span class="punctuation">)</span> |
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index e0df0d2b5..30b5b648e 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs | |||
@@ -91,6 +91,10 @@ fn never() -> ! { | |||
91 | loop {} | 91 | loop {} |
92 | } | 92 | } |
93 | 93 | ||
94 | fn const_param<const FOO: usize>() -> usize { | ||
95 | FOO | ||
96 | } | ||
97 | |||
94 | use ops::Fn; | 98 | use ops::Fn; |
95 | fn baz<F: Fn() -> ()>(f: F) { | 99 | fn baz<F: Fn() -> ()>(f: F) { |
96 | f() | 100 | f() |
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 @@ | |||
1 | use hir::{Function, Semantics}; | ||
2 | use ide_db::base_db::FilePosition; | ||
3 | use ide_db::RootDatabase; | ||
4 | use 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 | // |=== | ||
13 | pub(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 | |||
17 | fn 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 | } | ||