From 53bb46fa853bee99f673a0ed0a53798c46847d99 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sat, 6 Mar 2021 16:56:07 -0800 Subject: show function params in completion detail --- crates/hir/src/lib.rs | 8 ++++ crates/ide_completion/src/completions/dot.rs | 24 +++++----- crates/ide_completion/src/completions/flyimport.rs | 8 ++-- .../src/completions/qualified_path.rs | 56 +++++++++++----------- .../src/completions/unqualified_path.rs | 50 +++++++++---------- crates/ide_completion/src/lib.rs | 6 +-- crates/ide_completion/src/render.rs | 54 +++++++++++++++++---- crates/ide_completion/src/render/function.rs | 31 +++++++++++- 8 files changed, 155 insertions(+), 82 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 58adc8fd3..8d082994a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -921,6 +921,14 @@ impl SelfParam { }) .unwrap_or(Access::Owned) } + + pub fn display(self, db: &dyn HirDatabase) -> &'static str { + match self.access(db) { + Access::Shared => "&self", + Access::Exclusive => "&mut self", + Access::Owned => "self", + } + } } impl HasVisibility for Function { diff --git a/crates/ide_completion/src/completions/dot.rs b/crates/ide_completion/src/completions/dot.rs index 5ee9a9f07..cec2d0c3a 100644 --- a/crates/ide_completion/src/completions/dot.rs +++ b/crates/ide_completion/src/completions/dot.rs @@ -81,7 +81,7 @@ fn foo(s: S) { s.$0 } "#, expect![[r#" fd foo u32 - me bar() -> () + me bar() fn(&self) "#]], ); } @@ -97,7 +97,7 @@ impl S { "#, expect![[r#" fd the_field (u32,) - me foo() -> () + me foo() fn(self) "#]], ) } @@ -113,7 +113,7 @@ impl A { "#, expect![[r#" fd the_field (u32, i32) - me foo() -> () + me foo() fn(&self) "#]], ) } @@ -163,7 +163,7 @@ mod m { fn foo(a: A) { a.$0 } "#, expect![[r#" - me the_method() -> () + me the_method() fn(&self) "#]], ); } @@ -196,7 +196,7 @@ impl A { fn foo(a: A) { a.$0 } "#, expect![[r#" - me the_method() -> () + me the_method() fn(&self) "#]], ) } @@ -211,7 +211,7 @@ impl Trait for A {} fn foo(a: A) { a.$0 } "#, expect![[r#" - me the_method() -> () + me the_method() fn(&self) "#]], ); } @@ -226,7 +226,7 @@ impl Trait for T {} fn foo(a: &A) { a.$0 } ", expect![[r#" - me the_method() -> () + me the_method() fn(&self) "#]], ); } @@ -244,7 +244,7 @@ impl Trait for A {} fn foo(a: A) { a.$0 } ", expect![[r#" - me the_method() -> () + me the_method() fn(&self) "#]], ); } @@ -298,7 +298,7 @@ impl T { } "#, expect![[r#" - me blah() -> () + me blah() fn(&self) "#]], ); } @@ -407,7 +407,7 @@ fn foo() { } "#, expect![[r#" - me the_method() -> () + me the_method() fn(&self) "#]], ); } @@ -422,7 +422,7 @@ macro_rules! make_s { () => { S }; } fn main() { make_s!().f$0; } "#, expect![[r#" - me foo() -> () + me foo() fn(&self) "#]], ) } @@ -450,7 +450,7 @@ mod foo { } "#, expect![[r#" - me private() -> () + me private() fn(&self) "#]], ); } diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs index 391a11c91..08df2df3f 100644 --- a/crates/ide_completion/src/completions/flyimport.rs +++ b/crates/ide_completion/src/completions/flyimport.rs @@ -402,7 +402,7 @@ fn main() { check( fixture, expect![[r#" - fn weird_function() (dep::test_mod::TestTrait) -> () + fn weird_function() (dep::test_mod::TestTrait) fn() "#]], ); @@ -495,7 +495,7 @@ fn main() { check( fixture, expect![[r#" - me random_method() (dep::test_mod::TestTrait) -> () + me random_method() (dep::test_mod::TestTrait) fn(&self) "#]], ); @@ -665,7 +665,7 @@ fn main() { } "#, expect![[r#" - me random_method() (dep::test_mod::TestTrait) -> () DEPRECATED + me random_method() (dep::test_mod::TestTrait) fn(&self) DEPRECATED "#]], ); @@ -696,7 +696,7 @@ fn main() { "#, expect![[r#" ct SPECIAL_CONST (dep::test_mod::TestTrait) DEPRECATED - fn weird_function() (dep::test_mod::TestTrait) -> () DEPRECATED + fn weird_function() (dep::test_mod::TestTrait) fn() DEPRECATED "#]], ); } diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index df74b739e..105ff6013 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs @@ -359,8 +359,8 @@ impl S { fn foo() { let _ = S::$0 } "#, expect![[r#" - fn a() -> () - me b(…) -> () + fn a() fn() + me b(…) fn(&self) ct C const C: i32 = 42; ta T type T = i32; "#]], @@ -387,7 +387,7 @@ mod m { fn foo() { let _ = S::$0 } "#, expect![[r#" - fn public_method() -> () + fn public_method() fn() ct PUBLIC_CONST pub(crate) const PUBLIC_CONST: u32 = 1; ta PublicType pub(crate) type PublicType = u32; "#]], @@ -404,7 +404,7 @@ impl E { fn m() { } } fn foo() { let _ = E::$0 } "#, expect![[r#" - fn m() -> () + fn m() fn() "#]], ); } @@ -419,7 +419,7 @@ impl U { fn m() { } } fn foo() { let _ = U::$0 } "#, expect![[r#" - fn m() -> () + fn m() fn() "#]], ); } @@ -449,7 +449,7 @@ trait Trait { fn m(); } fn foo() { let _ = Trait::$0 } "#, expect![[r#" - fn m() -> () + fn m() fn() "#]], ); } @@ -466,7 +466,7 @@ impl Trait for S {} fn foo() { let _ = S::$0 } "#, expect![[r#" - fn m() -> () + fn m() fn() "#]], ); } @@ -483,7 +483,7 @@ impl Trait for S {} fn foo() { let _ = ::$0 } "#, expect![[r#" - fn m() -> () + fn m() fn() "#]], ); } @@ -512,11 +512,11 @@ fn foo() { T::$0 } ta SubTy type SubTy; ta Ty type Ty; ct C2 const C2: (); - fn subfunc() -> () - me submethod(…) -> () + fn subfunc() fn() + me submethod(…) fn(&self) ct CONST const CONST: u8; - fn func() -> () - me method(…) -> () + fn func() fn() + me method(…) fn(&self) "#]], ); } @@ -552,11 +552,11 @@ impl Sub for Wrap { ta SubTy type SubTy; ta Ty type Ty; ct CONST const CONST: u8 = 0; - fn func() -> () - me method(…) -> () + fn func() fn() + me method(…) fn(&self) ct C2 const C2: () = (); - fn subfunc() -> () - me submethod(…) -> () + fn subfunc() fn() + me submethod(…) fn(&self) "#]], ); } @@ -573,8 +573,8 @@ impl T { fn bar() {} } fn main() { T::$0; } "#, expect![[r#" - fn foo() -> () - fn bar() -> () + fn foo() fn() + fn bar() fn() "#]], ); } @@ -589,7 +589,7 @@ macro_rules! foo { () => {} } fn main() { let _ = crate::$0 } "#, expect![[r##" - fn main() -> () + fn main() fn() ma foo!(…) #[macro_export] macro_rules! foo "##]], ); @@ -633,7 +633,7 @@ mod p { "#, expect![[r#" ct RIGHT_CONST - fn right_fn() -> () + fn right_fn() fn() st RightType "#]], ); @@ -680,8 +680,8 @@ fn main() { m!(self::f$0); } fn foo() {} "#, expect![[r#" - fn main() -> () - fn foo() -> () + fn main() fn() + fn foo() fn() "#]], ); } @@ -699,7 +699,7 @@ mod m { "#, expect![[r#" md z - fn z() -> () + fn z() fn() "#]], ); } @@ -719,7 +719,7 @@ fn foo() { } "#, expect![[r#" - fn new() -> HashMap + fn new() fn() -> HashMap "#]], ); } @@ -752,8 +752,8 @@ fn main() { } "#, expect![[r#" - fn main() -> () - fn foo(…) -> () + fn main() fn() + fn foo(…) fn(i32, i32) "#]], ); } @@ -776,7 +776,7 @@ impl Foo { expect![[r#" ev Bar () ev Baz () - me foo(…) -> () + me foo(…) fn(self) "#]], ); } @@ -800,7 +800,7 @@ impl u8 { "#, expect![[r#" ct MAX pub const MAX: Self = 255; - me func(…) -> () + me func(…) fn(self) "#]], ); } diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 044dfd160..e4bf4a043 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -139,7 +139,7 @@ fn quux(x: i32) { expect![[r#" lc y i32 lc x i32 - fn quux(…) -> () + fn quux(…) fn(i32) "#]], ); } @@ -161,7 +161,7 @@ fn quux() { expect![[r#" lc b i32 lc a - fn quux() -> () + fn quux() fn() "#]], ); } @@ -176,7 +176,7 @@ fn quux() { "#, expect![[r#" lc x - fn quux() -> () + fn quux() fn() "#]], ); } @@ -207,14 +207,14 @@ fn main() { r#"fn quux() { $0 }"#, expect![[r#" tp T - fn quux() -> () + fn quux() fn() "#]], ); check( r#"fn quux() { $0 }"#, expect![[r#" cp C - fn quux() -> () + fn quux() fn() "#]], ); } @@ -225,7 +225,7 @@ fn main() { check( r#"fn quux<'a>() { $0 }"#, expect![[r#" - fn quux() -> () + fn quux() fn() "#]], ); } @@ -263,7 +263,7 @@ fn quux() { $0 } "#, expect![[r#" st S - fn quux() -> () + fn quux() fn() en E "#]], ); @@ -316,7 +316,7 @@ mod m { } "#, expect![[r#" - fn quux() -> () + fn quux() fn() st Bar "#]], ); @@ -331,7 +331,7 @@ fn x() -> $0 "#, expect![[r#" st Foo - fn x() -> () + fn x() fn() "#]], ); } @@ -352,7 +352,7 @@ fn foo() { expect![[r#" lc bar i32 lc bar i32 - fn foo() -> () + fn foo() fn() "#]], ); } @@ -382,7 +382,7 @@ use prelude::*; mod prelude { struct Option; } "#, expect![[r#" - fn foo() -> () + fn foo() fn() md std st Option "#]], @@ -412,7 +412,7 @@ mod macros { } "#, expect![[r##" - fn f() -> () + fn f() fn() ma concat!(…) #[macro_export] macro_rules! concat md std "##]], @@ -439,7 +439,7 @@ use prelude::*; mod prelude { struct String; } "#, expect![[r#" - fn foo() -> () + fn foo() fn() md std md core st String @@ -470,7 +470,7 @@ fn main() { let v = $0 } expect![[r##" md m1 ma baz!(…) #[macro_export] macro_rules! baz - fn main() -> () + fn main() fn() md m2 ma bar!(…) macro_rules! bar ma foo!(…) macro_rules! foo @@ -486,7 +486,7 @@ macro_rules! foo { () => {} } fn foo() { $0 } "#, expect![[r#" - fn foo() -> () + fn foo() fn() ma foo!(…) macro_rules! foo "#]], ); @@ -500,7 +500,7 @@ macro_rules! foo { () => {} } fn main() { let x: $0 } "#, expect![[r#" - fn main() -> () + fn main() fn() ma foo!(…) macro_rules! foo "#]], ); @@ -514,7 +514,7 @@ macro_rules! foo { () => {} } fn main() { $0 } "#, expect![[r#" - fn main() -> () + fn main() fn() ma foo!(…) macro_rules! foo "#]], ); @@ -530,8 +530,8 @@ fn main() { } "#, expect![[r#" - fn frobnicate() -> () - fn main() -> () + fn frobnicate() fn() + fn main() fn() "#]], ); } @@ -549,7 +549,7 @@ fn quux(x: i32) { expect![[r#" lc y i32 lc x i32 - fn quux(…) -> () + fn quux(…) fn(i32) ma m!(…) macro_rules! m "#]], ); @@ -568,7 +568,7 @@ fn quux(x: i32) { expect![[r#" lc y i32 lc x i32 - fn quux(…) -> () + fn quux(…) fn(i32) ma m!(…) macro_rules! m "#]], ); @@ -587,7 +587,7 @@ fn quux(x: i32) { expect![[r#" lc y i32 lc x i32 - fn quux(…) -> () + fn quux(…) fn(i32) ma m!(…) macro_rules! m "#]], ); @@ -602,7 +602,7 @@ use spam::Quux; fn main() { $0 } "#, expect![[r#" - fn main() -> () + fn main() fn() ?? Quux "#]], ); @@ -680,7 +680,7 @@ fn main() { let foo: Foo = Q$0 } ev Foo::Baz () ev Foo::Quux () en Foo - fn main() -> () + fn main() fn() "#]], ) } @@ -695,7 +695,7 @@ fn f() -> m::E { V$0 } expect![[r#" ev m::E::V () md m - fn f() -> E + fn f() fn() -> E "#]], ) } diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs index 263554ecf..5b7ad38d5 100644 --- a/crates/ide_completion/src/lib.rs +++ b/crates/ide_completion/src/lib.rs @@ -230,7 +230,7 @@ fn foo() { bar.fo$0; } "#, - DetailAndDocumentation { detail: "-> ()", documentation: "Do the foo" }, + DetailAndDocumentation { detail: "fn(&self)", documentation: "Do the foo" }, ); } @@ -255,7 +255,7 @@ fn foo() { bar.fo$0; } "#, - DetailAndDocumentation { detail: "-> ()", documentation: " Do the foo" }, + DetailAndDocumentation { detail: "fn(&self)", documentation: " Do the foo" }, ); } @@ -273,7 +273,7 @@ fn bar() { for c in fo$0 } "#, - DetailAndDocumentation { detail: "-> &str", documentation: "Do the foo" }, + DetailAndDocumentation { detail: "fn() -> &str", documentation: "Do the foo" }, ); } } diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index db31896e5..d9bf52582 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs @@ -424,6 +424,44 @@ fn main() { Foo::Fo$0 } ); } + #[test] + fn fn_detail_includes_args_and_return_type() { + check( + r#" +fn foo(a: u32, b: u32, t: T) -> (u32, T) { (a, t) } + +fn main() { fo$0 } +"#, + expect![[r#" + [ + CompletionItem { + label: "foo(…)", + source_range: 68..70, + delete: 68..70, + insert: "foo(${1:a}, ${2:b}, ${3:t})$0", + kind: SymbolKind( + Function, + ), + lookup: "foo", + detail: "fn(u32, u32, T) -> (u32, T)", + trigger_call_info: true, + }, + CompletionItem { + label: "main()", + source_range: 68..70, + delete: 68..70, + insert: "main()$0", + kind: SymbolKind( + Function, + ), + lookup: "main", + detail: "fn()", + }, + ] + "#]], + ); + } + #[test] fn enum_detail_just_parentheses_for_unit() { check( @@ -501,7 +539,7 @@ fn main() { let _: m::Spam = S$0 } Function, ), lookup: "main", - detail: "-> ()", + detail: "fn()", }, ] "#]], @@ -530,7 +568,7 @@ fn main() { som$0 } Function, ), lookup: "main", - detail: "-> ()", + detail: "fn()", }, CompletionItem { label: "something_deprecated()", @@ -541,7 +579,7 @@ fn main() { som$0 } Function, ), lookup: "something_deprecated", - detail: "-> ()", + detail: "fn()", deprecated: true, }, CompletionItem { @@ -553,7 +591,7 @@ fn main() { som$0 } Function, ), lookup: "something_else_deprecated", - detail: "-> ()", + detail: "fn()", deprecated: true, }, ] @@ -604,7 +642,7 @@ impl S { insert: "bar()$0", kind: Method, lookup: "bar", - detail: "-> ()", + detail: "fn(self)", documentation: Documentation( "Method docs", ), @@ -704,7 +742,7 @@ fn foo(s: S) { s.$0 } insert: "the_method()$0", kind: Method, lookup: "the_method", - detail: "-> ()", + detail: "fn(&self)", }, ] "#]], @@ -954,7 +992,7 @@ fn main() { Function, ), lookup: "foo", - detail: "-> ()", + detail: "fn(&mut S)", trigger_call_info: true, }, CompletionItem { @@ -966,7 +1004,7 @@ fn main() { Function, ), lookup: "main", - detail: "-> ()", + detail: "fn()", }, CompletionItem { label: "s", diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs index f4dabe3d1..e154d6302 100644 --- a/crates/ide_completion/src/render/function.rs +++ b/crates/ide_completion/src/render/function.rs @@ -2,6 +2,7 @@ use hir::{HasSource, HirDisplay, Type}; use ide_db::SymbolKind; +use itertools::Itertools; use syntax::ast::Fn; use crate::{ @@ -59,8 +60,34 @@ impl<'a> FunctionRender<'a> { } fn detail(&self) -> String { - let ty = self.func.ret_type(self.ctx.db()); - format!("-> {}", ty.display(self.ctx.db())) + let params = if let Some(self_param) = self.func.self_param(self.ctx.db()) { + let params = self + .func + .assoc_fn_params(self.ctx.db()) + .into_iter() + .skip(1) // skip the self param because we are manually handling that + .map(|p| p.ty().display(self.ctx.db()).to_string()); + + std::iter::once(self_param.display(self.ctx.db()).to_owned()).chain(params).join(", ") + } else { + let params = self + .func + .assoc_fn_params(self.ctx.db()) + .into_iter() + .map(|p| p.ty().display(self.ctx.db()).to_string()) + .join(", "); + params + }; + + let ret_ty = self.func.ret_type(self.ctx.db()); + let ret = if ret_ty.is_unit() { + // Omit the `-> ()` for unit return types + String::new() + } else { + format!(" -> {}", ret_ty.display(self.ctx.db())) + }; + + format!("fn({}){}", params, ret) } fn add_arg(&self, arg: &str, ty: &Type) -> String { -- cgit v1.2.3 From d5f0f58e6330efd8200f93a6904caafc600a904e Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Fri, 12 Mar 2021 13:46:40 -0800 Subject: add params_display and ty_display --- crates/ide_completion/src/render/function.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs index e154d6302..b6b67e7a7 100644 --- a/crates/ide_completion/src/render/function.rs +++ b/crates/ide_completion/src/render/function.rs @@ -60,7 +60,19 @@ impl<'a> FunctionRender<'a> { } fn detail(&self) -> String { - let params = if let Some(self_param) = self.func.self_param(self.ctx.db()) { + let ret_ty = self.func.ret_type(self.ctx.db()); + let ret = if ret_ty.is_unit() { + // Omit the return type if it is the unit type + String::new() + } else { + format!(" {}", self.ty_display()) + }; + + format!("fn({}){}", self.params_display(), ret) + } + + fn params_display(&self) -> String { + if let Some(self_param) = self.func.self_param(self.ctx.db()) { let params = self .func .assoc_fn_params(self.ctx.db()) @@ -77,17 +89,13 @@ impl<'a> FunctionRender<'a> { .map(|p| p.ty().display(self.ctx.db()).to_string()) .join(", "); params - }; + } + } + fn ty_display(&self) -> String { let ret_ty = self.func.ret_type(self.ctx.db()); - let ret = if ret_ty.is_unit() { - // Omit the `-> ()` for unit return types - String::new() - } else { - format!(" -> {}", ret_ty.display(self.ctx.db())) - }; - format!("fn({}){}", params, ret) + format!("-> {}", ret_ty.display(self.ctx.db())) } fn add_arg(&self, arg: &str, ty: &Type) -> String { -- cgit v1.2.3 From ef48d1ca3bfb512c245d9e9bdc73d0d5a5f79740 Mon Sep 17 00:00:00 2001 From: oxalica Date: Sun, 14 Mar 2021 01:07:05 +0800 Subject: Add test for hover of macro expanded function --- crates/ide/src/hover.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index ea45086ce..f872b68cf 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -3657,4 +3657,42 @@ cosnt _: &str$0 = ""; }"#; "#]], ); } + + #[test] + fn hover_macro_expanded_function() { + check( + r#" +struct S<'a, T>(&'a T); +trait Clone {} +macro_rules! foo { + () => { + fn bar<'t, T: Clone + 't>(s: &mut S<'t, T>, t: u32) -> *mut u32 where + 't: 't + 't, + for<'a> T: Clone + 'a + { 0 as _ } + }; +} + +foo!(); + +fn main() { + bar$0; +} +"#, + expect![[r#" + *bar* + + ```rust + test + ``` + + ```rust + fn bar<'t, T: Clone + 't>(s: &mut S<'t, T>, t: u32) -> *mut u32 + where + 't: 't + 't, + for<'a> T: Clone + 'a, + ``` + "#]], + ) + } } -- cgit v1.2.3 From b9c172a977135760006b6222820ac7240be67d58 Mon Sep 17 00:00:00 2001 From: oxalica Date: Sun, 14 Mar 2021 17:36:04 +0800 Subject: Collect HirDisplay impls to a single file --- crates/hir/src/display.rs | 25 +++++++++++++++++++++++++ crates/hir/src/lib.rs | 22 ++-------------------- 2 files changed, 27 insertions(+), 20 deletions(-) create mode 100644 crates/hir/src/display.rs diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs new file mode 100644 index 000000000..86f48256e --- /dev/null +++ b/crates/hir/src/display.rs @@ -0,0 +1,25 @@ +//! HirDisplay implementations for various hir types. +use hir_ty::display::{ + write_bounds_like_dyn_trait_with_prefix, HirDisplay, HirDisplayError, HirFormatter, +}; + +use crate::{Substs, Type, TypeParam}; + +impl HirDisplay for Type { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + self.ty.value.hir_fmt(f) + } +} + +impl HirDisplay for TypeParam { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + write!(f, "{}", self.name(f.db))?; + let bounds = f.db.generic_predicates_for_param(self.id); + let substs = Substs::type_params(f.db, self.id.parent); + let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::>(); + if !(predicates.is_empty() || f.omit_verbose_types()) { + write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; + } + Ok(()) + } +} diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c5161dadd..469ed5b5e 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -29,6 +29,8 @@ mod has_source; pub mod diagnostics; pub mod db; +mod display; + use std::{iter, sync::Arc}; use arrayvec::ArrayVec; @@ -50,7 +52,6 @@ use hir_def::{ use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; use hir_ty::{ autoderef, - display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, method_resolution::{self, TyFingerprint}, to_assoc_type_id, traits::{FnTrait, Solution, SolutionVariables}, @@ -1412,19 +1413,6 @@ impl TypeParam { } } -impl HirDisplay for TypeParam { - fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { - write!(f, "{}", self.name(f.db))?; - let bounds = f.db.generic_predicates_for_param(self.id); - let substs = Substs::type_params(f.db, self.id.parent); - let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::>(); - if !(predicates.is_empty() || f.omit_verbose_types()) { - write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; - } - Ok(()) - } -} - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct LifetimeParam { pub(crate) id: LifetimeParamId, @@ -2054,12 +2042,6 @@ impl Type { } } -impl HirDisplay for Type { - fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { - self.ty.value.hir_fmt(f) - } -} - // FIXME: closures #[derive(Debug)] pub struct Callable { -- cgit v1.2.3 From 2bb8956a102cb2efbea35e414a8214fba2efcaf6 Mon Sep 17 00:00:00 2001 From: oxalica Date: Sun, 14 Mar 2021 18:00:11 +0800 Subject: Introduce FunctionQualifier for hir::FunctionData --- crates/hir/src/lib.rs | 2 +- crates/hir_def/src/data.rs | 10 +++++----- crates/hir_def/src/item_tree.rs | 15 ++++++++++++--- crates/hir_def/src/item_tree/lower.rs | 27 +++++++++++++++++++++++---- crates/hir_ty/src/diagnostics/decl_check.rs | 2 +- crates/hir_ty/src/diagnostics/unsafe_check.rs | 6 +++--- 6 files changed, 45 insertions(+), 17 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 469ed5b5e..0d0e757fc 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -844,7 +844,7 @@ impl Function { } pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { - db.function_data(self.id).is_unsafe + db.function_data(self.id).qualifier.is_unsafe } pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index aea53d527..b09da0697 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -9,7 +9,7 @@ use crate::{ attr::Attrs, body::Expander, db::DefDatabase, - item_tree::{AssocItem, ItemTreeId, ModItem}, + item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem}, type_ref::{TypeBound, TypeRef}, visibility::RawVisibility, AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, @@ -26,9 +26,9 @@ pub struct FunctionData { /// can be called as a method. pub has_self_param: bool, pub has_body: bool, - pub is_unsafe: bool, + pub qualifier: FunctionQualifier, + pub is_in_extern_block: bool, pub is_varargs: bool, - pub is_extern: bool, pub visibility: RawVisibility, } @@ -46,9 +46,9 @@ impl FunctionData { attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), has_self_param: func.has_self_param, has_body: func.has_body, - is_unsafe: func.is_unsafe, + qualifier: func.qualifier.clone(), + is_in_extern_block: func.is_in_extern_block, is_varargs: func.is_varargs, - is_extern: func.is_extern, visibility: item_tree[func.visibility].clone(), }) } diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 09bcb10dc..d8f22d442 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -24,7 +24,7 @@ use la_arena::{Arena, Idx, RawIdx}; use profile::Count; use rustc_hash::FxHashMap; use smallvec::SmallVec; -use syntax::{ast, match_ast, SyntaxKind}; +use syntax::{ast, match_ast, SmolStr, SyntaxKind}; use crate::{ attr::{Attrs, RawAttrs}, @@ -551,16 +551,25 @@ pub struct Function { pub generic_params: GenericParamsId, pub has_self_param: bool, pub has_body: bool, - pub is_unsafe: bool, + pub qualifier: FunctionQualifier, /// Whether the function is located in an `extern` block (*not* whether it is an /// `extern "abi" fn`). - pub is_extern: bool, + pub is_in_extern_block: bool, pub params: Box<[Idx]>, pub is_varargs: bool, pub ret_type: Idx, pub ast_id: FileAstId, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct FunctionQualifier { + pub is_default: bool, + pub is_const: bool, + pub is_async: bool, + pub is_unsafe: bool, + pub abi: Option, +} + #[derive(Debug, Clone, Eq, PartialEq)] pub struct Struct { pub name: Name, diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 240fdacf9..6b5438dc9 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -391,14 +391,33 @@ impl Ctx { let has_body = func.body().is_some(); let ast_id = self.source_ast_id_map.ast_id(func); + let qualifier = FunctionQualifier { + is_default: func.default_token().is_some(), + is_const: func.const_token().is_some(), + is_async: func.async_token().is_some(), + is_unsafe: func.unsafe_token().is_some(), + abi: func.abi().map(|abi| { + // FIXME: Abi::abi() -> Option? + match abi.syntax().last_token() { + Some(tok) if tok.kind() == SyntaxKind::STRING => { + // FIXME: Better way to unescape? + tok.text().trim_matches('"').into() + } + _ => { + // `extern` default to be `extern "C"`. + "C".into() + } + } + }), + }; let mut res = Function { name, visibility, generic_params: GenericParamsId::EMPTY, has_self_param, has_body, - is_unsafe: func.unsafe_token().is_some(), - is_extern: false, + qualifier, + is_in_extern_block: false, params, is_varargs, ret_type, @@ -608,8 +627,8 @@ impl Ctx { ast::ExternItem::Fn(ast) => { let func_id = self.lower_function(&ast)?; let func = &mut self.data().functions[func_id.index]; - func.is_unsafe = is_intrinsic_fn_unsafe(&func.name); - func.is_extern = true; + func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name); + func.is_in_extern_block = true; func_id.into() } ast::ExternItem::Static(ast) => { diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs index 3605ca581..982ad5b9e 100644 --- a/crates/hir_ty/src/diagnostics/decl_check.rs +++ b/crates/hir_ty/src/diagnostics/decl_check.rs @@ -91,7 +91,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { fn validate_func(&mut self, func: FunctionId) { let data = self.db.function_data(func); - if data.is_extern { + if data.is_in_extern_block { cov_mark::hit!(extern_func_incorrect_case_ignored); return; } diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs index 20bb64827..44a7e5506 100644 --- a/crates/hir_ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs @@ -32,7 +32,7 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> { let def = self.owner.into(); let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); let is_unsafe = match self.owner { - DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe, + DefWithBodyId::FunctionId(it) => db.function_data(it).qualifier.is_unsafe, DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false, }; if is_unsafe @@ -86,7 +86,7 @@ fn walk_unsafe( match expr { &Expr::Call { callee, .. } => { if let Some(func) = infer[callee].as_fn_def(db) { - if db.function_data(func).is_unsafe { + if db.function_data(func).qualifier.is_unsafe { unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); } } @@ -103,7 +103,7 @@ fn walk_unsafe( Expr::MethodCall { .. } => { if infer .method_resolution(current) - .map(|func| db.function_data(func).is_unsafe) + .map(|func| db.function_data(func).qualifier.is_unsafe) .unwrap_or(false) { unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); -- cgit v1.2.3 From ef416e0154767619fcbfa0d1682b28bd338a8ce9 Mon Sep 17 00:00:00 2001 From: oxalica Date: Sun, 14 Mar 2021 20:03:39 +0800 Subject: Impl HirDisplay for function hover message --- crates/hir/src/display.rs | 234 ++++++++++++++++++++++++++++++++++++++++++- crates/hir/src/lib.rs | 17 +++- crates/hir_def/src/path.rs | 11 +- crates/hir_ty/src/display.rs | 203 +++++++++++++++++++++++++++++++++++-- crates/ide/src/hover.rs | 10 +- 5 files changed, 461 insertions(+), 14 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 86f48256e..ae08e2584 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -1,9 +1,120 @@ //! HirDisplay implementations for various hir types. +use hir_def::{ + generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, + type_ref::{TypeBound, TypeRef}, + GenericDefId, +}; use hir_ty::display::{ - write_bounds_like_dyn_trait_with_prefix, HirDisplay, HirDisplayError, HirFormatter, + write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError, + HirFormatter, }; +use syntax::ast::{self, NameOwner}; + +use crate::{Function, HasVisibility, Substs, Type, TypeParam}; + +impl HirDisplay for Function { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + let data = f.db.function_data(self.id); + write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; + let qual = &data.qualifier; + if qual.is_default { + write!(f, "default ")?; + } + if qual.is_const { + write!(f, "const ")?; + } + if qual.is_async { + write!(f, "async ")?; + } + if qual.is_unsafe { + write!(f, "unsafe ")?; + } + if let Some(abi) = &qual.abi { + // FIXME: String escape? + write!(f, "extern \"{}\" ", abi)?; + } + write!(f, "fn {}", data.name)?; + + write_generic_params(GenericDefId::FunctionId(self.id), f)?; + + write!(f, "(")?; -use crate::{Substs, Type, TypeParam}; + let write_self_param = |ty: &TypeRef, f: &mut HirFormatter| match ty { + TypeRef::Path(p) if p.is_self_type() => write!(f, "self"), + TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner,TypeRef::Path(p) if p.is_self_type()) => + { + write!(f, "&")?; + if let Some(lifetime) = lifetime { + write!(f, "{} ", lifetime.name)?; + } + if let hir_def::type_ref::Mutability::Mut = mut_ { + write!(f, "mut ")?; + } + write!(f, "self") + } + _ => { + write!(f, "self: ")?; + ty.hir_fmt(f) + } + }; + + let mut first = true; + for (param, type_ref) in self.assoc_fn_params(f.db).into_iter().zip(&data.params) { + if !first { + write!(f, ", ")?; + } else { + first = false; + if data.has_self_param { + write_self_param(type_ref, f)?; + continue; + } + } + match param.pattern_source(f.db) { + Some(ast::Pat::IdentPat(p)) if p.name().is_some() => { + write!(f, "{}: ", p.name().unwrap())? + } + _ => write!(f, "_: ")?, + } + // FIXME: Use resolved `param.ty` or raw `type_ref`? + // The former will ignore lifetime arguments currently. + type_ref.hir_fmt(f)?; + } + write!(f, ")")?; + + // `FunctionData::ret_type` will be `::core::future::Future` for async fns. + // Use ugly pattern match to strip the Future trait. + // Better way? + let ret_type = if !qual.is_async { + &data.ret_type + } else { + match &data.ret_type { + TypeRef::ImplTrait(bounds) => match &bounds[0] { + TypeBound::Path(path) => { + path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings + [0] + .type_ref + .as_ref() + .unwrap() + } + _ => panic!("Async fn ret_type should be impl Future"), + }, + _ => panic!("Async fn ret_type should be impl Future"), + } + }; + + match ret_type { + TypeRef::Tuple(tup) if tup.is_empty() => {} + ty => { + write!(f, " -> ")?; + ty.hir_fmt(f)?; + } + } + + write_where_clause(GenericDefId::FunctionId(self.id), f)?; + + Ok(()) + } +} impl HirDisplay for Type { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { @@ -23,3 +134,122 @@ impl HirDisplay for TypeParam { Ok(()) } } + +fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + let params = f.db.generic_params(def); + if params.lifetimes.is_empty() && params.types.is_empty() && params.consts.is_empty() { + return Ok(()); + } + write!(f, "<")?; + + let mut first = true; + let mut delim = |f: &mut HirFormatter| { + if first { + first = false; + Ok(()) + } else { + write!(f, ", ") + } + }; + for (_, lifetime) in params.lifetimes.iter() { + delim(f)?; + write!(f, "{}", lifetime.name)?; + } + for (_, ty) in params.types.iter() { + if ty.provenance != TypeParamProvenance::TypeParamList { + continue; + } + if let Some(name) = &ty.name { + delim(f)?; + write!(f, "{}", name)?; + if let Some(default) = &ty.default { + write!(f, " = ")?; + default.hir_fmt(f)?; + } + } + } + for (_, konst) in params.consts.iter() { + delim(f)?; + write!(f, "const {}: ", konst.name)?; + konst.ty.hir_fmt(f)?; + } + + write!(f, ">")?; + Ok(()) +} + +fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + let params = f.db.generic_params(def); + if params.where_predicates.is_empty() { + return Ok(()); + } + + let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target { + WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f), + WherePredicateTypeTarget::TypeParam(id) => match ¶ms.types[*id].name { + Some(name) => write!(f, "{}", name), + None => write!(f, "{{unnamed}}"), + }, + }; + + write!(f, "\nwhere")?; + + for (pred_idx, pred) in params.where_predicates.iter().enumerate() { + let prev_pred = + if pred_idx == 0 { None } else { Some(¶ms.where_predicates[pred_idx - 1]) }; + + let new_predicate = |f: &mut HirFormatter| { + write!(f, "{}", if pred_idx == 0 { "\n " } else { ",\n " }) + }; + + match pred { + WherePredicate::TypeBound { target, bound } => { + if matches!(prev_pred, Some(WherePredicate::TypeBound { target: target_, .. }) if target_ == target) + { + write!(f, " + ")?; + } else { + new_predicate(f)?; + write_target(target, f)?; + write!(f, ": ")?; + } + bound.hir_fmt(f)?; + } + WherePredicate::Lifetime { target, bound } => { + if matches!(prev_pred, Some(WherePredicate::Lifetime { target: target_, .. }) if target_ == target) + { + write!(f, " + {}", bound.name)?; + } else { + new_predicate(f)?; + write!(f, "{}: {}", target.name, bound.name)?; + } + } + WherePredicate::ForLifetime { lifetimes, target, bound } => { + if matches!( + prev_pred, + Some(WherePredicate::ForLifetime { lifetimes: lifetimes_, target: target_, .. }) + if lifetimes_ == lifetimes && target_ == target, + ) { + write!(f, " + ")?; + } else { + new_predicate(f)?; + write!(f, "for<")?; + for (idx, lifetime) in lifetimes.iter().enumerate() { + if idx != 0 { + write!(f, ", ")?; + } + write!(f, "{}", lifetime)?; + } + write!(f, "> ")?; + write_target(target, f)?; + write!(f, ": ")?; + } + bound.hir_fmt(f)?; + } + } + } + + // End of final predicate. There must be at least one predicate here. + write!(f, ",")?; + + Ok(()) +} diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 0d0e757fc..476fdb132 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -822,7 +822,8 @@ impl Function { db.function_data(self.id) .params .iter() - .map(|type_ref| { + .enumerate() + .map(|(idx, type_ref)| { let ty = Type { krate, ty: InEnvironment { @@ -830,7 +831,7 @@ impl Function { environment: environment.clone(), }, }; - Param { ty } + Param { func: self, ty, idx } }) .collect() } @@ -893,6 +894,9 @@ impl From for Access { #[derive(Debug)] pub struct Param { + func: Function, + /// The index in parameter list, including self parameter. + idx: usize, ty: Type, } @@ -900,6 +904,15 @@ impl Param { pub fn ty(&self) -> &Type { &self.ty } + + pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option { + let params = self.func.source(db)?.value.param_list()?; + if params.self_param().is_some() { + params.params().nth(self.idx.checked_sub(1)?)?.pat() + } else { + params.params().nth(self.idx)?.pat() + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index 0e60dc2b6..8c923bb7b 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs @@ -9,7 +9,10 @@ use std::{ use crate::{body::LowerCtx, type_ref::LifetimeRef}; use base_db::CrateId; -use hir_expand::{hygiene::Hygiene, name::Name}; +use hir_expand::{ + hygiene::Hygiene, + name::{name, Name}, +}; use syntax::ast; use crate::{ @@ -209,6 +212,12 @@ impl Path { }; Some(res) } + + pub fn is_self_type(&self) -> bool { + self.type_anchor.is_none() + && self.generic_args == &[None] + && self.mod_path.as_ident() == Some(&name!(Self)) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index c1062387e..c572bb114 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -5,7 +5,13 @@ use std::{borrow::Cow, fmt}; use arrayvec::ArrayVec; use chalk_ir::Mutability; use hir_def::{ - db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, + db::DefDatabase, + find_path, + generics::TypeParamProvenance, + item_scope::ItemInNs, + path::{GenericArg, Path, PathKind}, + type_ref::{TypeBound, TypeRef}, + visibility::Visibility, AssocContainerId, Lookup, ModuleId, TraitId, }; use hir_expand::name::Name; @@ -232,7 +238,7 @@ where const TYPE_HINT_TRUNCATION: &str = "…"; -impl HirDisplay for &Ty { +impl HirDisplay for &'_ T { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { HirDisplay::hir_fmt(*self, f) } @@ -761,12 +767,6 @@ impl HirDisplay for TraitRef { } } -impl HirDisplay for &GenericPredicate { - fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { - HirDisplay::hir_fmt(*self, f) - } -} - impl HirDisplay for GenericPredicate { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { if f.should_truncate() { @@ -825,3 +825,190 @@ impl HirDisplay for Obligation { } } } + +pub fn write_visibility( + module_id: ModuleId, + vis: Visibility, + f: &mut HirFormatter, +) -> Result<(), HirDisplayError> { + match vis { + Visibility::Public => write!(f, "pub "), + Visibility::Module(vis_id) => { + let def_map = module_id.def_map(f.db.upcast()); + let root_module_id = def_map.module_id(def_map.root()); + if vis_id == module_id { + // pub(self) or omitted + Ok(()) + } else if root_module_id == vis_id { + write!(f, "pub(crate) ") + } else if module_id.containing_module(f.db.upcast()) == Some(vis_id) { + write!(f, "pub(super) ") + } else { + write!(f, "pub(in ...) ") + } + } + } +} + +impl HirDisplay for TypeRef { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + match self { + TypeRef::Never => write!(f, "!")?, + TypeRef::Placeholder => write!(f, "_")?, + TypeRef::Tuple(elems) => { + write!(f, "(")?; + f.write_joined(elems, ", ")?; + if elems.len() == 1 { + write!(f, ",")?; + } + write!(f, ")")?; + } + TypeRef::Path(path) => path.hir_fmt(f)?, + TypeRef::RawPtr(inner, mutability) => { + let mutability = match mutability { + hir_def::type_ref::Mutability::Shared => "*const ", + hir_def::type_ref::Mutability::Mut => "*mut ", + }; + write!(f, "{}", mutability)?; + inner.hir_fmt(f)?; + } + TypeRef::Reference(inner, lifetime, mutability) => { + let mutability = match mutability { + hir_def::type_ref::Mutability::Shared => "", + hir_def::type_ref::Mutability::Mut => "mut ", + }; + write!(f, "&")?; + if let Some(lifetime) = lifetime { + write!(f, "{} ", lifetime.name)?; + } + write!(f, "{}", mutability)?; + inner.hir_fmt(f)?; + } + TypeRef::Array(inner) => { + write!(f, "[")?; + inner.hir_fmt(f)?; + // FIXME: Array length? + write!(f, "; _]")?; + } + TypeRef::Slice(inner) => { + write!(f, "[")?; + inner.hir_fmt(f)?; + write!(f, "]")?; + } + TypeRef::Fn(tys, is_varargs) => { + // FIXME: Function pointer qualifiers. + write!(f, "fn(")?; + f.write_joined(&tys[..tys.len() - 1], ", ")?; + if *is_varargs { + write!(f, "{}...", if tys.len() == 1 { "" } else { ", " })?; + } + write!(f, ")")?; + let ret_ty = tys.last().unwrap(); + match ret_ty { + TypeRef::Tuple(tup) if tup.is_empty() => {} + _ => { + write!(f, " -> ")?; + ret_ty.hir_fmt(f)?; + } + } + } + TypeRef::ImplTrait(bounds) => { + write!(f, "impl ")?; + f.write_joined(bounds, " + ")?; + } + TypeRef::DynTrait(bounds) => { + write!(f, "dyn ")?; + f.write_joined(bounds, " + ")?; + } + TypeRef::Error => write!(f, "{{error}}")?, + } + Ok(()) + } +} + +impl HirDisplay for TypeBound { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + match self { + TypeBound::Path(path) => path.hir_fmt(f), + TypeBound::Lifetime(lifetime) => write!(f, "{}", lifetime.name), + TypeBound::Error => write!(f, "{{error}}"), + } + } +} + +impl HirDisplay for Path { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + match (self.type_anchor(), self.kind()) { + (Some(anchor), _) => { + write!(f, "<")?; + anchor.hir_fmt(f)?; + write!(f, ">")?; + } + (_, PathKind::Plain) => {} + (_, PathKind::Abs) => write!(f, "::")?, + (_, PathKind::Crate) => write!(f, "crate")?, + (_, PathKind::Super(0)) => write!(f, "self")?, + (_, PathKind::Super(n)) => { + write!(f, "super")?; + for _ in 0..*n { + write!(f, "::super")?; + } + } + (_, PathKind::DollarCrate(_)) => write!(f, "{{extern_crate}}")?, + } + + for (seg_idx, segment) in self.segments().iter().enumerate() { + if seg_idx != 0 { + write!(f, "::")?; + } + write!(f, "{}", segment.name)?; + if let Some(generic_args) = segment.args_and_bindings { + // We should be in type context, so format as `Foo` instead of `Foo::`. + // Do we actually format expressions? + write!(f, "<")?; + let mut first = true; + for arg in &generic_args.args { + if first { + first = false; + if generic_args.has_self_type { + // FIXME: Convert to `` form. + write!(f, "Self = ")?; + } + } else { + write!(f, ", ")?; + } + arg.hir_fmt(f)?; + } + for binding in &generic_args.bindings { + if first { + first = false; + } else { + write!(f, ", ")?; + } + write!(f, "{}", binding.name)?; + match &binding.type_ref { + Some(ty) => { + write!(f, " = ")?; + ty.hir_fmt(f)? + } + None => { + write!(f, ": ")?; + f.write_joined(&binding.bounds, " + ")?; + } + } + } + write!(f, ">")?; + } + } + Ok(()) + } +} + +impl HirDisplay for GenericArg { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + match self { + GenericArg::Type(ty) => ty.hir_fmt(f), + GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name), + } + } +} diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index f872b68cf..1e4c247c0 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -354,7 +354,7 @@ fn hover_for_definition( }, mod_path, ), - ModuleDef::Function(it) => from_def_source(db, it, mod_path), + ModuleDef::Function(it) => from_hir_fmt(db, it, mod_path), ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path), ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it, mod_path), ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it, mod_path), @@ -383,6 +383,14 @@ fn hover_for_definition( }, }; + fn from_hir_fmt(db: &RootDatabase, def: D, mod_path: Option) -> Option + where + D: HasAttrs + HirDisplay, + { + let label = def.display(db).to_string(); + from_def_source_labeled(db, def, Some(label), mod_path) + } + fn from_def_source(db: &RootDatabase, def: D, mod_path: Option) -> Option where D: HasSource + HasAttrs + Copy, -- cgit v1.2.3 From 87171238c6c528c421f06de8cd7e41ed3b6ff57a Mon Sep 17 00:00:00 2001 From: oxalica Date: Tue, 16 Mar 2021 00:05:03 +0800 Subject: Use hir formatter more --- crates/hir/src/display.rs | 180 +++++++++++++++++++++++++++++++++- crates/hir/src/lib.rs | 36 ++++++- crates/hir_def/src/adt.rs | 10 +- crates/hir_def/src/data.rs | 12 ++- crates/hir_def/src/item_tree.rs | 4 +- crates/hir_def/src/item_tree/lower.rs | 8 +- crates/hir_ty/src/traits/chalk.rs | 2 +- crates/ide/src/hover.rs | 59 ++++------- 8 files changed, 258 insertions(+), 53 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index ae08e2584..0640712de 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -1,8 +1,9 @@ //! HirDisplay implementations for various hir types. use hir_def::{ + adt::VariantData, generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, type_ref::{TypeBound, TypeRef}, - GenericDefId, + AdtId, GenericDefId, }; use hir_ty::display::{ write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError, @@ -10,7 +11,10 @@ use hir_ty::display::{ }; use syntax::ast::{self, NameOwner}; -use crate::{Function, HasVisibility, Substs, Type, TypeParam}; +use crate::{ + Const, ConstParam, Enum, Field, Function, HasVisibility, Module, Static, Struct, Substs, Trait, + Type, TypeAlias, TypeParam, Union, Variant, +}; impl HirDisplay for Function { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { @@ -116,6 +120,91 @@ impl HirDisplay for Function { } } +impl HirDisplay for Struct { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; + write!(f, "struct ")?; + write!(f, "{}", self.name(f.db))?; + let def_id = GenericDefId::AdtId(AdtId::StructId(self.id)); + write_generic_params(def_id, f)?; + write_where_clause(def_id, f)?; + Ok(()) + } +} + +impl HirDisplay for Enum { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; + write!(f, "enum ")?; + write!(f, "{}", self.name(f.db))?; + let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id)); + write_generic_params(def_id, f)?; + write_where_clause(def_id, f)?; + Ok(()) + } +} + +impl HirDisplay for Union { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; + write!(f, "union ")?; + write!(f, "{}", self.name(f.db))?; + let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id)); + write_generic_params(def_id, f)?; + write_where_clause(def_id, f)?; + Ok(()) + } +} + +impl HirDisplay for Field { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?; + write!(f, "{}: ", self.name(f.db))?; + self.signature_ty(f.db).hir_fmt(f) + } +} + +impl HirDisplay for Variant { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + write!(f, "{}", self.name(f.db))?; + let data = self.variant_data(f.db); + match &*data { + VariantData::Unit => {} + VariantData::Tuple(fields) => { + write!(f, "(")?; + let mut first = true; + for (_, field) in fields.iter() { + if first { + first = false; + } else { + write!(f, ", ")?; + } + // Enum variant fields must be pub. + field.type_ref.hir_fmt(f)?; + } + write!(f, ")")?; + } + VariantData::Record(fields) => { + write!(f, " {{")?; + let mut first = true; + for (_, field) in fields.iter() { + if first { + first = false; + write!(f, " ")?; + } else { + write!(f, ", ")?; + } + // Enum variant fields must be pub. + write!(f, "{}: ", field.name)?; + field.type_ref.hir_fmt(f)?; + } + write!(f, " }}")?; + } + } + Ok(()) + } +} + impl HirDisplay for Type { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { self.ty.value.hir_fmt(f) @@ -135,6 +224,13 @@ impl HirDisplay for TypeParam { } } +impl HirDisplay for ConstParam { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + write!(f, "const {}: ", self.name(f.db))?; + self.ty(f.db).hir_fmt(f) + } +} + fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> { let params = f.db.generic_params(def); if params.lifetimes.is_empty() && params.types.is_empty() && params.consts.is_empty() { @@ -253,3 +349,83 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), Hir Ok(()) } + +impl HirDisplay for Const { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; + let data = f.db.const_data(self.id); + write!(f, "const ")?; + match &data.name { + Some(name) => write!(f, "{}: ", name)?, + None => write!(f, "_: ")?, + } + data.type_ref.hir_fmt(f)?; + Ok(()) + } +} + +impl HirDisplay for Static { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; + let data = f.db.static_data(self.id); + write!(f, "static ")?; + if data.mutable { + write!(f, "mut ")?; + } + match &data.name { + Some(name) => write!(f, "{}: ", name)?, + None => write!(f, "_: ")?, + } + data.type_ref.hir_fmt(f)?; + Ok(()) + } +} + +impl HirDisplay for Trait { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; + let data = f.db.trait_data(self.id); + if data.is_unsafe { + write!(f, "unsafe ")?; + } + if data.is_auto { + write!(f, "auto ")?; + } + write!(f, "trait {}", data.name)?; + let def_id = GenericDefId::TraitId(self.id); + write_generic_params(def_id, f)?; + if !data.bounds.is_empty() { + write!(f, ": ")?; + f.write_joined(&*data.bounds, " + ")?; + } + write_where_clause(def_id, f)?; + Ok(()) + } +} + +impl HirDisplay for TypeAlias { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; + let data = f.db.type_alias_data(self.id); + write!(f, "type {}", data.name)?; + if !data.bounds.is_empty() { + write!(f, ": ")?; + f.write_joined(&data.bounds, " + ")?; + } + if let Some(ty) = &data.type_ref { + write!(f, " = ")?; + ty.hir_fmt(f)?; + } + Ok(()) + } +} + +impl HirDisplay for Module { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + // FIXME: Module doesn't have visibility saved in data. + match self.name(f.db) { + Some(name) => write!(f, "mod {}", name), + None => write!(f, "mod {{unnamed}}"), + } + } +} diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 476fdb132..98135602a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -572,6 +572,12 @@ impl Struct { } } +impl HasVisibility for Struct { + fn visibility(&self, db: &dyn HirDatabase) -> Visibility { + db.struct_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Union { pub(crate) id: UnionId, @@ -604,6 +610,12 @@ impl Union { } } +impl HasVisibility for Union { + fn visibility(&self, db: &dyn HirDatabase) -> Visibility { + db.union_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Enum { pub(crate) id: EnumId, @@ -631,6 +643,12 @@ impl Enum { } } +impl HasVisibility for Enum { + fn visibility(&self, db: &dyn HirDatabase) -> Visibility { + db.enum_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Variant { pub(crate) parent: Enum, @@ -962,6 +980,10 @@ impl Const { pub fn name(self, db: &dyn HirDatabase) -> Option { db.const_data(self.id).name.clone() } + + pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef { + db.const_data(self.id).type_ref.clone() + } } impl HasVisibility for Const { @@ -995,6 +1017,12 @@ impl Static { } } +impl HasVisibility for Static { + fn visibility(&self, db: &dyn HirDatabase) -> Visibility { + db.static_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Trait { pub(crate) id: TraitId, @@ -1014,7 +1042,13 @@ impl Trait { } pub fn is_auto(self, db: &dyn HirDatabase) -> bool { - db.trait_data(self.id).auto + db.trait_data(self.id).is_auto + } +} + +impl HasVisibility for Trait { + fn visibility(&self, db: &dyn HirDatabase) -> Visibility { + db.trait_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) } } diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs index efbde17d8..1b9bb8235 100644 --- a/crates/hir_def/src/adt.rs +++ b/crates/hir_def/src/adt.rs @@ -31,12 +31,14 @@ pub struct StructData { pub name: Name, pub variant_data: Arc, pub repr: Option, + pub visibility: RawVisibility, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct EnumData { pub name: Name, pub variants: Arena, + pub visibility: RawVisibility, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -102,6 +104,7 @@ impl StructData { name: strukt.name.clone(), variant_data: Arc::new(variant_data), repr, + visibility: item_tree[strukt.visibility].clone(), }) } pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc { @@ -118,6 +121,7 @@ impl StructData { name: union.name.clone(), variant_data: Arc::new(variant_data), repr, + visibility: item_tree[union.visibility].clone(), }) } } @@ -150,7 +154,11 @@ impl EnumData { } } - Arc::new(EnumData { name: enum_.name.clone(), variants }) + Arc::new(EnumData { + name: enum_.name.clone(), + variants, + visibility: item_tree[enum_.visibility].clone(), + }) } pub fn variant(&self, name: &Name) -> Option { diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index b09da0697..74a2194e5 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -87,7 +87,10 @@ impl TypeAliasData { pub struct TraitData { pub name: Name, pub items: Vec<(Name, AssocItemId)>, - pub auto: bool, + pub is_auto: bool, + pub is_unsafe: bool, + pub visibility: RawVisibility, + pub bounds: Box<[TypeBound]>, } impl TraitData { @@ -96,10 +99,13 @@ impl TraitData { let item_tree = db.item_tree(tr_loc.id.file_id); let tr_def = &item_tree[tr_loc.id.value]; let name = tr_def.name.clone(); - let auto = tr_def.auto; + let is_auto = tr_def.is_auto; + let is_unsafe = tr_def.is_unsafe; let module_id = tr_loc.container; let container = AssocContainerId::TraitId(tr); let mut expander = Expander::new(db, tr_loc.id.file_id, module_id); + let visibility = item_tree[tr_def.visibility].clone(); + let bounds = tr_def.bounds.clone(); let items = collect_items( db, @@ -111,7 +117,7 @@ impl TraitData { 100, ); - Arc::new(TraitData { name, items, auto }) + Arc::new(TraitData { name, items, is_auto, is_unsafe, visibility, bounds }) } pub fn associated_types(&self) -> impl Iterator + '_ { diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index d8f22d442..d63ac3df3 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -633,7 +633,9 @@ pub struct Trait { pub name: Name, pub visibility: RawVisibilityId, pub generic_params: GenericParamsId, - pub auto: bool, + pub is_auto: bool, + pub is_unsafe: bool, + pub bounds: Box<[TypeBound]>, pub items: Box<[AssocItem]>, pub ast_id: FileAstId, } diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 6b5438dc9..7e91b991d 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -500,7 +500,9 @@ impl Ctx { let visibility = self.lower_visibility(trait_def); let generic_params = self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def); - let auto = trait_def.auto_token().is_some(); + let is_auto = trait_def.auto_token().is_some(); + let is_unsafe = trait_def.unsafe_token().is_some(); + let bounds = self.lower_type_bounds(trait_def); let items = trait_def.assoc_item_list().map(|list| { self.with_inherited_visibility(visibility, |this| { list.assoc_items() @@ -520,7 +522,9 @@ impl Ctx { name, visibility, generic_params, - auto, + is_auto, + is_unsafe, + bounds: bounds.into(), items: items.unwrap_or_default(), ast_id, }; diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 232cf9cd0..4bd8ba303 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs @@ -429,7 +429,7 @@ pub(crate) fn trait_datum_query( let generic_params = generics(db.upcast(), trait_.into()); let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); let flags = rust_ir::TraitFlags { - auto: trait_data.auto, + auto: trait_data.is_auto, upstream: trait_.lookup(db.upcast()).container.krate() != krate, non_enumerable: true, coinductive: false, // only relevant for Chalk testing diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 1e4c247c0..7328f410a 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -1,7 +1,7 @@ use either::Either; use hir::{ - Adt, AsAssocItem, AssocItemContainer, FieldSource, GenericParam, HasAttrs, HasSource, - HirDisplay, Module, ModuleDef, ModuleSource, Semantics, + Adt, AsAssocItem, AssocItemContainer, GenericParam, HasAttrs, HasSource, HirDisplay, Module, + ModuleDef, Semantics, }; use ide_db::{ base_db::SourceDatabase, @@ -14,7 +14,7 @@ use stdx::format_to; use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; use crate::{ - display::{macro_label, ShortLabel, TryToNav}, + display::{macro_label, TryToNav}, doc_links::{remove_links, rewrite_links}, markdown_remove::remove_markdown, markup::Markup, @@ -335,34 +335,18 @@ fn hover_for_definition( let label = macro_label(&it.source(db)?.value); from_def_source_labeled(db, it, Some(label), mod_path) } - Definition::Field(def) => { - let src = def.source(db)?.value; - if let FieldSource::Named(it) = src { - from_def_source_labeled(db, def, it.short_label(), mod_path) - } else { - None - } - } + Definition::Field(def) => from_hir_fmt(db, def, mod_path), Definition::ModuleDef(it) => match it { - ModuleDef::Module(it) => from_def_source_labeled( - db, - it, - match it.definition_source(db).value { - ModuleSource::Module(it) => it.short_label(), - ModuleSource::SourceFile(it) => it.short_label(), - ModuleSource::BlockExpr(it) => it.short_label(), - }, - mod_path, - ), + ModuleDef::Module(it) => from_hir_fmt(db, it, mod_path), ModuleDef::Function(it) => from_hir_fmt(db, it, mod_path), - ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path), - ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it, mod_path), - ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it, mod_path), - ModuleDef::Variant(it) => from_def_source(db, it, mod_path), - ModuleDef::Const(it) => from_def_source(db, it, mod_path), - ModuleDef::Static(it) => from_def_source(db, it, mod_path), - ModuleDef::Trait(it) => from_def_source(db, it, mod_path), - ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), + ModuleDef::Adt(Adt::Struct(it)) => from_hir_fmt(db, it, mod_path), + ModuleDef::Adt(Adt::Union(it)) => from_hir_fmt(db, it, mod_path), + ModuleDef::Adt(Adt::Enum(it)) => from_hir_fmt(db, it, mod_path), + ModuleDef::Variant(it) => from_hir_fmt(db, it, mod_path), + ModuleDef::Const(it) => from_hir_fmt(db, it, mod_path), + ModuleDef::Static(it) => from_hir_fmt(db, it, mod_path), + ModuleDef::Trait(it) => from_hir_fmt(db, it, mod_path), + ModuleDef::TypeAlias(it) => from_hir_fmt(db, it, mod_path), ModuleDef::BuiltinType(it) => famous_defs .and_then(|fd| hover_for_builtin(fd, it)) .or_else(|| Some(Markup::fenced_block(&it.name()))), @@ -370,16 +354,16 @@ fn hover_for_definition( Definition::Local(it) => hover_for_local(it, db), Definition::SelfType(impl_def) => { impl_def.target_ty(db).as_adt().and_then(|adt| match adt { - Adt::Struct(it) => from_def_source(db, it, mod_path), - Adt::Union(it) => from_def_source(db, it, mod_path), - Adt::Enum(it) => from_def_source(db, it, mod_path), + Adt::Struct(it) => from_hir_fmt(db, it, mod_path), + Adt::Union(it) => from_hir_fmt(db, it, mod_path), + Adt::Enum(it) => from_hir_fmt(db, it, mod_path), }) } Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))), Definition::GenericParam(it) => match it { GenericParam::TypeParam(it) => Some(Markup::fenced_block(&it.display(db))), GenericParam::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))), - GenericParam::ConstParam(it) => from_def_source(db, it, None), + GenericParam::ConstParam(it) => Some(Markup::fenced_block(&it.display(db))), }, }; @@ -391,15 +375,6 @@ fn hover_for_definition( from_def_source_labeled(db, def, Some(label), mod_path) } - fn from_def_source(db: &RootDatabase, def: D, mod_path: Option) -> Option - where - D: HasSource + HasAttrs + Copy, - A: ShortLabel, - { - let short_label = def.source(db)?.value.short_label(); - from_def_source_labeled(db, def, short_label, mod_path) - } - fn from_def_source_labeled( db: &RootDatabase, def: D, -- cgit v1.2.3 From 7101bada0f90eaf89718461affa583e1736f0099 Mon Sep 17 00:00:00 2001 From: oxalica Date: Tue, 16 Mar 2021 00:58:29 +0800 Subject: Fix trait type parameter --- crates/hir/src/display.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 0640712de..e3660442c 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -233,7 +233,13 @@ impl HirDisplay for ConstParam { fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> { let params = f.db.generic_params(def); - if params.lifetimes.is_empty() && params.types.is_empty() && params.consts.is_empty() { + if params.lifetimes.is_empty() + && params.consts.is_empty() + && params + .types + .iter() + .all(|(_, param)| !matches!(param.provenance, TypeParamProvenance::TypeParamList)) + { return Ok(()); } write!(f, "<")?; -- cgit v1.2.3 From 7c855c940a5fdb5c942ddb3d3401c6e2dbbfca67 Mon Sep 17 00:00:00 2001 From: oxalica Date: Tue, 16 Mar 2021 00:58:42 +0800 Subject: Clean usage of ShortLabel --- crates/ide/src/display.rs | 1 - crates/ide/src/display/navigation_target.rs | 14 ++++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/ide/src/display.rs b/crates/ide/src/display.rs index bae9e40df..1f7b665c0 100644 --- a/crates/ide/src/display.rs +++ b/crates/ide/src/display.rs @@ -5,6 +5,5 @@ pub(crate) mod navigation_target; mod short_label; pub(crate) use navigation_target::{ToNav, TryToNav}; -pub(crate) use short_label::ShortLabel; pub(crate) use syntax::display::{function_declaration, macro_label}; diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index 198243466..69c3751a1 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs @@ -3,7 +3,9 @@ use std::fmt; use either::Either; -use hir::{AssocItem, Documentation, FieldSource, HasAttrs, HasSource, InFile, ModuleSource}; +use hir::{ + AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirDisplay, InFile, ModuleSource, +}; use ide_db::{ base_db::{FileId, FileRange, SourceDatabase}, symbol_index::FileSymbolKind, @@ -98,7 +100,7 @@ impl NavigationTarget { SymbolKind::Module, ); res.docs = module.attrs(db).docs(); - res.description = src.value.short_label(); + res.description = Some(module.display(db).to_string()); return res; } module.to_nav(db) @@ -251,8 +253,8 @@ impl ToNavFromAst for hir::Trait { impl TryToNav for D where - D: HasSource + ToNavFromAst + Copy + HasAttrs, - D::Ast: ast::NameOwner + ShortLabel, + D: HasSource + ToNavFromAst + Copy + HasAttrs + HirDisplay, + D::Ast: ast::NameOwner, { fn try_to_nav(&self, db: &RootDatabase) -> Option { let src = self.source(db)?; @@ -262,7 +264,7 @@ where D::KIND, ); res.docs = self.docs(db); - res.description = src.value.short_label(); + res.description = Some(self.display(db).to_string()); Some(res) } } @@ -317,7 +319,7 @@ impl TryToNav for hir::Field { let mut res = NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field); res.docs = self.docs(db); - res.description = it.short_label(); + res.description = Some(self.display(db).to_string()); res } FieldSource::Pos(it) => { -- cgit v1.2.3 From 73fc05fdca348a899c78f527d08f323cd582100d Mon Sep 17 00:00:00 2001 From: oxalica Date: Tue, 16 Mar 2021 01:24:21 +0800 Subject: Pretty print root module of extern crates --- crates/hir/src/display.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index e3660442c..44cdcc296 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -431,6 +431,10 @@ impl HirDisplay for Module { // FIXME: Module doesn't have visibility saved in data. match self.name(f.db) { Some(name) => write!(f, "mod {}", name), + None if self.crate_root(f.db) == *self => match self.krate().display_name(f.db) { + Some(name) => write!(f, "extern crate {}", name), + None => write!(f, "extern crate {{unknown}}"), + }, None => write!(f, "mod {{unnamed}}"), } } -- cgit v1.2.3 From 455b418263df80da5cd80e2af1df27b7e165c0c3 Mon Sep 17 00:00:00 2001 From: oxalica Date: Tue, 16 Mar 2021 01:24:26 +0800 Subject: Update tests --- crates/ide/src/hover.rs | 85 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 7328f410a..a35805c5e 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -653,7 +653,9 @@ fn main() { let foo_test = fo$0o(); } ``` ```rust - pub fn foo<'a, T: AsRef>(b: &'a T) -> &'a str + pub fn foo<'a, T>(b: &'a T) -> &'a str + where + T: AsRef, ``` "#]], ); @@ -861,7 +863,7 @@ fn main() { So$0me(12); } ``` ```rust - Some + Some(T) ``` "#]], ); @@ -927,7 +929,7 @@ fn main() { ``` ```rust - Some + Some(T) ``` --- @@ -1424,13 +1426,14 @@ fn bar() { fo$0o(); } ``` "#]], ); + // Top level `pub(crate)` will be displayed as no visibility. check( - r#"pub(crate) async unsafe extern "C" fn foo$0() {}"#, + r#"mod m { pub(crate) async unsafe extern "C" fn foo$0() {} }"#, expect![[r#" *foo* ```rust - test + test::m ``` ```rust @@ -1472,11 +1475,18 @@ extern crate st$0d; //! abc123 "#, expect![[r#" - *std* - Standard library for this test + *std* + + ```rust + extern crate std + ``` - Printed? - abc123 + --- + + Standard library for this test + + Printed? + abc123 "#]], ); check( @@ -1490,11 +1500,18 @@ extern crate std as ab$0c; //! abc123 "#, expect![[r#" - *abc* - Standard library for this test + *abc* - Printed? - abc123 + ```rust + extern crate std + ``` + + --- + + Standard library for this test + + Printed? + abc123 "#]], ); } @@ -2004,7 +2021,7 @@ enum E { ``` ```rust - V + V { field: i32 } ``` --- @@ -2400,7 +2417,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; } focus_range: 24..25, name: "S", kind: Struct, - description: "struct S", + description: "struct S", }, }, HoverGotoTypeData { @@ -2446,7 +2463,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; } focus_range: 24..25, name: "S", kind: Struct, - description: "struct S", + description: "struct S", }, }, HoverGotoTypeData { @@ -2588,7 +2605,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo", }, }, HoverGotoTypeData { @@ -2685,7 +2702,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo", }, }, HoverGotoTypeData { @@ -2698,7 +2715,7 @@ fn main() { let s$0t = foo(); } focus_range: 22..25, name: "Bar", kind: Trait, - description: "trait Bar", + description: "trait Bar", }, }, HoverGotoTypeData { @@ -2802,7 +2819,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar", + description: "trait Bar", }, }, HoverGotoTypeData { @@ -2899,7 +2916,7 @@ fn foo(ar$0g: &impl Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo", }, }, HoverGotoTypeData { @@ -2949,7 +2966,7 @@ fn main() { let s$0t = foo(); } focus_range: 49..50, name: "B", kind: Struct, - description: "struct B", + description: "struct B", }, }, HoverGotoTypeData { @@ -3025,7 +3042,7 @@ fn foo(ar$0g: &dyn Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo", }, }, HoverGotoTypeData { @@ -3073,7 +3090,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 6..15, name: "ImplTrait", kind: Trait, - description: "trait ImplTrait", + description: "trait ImplTrait", }, }, HoverGotoTypeData { @@ -3086,7 +3103,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 50..51, name: "B", kind: Struct, - description: "struct B", + description: "struct B", }, }, HoverGotoTypeData { @@ -3099,7 +3116,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 28..36, name: "DynTrait", kind: Trait, - description: "trait DynTrait", + description: "trait DynTrait", }, }, HoverGotoTypeData { @@ -3565,6 +3582,17 @@ mod foo$0; "#, expect![[r#" *foo* + + ```rust + test + ``` + + ```rust + mod foo + ``` + + --- + For the horde! "#]], ); @@ -3589,7 +3617,7 @@ use foo::bar::{self$0}; ``` ```rust - pub mod bar + mod bar ``` --- @@ -3670,8 +3698,9 @@ fn main() { ``` ```rust - fn bar<'t, T: Clone + 't>(s: &mut S<'t, T>, t: u32) -> *mut u32 + fn bar<'t, T>(s: &mut S<'t, T>, t: u32) -> *mut u32 where + T: Clone + 't, 't: 't + 't, for<'a> T: Clone + 'a, ``` -- cgit v1.2.3