//! HirDisplay implementations for various hir types.

use either::Either;
use hir_def::{
    AdtId, GenericDefId,
    expr_store::ExpressionStore,
    hir::generics::{GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate},
    item_tree::FieldsShape,
    lang_item::LangItem,
    signatures::{StaticFlags, TraitFlags},
    type_ref::{TypeBound, TypeRef, TypeRefId},
};
use hir_ty::{
    GenericPredicates,
    db::HirDatabase,
    display::{
        HirDisplay, HirDisplayError, HirDisplayWithExpressionStore, HirFormatter, SizedByDefault,
        hir_display_with_store, write_bounds_like_dyn_trait_with_prefix, write_visibility,
    },
    next_solver::ClauseKind,
};
use itertools::Itertools;
use rustc_type_ir::inherent::IntoKind;

use crate::{
    Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Crate, Enum,
    ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam,
    Macro, Module, SelfParam, Static, Struct, StructKind, Trait, TraitRef, TupleField, Type,
    TypeAlias, TypeNs, TypeOrConstParam, TypeParam, Union, Variant,
};

impl<'db> HirDisplay<'db> for Function {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        let db = f.db;
        let data = db.function_signature(self.id);
        let container = self.as_assoc_item(db).map(|it| it.container(db));
        let mut module = self.module(db);

        // Write container (trait or impl)
        let container_params = match container {
            Some(AssocItemContainer::Trait(trait_)) => {
                let (params, params_store) = f.db.generic_params_and_store(trait_.id.into());
                if f.show_container_bounds() && !params.is_empty() {
                    write_trait_header(&trait_, f)?;
                    f.write_char('\n')?;
                    has_disaplayable_predicates(f.db, &params, &params_store)
                        .then_some((params, params_store))
                } else {
                    None
                }
            }
            Some(AssocItemContainer::Impl(impl_)) => {
                let (params, params_store) = f.db.generic_params_and_store(impl_.id.into());
                if f.show_container_bounds() && !params.is_empty() {
                    write_impl_header(&impl_, f)?;
                    f.write_char('\n')?;
                    has_disaplayable_predicates(f.db, &params, &params_store)
                        .then_some((params, params_store))
                } else {
                    None
                }
            }
            None => None,
        };

        // Write signature of the function

        // Block-local impls are "hoisted" to the nearest (non-block) module.
        if let Some(AssocItemContainer::Impl(_)) = container {
            module = module.nearest_non_block_module(db);
        }
        let module_id = module.id;

        write_visibility(module_id, self.visibility(db), f)?;

        if data.is_default() {
            f.write_str("default ")?;
        }
        if data.is_const() {
            f.write_str("const ")?;
        }
        if data.is_async() {
            f.write_str("async ")?;
        }
        // FIXME: This will show `unsafe` for functions that are `#[target_feature]` but not unsafe
        // (they are conditionally unsafe to call). We probably should show something else.
        if self.is_unsafe_to_call(db, None, f.edition()) {
            f.write_str("unsafe ")?;
        }
        if let Some(abi) = &data.abi {
            write!(f, "extern \"{}\" ", abi.as_str())?;
        }
        write!(f, "fn {}", data.name.display(f.db, f.edition()))?;

        write_generic_params(GenericDefId::FunctionId(self.id), f)?;

        f.write_char('(')?;

        let mut first = true;
        let mut skip_self = 0;
        if let Some(self_param) = self.self_param(db) {
            self_param.hir_fmt(f)?;
            first = false;
            skip_self = 1;
        }

        // FIXME: Use resolved `param.ty` once we no longer discard lifetimes
        let body = db.body(self.id.into());
        for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)).skip(skip_self) {
            if !first {
                f.write_str(", ")?;
            } else {
                first = false;
            }

            let pat_id = body.params[param.idx - body.self_param.is_some() as usize];
            let pat_str = body.pretty_print_pat(db, self.id.into(), pat_id, true, f.edition());
            f.write_str(&pat_str)?;

            f.write_str(": ")?;
            type_ref.hir_fmt(f, &data.store)?;
        }

        if data.is_varargs() {
            if !first {
                f.write_str(", ")?;
            }
            f.write_str("...")?;
        }

        f.write_char(')')?;

        // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns.
        // Use ugly pattern match to strip the Future trait.
        // Better way?
        let ret_type = if !data.is_async() {
            data.ret_type
        } else if let Some(ret_type) = data.ret_type {
            match &data.store[ret_type] {
                TypeRef::ImplTrait(bounds) => match &bounds[0] {
                    &TypeBound::Path(path, _) => Some(
                        *data.store[path]
                            .segments()
                            .iter()
                            .last()
                            .unwrap()
                            .args_and_bindings
                            .unwrap()
                            .bindings[0]
                            .type_ref
                            .as_ref()
                            .unwrap(),
                    ),
                    _ => None,
                },
                _ => None,
            }
        } else {
            None
        };

        if let Some(ret_type) = ret_type {
            match &data.store[ret_type] {
                TypeRef::Tuple(tup) if tup.is_empty() => {}
                _ => {
                    f.write_str(" -> ")?;
                    ret_type.hir_fmt(f, &data.store)?;
                }
            }
        }

        // Write where clauses
        let has_written_where = write_where_clause(GenericDefId::FunctionId(self.id), f)?;
        if let Some((container_params, container_params_store)) = container_params {
            if !has_written_where {
                f.write_str("\nwhere")?;
            }
            let container_name = match container.unwrap() {
                AssocItemContainer::Trait(_) => "trait",
                AssocItemContainer::Impl(_) => "impl",
            };
            write!(f, "\n    // Bounds from {container_name}:",)?;
            write_where_predicates(&container_params, &container_params_store, f)?;
        }
        Ok(())
    }
}

fn write_impl_header<'db>(
    impl_: &Impl,
    f: &mut HirFormatter<'_, 'db>,
) -> Result<(), HirDisplayError> {
    let db = f.db;

    f.write_str("impl")?;
    let def_id = GenericDefId::ImplId(impl_.id);
    write_generic_params(def_id, f)?;

    if let Some(trait_) = impl_.trait_(db) {
        let trait_data = db.trait_signature(trait_.id);
        write!(f, " {} for", trait_data.name.display(db, f.edition()))?;
    }

    f.write_char(' ')?;
    impl_.self_ty(db).hir_fmt(f)?;

    Ok(())
}

impl<'db> HirDisplay<'db> for SelfParam {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        let data = f.db.function_signature(self.func);
        let param = *data.params.first().unwrap();
        match &data.store[param] {
            TypeRef::Path(p) if p.is_self_type() => f.write_str("self"),
            TypeRef::Reference(ref_) if matches!(&data.store[ref_.ty], TypeRef::Path(p) if p.is_self_type()) =>
            {
                f.write_char('&')?;
                if let Some(lifetime) = &ref_.lifetime {
                    lifetime.hir_fmt(f, &data.store)?;
                    f.write_char(' ')?;
                }
                if let hir_def::type_ref::Mutability::Mut = ref_.mutability {
                    f.write_str("mut ")?;
                }
                f.write_str("self")
            }
            _ => {
                f.write_str("self: ")?;
                param.hir_fmt(f, &data.store)
            }
        }
    }
}

impl<'db> HirDisplay<'db> for Adt {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        match self {
            Adt::Struct(it) => it.hir_fmt(f),
            Adt::Union(it) => it.hir_fmt(f),
            Adt::Enum(it) => it.hir_fmt(f),
        }
    }
}

impl<'db> HirDisplay<'db> for Struct {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        let module_id = self.module(f.db).id;
        // FIXME: Render repr if its set explicitly?
        write_visibility(module_id, self.visibility(f.db), f)?;
        f.write_str("struct ")?;
        write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
        let def_id = GenericDefId::AdtId(AdtId::StructId(self.id));
        write_generic_params(def_id, f)?;

        let variant_data = self.variant_fields(f.db);
        match self.kind(f.db) {
            StructKind::Tuple => {
                f.write_char('(')?;
                let mut it = variant_data.fields().iter().peekable();

                while let Some((id, _)) = it.next() {
                    let field = Field { parent: (*self).into(), id };
                    write_visibility(module_id, field.visibility(f.db), f)?;
                    field.ty(f.db).hir_fmt(f)?;
                    if it.peek().is_some() {
                        f.write_str(", ")?;
                    }
                }

                f.write_char(')')?;
                write_where_clause(def_id, f)?;
            }
            StructKind::Record => {
                let has_where_clause = write_where_clause(def_id, f)?;
                if let Some(limit) = f.entity_limit {
                    write_fields(&self.fields(f.db), has_where_clause, limit, false, f)?;
                }
            }
            StructKind::Unit => _ = write_where_clause(def_id, f)?,
        }

        Ok(())
    }
}

impl<'db> HirDisplay<'db> for Enum {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
        f.write_str("enum ")?;
        write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
        let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
        write_generic_params(def_id, f)?;

        let has_where_clause = write_where_clause(def_id, f)?;
        if let Some(limit) = f.entity_limit {
            write_variants(&self.variants(f.db), has_where_clause, limit, f)?;
        }

        Ok(())
    }
}

impl<'db> HirDisplay<'db> for Union {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
        f.write_str("union ")?;
        write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
        let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
        write_generic_params(def_id, f)?;

        let has_where_clause = write_where_clause(def_id, f)?;
        if let Some(limit) = f.entity_limit {
            write_fields(&self.fields(f.db), has_where_clause, limit, false, f)?;
        }
        Ok(())
    }
}

fn write_fields<'db>(
    fields: &[Field],
    has_where_clause: bool,
    limit: usize,
    in_line: bool,
    f: &mut HirFormatter<'_, 'db>,
) -> Result<(), HirDisplayError> {
    let count = fields.len().min(limit);
    let (indent, separator) = if in_line { ("", ' ') } else { ("    ", '\n') };
    f.write_char(if !has_where_clause { ' ' } else { separator })?;
    if count == 0 {
        f.write_str(if fields.is_empty() { "{}" } else { "{ /* … */ }" })?;
    } else {
        f.write_char('{')?;

        if !fields.is_empty() {
            f.write_char(separator)?;
            for field in &fields[..count] {
                f.write_str(indent)?;
                field.hir_fmt(f)?;
                write!(f, ",{separator}")?;
            }

            if fields.len() > count {
                write!(f, "{indent}/* … */{separator}")?;
            }
        }

        f.write_str("}")?;
    }

    Ok(())
}

fn write_variants<'db>(
    variants: &[Variant],
    has_where_clause: bool,
    limit: usize,
    f: &mut HirFormatter<'_, 'db>,
) -> Result<(), HirDisplayError> {
    let count = variants.len().min(limit);
    f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
    if count == 0 {
        let variants = if variants.is_empty() { "{}" } else { "{ /* … */ }" };
        f.write_str(variants)?;
    } else {
        f.write_str("{\n")?;
        for variant in &variants[..count] {
            write!(f, "    {}", variant.name(f.db).display(f.db, f.edition()))?;
            match variant.kind(f.db) {
                StructKind::Tuple => {
                    let fields_str =
                        if variant.fields(f.db).is_empty() { "()" } else { "( /* … */ )" };
                    f.write_str(fields_str)?;
                }
                StructKind::Record => {
                    let fields_str =
                        if variant.fields(f.db).is_empty() { " {}" } else { " { /* … */ }" };
                    f.write_str(fields_str)?;
                }
                StructKind::Unit => {}
            }
            f.write_str(",\n")?;
        }

        if variants.len() > count {
            f.write_str("    /* … */\n")?;
        }
        f.write_str("}")?;
    }

    Ok(())
}

impl<'db> HirDisplay<'db> for Field {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
        write!(f, "{}: ", self.name(f.db).display(f.db, f.edition()))?;
        self.ty(f.db).hir_fmt(f)
    }
}

impl<'db> HirDisplay<'db> for TupleField {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        write!(f, "pub {}: ", self.name().display(f.db, f.edition()))?;
        self.ty(f.db).hir_fmt(f)
    }
}

impl<'db> HirDisplay<'db> for Variant {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
        let data = self.id.fields(f.db);
        match data.shape {
            FieldsShape::Unit => {}
            FieldsShape::Tuple => {
                f.write_char('(')?;
                let mut first = true;
                for (_, field) in data.fields().iter() {
                    if first {
                        first = false;
                    } else {
                        f.write_str(", ")?;
                    }
                    // Enum variant fields must be pub.
                    field.type_ref.hir_fmt(f, &data.store)?;
                }
                f.write_char(')')?;
            }
            FieldsShape::Record => {
                if let Some(limit) = f.entity_limit {
                    write_fields(&self.fields(f.db), false, limit, true, f)?;
                }
            }
        }
        Ok(())
    }
}

impl<'db> HirDisplay<'db> for Type<'db> {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        self.ty.hir_fmt(f)
    }
}

impl<'db> HirDisplay<'db> for TypeNs<'db> {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        self.ty.hir_fmt(f)
    }
}

impl<'db> HirDisplay<'db> for ExternCrateDecl {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
        f.write_str("extern crate ")?;
        write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
        if let Some(alias) = self.alias(f.db) {
            write!(f, " as {}", alias.display(f.edition()))?;
        }
        Ok(())
    }
}

impl<'db> HirDisplay<'db> for GenericParam {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        match self {
            GenericParam::TypeParam(it) => it.hir_fmt(f),
            GenericParam::ConstParam(it) => it.hir_fmt(f),
            GenericParam::LifetimeParam(it) => it.hir_fmt(f),
        }
    }
}

impl<'db> HirDisplay<'db> for TypeOrConstParam {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        match self.split(f.db) {
            either::Either::Left(it) => it.hir_fmt(f),
            either::Either::Right(it) => it.hir_fmt(f),
        }
    }
}

impl<'db> HirDisplay<'db> for TypeParam {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        let params = f.db.generic_params(self.id.parent());
        let param_data = &params[self.id.local_id()];
        let krate = self.id.parent().krate(f.db).id;
        let ty = self.ty(f.db).ty;
        let predicates = GenericPredicates::query_all(f.db, self.id.parent());
        let predicates = predicates
            .iter_identity_copied()
            .filter(|wc| match wc.kind().skip_binder() {
                ClauseKind::Trait(tr) => tr.self_ty() == ty,
                ClauseKind::Projection(proj) => proj.self_ty() == ty,
                ClauseKind::TypeOutlives(to) => to.0 == ty,
                _ => false,
            })
            .collect::<Vec<_>>();

        match param_data {
            TypeOrConstParamData::TypeParamData(p) => match p.provenance {
                TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
                    write!(f, "{}", p.name.clone().unwrap().display(f.db, f.edition()))?
                }
                TypeParamProvenance::ArgumentImplTrait => {
                    return write_bounds_like_dyn_trait_with_prefix(
                        f,
                        "impl",
                        Either::Left(ty),
                        &predicates,
                        SizedByDefault::Sized { anchor: krate },
                    );
                }
            },
            TypeOrConstParamData::ConstParamData(p) => {
                write!(f, "{}", p.name.display(f.db, f.edition()))?;
            }
        }

        if f.omit_verbose_types() {
            return Ok(());
        }

        let sized_trait = LangItem::Sized.resolve_trait(f.db, krate);
        let has_only_sized_bound =
            predicates.iter().all(move |pred| match pred.kind().skip_binder() {
                ClauseKind::Trait(it) => Some(it.def_id().0) == sized_trait,
                _ => false,
            });
        let has_only_not_sized_bound = predicates.is_empty();
        if !has_only_sized_bound || has_only_not_sized_bound {
            let default_sized = SizedByDefault::Sized { anchor: krate };
            write_bounds_like_dyn_trait_with_prefix(
                f,
                ":",
                Either::Left(ty),
                &predicates,
                default_sized,
            )?;
        }
        Ok(())
    }
}

impl<'db> HirDisplay<'db> for LifetimeParam {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        write!(f, "{}", self.name(f.db).display(f.db, f.edition()))
    }
}

impl<'db> HirDisplay<'db> for ConstParam {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        write!(f, "const {}: ", self.name(f.db).display(f.db, f.edition()))?;
        self.ty(f.db).hir_fmt(f)
    }
}

fn write_generic_params<'db>(
    def: GenericDefId,
    f: &mut HirFormatter<'_, 'db>,
) -> Result<(), HirDisplayError> {
    let (params, store) = f.db.generic_params_and_store(def);
    if params.iter_lt().next().is_none()
        && params.iter_type_or_consts().all(|it| it.1.const_param().is_none())
        && params
            .iter_type_or_consts()
            .filter_map(|it| it.1.type_param())
            .all(|param| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
    {
        return Ok(());
    }
    f.write_char('<')?;

    let mut first = true;
    let mut delim = |f: &mut HirFormatter<'_, 'db>| {
        if first {
            first = false;
            Ok(())
        } else {
            f.write_str(", ")
        }
    };
    for (_, lifetime) in params.iter_lt() {
        delim(f)?;
        write!(f, "{}", lifetime.name.display(f.db, f.edition()))?;
    }
    for (_, ty) in params.iter_type_or_consts() {
        if let Some(name) = &ty.name() {
            match ty {
                TypeOrConstParamData::TypeParamData(ty) => {
                    if ty.provenance != TypeParamProvenance::TypeParamList {
                        continue;
                    }
                    delim(f)?;
                    write!(f, "{}", name.display(f.db, f.edition()))?;
                    if let Some(default) = &ty.default {
                        f.write_str(" = ")?;
                        default.hir_fmt(f, &store)?;
                    }
                }
                TypeOrConstParamData::ConstParamData(c) => {
                    delim(f)?;
                    write!(f, "const {}: ", name.display(f.db, f.edition()))?;
                    c.ty.hir_fmt(f, &store)?;

                    if let Some(default) = &c.default {
                        f.write_str(" = ")?;
                        default.hir_fmt(f, &store)?;
                    }
                }
            }
        }
    }

    f.write_char('>')?;
    Ok(())
}

fn write_where_clause<'db>(
    def: GenericDefId,
    f: &mut HirFormatter<'_, 'db>,
) -> Result<bool, HirDisplayError> {
    let (params, store) = f.db.generic_params_and_store(def);
    if !has_disaplayable_predicates(f.db, &params, &store) {
        return Ok(false);
    }

    f.write_str("\nwhere")?;
    write_where_predicates(&params, &store, f)?;

    Ok(true)
}

fn has_disaplayable_predicates(
    db: &dyn HirDatabase,
    params: &GenericParams,
    store: &ExpressionStore,
) -> bool {
    params.where_predicates().iter().any(|pred| {
        !matches!(
            pred,
            WherePredicate::TypeBound { target, .. }
            if  matches!(store[*target],
                TypeRef::TypeParam(id) if db.generic_params(id.parent())[id.local_id()].name().is_none()
            )
        )
    })
}

fn write_where_predicates<'db>(
    params: &GenericParams,
    store: &ExpressionStore,
    f: &mut HirFormatter<'_, 'db>,
) -> Result<(), HirDisplayError> {
    use WherePredicate::*;

    // unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
    let is_unnamed_type_target = |target: TypeRefId| {
        matches!(store[target],
            TypeRef::TypeParam(id) if f.db.generic_params(id.parent())[id.local_id()].name().is_none()
        )
    };

    let check_same_target = |pred1: &WherePredicate, pred2: &WherePredicate| match (pred1, pred2) {
        (TypeBound { target: t1, .. }, TypeBound { target: t2, .. }) => t1 == t2,
        (Lifetime { target: t1, .. }, Lifetime { target: t2, .. }) => t1 == t2,
        (
            ForLifetime { lifetimes: l1, target: t1, .. },
            ForLifetime { lifetimes: l2, target: t2, .. },
        ) => l1 == l2 && t1 == t2,
        _ => false,
    };

    let mut iter = params.where_predicates().iter().peekable();
    while let Some(pred) = iter.next() {
        if matches!(pred, TypeBound { target, .. } if is_unnamed_type_target(*target)) {
            continue;
        }

        f.write_str("\n    ")?;
        match pred {
            TypeBound { target, bound } => {
                target.hir_fmt(f, store)?;
                f.write_str(": ")?;
                bound.hir_fmt(f, store)?;
            }
            Lifetime { target, bound } => {
                target.hir_fmt(f, store)?;
                write!(f, ": ")?;
                bound.hir_fmt(f, store)?;
            }
            ForLifetime { lifetimes, target, bound } => {
                let lifetimes = lifetimes.iter().map(|it| it.display(f.db, f.edition())).join(", ");
                write!(f, "for<{lifetimes}> ")?;
                target.hir_fmt(f, store)?;
                f.write_str(": ")?;
                bound.hir_fmt(f, store)?;
            }
        }

        while let Some(nxt) = iter.next_if(|nxt| check_same_target(pred, nxt)) {
            f.write_str(" + ")?;
            match nxt {
                TypeBound { bound, .. } | ForLifetime { bound, .. } => bound.hir_fmt(f, store)?,
                Lifetime { bound, .. } => bound.hir_fmt(f, store)?,
            }
        }
        f.write_str(",")?;
    }

    Ok(())
}

impl<'db> HirDisplay<'db> for Const {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        let db = f.db;
        let container = self.as_assoc_item(db).map(|it| it.container(db));
        let mut module = self.module(db);
        if let Some(AssocItemContainer::Impl(_)) = container {
            // Block-local impls are "hoisted" to the nearest (non-block) module.
            module = module.nearest_non_block_module(db);
        }
        write_visibility(module.id, self.visibility(db), f)?;
        let data = db.const_signature(self.id);
        f.write_str("const ")?;
        match &data.name {
            Some(name) => write!(f, "{}: ", name.display(f.db, f.edition()))?,
            None => f.write_str("_: ")?,
        }
        data.type_ref.hir_fmt(f, &data.store)?;
        Ok(())
    }
}

impl<'db> HirDisplay<'db> for Static {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
        let data = f.db.static_signature(self.id);
        f.write_str("static ")?;
        if data.flags.contains(StaticFlags::MUTABLE) {
            f.write_str("mut ")?;
        }
        write!(f, "{}: ", data.name.display(f.db, f.edition()))?;
        data.type_ref.hir_fmt(f, &data.store)?;
        Ok(())
    }
}

impl<'db> HirDisplay<'db> for TraitRef<'db> {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        self.trait_ref.hir_fmt(f)
    }
}

impl<'db> HirDisplay<'db> for Trait {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        // FIXME(trait-alias) needs special handling to print the equal sign
        write_trait_header(self, f)?;
        let def_id = GenericDefId::TraitId(self.id);
        let has_where_clause = write_where_clause(def_id, f)?;

        if let Some(limit) = f.entity_limit {
            let assoc_items = self.items(f.db);
            let count = assoc_items.len().min(limit);
            f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
            if count == 0 {
                if assoc_items.is_empty() {
                    f.write_str("{}")?;
                } else {
                    f.write_str("{ /* … */ }")?;
                }
            } else {
                f.write_str("{\n")?;
                for item in &assoc_items[..count] {
                    f.write_str("    ")?;
                    match item {
                        AssocItem::Function(func) => func.hir_fmt(f),
                        AssocItem::Const(cst) => cst.hir_fmt(f),
                        AssocItem::TypeAlias(type_alias) => type_alias.hir_fmt(f),
                    }?;
                    f.write_str(";\n")?;
                }

                if assoc_items.len() > count {
                    f.write_str("    /* … */\n")?;
                }
                f.write_str("}")?;
            }
        }

        Ok(())
    }
}

fn write_trait_header<'db>(
    trait_: &Trait,
    f: &mut HirFormatter<'_, 'db>,
) -> Result<(), HirDisplayError> {
    write_visibility(trait_.module(f.db).id, trait_.visibility(f.db), f)?;
    let data = f.db.trait_signature(trait_.id);
    if data.flags.contains(TraitFlags::UNSAFE) {
        f.write_str("unsafe ")?;
    }
    if data.flags.contains(TraitFlags::AUTO) {
        f.write_str("auto ")?;
    }
    write!(f, "trait {}", data.name.display(f.db, f.edition()))?;
    write_generic_params(GenericDefId::TraitId(trait_.id), f)?;
    Ok(())
}

impl<'db> HirDisplay<'db> for TypeAlias {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
        let data = f.db.type_alias_signature(self.id);
        write!(f, "type {}", data.name.display(f.db, f.edition()))?;
        let def_id = GenericDefId::TypeAliasId(self.id);
        write_generic_params(def_id, f)?;
        if !data.bounds.is_empty() {
            f.write_str(": ")?;
            f.write_joined(
                data.bounds.iter().map(|bound| hir_display_with_store(bound, &data.store)),
                " + ",
            )?;
        }
        if let Some(ty) = data.ty {
            f.write_str(" = ")?;
            ty.hir_fmt(f, &data.store)?;
        }
        write_where_clause(def_id, f)?;
        Ok(())
    }
}

impl<'db> HirDisplay<'db> for Module {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        match self.parent(f.db) {
            Some(m) => write_visibility(m.id, self.visibility(f.db), f)?,
            None => {
                return match self.krate(f.db).display_name(f.db) {
                    Some(name) => write!(f, "extern crate {name}"),
                    None => f.write_str("extern crate {unknown}"),
                };
            }
        }
        match self.name(f.db) {
            Some(name) => write!(f, "mod {}", name.display(f.db, f.edition())),
            None => f.write_str("mod {unknown}"),
        }
    }
}

impl<'db> HirDisplay<'db> for Crate {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        match self.display_name(f.db) {
            Some(name) => write!(f, "extern crate {name}"),
            None => f.write_str("extern crate {unknown}"),
        }
    }
}

impl<'db> HirDisplay<'db> for Macro {
    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
        match self.id {
            hir_def::MacroId::Macro2Id(_) => f.write_str("macro"),
            hir_def::MacroId::MacroRulesId(_) => f.write_str("macro_rules!"),
            hir_def::MacroId::ProcMacroId(_) => f.write_str("proc_macro"),
        }?;
        write!(f, " {}", self.name(f.db).display(f.db, f.edition()))
    }
}
