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