//! These from impls are used to create the JSON types which get serialized. They're very close to
//! the `clean` types but with some fields removed or stringified to simplify the output and not
//! expose unstable compiler internals.

use rustc_abi::ExternAbi;
use rustc_ast::ast;
use rustc_hir as hir;
use rustc_hir::attrs::{self, DeprecatedSince};
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::DefId;
use rustc_hir::{HeaderSafety, Safety};
use rustc_metadata::rendered_const;
use rustc_middle::ty::TyCtxt;
use rustc_middle::{bug, ty};
use rustc_span::{Pos, kw, sym};
use rustdoc_json_types::*;
use thin_vec::ThinVec;

use crate::clean::{self, ItemId};
use crate::formats::item_type::ItemType;
use crate::json::JsonRenderer;
use crate::passes::collect_intra_doc_links::UrlFragment;

impl JsonRenderer<'_> {
    pub(super) fn convert_item(&self, item: &clean::Item) -> Option<Item> {
        let deprecation = item.deprecation(self.tcx);
        let links = self
            .cache
            .intra_doc_links
            .get(&item.item_id)
            .into_iter()
            .flatten()
            .map(|clean::ItemLink { link, page_id, fragment, .. }| {
                let id = match fragment {
                    Some(UrlFragment::Item(frag_id)) => *frag_id,
                    // FIXME: Pass the `UserWritten` segment to JSON consumer.
                    Some(UrlFragment::UserWritten(_)) | None => *page_id,
                };

                (String::from(&**link), self.id_from_item_default(id.into()))
            })
            .collect();
        let docs = item.opt_doc_value();
        let attrs = item
            .attrs
            .other_attrs
            .iter()
            .filter_map(|a| maybe_from_hir_attr(a, item.item_id, self.tcx))
            .collect();
        let span = item.span(self.tcx);
        let visibility = item.visibility(self.tcx);
        let clean::ItemInner { name, item_id, .. } = *item.inner;
        let id = self.id_from_item(item);
        let inner = match item.kind {
            clean::KeywordItem | clean::AttributeItem => return None,
            clean::StrippedItem(ref inner) => {
                match &**inner {
                    // We document stripped modules as with `Module::is_stripped` set to
                    // `true`, to prevent contained items from being orphaned for downstream users,
                    // as JSON does no inlining.
                    clean::ModuleItem(_)
                        if self.imported_items.contains(&item_id.expect_def_id()) =>
                    {
                        from_clean_item(item, self)
                    }
                    _ => return None,
                }
            }
            _ => from_clean_item(item, self),
        };
        Some(Item {
            id,
            crate_id: item_id.krate().as_u32(),
            name: name.map(|sym| sym.to_string()),
            span: span.and_then(|span| span.into_json(self)),
            visibility: visibility.into_json(self),
            docs,
            attrs,
            deprecation: deprecation.into_json(self),
            inner,
            links,
        })
    }

    fn ids(&self, items: &[clean::Item]) -> Vec<Id> {
        items
            .iter()
            .filter(|i| !i.is_stripped() && !i.is_keyword() && !i.is_attribute())
            .map(|i| self.id_from_item(i))
            .collect()
    }

    fn ids_keeping_stripped(&self, items: &[clean::Item]) -> Vec<Option<Id>> {
        items
            .iter()
            .map(|i| {
                (!i.is_stripped() && !i.is_keyword() && !i.is_attribute())
                    .then(|| self.id_from_item(i))
            })
            .collect()
    }
}

pub(crate) trait FromClean<T> {
    fn from_clean(f: &T, renderer: &JsonRenderer<'_>) -> Self;
}

pub(crate) trait IntoJson<T> {
    fn into_json(&self, renderer: &JsonRenderer<'_>) -> T;
}

impl<T, U> IntoJson<U> for T
where
    U: FromClean<T>,
{
    fn into_json(&self, renderer: &JsonRenderer<'_>) -> U {
        U::from_clean(self, renderer)
    }
}

impl<T, U> FromClean<Box<T>> for U
where
    U: FromClean<T>,
{
    fn from_clean(opt: &Box<T>, renderer: &JsonRenderer<'_>) -> Self {
        opt.as_ref().into_json(renderer)
    }
}

impl<T, U> FromClean<Option<T>> for Option<U>
where
    U: FromClean<T>,
{
    fn from_clean(opt: &Option<T>, renderer: &JsonRenderer<'_>) -> Self {
        opt.as_ref().map(|x| x.into_json(renderer))
    }
}

impl<T, U> FromClean<Vec<T>> for Vec<U>
where
    U: FromClean<T>,
{
    fn from_clean(items: &Vec<T>, renderer: &JsonRenderer<'_>) -> Self {
        items.iter().map(|i| i.into_json(renderer)).collect()
    }
}

impl<T, U> FromClean<ThinVec<T>> for Vec<U>
where
    U: FromClean<T>,
{
    fn from_clean(items: &ThinVec<T>, renderer: &JsonRenderer<'_>) -> Self {
        items.iter().map(|i| i.into_json(renderer)).collect()
    }
}

impl FromClean<clean::Span> for Option<Span> {
    fn from_clean(span: &clean::Span, renderer: &JsonRenderer<'_>) -> Self {
        match span.filename(renderer.sess()) {
            rustc_span::FileName::Real(name) => {
                if let Some(local_path) = name.into_local_path() {
                    let hi = span.hi(renderer.sess());
                    let lo = span.lo(renderer.sess());
                    Some(Span {
                        filename: local_path,
                        begin: (lo.line, lo.col.to_usize() + 1),
                        end: (hi.line, hi.col.to_usize() + 1),
                    })
                } else {
                    None
                }
            }
            _ => None,
        }
    }
}

impl FromClean<Option<ty::Visibility<DefId>>> for Visibility {
    fn from_clean(v: &Option<ty::Visibility<DefId>>, renderer: &JsonRenderer<'_>) -> Self {
        match v {
            None => Visibility::Default,
            Some(ty::Visibility::Public) => Visibility::Public,
            Some(ty::Visibility::Restricted(did)) if did.is_crate_root() => Visibility::Crate,
            Some(ty::Visibility::Restricted(did)) => Visibility::Restricted {
                parent: renderer.id_from_item_default((*did).into()),
                path: renderer.tcx.def_path(*did).to_string_no_crate_verbose(),
            },
        }
    }
}

impl FromClean<attrs::Deprecation> for Deprecation {
    fn from_clean(deprecation: &attrs::Deprecation, _renderer: &JsonRenderer<'_>) -> Self {
        let attrs::Deprecation { since, note, suggestion: _ } = deprecation;
        let since = match since {
            DeprecatedSince::RustcVersion(version) => Some(version.to_string()),
            DeprecatedSince::Future => Some("TBD".to_string()),
            DeprecatedSince::NonStandard(since) => Some(since.to_string()),
            DeprecatedSince::Unspecified | DeprecatedSince::Err => None,
        };
        Deprecation { since, note: note.map(|sym| sym.to_string()) }
    }
}

impl FromClean<clean::GenericArgs> for Option<Box<GenericArgs>> {
    fn from_clean(generic_args: &clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self {
        use clean::GenericArgs::*;
        match generic_args {
            AngleBracketed { args, constraints } => {
                if generic_args.is_empty() {
                    None
                } else {
                    Some(Box::new(GenericArgs::AngleBracketed {
                        args: args.into_json(renderer),
                        constraints: constraints.into_json(renderer),
                    }))
                }
            }
            Parenthesized { inputs, output } => Some(Box::new(GenericArgs::Parenthesized {
                inputs: inputs.into_json(renderer),
                output: output.into_json(renderer),
            })),
            ReturnTypeNotation => Some(Box::new(GenericArgs::ReturnTypeNotation)),
        }
    }
}

impl FromClean<clean::GenericArg> for GenericArg {
    fn from_clean(arg: &clean::GenericArg, renderer: &JsonRenderer<'_>) -> Self {
        use clean::GenericArg::*;
        match arg {
            Lifetime(l) => GenericArg::Lifetime(l.into_json(renderer)),
            Type(t) => GenericArg::Type(t.into_json(renderer)),
            Const(box c) => GenericArg::Const(c.into_json(renderer)),
            Infer => GenericArg::Infer,
        }
    }
}

impl FromClean<clean::ConstantKind> for Constant {
    // FIXME(generic_const_items): Add support for generic const items.
    fn from_clean(constant: &clean::ConstantKind, renderer: &JsonRenderer<'_>) -> Self {
        let tcx = renderer.tcx;
        let expr = constant.expr(tcx);
        let value = constant.value(tcx);
        let is_literal = constant.is_literal(tcx);
        Constant { expr, value, is_literal }
    }
}

impl FromClean<clean::AssocItemConstraint> for AssocItemConstraint {
    fn from_clean(constraint: &clean::AssocItemConstraint, renderer: &JsonRenderer<'_>) -> Self {
        AssocItemConstraint {
            name: constraint.assoc.name.to_string(),
            args: constraint.assoc.args.into_json(renderer),
            binding: constraint.kind.into_json(renderer),
        }
    }
}

impl FromClean<clean::AssocItemConstraintKind> for AssocItemConstraintKind {
    fn from_clean(kind: &clean::AssocItemConstraintKind, renderer: &JsonRenderer<'_>) -> Self {
        use clean::AssocItemConstraintKind::*;
        match kind {
            Equality { term } => AssocItemConstraintKind::Equality(term.into_json(renderer)),
            Bound { bounds } => AssocItemConstraintKind::Constraint(bounds.into_json(renderer)),
        }
    }
}

fn from_clean_item(item: &clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
    use clean::ItemKind::*;
    let name = item.name;
    let is_crate = item.is_crate();
    let header = item.fn_header(renderer.tcx);

    match &item.inner.kind {
        ModuleItem(m) => {
            ItemEnum::Module(Module { is_crate, items: renderer.ids(&m.items), is_stripped: false })
        }
        ImportItem(i) => ItemEnum::Use(i.into_json(renderer)),
        StructItem(s) => ItemEnum::Struct(s.into_json(renderer)),
        UnionItem(u) => ItemEnum::Union(u.into_json(renderer)),
        StructFieldItem(f) => ItemEnum::StructField(f.into_json(renderer)),
        EnumItem(e) => ItemEnum::Enum(e.into_json(renderer)),
        VariantItem(v) => ItemEnum::Variant(v.into_json(renderer)),
        FunctionItem(f) => {
            ItemEnum::Function(from_clean_function(f, true, header.unwrap(), renderer))
        }
        ForeignFunctionItem(f, _) => {
            ItemEnum::Function(from_clean_function(f, false, header.unwrap(), renderer))
        }
        TraitItem(t) => ItemEnum::Trait(t.into_json(renderer)),
        TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_json(renderer)),
        MethodItem(m, _) => {
            ItemEnum::Function(from_clean_function(m, true, header.unwrap(), renderer))
        }
        RequiredMethodItem(m) => {
            ItemEnum::Function(from_clean_function(m, false, header.unwrap(), renderer))
        }
        ImplItem(i) => ItemEnum::Impl(i.into_json(renderer)),
        StaticItem(s) => ItemEnum::Static(from_clean_static(s, rustc_hir::Safety::Safe, renderer)),
        ForeignStaticItem(s, safety) => ItemEnum::Static(from_clean_static(s, *safety, renderer)),
        ForeignTypeItem => ItemEnum::ExternType,
        TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)),
        // FIXME(generic_const_items): Add support for generic free consts
        ConstantItem(ci) => ItemEnum::Constant {
            type_: ci.type_.into_json(renderer),
            const_: ci.kind.into_json(renderer),
        },
        MacroItem(m) => ItemEnum::Macro(m.source.clone()),
        ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_json(renderer)),
        PrimitiveItem(p) => {
            ItemEnum::Primitive(Primitive {
                name: p.as_sym().to_string(),
                impls: Vec::new(), // Added in JsonRenderer::item
            })
        }
        // FIXME(generic_const_items): Add support for generic associated consts.
        RequiredAssocConstItem(_generics, ty) => {
            ItemEnum::AssocConst { type_: ty.into_json(renderer), value: None }
        }
        // FIXME(generic_const_items): Add support for generic associated consts.
        ProvidedAssocConstItem(ci) | ImplAssocConstItem(ci) => ItemEnum::AssocConst {
            type_: ci.type_.into_json(renderer),
            value: Some(ci.kind.expr(renderer.tcx)),
        },
        RequiredAssocTypeItem(g, b) => ItemEnum::AssocType {
            generics: g.into_json(renderer),
            bounds: b.into_json(renderer),
            type_: None,
        },
        AssocTypeItem(t, b) => ItemEnum::AssocType {
            generics: t.generics.into_json(renderer),
            bounds: b.into_json(renderer),
            type_: Some(t.item_type.as_ref().unwrap_or(&t.type_).into_json(renderer)),
        },
        // `convert_item` early returns `None` for stripped items, keywords and attributes.
        KeywordItem | AttributeItem => unreachable!(),
        StrippedItem(inner) => {
            match inner.as_ref() {
                ModuleItem(m) => ItemEnum::Module(Module {
                    is_crate,
                    items: renderer.ids(&m.items),
                    is_stripped: true,
                }),
                // `convert_item` early returns `None` for stripped items we're not including
                _ => unreachable!(),
            }
        }
        ExternCrateItem { src } => ItemEnum::ExternCrate {
            name: name.as_ref().unwrap().to_string(),
            rename: src.map(|x| x.to_string()),
        },
    }
}

impl FromClean<clean::Struct> for Struct {
    fn from_clean(struct_: &clean::Struct, renderer: &JsonRenderer<'_>) -> Self {
        let has_stripped_fields = struct_.has_stripped_entries();
        let clean::Struct { ctor_kind, generics, fields } = struct_;

        let kind = match ctor_kind {
            Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(fields)),
            Some(CtorKind::Const) => {
                assert!(fields.is_empty());
                StructKind::Unit
            }
            None => StructKind::Plain { fields: renderer.ids(fields), has_stripped_fields },
        };

        Struct {
            kind,
            generics: generics.into_json(renderer),
            impls: Vec::new(), // Added in JsonRenderer::item
        }
    }
}

impl FromClean<clean::Union> for Union {
    fn from_clean(union_: &clean::Union, renderer: &JsonRenderer<'_>) -> Self {
        let has_stripped_fields = union_.has_stripped_entries();
        let clean::Union { generics, fields } = union_;
        Union {
            generics: generics.into_json(renderer),
            has_stripped_fields,
            fields: renderer.ids(fields),
            impls: Vec::new(), // Added in JsonRenderer::item
        }
    }
}

impl FromClean<rustc_hir::FnHeader> for FunctionHeader {
    fn from_clean(header: &rustc_hir::FnHeader, renderer: &JsonRenderer<'_>) -> Self {
        let is_unsafe = match header.safety {
            HeaderSafety::SafeTargetFeatures => {
                // The type system's internal implementation details consider
                // safe functions with the `#[target_feature]` attribute to be analogous
                // to unsafe functions: `header.is_unsafe()` returns `true` for them.
                // For rustdoc, this isn't the right decision, so we explicitly return `false`.
                // Context: https://github.com/rust-lang/rust/issues/142655
                false
            }
            HeaderSafety::Normal(Safety::Safe) => false,
            HeaderSafety::Normal(Safety::Unsafe) => true,
        };
        FunctionHeader {
            is_async: header.is_async(),
            is_const: header.is_const(),
            is_unsafe,
            abi: header.abi.into_json(renderer),
        }
    }
}

impl FromClean<ExternAbi> for Abi {
    fn from_clean(a: &ExternAbi, _renderer: &JsonRenderer<'_>) -> Self {
        match *a {
            ExternAbi::Rust => Abi::Rust,
            ExternAbi::C { unwind } => Abi::C { unwind },
            ExternAbi::Cdecl { unwind } => Abi::Cdecl { unwind },
            ExternAbi::Stdcall { unwind } => Abi::Stdcall { unwind },
            ExternAbi::Fastcall { unwind } => Abi::Fastcall { unwind },
            ExternAbi::Aapcs { unwind } => Abi::Aapcs { unwind },
            ExternAbi::Win64 { unwind } => Abi::Win64 { unwind },
            ExternAbi::SysV64 { unwind } => Abi::SysV64 { unwind },
            ExternAbi::System { unwind } => Abi::System { unwind },
            _ => Abi::Other(a.to_string()),
        }
    }
}

impl FromClean<clean::Lifetime> for String {
    fn from_clean(l: &clean::Lifetime, _renderer: &JsonRenderer<'_>) -> String {
        l.0.to_string()
    }
}

impl FromClean<clean::Generics> for Generics {
    fn from_clean(generics: &clean::Generics, renderer: &JsonRenderer<'_>) -> Self {
        Generics {
            params: generics.params.into_json(renderer),
            where_predicates: generics.where_predicates.into_json(renderer),
        }
    }
}

impl FromClean<clean::GenericParamDef> for GenericParamDef {
    fn from_clean(generic_param: &clean::GenericParamDef, renderer: &JsonRenderer<'_>) -> Self {
        GenericParamDef {
            name: generic_param.name.to_string(),
            kind: generic_param.kind.into_json(renderer),
        }
    }
}

impl FromClean<clean::GenericParamDefKind> for GenericParamDefKind {
    fn from_clean(kind: &clean::GenericParamDefKind, renderer: &JsonRenderer<'_>) -> Self {
        use clean::GenericParamDefKind::*;
        match kind {
            Lifetime { outlives } => {
                GenericParamDefKind::Lifetime { outlives: outlives.into_json(renderer) }
            }
            Type { bounds, default, synthetic } => GenericParamDefKind::Type {
                bounds: bounds.into_json(renderer),
                default: default.into_json(renderer),
                is_synthetic: *synthetic,
            },
            Const { ty, default } => GenericParamDefKind::Const {
                type_: ty.into_json(renderer),
                default: default.as_ref().map(|x| x.as_ref().clone()),
            },
        }
    }
}

impl FromClean<clean::WherePredicate> for WherePredicate {
    fn from_clean(predicate: &clean::WherePredicate, renderer: &JsonRenderer<'_>) -> Self {
        use clean::WherePredicate::*;
        match predicate {
            BoundPredicate { ty, bounds, bound_params } => WherePredicate::BoundPredicate {
                type_: ty.into_json(renderer),
                bounds: bounds.into_json(renderer),
                generic_params: bound_params.into_json(renderer),
            },
            RegionPredicate { lifetime, bounds } => WherePredicate::LifetimePredicate {
                lifetime: lifetime.into_json(renderer),
                outlives: bounds
                    .iter()
                    .map(|bound| match bound {
                        clean::GenericBound::Outlives(lt) => lt.into_json(renderer),
                        _ => bug!("found non-outlives-bound on lifetime predicate"),
                    })
                    .collect(),
            },
            EqPredicate { lhs, rhs } => WherePredicate::EqPredicate {
                // The LHS currently has type `Type` but it should be a `QualifiedPath` since it may
                // refer to an associated const. However, `EqPredicate` shouldn't exist in the first
                // place: <https://github.com/rust-lang/rust/141368>.
                lhs: lhs.into_json(renderer),
                rhs: rhs.into_json(renderer),
            },
        }
    }
}

impl FromClean<clean::GenericBound> for GenericBound {
    fn from_clean(bound: &clean::GenericBound, renderer: &JsonRenderer<'_>) -> Self {
        use clean::GenericBound::*;
        match bound {
            TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
                GenericBound::TraitBound {
                    trait_: trait_.into_json(renderer),
                    generic_params: generic_params.into_json(renderer),
                    modifier: modifier.into_json(renderer),
                }
            }
            Outlives(lifetime) => GenericBound::Outlives(lifetime.into_json(renderer)),
            Use(args) => GenericBound::Use(
                args.iter()
                    .map(|arg| match arg {
                        clean::PreciseCapturingArg::Lifetime(lt) => {
                            PreciseCapturingArg::Lifetime(lt.into_json(renderer))
                        }
                        clean::PreciseCapturingArg::Param(param) => {
                            PreciseCapturingArg::Param(param.to_string())
                        }
                    })
                    .collect(),
            ),
        }
    }
}

impl FromClean<rustc_hir::TraitBoundModifiers> for TraitBoundModifier {
    fn from_clean(
        modifiers: &rustc_hir::TraitBoundModifiers,
        _renderer: &JsonRenderer<'_>,
    ) -> Self {
        use rustc_hir as hir;
        let hir::TraitBoundModifiers { constness, polarity } = modifiers;
        match (constness, polarity) {
            (hir::BoundConstness::Never, hir::BoundPolarity::Positive) => TraitBoundModifier::None,
            (hir::BoundConstness::Never, hir::BoundPolarity::Maybe(_)) => TraitBoundModifier::Maybe,
            (hir::BoundConstness::Maybe(_), hir::BoundPolarity::Positive) => {
                TraitBoundModifier::MaybeConst
            }
            // FIXME: Fill out the rest of this matrix.
            _ => TraitBoundModifier::None,
        }
    }
}

impl FromClean<clean::Type> for Type {
    fn from_clean(ty: &clean::Type, renderer: &JsonRenderer<'_>) -> Self {
        use clean::Type::{
            Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
            RawPointer, SelfTy, Slice, Tuple, UnsafeBinder,
        };

        match ty {
            clean::Type::Path { path } => Type::ResolvedPath(path.into_json(renderer)),
            clean::Type::DynTrait(bounds, lt) => Type::DynTrait(DynTrait {
                lifetime: lt.into_json(renderer),
                traits: bounds.into_json(renderer),
            }),
            Generic(s) => Type::Generic(s.to_string()),
            // FIXME: add dedicated variant to json Type?
            SelfTy => Type::Generic("Self".to_owned()),
            Primitive(p) => Type::Primitive(p.as_sym().to_string()),
            BareFunction(f) => Type::FunctionPointer(Box::new(f.into_json(renderer))),
            Tuple(t) => Type::Tuple(t.into_json(renderer)),
            Slice(t) => Type::Slice(Box::new(t.into_json(renderer))),
            Array(t, s) => {
                Type::Array { type_: Box::new(t.into_json(renderer)), len: s.to_string() }
            }
            clean::Type::Pat(t, p) => Type::Pat {
                type_: Box::new(t.into_json(renderer)),
                __pat_unstable_do_not_use: p.to_string(),
            },
            ImplTrait(g) => Type::ImplTrait(g.into_json(renderer)),
            Infer => Type::Infer,
            RawPointer(mutability, type_) => Type::RawPointer {
                is_mutable: *mutability == ast::Mutability::Mut,
                type_: Box::new(type_.into_json(renderer)),
            },
            BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
                lifetime: lifetime.into_json(renderer),
                is_mutable: *mutability == ast::Mutability::Mut,
                type_: Box::new(type_.into_json(renderer)),
            },
            QPath(qpath) => qpath.into_json(renderer),
            // FIXME(unsafe_binder): Implement rustdoc-json.
            UnsafeBinder(_) => todo!(),
        }
    }
}

impl FromClean<clean::Path> for Path {
    fn from_clean(path: &clean::Path, renderer: &JsonRenderer<'_>) -> Self {
        Path {
            path: path.whole_name(),
            id: renderer.id_from_item_default(path.def_id().into()),
            args: {
                if let Some((final_seg, rest_segs)) = path.segments.split_last() {
                    // In general, `clean::Path` can hold things like
                    // `std::vec::Vec::<u32>::new`, where generic args appear
                    // in a middle segment. But for the places where `Path` is
                    // used by rustdoc-json-types, generic args can only be
                    // used in the final segment, e.g. `std::vec::Vec<u32>`. So
                    // check that the non-final segments have no generic args.
                    assert!(rest_segs.iter().all(|seg| seg.args.is_empty()));
                    final_seg.args.into_json(renderer)
                } else {
                    None // no generics on any segments because there are no segments
                }
            },
        }
    }
}

impl FromClean<clean::QPathData> for Type {
    fn from_clean(qpath: &clean::QPathData, renderer: &JsonRenderer<'_>) -> Self {
        let clean::QPathData { assoc, self_type, should_fully_qualify: _, trait_ } = qpath;

        Self::QualifiedPath {
            name: assoc.name.to_string(),
            args: assoc.args.into_json(renderer),
            self_type: Box::new(self_type.into_json(renderer)),
            trait_: trait_.into_json(renderer),
        }
    }
}

impl FromClean<clean::Term> for Term {
    fn from_clean(term: &clean::Term, renderer: &JsonRenderer<'_>) -> Self {
        match term {
            clean::Term::Type(ty) => Term::Type(ty.into_json(renderer)),
            clean::Term::Constant(c) => Term::Constant(c.into_json(renderer)),
        }
    }
}

impl FromClean<clean::BareFunctionDecl> for FunctionPointer {
    fn from_clean(bare_decl: &clean::BareFunctionDecl, renderer: &JsonRenderer<'_>) -> Self {
        let clean::BareFunctionDecl { safety, generic_params, decl, abi } = bare_decl;
        FunctionPointer {
            header: FunctionHeader {
                is_unsafe: safety.is_unsafe(),
                is_const: false,
                is_async: false,
                abi: abi.into_json(renderer),
            },
            generic_params: generic_params.into_json(renderer),
            sig: decl.into_json(renderer),
        }
    }
}

impl FromClean<clean::FnDecl> for FunctionSignature {
    fn from_clean(decl: &clean::FnDecl, renderer: &JsonRenderer<'_>) -> Self {
        let clean::FnDecl { inputs, output, c_variadic } = decl;
        FunctionSignature {
            inputs: inputs
                .iter()
                .map(|param| {
                    // `_` is the most sensible name for missing param names.
                    let name = param.name.unwrap_or(kw::Underscore).to_string();
                    let type_ = param.type_.into_json(renderer);
                    (name, type_)
                })
                .collect(),
            output: if output.is_unit() { None } else { Some(output.into_json(renderer)) },
            is_c_variadic: *c_variadic,
        }
    }
}

impl FromClean<clean::Trait> for Trait {
    fn from_clean(trait_: &clean::Trait, renderer: &JsonRenderer<'_>) -> Self {
        let tcx = renderer.tcx;
        let is_auto = trait_.is_auto(tcx);
        let is_unsafe = trait_.safety(tcx).is_unsafe();
        let is_dyn_compatible = trait_.is_dyn_compatible(tcx);
        let clean::Trait { items, generics, bounds, .. } = trait_;
        Trait {
            is_auto,
            is_unsafe,
            is_dyn_compatible,
            items: renderer.ids(items),
            generics: generics.into_json(renderer),
            bounds: bounds.into_json(renderer),
            implementations: Vec::new(), // Added in JsonRenderer::item
        }
    }
}

impl FromClean<clean::PolyTrait> for PolyTrait {
    fn from_clean(
        clean::PolyTrait { trait_, generic_params }: &clean::PolyTrait,
        renderer: &JsonRenderer<'_>,
    ) -> Self {
        PolyTrait {
            trait_: trait_.into_json(renderer),
            generic_params: generic_params.into_json(renderer),
        }
    }
}

impl FromClean<clean::Impl> for Impl {
    fn from_clean(impl_: &clean::Impl, renderer: &JsonRenderer<'_>) -> Self {
        let provided_trait_methods = impl_.provided_trait_methods(renderer.tcx);
        let clean::Impl { safety, generics, trait_, for_, items, polarity, kind } = impl_;
        // FIXME: use something like ImplKind in JSON?
        let (is_synthetic, blanket_impl) = match kind {
            clean::ImplKind::Normal | clean::ImplKind::FakeVariadic => (false, None),
            clean::ImplKind::Auto => (true, None),
            clean::ImplKind::Blanket(ty) => (false, Some(ty)),
        };
        let is_negative = match polarity {
            ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false,
            ty::ImplPolarity::Negative => true,
        };
        Impl {
            is_unsafe: safety.is_unsafe(),
            generics: generics.into_json(renderer),
            provided_trait_methods: provided_trait_methods
                .into_iter()
                .map(|x| x.to_string())
                .collect(),
            trait_: trait_.into_json(renderer),
            for_: for_.into_json(renderer),
            items: renderer.ids(items),
            is_negative,
            is_synthetic,
            blanket_impl: blanket_impl.map(|x| x.into_json(renderer)),
        }
    }
}

pub(crate) fn from_clean_function(
    clean::Function { decl, generics }: &clean::Function,
    has_body: bool,
    header: rustc_hir::FnHeader,
    renderer: &JsonRenderer<'_>,
) -> Function {
    Function {
        sig: decl.into_json(renderer),
        generics: generics.into_json(renderer),
        header: header.into_json(renderer),
        has_body,
    }
}

impl FromClean<clean::Enum> for Enum {
    fn from_clean(enum_: &clean::Enum, renderer: &JsonRenderer<'_>) -> Self {
        let has_stripped_variants = enum_.has_stripped_entries();
        let clean::Enum { variants, generics } = enum_;
        Enum {
            generics: generics.into_json(renderer),
            has_stripped_variants,
            variants: renderer.ids(&variants.as_slice().raw),
            impls: Vec::new(), // Added in JsonRenderer::item
        }
    }
}

impl FromClean<clean::Variant> for Variant {
    fn from_clean(variant: &clean::Variant, renderer: &JsonRenderer<'_>) -> Self {
        use clean::VariantKind::*;

        let discriminant = variant.discriminant.into_json(renderer);

        let kind = match &variant.kind {
            CLike => VariantKind::Plain,
            Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(fields)),
            Struct(s) => VariantKind::Struct {
                has_stripped_fields: s.has_stripped_entries(),
                fields: renderer.ids(&s.fields),
            },
        };

        Variant { kind, discriminant }
    }
}

impl FromClean<clean::Discriminant> for Discriminant {
    fn from_clean(disr: &clean::Discriminant, renderer: &JsonRenderer<'_>) -> Self {
        let tcx = renderer.tcx;
        Discriminant {
            // expr is only none if going through the inlining path, which gets
            // `rustc_middle` types, not `rustc_hir`, but because JSON never inlines
            // the expr is always some.
            expr: disr.expr(tcx).unwrap(),
            value: disr.value(tcx, false),
        }
    }
}

impl FromClean<clean::Import> for Use {
    fn from_clean(import: &clean::Import, renderer: &JsonRenderer<'_>) -> Self {
        use clean::ImportKind::*;
        let (name, is_glob) = match import.kind {
            Simple(s) => (s.to_string(), false),
            Glob => (import.source.path.last_opt().unwrap_or(sym::asterisk).to_string(), true),
        };
        Use {
            source: import.source.path.whole_name(),
            name,
            id: import.source.did.map(ItemId::from).map(|i| renderer.id_from_item_default(i)),
            is_glob,
        }
    }
}

impl FromClean<clean::ProcMacro> for ProcMacro {
    fn from_clean(mac: &clean::ProcMacro, renderer: &JsonRenderer<'_>) -> Self {
        ProcMacro {
            kind: mac.kind.into_json(renderer),
            helpers: mac.helpers.iter().map(|x| x.to_string()).collect(),
        }
    }
}

impl FromClean<rustc_span::hygiene::MacroKind> for MacroKind {
    fn from_clean(kind: &rustc_span::hygiene::MacroKind, _renderer: &JsonRenderer<'_>) -> Self {
        use rustc_span::hygiene::MacroKind::*;
        match kind {
            Bang => MacroKind::Bang,
            Attr => MacroKind::Attr,
            Derive => MacroKind::Derive,
        }
    }
}

impl FromClean<clean::TypeAlias> for TypeAlias {
    fn from_clean(type_alias: &clean::TypeAlias, renderer: &JsonRenderer<'_>) -> Self {
        let clean::TypeAlias { type_, generics, item_type: _, inner_type: _ } = type_alias;
        TypeAlias { type_: type_.into_json(renderer), generics: generics.into_json(renderer) }
    }
}

fn from_clean_static(
    stat: &clean::Static,
    safety: rustc_hir::Safety,
    renderer: &JsonRenderer<'_>,
) -> Static {
    let tcx = renderer.tcx;
    Static {
        type_: stat.type_.as_ref().into_json(renderer),
        is_mutable: stat.mutability == ast::Mutability::Mut,
        is_unsafe: safety.is_unsafe(),
        expr: stat
            .expr
            .map(|e| rendered_const(tcx, tcx.hir_body(e), tcx.hir_body_owner_def_id(e)))
            .unwrap_or_default(),
    }
}

impl FromClean<clean::TraitAlias> for TraitAlias {
    fn from_clean(alias: &clean::TraitAlias, renderer: &JsonRenderer<'_>) -> Self {
        TraitAlias {
            generics: alias.generics.into_json(renderer),
            params: alias.bounds.into_json(renderer),
        }
    }
}

impl FromClean<ItemType> for ItemKind {
    fn from_clean(kind: &ItemType, _renderer: &JsonRenderer<'_>) -> Self {
        use ItemType::*;
        match kind {
            Module => ItemKind::Module,
            ExternCrate => ItemKind::ExternCrate,
            Import => ItemKind::Use,
            Struct => ItemKind::Struct,
            Union => ItemKind::Union,
            Enum => ItemKind::Enum,
            Function | TyMethod | Method => ItemKind::Function,
            TypeAlias => ItemKind::TypeAlias,
            Static => ItemKind::Static,
            Constant => ItemKind::Constant,
            Trait => ItemKind::Trait,
            Impl => ItemKind::Impl,
            StructField => ItemKind::StructField,
            Variant => ItemKind::Variant,
            Macro => ItemKind::Macro,
            Primitive => ItemKind::Primitive,
            AssocConst => ItemKind::AssocConst,
            AssocType => ItemKind::AssocType,
            ForeignType => ItemKind::ExternType,
            Keyword => ItemKind::Keyword,
            Attribute => ItemKind::Attribute,
            TraitAlias => ItemKind::TraitAlias,
            ProcAttribute => ItemKind::ProcAttribute,
            ProcDerive => ItemKind::ProcDerive,
        }
    }
}

/// Maybe convert a attribute from hir to json.
///
/// Returns `None` if the attribute shouldn't be in the output.
fn maybe_from_hir_attr(
    attr: &hir::Attribute,
    item_id: ItemId,
    tcx: TyCtxt<'_>,
) -> Option<Attribute> {
    use attrs::AttributeKind as AK;

    let kind = match attr {
        hir::Attribute::Parsed(kind) => kind,

        hir::Attribute::Unparsed(_) => {
            return Some(if attr.has_name(sym::macro_export) {
                Attribute::MacroExport
                // FIXME: We should handle `#[doc(hidden)]`.
            } else {
                other_attr(tcx, attr)
            });
        }
    };

    Some(match kind {
        AK::Deprecation { .. } => return None, // Handled separately into Item::deprecation.
        AK::DocComment { .. } => unreachable!("doc comments stripped out earlier"),

        AK::MustUse { reason, span: _ } => {
            Attribute::MustUse { reason: reason.map(|s| s.to_string()) }
        }
        AK::Repr { .. } => repr_attr(
            tcx,
            item_id.as_def_id().expect("all items that could have #[repr] have a DefId"),
        ),
        AK::ExportName { name, span: _ } => Attribute::ExportName(name.to_string()),
        AK::LinkSection { name, span: _ } => Attribute::LinkSection(name.to_string()),
        AK::TargetFeature { features, .. } => Attribute::TargetFeature {
            enable: features.iter().map(|(feat, _span)| feat.to_string()).collect(),
        },

        AK::NoMangle(_) => Attribute::NoMangle,
        AK::NonExhaustive(_) => Attribute::NonExhaustive,
        AK::AutomaticallyDerived(_) => Attribute::AutomaticallyDerived,

        _ => other_attr(tcx, attr),
    })
}

fn other_attr(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Attribute {
    let mut s = rustc_hir_pretty::attribute_to_string(&tcx, attr);
    assert_eq!(s.pop(), Some('\n'));
    Attribute::Other(s)
}

fn repr_attr(tcx: TyCtxt<'_>, def_id: DefId) -> Attribute {
    let repr = tcx.adt_def(def_id).repr();

    let kind = if repr.c() {
        ReprKind::C
    } else if repr.transparent() {
        ReprKind::Transparent
    } else if repr.simd() {
        ReprKind::Simd
    } else {
        ReprKind::Rust
    };

    let align = repr.align.map(|a| a.bytes());
    let packed = repr.pack.map(|p| p.bytes());
    let int = repr.int.map(format_integer_type);

    Attribute::Repr(AttributeRepr { kind, align, packed, int })
}

fn format_integer_type(it: rustc_abi::IntegerType) -> String {
    use rustc_abi::Integer::*;
    use rustc_abi::IntegerType::*;
    match it {
        Pointer(true) => "isize",
        Pointer(false) => "usize",
        Fixed(I8, true) => "i8",
        Fixed(I8, false) => "u8",
        Fixed(I16, true) => "i16",
        Fixed(I16, false) => "u16",
        Fixed(I32, true) => "i32",
        Fixed(I32, false) => "u32",
        Fixed(I64, true) => "i64",
        Fixed(I64, false) => "u64",
        Fixed(I128, true) => "i128",
        Fixed(I128, false) => "u128",
    }
    .to_owned()
}
