//! 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::{
    AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause,
    db::HirDatabase,
    display::{
        HirDisplay, HirDisplayError, HirDisplayWithExpressionStore, HirFormatter, SizedByDefault,
        hir_display_with_store, write_bounds_like_dyn_trait_with_prefix, write_visibility,
    },
};
use itertools::Itertools;

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, TyBuilder,
    Type, TypeAlias, TypeNs, TypeOrConstParam, TypeParam, Union, Variant,
};

impl HirDisplay for Function {
    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> 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(impl_: &Impl, f: &mut HirFormatter<'_>) -> 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 HirDisplay for SelfParam {
    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> 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 HirDisplay for Adt {
    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> 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 HirDisplay for Struct {
    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> 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 HirDisplay for Enum {
    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> 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 HirDisplay for Union {
    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> 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(
    fields: &[Field],
    has_where_clause: bool,
    limit: usize,
    in_line: bool,
    f: &mut HirFormatter<'_>,
) -> 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(
    variants: &[Variant],
    has_where_clause: bool,
    limit: usize,
    f: &mut HirFormatter<'_>,
) -> 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 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).display(f.db, f.edition()))?;
        self.ty(f.db).hir_fmt(f)
    }
}

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

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

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

impl HirDisplay for TypeParam {
    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
        let params = f.db.generic_params(self.id.parent());
        let param_data = &params[self.id.local_id()];
        let substs = TyBuilder::placeholder_subst(f.db, self.id.parent());
        let krate = self.id.parent().krate(f.db).id;
        let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(f.db, self.id.into()))
            .intern(Interner);
        let predicates = f.db.generic_predicates(self.id.parent());
        let predicates = predicates
            .iter()
            .cloned()
            .map(|pred| pred.substitute(Interner, &substs))
            .filter(|wc| match wc.skip_binders() {
                WhereClause::Implemented(tr) => tr.self_type_parameter(Interner) == ty,
                WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), ty: _ }) => {
                    proj.self_type_parameter(f.db) == ty
                }
                WhereClause::AliasEq(_) => false,
                WhereClause::TypeOutlives(to) => to.ty == ty,
                WhereClause::LifetimeOutlives(_) => 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.skip_binders() {
            WhereClause::Implemented(it) => Some(it.hir_trait_id()) == 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(
                    &hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(
                        f.db,
                        self.id.into(),
                    ))
                    .intern(Interner),
                ),
                &predicates,
                default_sized,
            )?;
        }
        Ok(())
    }
}

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

impl HirDisplay for ConstParam {
    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> 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(
    def: GenericDefId,
    f: &mut HirFormatter<'_>,
) -> 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<'_>| {
        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(
    def: GenericDefId,
    f: &mut HirFormatter<'_>,
) -> 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(
    params: &GenericParams,
    store: &ExpressionStore,
    f: &mut HirFormatter<'_>,
) -> 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 HirDisplay for Const {
    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> 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 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_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 HirDisplay for TraitRef<'_> {
    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
        self.trait_ref.hir_fmt(f)
    }
}

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

impl HirDisplay for Macro {
    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> 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()))
    }
}
