From cf696c0ed64b9a63cdb738a68a6209278664de67 Mon Sep 17 00:00:00 2001 From: Teddy_Wang Date: Wed, 8 Sep 2021 22:28:52 -0400 Subject: [PATCH 1/6] Show the type of what is being dereferenced in a deref expression --- crates/ide/src/hover.rs | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 2a505c621f..af65cfce86 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -243,6 +243,9 @@ fn hover_ranged( })?; let res = match &expr_or_pat { Either::Left(ast::Expr::TryExpr(try_expr)) => hover_try_expr(sema, config, try_expr), + Either::Left(ast::Expr::PrefixExpr(prefix_expr)) if prefix_expr.op_kind() == Some(ast::UnaryOp::Deref) => { + hover_deref_expr(sema, config, prefix_expr) + } _ => None, }; let res = res.or_else(|| hover_type_info(sema, config, &expr_or_pat)); @@ -346,6 +349,67 @@ fn hover_try_expr( Some(res) } +fn hover_deref_expr( + sema: &Semantics, + config: &HoverConfig, + deref_expr: &ast::PrefixExpr, +) -> Option { + let inner_ty = sema.type_of_expr(&deref_expr.expr()?)?.original; + let TypeInfo { original, adjusted } = sema.type_of_expr(&ast::Expr::from(deref_expr.clone()))?; + + let mut res = HoverResult::default(); + let mut targets: Vec = Vec::new(); + let mut push_new_def = |item: hir::ModuleDef| { + if !targets.contains(&item) { + targets.push(item); + } + }; + walk_and_push_ty(sema.db, &inner_ty, &mut push_new_def); + walk_and_push_ty(sema.db, &original, &mut push_new_def); + + res.markup = if let Some(adjusted_ty) = adjusted { + walk_and_push_ty(sema.db, &adjusted_ty, &mut push_new_def); + let original = original.display(sema.db).to_string(); + let adjusted = adjusted_ty.display(sema.db).to_string(); + let inner = inner_ty.display(sema.db).to_string(); + let type_len = "Type: ".len(); + let coerced_len = "Coerced to: ".len(); + let deref_len = "Derefenced from: ".len(); + let max_len = (original.len() + type_len).max(adjusted.len() + coerced_len).max(inner.len() + deref_len); + format!( + "{bt_start}Type: {:>apad$}\nCoerced to: {:>opad$}\nDerefenced from: {:>ipad$}\n{bt_end}", + original, + adjusted, + inner, + apad = max_len - type_len, + opad = max_len - coerced_len, + ipad = max_len - deref_len, + bt_start = if config.markdown() { "```text\n" } else { "" }, + bt_end = if config.markdown() { "```\n" } else { "" } + ) + .into() + } else { + let original = original.display(sema.db).to_string(); + let inner = inner_ty.display(sema.db).to_string(); + let type_len = "Type: ".len(); + let deref_len = "Derefenced from: ".len(); + let max_len = (original.len() + type_len).max(inner.len() + deref_len); + format!( + "{bt_start}Type: {:>apad$}\nDerefenced from: {:>ipad$}\n{bt_end}", + original, + inner, + apad = max_len - type_len, + ipad = max_len - deref_len, + bt_start = if config.markdown() { "```text\n" } else { "" }, + bt_end = if config.markdown() { "```\n" } else { "" } + ) + .into() + }; + res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets)); + + Some(res) +} + fn hover_type_info( sema: &Semantics, config: &HoverConfig, From 67a9c457e665e99f5976f7ceb2724f308dcd1bfb Mon Sep 17 00:00:00 2001 From: Teddy_Wang Date: Thu, 9 Sep 2021 23:31:13 -0400 Subject: [PATCH 2/6] Add tests. The tests with coercion fail, but I have no clue why. --- crates/ide/src/hover.rs | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index af65cfce86..49c9f487e0 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -4510,4 +4510,68 @@ fn foo() -> Option<()> { ```"#]], ); } + + + #[test] + fn hover_deref_expr() { + check_hover_range( + r#" +//- minicore: deref +struct DerefExample { + value: T +} + +impl Deref for DerefExample { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + +fn foo() { + let x = DerefExample { value: 0 }; + let y: i32 = $0*x$0; +} +"#, + expect![[r#" + ```text + Type: i32 + Derefenced from: DerefExample + ``` + "#]], + ); + } + + #[test] + fn hover_deref_expr_with_coercion() { + check_hover_range( + r#" +//- minicore: deref +struct DerefExample { + value: T +} + +impl Deref for DerefExample { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + +fn foo() { + let x = DerefExample { value: &&&&&0 }; + let y: &i32 = $0*x$0; +} +"#, + expect![[r#" + ```text + Type: &&&&&i32 + Coerced to: &i32 + Derefenced from: DerefExample<&&&&&i32> + ``` + "#]], + ); + } } From 1d4d9a1e1a2560a1cfd51ed1ebc41248be386548 Mon Sep 17 00:00:00 2001 From: Teddy_Wang Date: Sat, 11 Sep 2021 11:40:16 -0400 Subject: [PATCH 3/6] Fix tests by importing core::ops::Deref --- crates/ide/src/hover.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 49c9f487e0..94cf209e21 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -243,7 +243,9 @@ fn hover_ranged( })?; let res = match &expr_or_pat { Either::Left(ast::Expr::TryExpr(try_expr)) => hover_try_expr(sema, config, try_expr), - Either::Left(ast::Expr::PrefixExpr(prefix_expr)) if prefix_expr.op_kind() == Some(ast::UnaryOp::Deref) => { + Either::Left(ast::Expr::PrefixExpr(prefix_expr)) + if prefix_expr.op_kind() == Some(ast::UnaryOp::Deref) => + { hover_deref_expr(sema, config, prefix_expr) } _ => None, @@ -355,7 +357,8 @@ fn hover_deref_expr( deref_expr: &ast::PrefixExpr, ) -> Option { let inner_ty = sema.type_of_expr(&deref_expr.expr()?)?.original; - let TypeInfo { original, adjusted } = sema.type_of_expr(&ast::Expr::from(deref_expr.clone()))?; + let TypeInfo { original, adjusted } = + sema.type_of_expr(&ast::Expr::from(deref_expr.clone()))?; let mut res = HoverResult::default(); let mut targets: Vec = Vec::new(); @@ -366,7 +369,7 @@ fn hover_deref_expr( }; walk_and_push_ty(sema.db, &inner_ty, &mut push_new_def); walk_and_push_ty(sema.db, &original, &mut push_new_def); - + res.markup = if let Some(adjusted_ty) = adjusted { walk_and_push_ty(sema.db, &adjusted_ty, &mut push_new_def); let original = original.display(sema.db).to_string(); @@ -375,7 +378,9 @@ fn hover_deref_expr( let type_len = "Type: ".len(); let coerced_len = "Coerced to: ".len(); let deref_len = "Derefenced from: ".len(); - let max_len = (original.len() + type_len).max(adjusted.len() + coerced_len).max(inner.len() + deref_len); + let max_len = (original.len() + type_len) + .max(adjusted.len() + coerced_len) + .max(inner.len() + deref_len); format!( "{bt_start}Type: {:>apad$}\nCoerced to: {:>opad$}\nDerefenced from: {:>ipad$}\n{bt_end}", original, @@ -4511,12 +4516,13 @@ fn foo() -> Option<()> { ); } - #[test] fn hover_deref_expr() { check_hover_range( r#" -//- minicore: deref +//- minicore: deref +use core::ops::Deref; + struct DerefExample { value: T } @@ -4547,19 +4553,21 @@ fn foo() { fn hover_deref_expr_with_coercion() { check_hover_range( r#" -//- minicore: deref +//- minicore: deref +use core::ops::Deref; + struct DerefExample { value: T } - + impl Deref for DerefExample { type Target = T; - + fn deref(&self) -> &Self::Target { &self.value } } - + fn foo() { let x = DerefExample { value: &&&&&0 }; let y: &i32 = $0*x$0; From 0c6a993f5912e01a5af8167314dcbbf715d24c8e Mon Sep 17 00:00:00 2001 From: Teddy_Wang Date: Mon, 13 Sep 2021 19:16:10 -0400 Subject: [PATCH 4/6] Fix spelling --- crates/ide/src/hover.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 94cf209e21..8d2ebd96e1 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -377,12 +377,12 @@ fn hover_deref_expr( let inner = inner_ty.display(sema.db).to_string(); let type_len = "Type: ".len(); let coerced_len = "Coerced to: ".len(); - let deref_len = "Derefenced from: ".len(); + let deref_len = "Dereferenced from: ".len(); let max_len = (original.len() + type_len) .max(adjusted.len() + coerced_len) .max(inner.len() + deref_len); format!( - "{bt_start}Type: {:>apad$}\nCoerced to: {:>opad$}\nDerefenced from: {:>ipad$}\n{bt_end}", + "{bt_start}Type: {:>apad$}\nCoerced to: {:>opad$}\nDereferenced from: {:>ipad$}\n{bt_end}", original, adjusted, inner, @@ -397,10 +397,10 @@ fn hover_deref_expr( let original = original.display(sema.db).to_string(); let inner = inner_ty.display(sema.db).to_string(); let type_len = "Type: ".len(); - let deref_len = "Derefenced from: ".len(); + let deref_len = "Dereferenced from: ".len(); let max_len = (original.len() + type_len).max(inner.len() + deref_len); format!( - "{bt_start}Type: {:>apad$}\nDerefenced from: {:>ipad$}\n{bt_end}", + "{bt_start}Type: {:>apad$}\nDereferenced from: {:>ipad$}\n{bt_end}", original, inner, apad = max_len - type_len, @@ -4543,7 +4543,7 @@ fn foo() { expect![[r#" ```text Type: i32 - Derefenced from: DerefExample + Dereferenced from: DerefExample ``` "#]], ); @@ -4577,7 +4577,7 @@ fn foo() { ```text Type: &&&&&i32 Coerced to: &i32 - Derefenced from: DerefExample<&&&&&i32> + Dereferenced from: DerefExample<&&&&&i32> ``` "#]], ); From 4d9728ccb2d207c4cb6a2f200cc1d1f0bb919c28 Mon Sep 17 00:00:00 2001 From: Teddy_Wang Date: Mon, 13 Sep 2021 19:47:53 -0400 Subject: [PATCH 5/6] Fix hover tests --- crates/ide/src/hover.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 8d2ebd96e1..8753e3e391 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -4542,7 +4542,7 @@ fn foo() { "#, expect![[r#" ```text - Type: i32 + Type: i32 Dereferenced from: DerefExample ``` "#]], @@ -4575,8 +4575,8 @@ fn foo() { "#, expect![[r#" ```text - Type: &&&&&i32 - Coerced to: &i32 + Type: &&&&&i32 + Coerced to: &i32 Dereferenced from: DerefExample<&&&&&i32> ``` "#]], From 8de5d66e25d256ff4949118ef6de56a166408806 Mon Sep 17 00:00:00 2001 From: Teddy_Wang Date: Mon, 13 Sep 2021 20:19:30 -0400 Subject: [PATCH 6/6] Improve hover over derference message --- crates/ide/src/hover.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 8753e3e391..13c5fc1aec 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -375,20 +375,20 @@ fn hover_deref_expr( let original = original.display(sema.db).to_string(); let adjusted = adjusted_ty.display(sema.db).to_string(); let inner = inner_ty.display(sema.db).to_string(); - let type_len = "Type: ".len(); + let type_len = "To type: ".len(); let coerced_len = "Coerced to: ".len(); let deref_len = "Dereferenced from: ".len(); let max_len = (original.len() + type_len) .max(adjusted.len() + coerced_len) .max(inner.len() + deref_len); format!( - "{bt_start}Type: {:>apad$}\nCoerced to: {:>opad$}\nDereferenced from: {:>ipad$}\n{bt_end}", + "{bt_start}Dereferenced from: {:>ipad$}\nTo type: {:>apad$}\nCoerced to: {:>opad$}\n{bt_end}", + inner, original, adjusted, - inner, + ipad = max_len - deref_len, apad = max_len - type_len, opad = max_len - coerced_len, - ipad = max_len - deref_len, bt_start = if config.markdown() { "```text\n" } else { "" }, bt_end = if config.markdown() { "```\n" } else { "" } ) @@ -396,15 +396,15 @@ fn hover_deref_expr( } else { let original = original.display(sema.db).to_string(); let inner = inner_ty.display(sema.db).to_string(); - let type_len = "Type: ".len(); + let type_len = "To type: ".len(); let deref_len = "Dereferenced from: ".len(); let max_len = (original.len() + type_len).max(inner.len() + deref_len); format!( - "{bt_start}Type: {:>apad$}\nDereferenced from: {:>ipad$}\n{bt_end}", - original, + "{bt_start}Dereferenced from: {:>ipad$}\nTo type: {:>apad$}\n{bt_end}", inner, - apad = max_len - type_len, + original, ipad = max_len - deref_len, + apad = max_len - type_len, bt_start = if config.markdown() { "```text\n" } else { "" }, bt_end = if config.markdown() { "```\n" } else { "" } ) @@ -4542,8 +4542,8 @@ fn foo() { "#, expect![[r#" ```text - Type: i32 Dereferenced from: DerefExample + To type: i32 ``` "#]], ); @@ -4575,9 +4575,9 @@ fn foo() { "#, expect![[r#" ```text - Type: &&&&&i32 - Coerced to: &i32 Dereferenced from: DerefExample<&&&&&i32> + To type: &&&&&i32 + Coerced to: &i32 ``` "#]], );