From 87171238c6c528c421f06de8cd7e41ed3b6ff57a Mon Sep 17 00:00:00 2001 From: oxalica Date: Tue, 16 Mar 2021 00:05:03 +0800 Subject: [PATCH] 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 ae08e258472..0640712de72 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 476fdb13285..98135602a53 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 efbde17d887..1b9bb8235f2 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 b09da06979d..74a2194e5e7 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 d8f22d44296..d63ac3df342 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 6b5438dc93d..7e91b991d2c 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 232cf9cd0d6..4bd8ba30315 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 1e4c247c03f..7328f410a53 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,