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 ++++++++ 1 file changed, 8 insertions(+) (limited to 'crates/hir') 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 { -- 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 (limited to 'crates/hir') 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/hir') 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) { -- 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 +++- 2 files changed, 247 insertions(+), 4 deletions(-) (limited to 'crates/hir') 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)] -- 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 +++++++++- 2 files changed, 213 insertions(+), 3 deletions(-) (limited to 'crates/hir') 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())) } } -- 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(-) (limited to 'crates/hir') 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 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(+) (limited to 'crates/hir') 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