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