1use rustc_abi::ExternAbi;
6use rustc_ast::ast;
7use rustc_attr_data_structures::{self as attrs, DeprecatedSince};
8use rustc_hir::def::CtorKind;
9use rustc_hir::def_id::DefId;
10use rustc_metadata::rendered_const;
11use rustc_middle::{bug, ty};
12use rustc_span::{Pos, kw, sym};
13use rustdoc_json_types::*;
14use thin_vec::ThinVec;
15
16use crate::clean::{self, ItemId};
17use crate::formats::item_type::ItemType;
18use crate::json::JsonRenderer;
19use crate::passes::collect_intra_doc_links::UrlFragment;
20
21impl JsonRenderer<'_> {
22 pub(super) fn convert_item(&self, item: &clean::Item) -> Option<Item> {
23 let deprecation = item.deprecation(self.tcx);
24 let links = self
25 .cache
26 .intra_doc_links
27 .get(&item.item_id)
28 .into_iter()
29 .flatten()
30 .map(|clean::ItemLink { link, page_id, fragment, .. }| {
31 let id = match fragment {
32 Some(UrlFragment::Item(frag_id)) => *frag_id,
33 Some(UrlFragment::UserWritten(_)) | None => *page_id,
35 };
36
37 (String::from(&**link), self.id_from_item_default(id.into()))
38 })
39 .collect();
40 let docs = item.opt_doc_value();
41 let attrs = item.attributes(self.tcx, &self.cache, true);
42 let span = item.span(self.tcx);
43 let visibility = item.visibility(self.tcx);
44 let clean::ItemInner { name, item_id, .. } = *item.inner;
45 let id = self.id_from_item(&item);
46 let inner = match item.kind {
47 clean::KeywordItem => return None,
48 clean::StrippedItem(ref inner) => {
49 match &**inner {
50 clean::ModuleItem(_)
54 if self.imported_items.contains(&item_id.expect_def_id()) =>
55 {
56 from_clean_item(item, self)
57 }
58 _ => return None,
59 }
60 }
61 _ => from_clean_item(item, self),
62 };
63 Some(Item {
64 id,
65 crate_id: item_id.krate().as_u32(),
66 name: name.map(|sym| sym.to_string()),
67 span: span.and_then(|span| span.into_json(self)),
68 visibility: visibility.into_json(self),
69 docs,
70 attrs,
71 deprecation: deprecation.into_json(self),
72 inner,
73 links,
74 })
75 }
76
77 fn ids(&self, items: &[clean::Item]) -> Vec<Id> {
78 items
79 .iter()
80 .filter(|i| !i.is_stripped() && !i.is_keyword())
81 .map(|i| self.id_from_item(&i))
82 .collect()
83 }
84
85 fn ids_keeping_stripped(&self, items: &[clean::Item]) -> Vec<Option<Id>> {
86 items
87 .iter()
88 .map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(&i)))
89 .collect()
90 }
91}
92
93pub(crate) trait FromClean<T> {
94 fn from_clean(f: &T, renderer: &JsonRenderer<'_>) -> Self;
95}
96
97pub(crate) trait IntoJson<T> {
98 fn into_json(&self, renderer: &JsonRenderer<'_>) -> T;
99}
100
101impl<T, U> IntoJson<U> for T
102where
103 U: FromClean<T>,
104{
105 fn into_json(&self, renderer: &JsonRenderer<'_>) -> U {
106 U::from_clean(self, renderer)
107 }
108}
109
110impl<T, U> FromClean<Box<T>> for U
111where
112 U: FromClean<T>,
113{
114 fn from_clean(opt: &Box<T>, renderer: &JsonRenderer<'_>) -> Self {
115 opt.as_ref().into_json(renderer)
116 }
117}
118
119impl<T, U> FromClean<Option<T>> for Option<U>
120where
121 U: FromClean<T>,
122{
123 fn from_clean(opt: &Option<T>, renderer: &JsonRenderer<'_>) -> Self {
124 opt.as_ref().map(|x| x.into_json(renderer))
125 }
126}
127
128impl<T, U> FromClean<Vec<T>> for Vec<U>
129where
130 U: FromClean<T>,
131{
132 fn from_clean(items: &Vec<T>, renderer: &JsonRenderer<'_>) -> Self {
133 items.iter().map(|i| i.into_json(renderer)).collect()
134 }
135}
136
137impl<T, U> FromClean<ThinVec<T>> for Vec<U>
138where
139 U: FromClean<T>,
140{
141 fn from_clean(items: &ThinVec<T>, renderer: &JsonRenderer<'_>) -> Self {
142 items.iter().map(|i| i.into_json(renderer)).collect()
143 }
144}
145
146impl FromClean<clean::Span> for Option<Span> {
147 fn from_clean(span: &clean::Span, renderer: &JsonRenderer<'_>) -> Self {
148 match span.filename(renderer.sess()) {
149 rustc_span::FileName::Real(name) => {
150 if let Some(local_path) = name.into_local_path() {
151 let hi = span.hi(renderer.sess());
152 let lo = span.lo(renderer.sess());
153 Some(Span {
154 filename: local_path,
155 begin: (lo.line, lo.col.to_usize() + 1),
156 end: (hi.line, hi.col.to_usize() + 1),
157 })
158 } else {
159 None
160 }
161 }
162 _ => None,
163 }
164 }
165}
166
167impl FromClean<Option<ty::Visibility<DefId>>> for Visibility {
168 fn from_clean(v: &Option<ty::Visibility<DefId>>, renderer: &JsonRenderer<'_>) -> Self {
169 match v {
170 None => Visibility::Default,
171 Some(ty::Visibility::Public) => Visibility::Public,
172 Some(ty::Visibility::Restricted(did)) if did.is_crate_root() => Visibility::Crate,
173 Some(ty::Visibility::Restricted(did)) => Visibility::Restricted {
174 parent: renderer.id_from_item_default((*did).into()),
175 path: renderer.tcx.def_path(*did).to_string_no_crate_verbose(),
176 },
177 }
178 }
179}
180
181impl FromClean<attrs::Deprecation> for Deprecation {
182 fn from_clean(deprecation: &attrs::Deprecation, _renderer: &JsonRenderer<'_>) -> Self {
183 let attrs::Deprecation { since, note, suggestion: _ } = deprecation;
184 let since = match since {
185 DeprecatedSince::RustcVersion(version) => Some(version.to_string()),
186 DeprecatedSince::Future => Some("TBD".to_string()),
187 DeprecatedSince::NonStandard(since) => Some(since.to_string()),
188 DeprecatedSince::Unspecified | DeprecatedSince::Err => None,
189 };
190 Deprecation { since, note: note.map(|sym| sym.to_string()) }
191 }
192}
193
194impl FromClean<clean::GenericArgs> for Option<Box<GenericArgs>> {
195 fn from_clean(generic_args: &clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self {
196 use clean::GenericArgs::*;
197 match generic_args {
198 AngleBracketed { args, constraints } => {
199 if generic_args.is_empty() {
200 None
201 } else {
202 Some(Box::new(GenericArgs::AngleBracketed {
203 args: args.into_json(renderer),
204 constraints: constraints.into_json(renderer),
205 }))
206 }
207 }
208 Parenthesized { inputs, output } => Some(Box::new(GenericArgs::Parenthesized {
209 inputs: inputs.into_json(renderer),
210 output: output.into_json(renderer),
211 })),
212 ReturnTypeNotation => Some(Box::new(GenericArgs::ReturnTypeNotation)),
213 }
214 }
215}
216
217impl FromClean<clean::GenericArg> for GenericArg {
218 fn from_clean(arg: &clean::GenericArg, renderer: &JsonRenderer<'_>) -> Self {
219 use clean::GenericArg::*;
220 match arg {
221 Lifetime(l) => GenericArg::Lifetime(l.into_json(renderer)),
222 Type(t) => GenericArg::Type(t.into_json(renderer)),
223 Const(box c) => GenericArg::Const(c.into_json(renderer)),
224 Infer => GenericArg::Infer,
225 }
226 }
227}
228
229impl FromClean<clean::ConstantKind> for Constant {
230 fn from_clean(constant: &clean::ConstantKind, renderer: &JsonRenderer<'_>) -> Self {
232 let tcx = renderer.tcx;
233 let expr = constant.expr(tcx);
234 let value = constant.value(tcx);
235 let is_literal = constant.is_literal(tcx);
236 Constant { expr, value, is_literal }
237 }
238}
239
240impl FromClean<clean::AssocItemConstraint> for AssocItemConstraint {
241 fn from_clean(constraint: &clean::AssocItemConstraint, renderer: &JsonRenderer<'_>) -> Self {
242 AssocItemConstraint {
243 name: constraint.assoc.name.to_string(),
244 args: constraint.assoc.args.into_json(renderer),
245 binding: constraint.kind.into_json(renderer),
246 }
247 }
248}
249
250impl FromClean<clean::AssocItemConstraintKind> for AssocItemConstraintKind {
251 fn from_clean(kind: &clean::AssocItemConstraintKind, renderer: &JsonRenderer<'_>) -> Self {
252 use clean::AssocItemConstraintKind::*;
253 match kind {
254 Equality { term } => AssocItemConstraintKind::Equality(term.into_json(renderer)),
255 Bound { bounds } => AssocItemConstraintKind::Constraint(bounds.into_json(renderer)),
256 }
257 }
258}
259
260fn from_clean_item(item: &clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
261 use clean::ItemKind::*;
262 let name = item.name;
263 let is_crate = item.is_crate();
264 let header = item.fn_header(renderer.tcx);
265
266 match &item.inner.kind {
267 ModuleItem(m) => {
268 ItemEnum::Module(Module { is_crate, items: renderer.ids(&m.items), is_stripped: false })
269 }
270 ImportItem(i) => ItemEnum::Use(i.into_json(renderer)),
271 StructItem(s) => ItemEnum::Struct(s.into_json(renderer)),
272 UnionItem(u) => ItemEnum::Union(u.into_json(renderer)),
273 StructFieldItem(f) => ItemEnum::StructField(f.into_json(renderer)),
274 EnumItem(e) => ItemEnum::Enum(e.into_json(renderer)),
275 VariantItem(v) => ItemEnum::Variant(v.into_json(renderer)),
276 FunctionItem(f) => {
277 ItemEnum::Function(from_clean_function(f, true, header.unwrap(), renderer))
278 }
279 ForeignFunctionItem(f, _) => {
280 ItemEnum::Function(from_clean_function(f, false, header.unwrap(), renderer))
281 }
282 TraitItem(t) => ItemEnum::Trait(t.into_json(renderer)),
283 TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_json(renderer)),
284 MethodItem(m, _) => {
285 ItemEnum::Function(from_clean_function(m, true, header.unwrap(), renderer))
286 }
287 RequiredMethodItem(m) => {
288 ItemEnum::Function(from_clean_function(m, false, header.unwrap(), renderer))
289 }
290 ImplItem(i) => ItemEnum::Impl(i.into_json(renderer)),
291 StaticItem(s) => ItemEnum::Static(from_clean_static(s, rustc_hir::Safety::Safe, renderer)),
292 ForeignStaticItem(s, safety) => ItemEnum::Static(from_clean_static(s, *safety, renderer)),
293 ForeignTypeItem => ItemEnum::ExternType,
294 TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)),
295 ConstantItem(ci) => ItemEnum::Constant {
297 type_: ci.type_.into_json(renderer),
298 const_: ci.kind.into_json(renderer),
299 },
300 MacroItem(m) => ItemEnum::Macro(m.source.clone()),
301 ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_json(renderer)),
302 PrimitiveItem(p) => {
303 ItemEnum::Primitive(Primitive {
304 name: p.as_sym().to_string(),
305 impls: Vec::new(), })
307 }
308 RequiredAssocConstItem(_generics, ty) => {
310 ItemEnum::AssocConst { type_: ty.into_json(renderer), value: None }
311 }
312 ProvidedAssocConstItem(ci) | ImplAssocConstItem(ci) => ItemEnum::AssocConst {
314 type_: ci.type_.into_json(renderer),
315 value: Some(ci.kind.expr(renderer.tcx)),
316 },
317 RequiredAssocTypeItem(g, b) => ItemEnum::AssocType {
318 generics: g.into_json(renderer),
319 bounds: b.into_json(renderer),
320 type_: None,
321 },
322 AssocTypeItem(t, b) => ItemEnum::AssocType {
323 generics: t.generics.into_json(renderer),
324 bounds: b.into_json(renderer),
325 type_: Some(t.item_type.as_ref().unwrap_or(&t.type_).into_json(renderer)),
326 },
327 KeywordItem => unreachable!(),
329 StrippedItem(inner) => {
330 match inner.as_ref() {
331 ModuleItem(m) => ItemEnum::Module(Module {
332 is_crate,
333 items: renderer.ids(&m.items),
334 is_stripped: true,
335 }),
336 _ => unreachable!(),
338 }
339 }
340 ExternCrateItem { src } => ItemEnum::ExternCrate {
341 name: name.as_ref().unwrap().to_string(),
342 rename: src.map(|x| x.to_string()),
343 },
344 }
345}
346
347impl FromClean<clean::Struct> for Struct {
348 fn from_clean(struct_: &clean::Struct, renderer: &JsonRenderer<'_>) -> Self {
349 let has_stripped_fields = struct_.has_stripped_entries();
350 let clean::Struct { ctor_kind, generics, fields } = struct_;
351
352 let kind = match ctor_kind {
353 Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(&fields)),
354 Some(CtorKind::Const) => {
355 assert!(fields.is_empty());
356 StructKind::Unit
357 }
358 None => StructKind::Plain { fields: renderer.ids(&fields), has_stripped_fields },
359 };
360
361 Struct {
362 kind,
363 generics: generics.into_json(renderer),
364 impls: Vec::new(), }
366 }
367}
368
369impl FromClean<clean::Union> for Union {
370 fn from_clean(union_: &clean::Union, renderer: &JsonRenderer<'_>) -> Self {
371 let has_stripped_fields = union_.has_stripped_entries();
372 let clean::Union { generics, fields } = union_;
373 Union {
374 generics: generics.into_json(renderer),
375 has_stripped_fields,
376 fields: renderer.ids(&fields),
377 impls: Vec::new(), }
379 }
380}
381
382impl FromClean<rustc_hir::FnHeader> for FunctionHeader {
383 fn from_clean(header: &rustc_hir::FnHeader, renderer: &JsonRenderer<'_>) -> Self {
384 FunctionHeader {
385 is_async: header.is_async(),
386 is_const: header.is_const(),
387 is_unsafe: header.is_unsafe(),
388 abi: header.abi.into_json(renderer),
389 }
390 }
391}
392
393impl FromClean<ExternAbi> for Abi {
394 fn from_clean(a: &ExternAbi, _renderer: &JsonRenderer<'_>) -> Self {
395 match *a {
396 ExternAbi::Rust => Abi::Rust,
397 ExternAbi::C { unwind } => Abi::C { unwind },
398 ExternAbi::Cdecl { unwind } => Abi::Cdecl { unwind },
399 ExternAbi::Stdcall { unwind } => Abi::Stdcall { unwind },
400 ExternAbi::Fastcall { unwind } => Abi::Fastcall { unwind },
401 ExternAbi::Aapcs { unwind } => Abi::Aapcs { unwind },
402 ExternAbi::Win64 { unwind } => Abi::Win64 { unwind },
403 ExternAbi::SysV64 { unwind } => Abi::SysV64 { unwind },
404 ExternAbi::System { unwind } => Abi::System { unwind },
405 _ => Abi::Other(a.to_string()),
406 }
407 }
408}
409
410impl FromClean<clean::Lifetime> for String {
411 fn from_clean(l: &clean::Lifetime, _renderer: &JsonRenderer<'_>) -> String {
412 l.0.to_string()
413 }
414}
415
416impl FromClean<clean::Generics> for Generics {
417 fn from_clean(generics: &clean::Generics, renderer: &JsonRenderer<'_>) -> Self {
418 Generics {
419 params: generics.params.into_json(renderer),
420 where_predicates: generics.where_predicates.into_json(renderer),
421 }
422 }
423}
424
425impl FromClean<clean::GenericParamDef> for GenericParamDef {
426 fn from_clean(generic_param: &clean::GenericParamDef, renderer: &JsonRenderer<'_>) -> Self {
427 GenericParamDef {
428 name: generic_param.name.to_string(),
429 kind: generic_param.kind.into_json(renderer),
430 }
431 }
432}
433
434impl FromClean<clean::GenericParamDefKind> for GenericParamDefKind {
435 fn from_clean(kind: &clean::GenericParamDefKind, renderer: &JsonRenderer<'_>) -> Self {
436 use clean::GenericParamDefKind::*;
437 match kind {
438 Lifetime { outlives } => {
439 GenericParamDefKind::Lifetime { outlives: outlives.into_json(renderer) }
440 }
441 Type { bounds, default, synthetic } => GenericParamDefKind::Type {
442 bounds: bounds.into_json(renderer),
443 default: default.into_json(renderer),
444 is_synthetic: *synthetic,
445 },
446 Const { ty, default, synthetic: _ } => GenericParamDefKind::Const {
447 type_: ty.into_json(renderer),
448 default: default.as_ref().map(|x| x.as_ref().clone()),
449 },
450 }
451 }
452}
453
454impl FromClean<clean::WherePredicate> for WherePredicate {
455 fn from_clean(predicate: &clean::WherePredicate, renderer: &JsonRenderer<'_>) -> Self {
456 use clean::WherePredicate::*;
457 match predicate {
458 BoundPredicate { ty, bounds, bound_params } => WherePredicate::BoundPredicate {
459 type_: ty.into_json(renderer),
460 bounds: bounds.into_json(renderer),
461 generic_params: bound_params.into_json(renderer),
462 },
463 RegionPredicate { lifetime, bounds } => WherePredicate::LifetimePredicate {
464 lifetime: lifetime.into_json(renderer),
465 outlives: bounds
466 .iter()
467 .map(|bound| match bound {
468 clean::GenericBound::Outlives(lt) => lt.into_json(renderer),
469 _ => bug!("found non-outlives-bound on lifetime predicate"),
470 })
471 .collect(),
472 },
473 EqPredicate { lhs, rhs } => WherePredicate::EqPredicate {
474 lhs: lhs.into_json(renderer),
478 rhs: rhs.into_json(renderer),
479 },
480 }
481 }
482}
483
484impl FromClean<clean::GenericBound> for GenericBound {
485 fn from_clean(bound: &clean::GenericBound, renderer: &JsonRenderer<'_>) -> Self {
486 use clean::GenericBound::*;
487 match bound {
488 TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
489 GenericBound::TraitBound {
490 trait_: trait_.into_json(renderer),
491 generic_params: generic_params.into_json(renderer),
492 modifier: modifier.into_json(renderer),
493 }
494 }
495 Outlives(lifetime) => GenericBound::Outlives(lifetime.into_json(renderer)),
496 Use(args) => GenericBound::Use(
497 args.iter()
498 .map(|arg| match arg {
499 clean::PreciseCapturingArg::Lifetime(lt) => {
500 PreciseCapturingArg::Lifetime(lt.into_json(renderer))
501 }
502 clean::PreciseCapturingArg::Param(param) => {
503 PreciseCapturingArg::Param(param.to_string())
504 }
505 })
506 .collect(),
507 ),
508 }
509 }
510}
511
512impl FromClean<rustc_hir::TraitBoundModifiers> for TraitBoundModifier {
513 fn from_clean(
514 modifiers: &rustc_hir::TraitBoundModifiers,
515 _renderer: &JsonRenderer<'_>,
516 ) -> Self {
517 use rustc_hir as hir;
518 let hir::TraitBoundModifiers { constness, polarity } = modifiers;
519 match (constness, polarity) {
520 (hir::BoundConstness::Never, hir::BoundPolarity::Positive) => TraitBoundModifier::None,
521 (hir::BoundConstness::Never, hir::BoundPolarity::Maybe(_)) => TraitBoundModifier::Maybe,
522 (hir::BoundConstness::Maybe(_), hir::BoundPolarity::Positive) => {
523 TraitBoundModifier::MaybeConst
524 }
525 _ => TraitBoundModifier::None,
527 }
528 }
529}
530
531impl FromClean<clean::Type> for Type {
532 fn from_clean(ty: &clean::Type, renderer: &JsonRenderer<'_>) -> Self {
533 use clean::Type::{
534 Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
535 RawPointer, SelfTy, Slice, Tuple, UnsafeBinder,
536 };
537
538 match ty {
539 clean::Type::Path { path } => Type::ResolvedPath(path.into_json(renderer)),
540 clean::Type::DynTrait(bounds, lt) => Type::DynTrait(DynTrait {
541 lifetime: lt.into_json(renderer),
542 traits: bounds.into_json(renderer),
543 }),
544 Generic(s) => Type::Generic(s.to_string()),
545 SelfTy => Type::Generic("Self".to_owned()),
547 Primitive(p) => Type::Primitive(p.as_sym().to_string()),
548 BareFunction(f) => Type::FunctionPointer(Box::new(f.into_json(renderer))),
549 Tuple(t) => Type::Tuple(t.into_json(renderer)),
550 Slice(t) => Type::Slice(Box::new(t.into_json(renderer))),
551 Array(t, s) => {
552 Type::Array { type_: Box::new(t.into_json(renderer)), len: s.to_string() }
553 }
554 clean::Type::Pat(t, p) => Type::Pat {
555 type_: Box::new(t.into_json(renderer)),
556 __pat_unstable_do_not_use: p.to_string(),
557 },
558 ImplTrait(g) => Type::ImplTrait(g.into_json(renderer)),
559 Infer => Type::Infer,
560 RawPointer(mutability, type_) => Type::RawPointer {
561 is_mutable: *mutability == ast::Mutability::Mut,
562 type_: Box::new(type_.into_json(renderer)),
563 },
564 BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
565 lifetime: lifetime.into_json(renderer),
566 is_mutable: *mutability == ast::Mutability::Mut,
567 type_: Box::new(type_.into_json(renderer)),
568 },
569 QPath(qpath) => qpath.into_json(renderer),
570 UnsafeBinder(_) => todo!(),
572 }
573 }
574}
575
576impl FromClean<clean::Path> for Path {
577 fn from_clean(path: &clean::Path, renderer: &JsonRenderer<'_>) -> Self {
578 Path {
579 path: path.whole_name(),
580 id: renderer.id_from_item_default(path.def_id().into()),
581 args: {
582 if let Some((final_seg, rest_segs)) = path.segments.split_last() {
583 assert!(rest_segs.iter().all(|seg| seg.args.is_empty()));
590 final_seg.args.into_json(renderer)
591 } else {
592 None }
594 },
595 }
596 }
597}
598
599impl FromClean<clean::QPathData> for Type {
600 fn from_clean(qpath: &clean::QPathData, renderer: &JsonRenderer<'_>) -> Self {
601 let clean::QPathData { assoc, self_type, should_fully_qualify: _, trait_ } = qpath;
602
603 Self::QualifiedPath {
604 name: assoc.name.to_string(),
605 args: assoc.args.into_json(renderer),
606 self_type: Box::new(self_type.into_json(renderer)),
607 trait_: trait_.into_json(renderer),
608 }
609 }
610}
611
612impl FromClean<clean::Term> for Term {
613 fn from_clean(term: &clean::Term, renderer: &JsonRenderer<'_>) -> Self {
614 match term {
615 clean::Term::Type(ty) => Term::Type(ty.into_json(renderer)),
616 clean::Term::Constant(c) => Term::Constant(c.into_json(renderer)),
617 }
618 }
619}
620
621impl FromClean<clean::BareFunctionDecl> for FunctionPointer {
622 fn from_clean(bare_decl: &clean::BareFunctionDecl, renderer: &JsonRenderer<'_>) -> Self {
623 let clean::BareFunctionDecl { safety, generic_params, decl, abi } = bare_decl;
624 FunctionPointer {
625 header: FunctionHeader {
626 is_unsafe: safety.is_unsafe(),
627 is_const: false,
628 is_async: false,
629 abi: abi.into_json(renderer),
630 },
631 generic_params: generic_params.into_json(renderer),
632 sig: decl.into_json(renderer),
633 }
634 }
635}
636
637impl FromClean<clean::FnDecl> for FunctionSignature {
638 fn from_clean(decl: &clean::FnDecl, renderer: &JsonRenderer<'_>) -> Self {
639 let clean::FnDecl { inputs, output, c_variadic } = decl;
640 FunctionSignature {
641 inputs: inputs
642 .into_iter()
643 .map(|param| {
644 let name = param.name.unwrap_or(kw::Underscore).to_string();
646 let type_ = param.type_.into_json(renderer);
647 (name, type_)
648 })
649 .collect(),
650 output: if output.is_unit() { None } else { Some(output.into_json(renderer)) },
651 is_c_variadic: *c_variadic,
652 }
653 }
654}
655
656impl FromClean<clean::Trait> for Trait {
657 fn from_clean(trait_: &clean::Trait, renderer: &JsonRenderer<'_>) -> Self {
658 let tcx = renderer.tcx;
659 let is_auto = trait_.is_auto(tcx);
660 let is_unsafe = trait_.safety(tcx).is_unsafe();
661 let is_dyn_compatible = trait_.is_dyn_compatible(tcx);
662 let clean::Trait { items, generics, bounds, .. } = trait_;
663 Trait {
664 is_auto,
665 is_unsafe,
666 is_dyn_compatible,
667 items: renderer.ids(&items),
668 generics: generics.into_json(renderer),
669 bounds: bounds.into_json(renderer),
670 implementations: Vec::new(), }
672 }
673}
674
675impl FromClean<clean::PolyTrait> for PolyTrait {
676 fn from_clean(
677 clean::PolyTrait { trait_, generic_params }: &clean::PolyTrait,
678 renderer: &JsonRenderer<'_>,
679 ) -> Self {
680 PolyTrait {
681 trait_: trait_.into_json(renderer),
682 generic_params: generic_params.into_json(renderer),
683 }
684 }
685}
686
687impl FromClean<clean::Impl> for Impl {
688 fn from_clean(impl_: &clean::Impl, renderer: &JsonRenderer<'_>) -> Self {
689 let provided_trait_methods = impl_.provided_trait_methods(renderer.tcx);
690 let clean::Impl { safety, generics, trait_, for_, items, polarity, kind } = impl_;
691 let (is_synthetic, blanket_impl) = match kind {
693 clean::ImplKind::Normal | clean::ImplKind::FakeVariadic => (false, None),
694 clean::ImplKind::Auto => (true, None),
695 clean::ImplKind::Blanket(ty) => (false, Some(ty)),
696 };
697 let is_negative = match polarity {
698 ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false,
699 ty::ImplPolarity::Negative => true,
700 };
701 Impl {
702 is_unsafe: safety.is_unsafe(),
703 generics: generics.into_json(renderer),
704 provided_trait_methods: provided_trait_methods
705 .into_iter()
706 .map(|x| x.to_string())
707 .collect(),
708 trait_: trait_.into_json(renderer),
709 for_: for_.into_json(renderer),
710 items: renderer.ids(&items),
711 is_negative,
712 is_synthetic,
713 blanket_impl: blanket_impl.map(|x| x.into_json(renderer)),
714 }
715 }
716}
717
718pub(crate) fn from_clean_function(
719 clean::Function { decl, generics }: &clean::Function,
720 has_body: bool,
721 header: rustc_hir::FnHeader,
722 renderer: &JsonRenderer<'_>,
723) -> Function {
724 Function {
725 sig: decl.into_json(renderer),
726 generics: generics.into_json(renderer),
727 header: header.into_json(renderer),
728 has_body,
729 }
730}
731
732impl FromClean<clean::Enum> for Enum {
733 fn from_clean(enum_: &clean::Enum, renderer: &JsonRenderer<'_>) -> Self {
734 let has_stripped_variants = enum_.has_stripped_entries();
735 let clean::Enum { variants, generics } = enum_;
736 Enum {
737 generics: generics.into_json(renderer),
738 has_stripped_variants,
739 variants: renderer.ids(&variants.as_slice().raw),
740 impls: Vec::new(), }
742 }
743}
744
745impl FromClean<clean::Variant> for Variant {
746 fn from_clean(variant: &clean::Variant, renderer: &JsonRenderer<'_>) -> Self {
747 use clean::VariantKind::*;
748
749 let discriminant = variant.discriminant.into_json(renderer);
750
751 let kind = match &variant.kind {
752 CLike => VariantKind::Plain,
753 Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(&fields)),
754 Struct(s) => VariantKind::Struct {
755 has_stripped_fields: s.has_stripped_entries(),
756 fields: renderer.ids(&s.fields),
757 },
758 };
759
760 Variant { kind, discriminant }
761 }
762}
763
764impl FromClean<clean::Discriminant> for Discriminant {
765 fn from_clean(disr: &clean::Discriminant, renderer: &JsonRenderer<'_>) -> Self {
766 let tcx = renderer.tcx;
767 Discriminant {
768 expr: disr.expr(tcx).unwrap(),
772 value: disr.value(tcx, false),
773 }
774 }
775}
776
777impl FromClean<clean::Import> for Use {
778 fn from_clean(import: &clean::Import, renderer: &JsonRenderer<'_>) -> Self {
779 use clean::ImportKind::*;
780 let (name, is_glob) = match import.kind {
781 Simple(s) => (s.to_string(), false),
782 Glob => (import.source.path.last_opt().unwrap_or(sym::asterisk).to_string(), true),
783 };
784 Use {
785 source: import.source.path.whole_name(),
786 name,
787 id: import.source.did.map(ItemId::from).map(|i| renderer.id_from_item_default(i)),
788 is_glob,
789 }
790 }
791}
792
793impl FromClean<clean::ProcMacro> for ProcMacro {
794 fn from_clean(mac: &clean::ProcMacro, renderer: &JsonRenderer<'_>) -> Self {
795 ProcMacro {
796 kind: mac.kind.into_json(renderer),
797 helpers: mac.helpers.iter().map(|x| x.to_string()).collect(),
798 }
799 }
800}
801
802impl FromClean<rustc_span::hygiene::MacroKind> for MacroKind {
803 fn from_clean(kind: &rustc_span::hygiene::MacroKind, _renderer: &JsonRenderer<'_>) -> Self {
804 use rustc_span::hygiene::MacroKind::*;
805 match kind {
806 Bang => MacroKind::Bang,
807 Attr => MacroKind::Attr,
808 Derive => MacroKind::Derive,
809 }
810 }
811}
812
813impl FromClean<clean::TypeAlias> for TypeAlias {
814 fn from_clean(type_alias: &clean::TypeAlias, renderer: &JsonRenderer<'_>) -> Self {
815 let clean::TypeAlias { type_, generics, item_type: _, inner_type: _ } = type_alias;
816 TypeAlias { type_: type_.into_json(renderer), generics: generics.into_json(renderer) }
817 }
818}
819
820fn from_clean_static(
821 stat: &clean::Static,
822 safety: rustc_hir::Safety,
823 renderer: &JsonRenderer<'_>,
824) -> Static {
825 let tcx = renderer.tcx;
826 Static {
827 type_: stat.type_.as_ref().into_json(renderer),
828 is_mutable: stat.mutability == ast::Mutability::Mut,
829 is_unsafe: safety.is_unsafe(),
830 expr: stat
831 .expr
832 .map(|e| rendered_const(tcx, tcx.hir_body(e), tcx.hir_body_owner_def_id(e)))
833 .unwrap_or_default(),
834 }
835}
836
837impl FromClean<clean::TraitAlias> for TraitAlias {
838 fn from_clean(alias: &clean::TraitAlias, renderer: &JsonRenderer<'_>) -> Self {
839 TraitAlias {
840 generics: alias.generics.into_json(renderer),
841 params: alias.bounds.into_json(renderer),
842 }
843 }
844}
845
846impl FromClean<ItemType> for ItemKind {
847 fn from_clean(kind: &ItemType, _renderer: &JsonRenderer<'_>) -> Self {
848 use ItemType::*;
849 match kind {
850 Module => ItemKind::Module,
851 ExternCrate => ItemKind::ExternCrate,
852 Import => ItemKind::Use,
853 Struct => ItemKind::Struct,
854 Union => ItemKind::Union,
855 Enum => ItemKind::Enum,
856 Function | TyMethod | Method => ItemKind::Function,
857 TypeAlias => ItemKind::TypeAlias,
858 Static => ItemKind::Static,
859 Constant => ItemKind::Constant,
860 Trait => ItemKind::Trait,
861 Impl => ItemKind::Impl,
862 StructField => ItemKind::StructField,
863 Variant => ItemKind::Variant,
864 Macro => ItemKind::Macro,
865 Primitive => ItemKind::Primitive,
866 AssocConst => ItemKind::AssocConst,
867 AssocType => ItemKind::AssocType,
868 ForeignType => ItemKind::ExternType,
869 Keyword => ItemKind::Keyword,
870 TraitAlias => ItemKind::TraitAlias,
871 ProcAttribute => ItemKind::ProcAttribute,
872 ProcDerive => ItemKind::ProcDerive,
873 }
874 }
875}