]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/json/conversions.rs
Rollup merge of #82714 - estebank:missing-braces, r=oli-obk
[rust.git] / src / librustdoc / json / conversions.rs
1 //! These from impls are used to create the JSON types which get serialized. They're very close to
2 //! the `clean` types but with some fields removed or stringified to simplify the output and not
3 //! expose unstable compiler internals.
4
5 #![allow(rustc::default_hash_types)]
6
7 use std::convert::From;
8
9 use rustc_ast::ast;
10 use rustc_hir::def::CtorKind;
11 use rustc_middle::ty::TyCtxt;
12 use rustc_span::def_id::{DefId, CRATE_DEF_INDEX};
13 use rustc_span::symbol::Symbol;
14 use rustc_span::Pos;
15
16 use rustdoc_json_types::*;
17
18 use crate::clean;
19 use crate::clean::utils::print_const_expr;
20 use crate::formats::item_type::ItemType;
21 use crate::json::JsonRenderer;
22 use std::collections::HashSet;
23
24 impl JsonRenderer<'_> {
25     pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
26         let item_type = ItemType::from(&item);
27         let deprecation = item.deprecation(self.tcx);
28         let clean::Item { source, name, attrs, kind, visibility, def_id } = item;
29         let inner = match *kind {
30             clean::StrippedItem(_) => return None,
31             x => from_clean_item_kind(x, self.tcx, &name),
32         };
33         Some(Item {
34             id: from_def_id(def_id),
35             crate_id: def_id.krate.as_u32(),
36             name: name.map(|sym| sym.to_string()),
37             source: self.convert_span(source),
38             visibility: self.convert_visibility(visibility),
39             docs: attrs.collapsed_doc_value(),
40             links: attrs
41                 .links
42                 .into_iter()
43                 .filter_map(|clean::ItemLink { link, did, .. }| {
44                     did.map(|did| (link, from_def_id(did)))
45                 })
46                 .collect(),
47             attrs: attrs
48                 .other_attrs
49                 .iter()
50                 .map(rustc_ast_pretty::pprust::attribute_to_string)
51                 .collect(),
52             deprecation: deprecation.map(from_deprecation),
53             kind: item_type.into(),
54             inner,
55         })
56     }
57
58     fn convert_span(&self, span: clean::Span) -> Option<Span> {
59         match span.filename(self.sess()) {
60             rustc_span::FileName::Real(name) => {
61                 let hi = span.hi(self.sess());
62                 let lo = span.lo(self.sess());
63                 Some(Span {
64                     filename: match name {
65                         rustc_span::RealFileName::Named(path) => path,
66                         rustc_span::RealFileName::Devirtualized { local_path, virtual_name: _ } => {
67                             local_path
68                         }
69                     },
70                     begin: (lo.line, lo.col.to_usize()),
71                     end: (hi.line, hi.col.to_usize()),
72                 })
73             }
74             _ => None,
75         }
76     }
77
78     fn convert_visibility(&self, v: clean::Visibility) -> Visibility {
79         use clean::Visibility::*;
80         match v {
81             Public => Visibility::Public,
82             Inherited => Visibility::Default,
83             Restricted(did) if did.index == CRATE_DEF_INDEX => Visibility::Crate,
84             Restricted(did) => Visibility::Restricted {
85                 parent: from_def_id(did),
86                 path: self.tcx.def_path(did).to_string_no_crate_verbose(),
87             },
88         }
89     }
90 }
91
92 crate fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation {
93     #[rustfmt::skip]
94     let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation;
95     Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) }
96 }
97
98 impl From<clean::GenericArgs> for GenericArgs {
99     fn from(args: clean::GenericArgs) -> Self {
100         use clean::GenericArgs::*;
101         match args {
102             AngleBracketed { args, bindings } => GenericArgs::AngleBracketed {
103                 args: args.into_iter().map(Into::into).collect(),
104                 bindings: bindings.into_iter().map(Into::into).collect(),
105             },
106             Parenthesized { inputs, output } => GenericArgs::Parenthesized {
107                 inputs: inputs.into_iter().map(Into::into).collect(),
108                 output: output.map(Into::into),
109             },
110         }
111     }
112 }
113
114 impl From<clean::GenericArg> for GenericArg {
115     fn from(arg: clean::GenericArg) -> Self {
116         use clean::GenericArg::*;
117         match arg {
118             Lifetime(l) => GenericArg::Lifetime(l.0.to_string()),
119             Type(t) => GenericArg::Type(t.into()),
120             Const(c) => GenericArg::Const(c.into()),
121         }
122     }
123 }
124
125 impl From<clean::Constant> for Constant {
126     fn from(constant: clean::Constant) -> Self {
127         let clean::Constant { type_, expr, value, is_literal } = constant;
128         Constant { type_: type_.into(), expr, value, is_literal }
129     }
130 }
131
132 impl From<clean::TypeBinding> for TypeBinding {
133     fn from(binding: clean::TypeBinding) -> Self {
134         TypeBinding { name: binding.name.to_string(), binding: binding.kind.into() }
135     }
136 }
137
138 impl From<clean::TypeBindingKind> for TypeBindingKind {
139     fn from(kind: clean::TypeBindingKind) -> Self {
140         use clean::TypeBindingKind::*;
141         match kind {
142             Equality { ty } => TypeBindingKind::Equality(ty.into()),
143             Constraint { bounds } => {
144                 TypeBindingKind::Constraint(bounds.into_iter().map(Into::into).collect())
145             }
146         }
147     }
148 }
149
150 crate fn from_def_id(did: DefId) -> Id {
151     Id(format!("{}:{}", did.krate.as_u32(), u32::from(did.index)))
152 }
153
154 fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option<Symbol>) -> ItemEnum {
155     use clean::ItemKind::*;
156     match item {
157         ModuleItem(m) => ItemEnum::ModuleItem(m.into()),
158         ImportItem(i) => ItemEnum::ImportItem(i.into()),
159         StructItem(s) => ItemEnum::StructItem(s.into()),
160         UnionItem(u) => ItemEnum::UnionItem(u.into()),
161         StructFieldItem(f) => ItemEnum::StructFieldItem(f.into()),
162         EnumItem(e) => ItemEnum::EnumItem(e.into()),
163         VariantItem(v) => ItemEnum::VariantItem(v.into()),
164         FunctionItem(f) => ItemEnum::FunctionItem(f.into()),
165         ForeignFunctionItem(f) => ItemEnum::FunctionItem(f.into()),
166         TraitItem(t) => ItemEnum::TraitItem(t.into()),
167         TraitAliasItem(t) => ItemEnum::TraitAliasItem(t.into()),
168         MethodItem(m, _) => ItemEnum::MethodItem(from_function_method(m, true)),
169         TyMethodItem(m) => ItemEnum::MethodItem(from_function_method(m, false)),
170         ImplItem(i) => ItemEnum::ImplItem(i.into()),
171         StaticItem(s) => ItemEnum::StaticItem(from_clean_static(s, tcx)),
172         ForeignStaticItem(s) => ItemEnum::StaticItem(from_clean_static(s, tcx)),
173         ForeignTypeItem => ItemEnum::ForeignTypeItem,
174         TypedefItem(t, _) => ItemEnum::TypedefItem(t.into()),
175         OpaqueTyItem(t) => ItemEnum::OpaqueTyItem(t.into()),
176         ConstantItem(c) => ItemEnum::ConstantItem(c.into()),
177         MacroItem(m) => ItemEnum::MacroItem(m.source),
178         ProcMacroItem(m) => ItemEnum::ProcMacroItem(m.into()),
179         AssocConstItem(t, s) => ItemEnum::AssocConstItem { type_: t.into(), default: s },
180         AssocTypeItem(g, t) => ItemEnum::AssocTypeItem {
181             bounds: g.into_iter().map(Into::into).collect(),
182             default: t.map(Into::into),
183         },
184         StrippedItem(inner) => from_clean_item_kind(*inner, tcx, name),
185         PrimitiveItem(_) | KeywordItem(_) => {
186             panic!("{:?} is not supported for JSON output", item)
187         }
188         ExternCrateItem { ref src } => ItemEnum::ExternCrateItem {
189             name: name.as_ref().unwrap().to_string(),
190             rename: src.map(|x| x.to_string()),
191         },
192     }
193 }
194
195 impl From<clean::Module> for Module {
196     fn from(module: clean::Module) -> Self {
197         Module { is_crate: module.is_crate, items: ids(module.items) }
198     }
199 }
200
201 impl From<clean::Struct> for Struct {
202     fn from(struct_: clean::Struct) -> Self {
203         let clean::Struct { struct_type, generics, fields, fields_stripped } = struct_;
204         Struct {
205             struct_type: from_ctor_kind(struct_type),
206             generics: generics.into(),
207             fields_stripped,
208             fields: ids(fields),
209             impls: Vec::new(), // Added in JsonRenderer::item
210         }
211     }
212 }
213
214 impl From<clean::Union> for Union {
215     fn from(struct_: clean::Union) -> Self {
216         let clean::Union { generics, fields, fields_stripped } = struct_;
217         Union {
218             generics: generics.into(),
219             fields_stripped,
220             fields: ids(fields),
221             impls: Vec::new(), // Added in JsonRenderer::item
222         }
223     }
224 }
225
226 crate fn from_ctor_kind(struct_type: CtorKind) -> StructType {
227     match struct_type {
228         CtorKind::Fictive => StructType::Plain,
229         CtorKind::Fn => StructType::Tuple,
230         CtorKind::Const => StructType::Unit,
231     }
232 }
233
234 crate fn from_fn_header(header: &rustc_hir::FnHeader) -> HashSet<Qualifiers> {
235     let mut v = HashSet::new();
236
237     if let rustc_hir::Unsafety::Unsafe = header.unsafety {
238         v.insert(Qualifiers::Unsafe);
239     }
240
241     if let rustc_hir::IsAsync::Async = header.asyncness {
242         v.insert(Qualifiers::Async);
243     }
244
245     if let rustc_hir::Constness::Const = header.constness {
246         v.insert(Qualifiers::Const);
247     }
248
249     v
250 }
251
252 impl From<clean::Function> for Function {
253     fn from(function: clean::Function) -> Self {
254         let clean::Function { decl, generics, header } = function;
255         Function {
256             decl: decl.into(),
257             generics: generics.into(),
258             header: from_fn_header(&header),
259             abi: header.abi.to_string(),
260         }
261     }
262 }
263
264 impl From<clean::Generics> for Generics {
265     fn from(generics: clean::Generics) -> Self {
266         Generics {
267             params: generics.params.into_iter().map(Into::into).collect(),
268             where_predicates: generics.where_predicates.into_iter().map(Into::into).collect(),
269         }
270     }
271 }
272
273 impl From<clean::GenericParamDef> for GenericParamDef {
274     fn from(generic_param: clean::GenericParamDef) -> Self {
275         GenericParamDef { name: generic_param.name.to_string(), kind: generic_param.kind.into() }
276     }
277 }
278
279 impl From<clean::GenericParamDefKind> for GenericParamDefKind {
280     fn from(kind: clean::GenericParamDefKind) -> Self {
281         use clean::GenericParamDefKind::*;
282         match kind {
283             Lifetime => GenericParamDefKind::Lifetime,
284             Type { did: _, bounds, default, synthetic: _ } => GenericParamDefKind::Type {
285                 bounds: bounds.into_iter().map(Into::into).collect(),
286                 default: default.map(Into::into),
287             },
288             Const { did: _, ty } => GenericParamDefKind::Const(ty.into()),
289         }
290     }
291 }
292
293 impl From<clean::WherePredicate> for WherePredicate {
294     fn from(predicate: clean::WherePredicate) -> Self {
295         use clean::WherePredicate::*;
296         match predicate {
297             BoundPredicate { ty, bounds } => WherePredicate::BoundPredicate {
298                 ty: ty.into(),
299                 bounds: bounds.into_iter().map(Into::into).collect(),
300             },
301             RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
302                 lifetime: lifetime.0.to_string(),
303                 bounds: bounds.into_iter().map(Into::into).collect(),
304             },
305             EqPredicate { lhs, rhs } => {
306                 WherePredicate::EqPredicate { lhs: lhs.into(), rhs: rhs.into() }
307             }
308         }
309     }
310 }
311
312 impl From<clean::GenericBound> for GenericBound {
313     fn from(bound: clean::GenericBound) -> Self {
314         use clean::GenericBound::*;
315         match bound {
316             TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
317                 GenericBound::TraitBound {
318                     trait_: trait_.into(),
319                     generic_params: generic_params.into_iter().map(Into::into).collect(),
320                     modifier: from_trait_bound_modifier(modifier),
321                 }
322             }
323             Outlives(lifetime) => GenericBound::Outlives(lifetime.0.to_string()),
324         }
325     }
326 }
327
328 crate fn from_trait_bound_modifier(modifier: rustc_hir::TraitBoundModifier) -> TraitBoundModifier {
329     use rustc_hir::TraitBoundModifier::*;
330     match modifier {
331         None => TraitBoundModifier::None,
332         Maybe => TraitBoundModifier::Maybe,
333         MaybeConst => TraitBoundModifier::MaybeConst,
334     }
335 }
336
337 impl From<clean::Type> for Type {
338     fn from(ty: clean::Type) -> Self {
339         use clean::Type::*;
340         match ty {
341             ResolvedPath { path, param_names, did, is_generic: _ } => Type::ResolvedPath {
342                 name: path.whole_name(),
343                 id: from_def_id(did),
344                 args: path.segments.last().map(|args| Box::new(args.clone().args.into())),
345                 param_names: param_names
346                     .map(|v| v.into_iter().map(Into::into).collect())
347                     .unwrap_or_default(),
348             },
349             Generic(s) => Type::Generic(s.to_string()),
350             Primitive(p) => Type::Primitive(p.as_str().to_string()),
351             BareFunction(f) => Type::FunctionPointer(Box::new((*f).into())),
352             Tuple(t) => Type::Tuple(t.into_iter().map(Into::into).collect()),
353             Slice(t) => Type::Slice(Box::new((*t).into())),
354             Array(t, s) => Type::Array { type_: Box::new((*t).into()), len: s },
355             ImplTrait(g) => Type::ImplTrait(g.into_iter().map(Into::into).collect()),
356             Never => Type::Never,
357             Infer => Type::Infer,
358             RawPointer(mutability, type_) => Type::RawPointer {
359                 mutable: mutability == ast::Mutability::Mut,
360                 type_: Box::new((*type_).into()),
361             },
362             BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
363                 lifetime: lifetime.map(|l| l.0.to_string()),
364                 mutable: mutability == ast::Mutability::Mut,
365                 type_: Box::new((*type_).into()),
366             },
367             QPath { name, self_type, trait_ } => Type::QualifiedPath {
368                 name: name.to_string(),
369                 self_type: Box::new((*self_type).into()),
370                 trait_: Box::new((*trait_).into()),
371             },
372         }
373     }
374 }
375
376 impl From<clean::BareFunctionDecl> for FunctionPointer {
377     fn from(bare_decl: clean::BareFunctionDecl) -> Self {
378         let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl;
379         FunctionPointer {
380             header: if let rustc_hir::Unsafety::Unsafe = unsafety {
381                 let mut hs = HashSet::new();
382                 hs.insert(Qualifiers::Unsafe);
383                 hs
384             } else {
385                 HashSet::new()
386             },
387             generic_params: generic_params.into_iter().map(Into::into).collect(),
388             decl: decl.into(),
389             abi: abi.to_string(),
390         }
391     }
392 }
393
394 impl From<clean::FnDecl> for FnDecl {
395     fn from(decl: clean::FnDecl) -> Self {
396         let clean::FnDecl { inputs, output, c_variadic, attrs: _ } = decl;
397         FnDecl {
398             inputs: inputs
399                 .values
400                 .into_iter()
401                 .map(|arg| (arg.name.to_string(), arg.type_.into()))
402                 .collect(),
403             output: match output {
404                 clean::FnRetTy::Return(t) => Some(t.into()),
405                 clean::FnRetTy::DefaultReturn => None,
406             },
407             c_variadic,
408         }
409     }
410 }
411
412 impl From<clean::Trait> for Trait {
413     fn from(trait_: clean::Trait) -> Self {
414         let clean::Trait { unsafety, items, generics, bounds, is_auto } = trait_;
415         Trait {
416             is_auto,
417             is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
418             items: ids(items),
419             generics: generics.into(),
420             bounds: bounds.into_iter().map(Into::into).collect(),
421             implementors: Vec::new(), // Added in JsonRenderer::item
422         }
423     }
424 }
425
426 impl From<clean::Impl> for Impl {
427     fn from(impl_: clean::Impl) -> Self {
428         let clean::Impl {
429             unsafety,
430             generics,
431             provided_trait_methods,
432             trait_,
433             for_,
434             items,
435             negative_polarity,
436             synthetic,
437             blanket_impl,
438         } = impl_;
439         Impl {
440             is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
441             generics: generics.into(),
442             provided_trait_methods: provided_trait_methods
443                 .into_iter()
444                 .map(|x| x.to_string())
445                 .collect(),
446             trait_: trait_.map(Into::into),
447             for_: for_.into(),
448             items: ids(items),
449             negative: negative_polarity,
450             synthetic,
451             blanket_impl: blanket_impl.map(Into::into),
452         }
453     }
454 }
455
456 crate fn from_function_method(function: clean::Function, has_body: bool) -> Method {
457     let clean::Function { header, decl, generics } = function;
458     Method {
459         decl: decl.into(),
460         generics: generics.into(),
461         header: from_fn_header(&header),
462         abi: header.abi.to_string(),
463         has_body,
464     }
465 }
466
467 impl From<clean::Enum> for Enum {
468     fn from(enum_: clean::Enum) -> Self {
469         let clean::Enum { variants, generics, variants_stripped } = enum_;
470         Enum {
471             generics: generics.into(),
472             variants_stripped,
473             variants: ids(variants),
474             impls: Vec::new(), // Added in JsonRenderer::item
475         }
476     }
477 }
478
479 impl From<clean::VariantStruct> for Struct {
480     fn from(struct_: clean::VariantStruct) -> Self {
481         let clean::VariantStruct { struct_type, fields, fields_stripped } = struct_;
482         Struct {
483             struct_type: from_ctor_kind(struct_type),
484             generics: Default::default(),
485             fields_stripped,
486             fields: ids(fields),
487             impls: Vec::new(),
488         }
489     }
490 }
491
492 impl From<clean::Variant> for Variant {
493     fn from(variant: clean::Variant) -> Self {
494         use clean::Variant::*;
495         match variant {
496             CLike => Variant::Plain,
497             Tuple(t) => Variant::Tuple(t.into_iter().map(Into::into).collect()),
498             Struct(s) => Variant::Struct(ids(s.fields)),
499         }
500     }
501 }
502
503 impl From<clean::Import> for Import {
504     fn from(import: clean::Import) -> Self {
505         use clean::ImportKind::*;
506         match import.kind {
507             Simple(s) => Import {
508                 span: import.source.path.whole_name(),
509                 name: s.to_string(),
510                 id: import.source.did.map(from_def_id),
511                 glob: false,
512             },
513             Glob => Import {
514                 span: import.source.path.whole_name(),
515                 name: import.source.path.last_name().to_string(),
516                 id: import.source.did.map(from_def_id),
517                 glob: true,
518             },
519         }
520     }
521 }
522
523 impl From<clean::ProcMacro> for ProcMacro {
524     fn from(mac: clean::ProcMacro) -> Self {
525         ProcMacro {
526             kind: from_macro_kind(mac.kind),
527             helpers: mac.helpers.iter().map(|x| x.to_string()).collect(),
528         }
529     }
530 }
531
532 crate fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind {
533     use rustc_span::hygiene::MacroKind::*;
534     match kind {
535         Bang => MacroKind::Bang,
536         Attr => MacroKind::Attr,
537         Derive => MacroKind::Derive,
538     }
539 }
540
541 impl From<clean::Typedef> for Typedef {
542     fn from(typedef: clean::Typedef) -> Self {
543         let clean::Typedef { type_, generics, item_type: _ } = typedef;
544         Typedef { type_: type_.into(), generics: generics.into() }
545     }
546 }
547
548 impl From<clean::OpaqueTy> for OpaqueTy {
549     fn from(opaque: clean::OpaqueTy) -> Self {
550         OpaqueTy {
551             bounds: opaque.bounds.into_iter().map(Into::into).collect(),
552             generics: opaque.generics.into(),
553         }
554     }
555 }
556
557 fn from_clean_static(stat: clean::Static, tcx: TyCtxt<'_>) -> Static {
558     Static {
559         type_: stat.type_.into(),
560         mutable: stat.mutability == ast::Mutability::Mut,
561         expr: stat.expr.map(|e| print_const_expr(tcx, e)).unwrap_or_default(),
562     }
563 }
564
565 impl From<clean::TraitAlias> for TraitAlias {
566     fn from(alias: clean::TraitAlias) -> Self {
567         TraitAlias {
568             generics: alias.generics.into(),
569             params: alias.bounds.into_iter().map(Into::into).collect(),
570         }
571     }
572 }
573
574 impl From<ItemType> for ItemKind {
575     fn from(kind: ItemType) -> Self {
576         use ItemType::*;
577         match kind {
578             Module => ItemKind::Module,
579             ExternCrate => ItemKind::ExternCrate,
580             Import => ItemKind::Import,
581             Struct => ItemKind::Struct,
582             Union => ItemKind::Union,
583             Enum => ItemKind::Enum,
584             Function => ItemKind::Function,
585             Typedef => ItemKind::Typedef,
586             OpaqueTy => ItemKind::OpaqueTy,
587             Static => ItemKind::Static,
588             Constant => ItemKind::Constant,
589             Trait => ItemKind::Trait,
590             Impl => ItemKind::Impl,
591             TyMethod | Method => ItemKind::Method,
592             StructField => ItemKind::StructField,
593             Variant => ItemKind::Variant,
594             Macro => ItemKind::Macro,
595             Primitive => ItemKind::Primitive,
596             AssocConst => ItemKind::AssocConst,
597             AssocType => ItemKind::AssocType,
598             ForeignType => ItemKind::ForeignType,
599             Keyword => ItemKind::Keyword,
600             TraitAlias => ItemKind::TraitAlias,
601             ProcAttribute => ItemKind::ProcAttribute,
602             ProcDerive => ItemKind::ProcDerive,
603         }
604     }
605 }
606
607 fn ids(items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
608     items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_def_id(i.def_id)).collect()
609 }