"compiler/rustc",
"library/std",
"library/test",
+ "src/librustdoc/json-types",
"src/tools/cargotest",
"src/tools/clippy",
"src/tools/compiletest",
tempfile = "3"
itertools = "0.9"
regex = "1"
+json-types = { path = "./json-types" }
[dev-dependencies]
expect-test = "1.0"
--- /dev/null
+[package]
+name = "json-types"
+version = "0.1.0"
+authors = ["The Rust Project Developers"]
+edition = "2018"
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+serde = { version = "1.0", features = ["derive"] }
--- /dev/null
+//! Rustdoc's JSON output interface
+//!
+//! These types are the public API exposed through the `--output-format json` flag. The [`Crate`]
+//! struct is the root of the JSON blob and all other items are contained within.
+
+use std::collections::HashMap;
+use std::path::PathBuf;
+
+use serde::{Deserialize, Serialize};
+
+/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
+/// about the language items in the local crate, as well as info about external items to allow
+/// tools to find or link to them.
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Crate {
+ /// The id of the root [`Module`] item of the local crate.
+ pub root: Id,
+ /// The version string given to `--crate-version`, if any.
+ pub crate_version: Option<String>,
+ /// Whether or not the output includes private items.
+ pub includes_private: bool,
+ /// A collection of all items in the local crate as well as some external traits and their
+ /// items that are referenced locally.
+ pub index: HashMap<Id, Item>,
+ /// Maps IDs to fully qualified paths and other info helpful for generating links.
+ pub paths: HashMap<Id, ItemSummary>,
+ /// Maps `crate_id` of items to a crate name and html_root_url if it exists.
+ pub external_crates: HashMap<u32, ExternalCrate>,
+ /// A single version number to be used in the future when making backwards incompatible changes
+ /// to the JSON output.
+ pub format_version: u32,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct ExternalCrate {
+ pub name: String,
+ pub html_root_url: Option<String>,
+}
+
+/// For external (not defined in the local crate) items, you don't get the same level of
+/// information. This struct should contain enough to generate a link/reference to the item in
+/// question, or can be used by a tool that takes the json output of multiple crates to find
+/// the actual item definition with all the relevant info.
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct ItemSummary {
+ /// Can be used to look up the name and html_root_url of the crate this item came from in the
+ /// `external_crates` map.
+ pub crate_id: u32,
+ /// The list of path components for the fully qualified path of this item (e.g.
+ /// `["std", "io", "lazy", "Lazy"]` for `std::io::lazy::Lazy`).
+ pub path: Vec<String>,
+ /// Whether this item is a struct, trait, macro, etc.
+ pub kind: ItemKind,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Item {
+ /// The unique identifier of this item. Can be used to find this item in various mappings.
+ pub id: Id,
+ /// This can be used as a key to the `external_crates` map of [`Crate`] to see which crate
+ /// this item came from.
+ pub crate_id: u32,
+ /// Some items such as impls don't have names.
+ pub name: Option<String>,
+ /// The source location of this item (absent if it came from a macro expansion or inline
+ /// assembly).
+ pub source: Option<Span>,
+ /// By default all documented items are public, but you can tell rustdoc to output private items
+ /// so this field is needed to differentiate.
+ pub visibility: Visibility,
+ /// The full markdown docstring of this item. Absent if there is no documentation at all,
+ /// Some("") if there is some documentation but it is empty (EG `#[doc = ""]`).
+ pub docs: Option<String>,
+ /// This mapping resolves [intra-doc links](https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md) from the docstring to their IDs
+ pub links: HashMap<String, Id>,
+ /// Stringified versions of the attributes on this item (e.g. `"#[inline]"`)
+ pub attrs: Vec<String>,
+ pub deprecation: Option<Deprecation>,
+ pub kind: ItemKind,
+ pub inner: ItemEnum,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Span {
+ /// The path to the source file for this span relative to the path `rustdoc` was invoked with.
+ pub filename: PathBuf,
+ /// Zero indexed Line and Column of the first character of the `Span`
+ pub begin: (usize, usize),
+ /// Zero indexed Line and Column of the last character of the `Span`
+ pub end: (usize, usize),
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Deprecation {
+ pub since: Option<String>,
+ pub note: Option<String>,
+}
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum Visibility {
+ Public,
+ /// For the most part items are private by default. The exceptions are associated items of
+ /// public traits and variants of public enums.
+ Default,
+ Crate,
+ /// For `pub(in path)` visibility. `parent` is the module it's restricted to and `path` is how
+ /// that module was referenced (like `"super::super"` or `"crate::foo::bar"`).
+ Restricted {
+ parent: Id,
+ path: String,
+ },
+}
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum GenericArgs {
+ /// <'a, 32, B: Copy, C = u32>
+ AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
+ /// Fn(A, B) -> C
+ Parenthesized { inputs: Vec<Type>, output: Option<Type> },
+}
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum GenericArg {
+ Lifetime(String),
+ Type(Type),
+ Const(Constant),
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Constant {
+ #[serde(rename = "type")]
+ pub type_: Type,
+ pub expr: String,
+ pub value: Option<String>,
+ pub is_literal: bool,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct TypeBinding {
+ pub name: String,
+ pub binding: TypeBindingKind,
+}
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum TypeBindingKind {
+ Equality(Type),
+ Constraint(Vec<GenericBound>),
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub struct Id(pub String);
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum ItemKind {
+ Module,
+ ExternCrate,
+ Import,
+ Struct,
+ StructField,
+ Union,
+ Enum,
+ Variant,
+ Function,
+ Typedef,
+ OpaqueTy,
+ Constant,
+ Trait,
+ TraitAlias,
+ Method,
+ Impl,
+ Static,
+ ForeignType,
+ Macro,
+ ProcAttribute,
+ ProcDerive,
+ AssocConst,
+ AssocType,
+ Primitive,
+ Keyword,
+}
+
+#[serde(untagged)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum ItemEnum {
+ ModuleItem(Module),
+ ExternCrateItem {
+ name: String,
+ rename: Option<String>,
+ },
+ ImportItem(Import),
+
+ StructItem(Struct),
+ StructFieldItem(Type),
+ EnumItem(Enum),
+ VariantItem(Variant),
+
+ FunctionItem(Function),
+
+ TraitItem(Trait),
+ TraitAliasItem(TraitAlias),
+ MethodItem(Method),
+ ImplItem(Impl),
+
+ TypedefItem(Typedef),
+ OpaqueTyItem(OpaqueTy),
+ ConstantItem(Constant),
+
+ StaticItem(Static),
+
+ /// `type`s from an extern block
+ ForeignTypeItem,
+
+ /// Declarative macro_rules! macro
+ MacroItem(String),
+ ProcMacroItem(ProcMacro),
+
+ AssocConstItem {
+ #[serde(rename = "type")]
+ type_: Type,
+ /// e.g. `const X: usize = 5;`
+ default: Option<String>,
+ },
+ AssocTypeItem {
+ bounds: Vec<GenericBound>,
+ /// e.g. `type X = usize;`
+ default: Option<Type>,
+ },
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Module {
+ pub is_crate: bool,
+ pub items: Vec<Id>,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Struct {
+ pub struct_type: StructType,
+ pub generics: Generics,
+ pub fields_stripped: bool,
+ pub fields: Vec<Id>,
+ pub impls: Vec<Id>,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Enum {
+ pub generics: Generics,
+ pub variants_stripped: bool,
+ pub variants: Vec<Id>,
+ pub impls: Vec<Id>,
+}
+
+#[serde(rename_all = "snake_case")]
+#[serde(tag = "variant_kind", content = "variant_inner")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum Variant {
+ Plain,
+ Tuple(Vec<Type>),
+ Struct(Vec<Id>),
+}
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum StructType {
+ Plain,
+ Tuple,
+ Unit,
+ Union,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Function {
+ pub decl: FnDecl,
+ pub generics: Generics,
+ pub header: String,
+ pub abi: String,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Method {
+ pub decl: FnDecl,
+ pub generics: Generics,
+ pub header: String,
+ pub has_body: bool,
+}
+
+#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
+pub struct Generics {
+ pub params: Vec<GenericParamDef>,
+ pub where_predicates: Vec<WherePredicate>,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct GenericParamDef {
+ pub name: String,
+ pub kind: GenericParamDefKind,
+}
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum GenericParamDefKind {
+ Lifetime,
+ Type { bounds: Vec<GenericBound>, default: Option<Type> },
+ Const(Type),
+}
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum WherePredicate {
+ BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
+ RegionPredicate { lifetime: String, bounds: Vec<GenericBound> },
+ EqPredicate { lhs: Type, rhs: Type },
+}
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum GenericBound {
+ TraitBound {
+ #[serde(rename = "trait")]
+ trait_: Type,
+ /// Used for HRTBs
+ generic_params: Vec<GenericParamDef>,
+ modifier: TraitBoundModifier,
+ },
+ Outlives(String),
+}
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum TraitBoundModifier {
+ None,
+ Maybe,
+ MaybeConst,
+}
+
+#[serde(rename_all = "snake_case")]
+#[serde(tag = "kind", content = "inner")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum Type {
+ /// Structs, enums, and traits
+ ResolvedPath {
+ name: String,
+ id: Id,
+ args: Option<Box<GenericArgs>>,
+ param_names: Vec<GenericBound>,
+ },
+ /// Parameterized types
+ Generic(String),
+ /// Fixed-size numeric types (plus int/usize/float), char, arrays, slices, and tuples
+ Primitive(String),
+ /// `extern "ABI" fn`
+ FunctionPointer(Box<FunctionPointer>),
+ /// `(String, u32, Box<usize>)`
+ Tuple(Vec<Type>),
+ /// `[u32]`
+ Slice(Box<Type>),
+ /// [u32; 15]
+ Array {
+ #[serde(rename = "type")]
+ type_: Box<Type>,
+ len: String,
+ },
+ /// `impl TraitA + TraitB + ...`
+ ImplTrait(Vec<GenericBound>),
+ /// `!`
+ Never,
+ /// `_`
+ Infer,
+ /// `*mut u32`, `*u8`, etc.
+ RawPointer {
+ mutable: bool,
+ #[serde(rename = "type")]
+ type_: Box<Type>,
+ },
+ /// `&'a mut String`, `&str`, etc.
+ BorrowedRef {
+ lifetime: Option<String>,
+ mutable: bool,
+ #[serde(rename = "type")]
+ type_: Box<Type>,
+ },
+ /// `<Type as Trait>::Name` or associated types like `T::Item` where `T: Iterator`
+ QualifiedPath {
+ name: String,
+ self_type: Box<Type>,
+ #[serde(rename = "trait")]
+ trait_: Box<Type>,
+ },
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct FunctionPointer {
+ pub is_unsafe: bool,
+ pub generic_params: Vec<GenericParamDef>,
+ pub decl: FnDecl,
+ pub abi: String,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct FnDecl {
+ pub inputs: Vec<(String, Type)>,
+ pub output: Option<Type>,
+ pub c_variadic: bool,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Trait {
+ pub is_auto: bool,
+ pub is_unsafe: bool,
+ pub items: Vec<Id>,
+ pub generics: Generics,
+ pub bounds: Vec<GenericBound>,
+ pub implementors: Vec<Id>,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct TraitAlias {
+ pub generics: Generics,
+ pub params: Vec<GenericBound>,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Impl {
+ pub is_unsafe: bool,
+ pub generics: Generics,
+ pub provided_trait_methods: Vec<String>,
+ #[serde(rename = "trait")]
+ pub trait_: Option<Type>,
+ #[serde(rename = "for")]
+ pub for_: Type,
+ pub items: Vec<Id>,
+ pub negative: bool,
+ pub synthetic: bool,
+ pub blanket_impl: Option<Type>,
+}
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Import {
+ /// The full path being imported.
+ pub span: String,
+ /// May be different from the last segment of `source` when renaming imports:
+ /// `use source as name;`
+ pub name: String,
+ /// The ID of the item being imported.
+ pub id: Option<Id>, // FIXME is this actually ever None?
+ /// Whether this import uses a glob: `use source::*;`
+ pub glob: bool,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct ProcMacro {
+ pub kind: MacroKind,
+ pub helpers: Vec<String>,
+}
+
+#[serde(rename_all = "snake_case")]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum MacroKind {
+ /// A bang macro `foo!()`.
+ Bang,
+ /// An attribute macro `#[foo]`.
+ Attr,
+ /// A derive macro `#[derive(Foo)]`
+ Derive,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Typedef {
+ #[serde(rename = "type")]
+ pub type_: Type,
+ pub generics: Generics,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct OpaqueTy {
+ pub bounds: Vec<GenericBound>,
+ pub generics: Generics,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Static {
+ #[serde(rename = "type")]
+ pub type_: Type,
+ pub mutable: bool,
+ pub expr: String,
+}
use rustc_span::def_id::{DefId, CRATE_DEF_INDEX};
use rustc_span::Pos;
+use json_types::*;
+
use crate::clean;
use crate::formats::item_type::ItemType;
-use crate::json::types::*;
use crate::json::JsonRenderer;
impl JsonRenderer<'_> {
match *kind {
clean::StrippedItem(_) => None,
kind => Some(Item {
- id: def_id.into(),
+ id: from_def_id(def_id),
crate_id: def_id.krate.as_u32(),
name: name.map(|sym| sym.to_string()),
source: self.convert_span(source),
.links
.into_iter()
.filter_map(|clean::ItemLink { link, did, .. }| {
- did.map(|did| (link, did.into()))
+ did.map(|did| (link, from_def_id(did)))
})
.collect(),
attrs: attrs
.iter()
.map(rustc_ast_pretty::pprust::attribute_to_string)
.collect(),
- deprecation: deprecation.map(Into::into),
+ deprecation: deprecation.map(from_deprecation),
kind: item_type.into(),
inner: kind.into(),
}),
Inherited => Visibility::Default,
Restricted(did) if did.index == CRATE_DEF_INDEX => Visibility::Crate,
Restricted(did) => Visibility::Restricted {
- parent: did.into(),
+ parent: from_def_id(did),
path: self.tcx.def_path(did).to_string_no_crate_verbose(),
},
}
}
}
-impl From<rustc_attr::Deprecation> for Deprecation {
- fn from(deprecation: rustc_attr::Deprecation) -> Self {
- #[rustfmt::skip]
- let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation;
- Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) }
- }
+crate fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation {
+ #[rustfmt::skip]
+ let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation;
+ Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) }
}
impl From<clean::GenericArgs> for GenericArgs {
}
}
-impl From<DefId> for Id {
- fn from(did: DefId) -> Self {
- Id(format!("{}:{}", did.krate.as_u32(), u32::from(did.index)))
- }
+crate fn from_def_id(did: DefId) -> Id {
+ Id(format!("{}:{}", did.krate.as_u32(), u32::from(did.index)))
}
impl From<clean::ItemKind> for ItemEnum {
fn from(struct_: clean::Struct) -> Self {
let clean::Struct { struct_type, generics, fields, fields_stripped } = struct_;
Struct {
- struct_type: struct_type.into(),
+ struct_type: from_ctor_kind(struct_type),
generics: generics.into(),
fields_stripped,
fields: ids(fields),
}
}
-impl From<CtorKind> for StructType {
- fn from(struct_type: CtorKind) -> Self {
- match struct_type {
- CtorKind::Fictive => StructType::Plain,
- CtorKind::Fn => StructType::Tuple,
- CtorKind::Const => StructType::Unit,
- }
+crate fn from_ctor_kind(struct_type: CtorKind) -> StructType {
+ match struct_type {
+ CtorKind::Fictive => StructType::Plain,
+ CtorKind::Fn => StructType::Tuple,
+ CtorKind::Const => StructType::Unit,
}
}
GenericBound::TraitBound {
trait_: trait_.into(),
generic_params: generic_params.into_iter().map(Into::into).collect(),
- modifier: modifier.into(),
+ modifier: from_trait_bound_modifier(modifier),
}
}
Outlives(lifetime) => GenericBound::Outlives(lifetime.0.to_string()),
}
}
-impl From<rustc_hir::TraitBoundModifier> for TraitBoundModifier {
- fn from(modifier: rustc_hir::TraitBoundModifier) -> Self {
- use rustc_hir::TraitBoundModifier::*;
- match modifier {
- None => TraitBoundModifier::None,
- Maybe => TraitBoundModifier::Maybe,
- MaybeConst => TraitBoundModifier::MaybeConst,
- }
+crate fn from_trait_bound_modifier(modifier: rustc_hir::TraitBoundModifier) -> TraitBoundModifier {
+ use rustc_hir::TraitBoundModifier::*;
+ match modifier {
+ None => TraitBoundModifier::None,
+ Maybe => TraitBoundModifier::Maybe,
+ MaybeConst => TraitBoundModifier::MaybeConst,
}
}
match ty {
ResolvedPath { path, param_names, did, is_generic: _ } => Type::ResolvedPath {
name: path.whole_name(),
- id: did.into(),
+ id: from_def_id(did),
args: path.segments.last().map(|args| Box::new(args.clone().args.into())),
param_names: param_names
.map(|v| v.into_iter().map(Into::into).collect())
fn from(struct_: clean::VariantStruct) -> Self {
let clean::VariantStruct { struct_type, fields, fields_stripped } = struct_;
Struct {
- struct_type: struct_type.into(),
+ struct_type: from_ctor_kind(struct_type),
generics: Default::default(),
fields_stripped,
fields: ids(fields),
Simple(s) => Import {
span: import.source.path.whole_name(),
name: s.to_string(),
- id: import.source.did.map(Into::into),
+ id: import.source.did.map(from_def_id),
glob: false,
},
Glob => Import {
span: import.source.path.whole_name(),
name: import.source.path.last_name().to_string(),
- id: import.source.did.map(Into::into),
+ id: import.source.did.map(from_def_id),
glob: true,
},
}
impl From<clean::ProcMacro> for ProcMacro {
fn from(mac: clean::ProcMacro) -> Self {
ProcMacro {
- kind: mac.kind.into(),
+ kind: from_macro_kind(mac.kind),
helpers: mac.helpers.iter().map(|x| x.to_string()).collect(),
}
}
}
-impl From<rustc_span::hygiene::MacroKind> for MacroKind {
- fn from(kind: rustc_span::hygiene::MacroKind) -> Self {
- use rustc_span::hygiene::MacroKind::*;
- match kind {
- Bang => MacroKind::Bang,
- Attr => MacroKind::Attr,
- Derive => MacroKind::Derive,
- }
+crate fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind {
+ use rustc_span::hygiene::MacroKind::*;
+ match kind {
+ Bang => MacroKind::Bang,
+ Attr => MacroKind::Attr,
+ Derive => MacroKind::Derive,
}
}
}
fn ids(items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
- items.into_iter().filter(|x| !x.is_stripped()).map(|i| i.def_id.into()).collect()
+ items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_def_id(i.def_id)).collect()
}
//! docs for usage and details.
mod conversions;
-pub mod types;
use std::cell::RefCell;
use std::fs::File;
use rustc_session::Session;
use rustc_span::edition::Edition;
+use json_types as types;
+
use crate::clean;
use crate::config::{RenderInfo, RenderOptions};
use crate::error::Error;
use crate::formats::cache::Cache;
use crate::formats::FormatRenderer;
use crate::html::render::cache::ExternalLocation;
+use crate::json::conversions::from_def_id;
#[derive(Clone)]
crate struct JsonRenderer<'tcx> {
.map(|i| {
let item = &i.impl_item;
self.item(item.clone()).unwrap();
- item.def_id.into()
+ from_def_id(item.def_id)
})
.collect()
})
let item = &i.impl_item;
if item.def_id.is_local() {
self.item(item.clone()).unwrap();
- Some(item.def_id.into())
+ Some(from_def_id(item.def_id))
} else {
None
}
if !id.is_local() {
trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap());
Some((
- id.into(),
+ from_def_id(id),
types::Item {
- id: id.into(),
+ id: from_def_id(id),
crate_id: id.krate.as_u32(),
name: self
.cache
} else if let types::ItemEnum::EnumItem(ref mut e) = new_item.inner {
e.impls = self.get_impls(id)
}
- let removed = self.index.borrow_mut().insert(id.into(), new_item.clone());
+ let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone());
// FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
// to make sure the items are unique.
if let Some(old_item) = removed {
debug!("Done with crate");
let mut index = (*self.index).clone().into_inner();
index.extend(self.get_trait_items());
+ let len = index.len();
let output = types::Crate {
root: types::Id(String::from("0:0")),
crate_version: krate.version.clone(),
includes_private: self.cache.document_private,
- index,
+ index: index.into_iter().fold(
+ std::collections::HashMap::with_capacity(len),
+ |mut acc, (key, val)| {
+ acc.insert(key, val);
+ acc
+ },
+ ),
paths: self
.cache
.paths
.chain(self.cache.external_paths.clone().into_iter())
.map(|(k, (path, kind))| {
(
- k.into(),
+ from_def_id(k),
types::ItemSummary { crate_id: k.krate.as_u32(), path, kind: kind.into() },
)
})
+++ /dev/null
-//! Rustdoc's JSON output interface
-//!
-//! These types are the public API exposed through the `--output-format json` flag. The [`Crate`]
-//! struct is the root of the JSON blob and all other items are contained within.
-
-use std::path::PathBuf;
-
-use rustc_data_structures::fx::FxHashMap;
-use serde::{Deserialize, Serialize};
-
-/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
-/// about the language items in the local crate, as well as info about external items to allow
-/// tools to find or link to them.
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Crate {
- /// The id of the root [`Module`] item of the local crate.
- pub root: Id,
- /// The version string given to `--crate-version`, if any.
- pub crate_version: Option<String>,
- /// Whether or not the output includes private items.
- pub includes_private: bool,
- /// A collection of all items in the local crate as well as some external traits and their
- /// items that are referenced locally.
- pub index: FxHashMap<Id, Item>,
- /// Maps IDs to fully qualified paths and other info helpful for generating links.
- pub paths: FxHashMap<Id, ItemSummary>,
- /// Maps `crate_id` of items to a crate name and html_root_url if it exists.
- pub external_crates: FxHashMap<u32, ExternalCrate>,
- /// A single version number to be used in the future when making backwards incompatible changes
- /// to the JSON output.
- pub format_version: u32,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct ExternalCrate {
- pub name: String,
- pub html_root_url: Option<String>,
-}
-
-/// For external (not defined in the local crate) items, you don't get the same level of
-/// information. This struct should contain enough to generate a link/reference to the item in
-/// question, or can be used by a tool that takes the json output of multiple crates to find
-/// the actual item definition with all the relevant info.
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct ItemSummary {
- /// Can be used to look up the name and html_root_url of the crate this item came from in the
- /// `external_crates` map.
- pub crate_id: u32,
- /// The list of path components for the fully qualified path of this item (e.g.
- /// `["std", "io", "lazy", "Lazy"]` for `std::io::lazy::Lazy`).
- pub path: Vec<String>,
- /// Whether this item is a struct, trait, macro, etc.
- pub kind: ItemKind,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Item {
- /// The unique identifier of this item. Can be used to find this item in various mappings.
- pub id: Id,
- /// This can be used as a key to the `external_crates` map of [`Crate`] to see which crate
- /// this item came from.
- pub crate_id: u32,
- /// Some items such as impls don't have names.
- pub name: Option<String>,
- /// The source location of this item (absent if it came from a macro expansion or inline
- /// assembly).
- pub source: Option<Span>,
- /// By default all documented items are public, but you can tell rustdoc to output private items
- /// so this field is needed to differentiate.
- pub visibility: Visibility,
- /// The full markdown docstring of this item. Absent if there is no documentation at all,
- /// Some("") if there is some documentation but it is empty (EG `#[doc = ""]`).
- pub docs: Option<String>,
- /// This mapping resolves [intra-doc links](https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md) from the docstring to their IDs
- pub links: FxHashMap<String, Id>,
- /// Stringified versions of the attributes on this item (e.g. `"#[inline]"`)
- pub attrs: Vec<String>,
- pub deprecation: Option<Deprecation>,
- pub kind: ItemKind,
- pub inner: ItemEnum,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Span {
- /// The path to the source file for this span relative to the path `rustdoc` was invoked with.
- pub filename: PathBuf,
- /// Zero indexed Line and Column of the first character of the `Span`
- pub begin: (usize, usize),
- /// Zero indexed Line and Column of the last character of the `Span`
- pub end: (usize, usize),
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Deprecation {
- pub since: Option<String>,
- pub note: Option<String>,
-}
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum Visibility {
- Public,
- /// For the most part items are private by default. The exceptions are associated items of
- /// public traits and variants of public enums.
- Default,
- Crate,
- /// For `pub(in path)` visibility. `parent` is the module it's restricted to and `path` is how
- /// that module was referenced (like `"super::super"` or `"crate::foo::bar"`).
- Restricted {
- parent: Id,
- path: String,
- },
-}
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum GenericArgs {
- /// <'a, 32, B: Copy, C = u32>
- AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
- /// Fn(A, B) -> C
- Parenthesized { inputs: Vec<Type>, output: Option<Type> },
-}
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum GenericArg {
- Lifetime(String),
- Type(Type),
- Const(Constant),
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Constant {
- #[serde(rename = "type")]
- pub type_: Type,
- pub expr: String,
- pub value: Option<String>,
- pub is_literal: bool,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct TypeBinding {
- pub name: String,
- pub binding: TypeBindingKind,
-}
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum TypeBindingKind {
- Equality(Type),
- Constraint(Vec<GenericBound>),
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-pub struct Id(pub String);
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum ItemKind {
- Module,
- ExternCrate,
- Import,
- Struct,
- StructField,
- Union,
- Enum,
- Variant,
- Function,
- Typedef,
- OpaqueTy,
- Constant,
- Trait,
- TraitAlias,
- Method,
- Impl,
- Static,
- ForeignType,
- Macro,
- ProcAttribute,
- ProcDerive,
- AssocConst,
- AssocType,
- Primitive,
- Keyword,
-}
-
-#[serde(untagged)]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum ItemEnum {
- ModuleItem(Module),
- ExternCrateItem {
- name: String,
- rename: Option<String>,
- },
- ImportItem(Import),
-
- StructItem(Struct),
- StructFieldItem(Type),
- EnumItem(Enum),
- VariantItem(Variant),
-
- FunctionItem(Function),
-
- TraitItem(Trait),
- TraitAliasItem(TraitAlias),
- MethodItem(Method),
- ImplItem(Impl),
-
- TypedefItem(Typedef),
- OpaqueTyItem(OpaqueTy),
- ConstantItem(Constant),
-
- StaticItem(Static),
-
- /// `type`s from an extern block
- ForeignTypeItem,
-
- /// Declarative macro_rules! macro
- MacroItem(String),
- ProcMacroItem(ProcMacro),
-
- AssocConstItem {
- #[serde(rename = "type")]
- type_: Type,
- /// e.g. `const X: usize = 5;`
- default: Option<String>,
- },
- AssocTypeItem {
- bounds: Vec<GenericBound>,
- /// e.g. `type X = usize;`
- default: Option<Type>,
- },
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Module {
- pub is_crate: bool,
- pub items: Vec<Id>,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Struct {
- pub struct_type: StructType,
- pub generics: Generics,
- pub fields_stripped: bool,
- pub fields: Vec<Id>,
- pub impls: Vec<Id>,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Enum {
- pub generics: Generics,
- pub variants_stripped: bool,
- pub variants: Vec<Id>,
- pub impls: Vec<Id>,
-}
-
-#[serde(rename_all = "snake_case")]
-#[serde(tag = "variant_kind", content = "variant_inner")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum Variant {
- Plain,
- Tuple(Vec<Type>),
- Struct(Vec<Id>),
-}
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum StructType {
- Plain,
- Tuple,
- Unit,
- Union,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Function {
- pub decl: FnDecl,
- pub generics: Generics,
- pub header: String,
- pub abi: String,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Method {
- pub decl: FnDecl,
- pub generics: Generics,
- pub header: String,
- pub has_body: bool,
-}
-
-#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
-pub struct Generics {
- pub params: Vec<GenericParamDef>,
- pub where_predicates: Vec<WherePredicate>,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct GenericParamDef {
- pub name: String,
- pub kind: GenericParamDefKind,
-}
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum GenericParamDefKind {
- Lifetime,
- Type { bounds: Vec<GenericBound>, default: Option<Type> },
- Const(Type),
-}
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum WherePredicate {
- BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
- RegionPredicate { lifetime: String, bounds: Vec<GenericBound> },
- EqPredicate { lhs: Type, rhs: Type },
-}
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum GenericBound {
- TraitBound {
- #[serde(rename = "trait")]
- trait_: Type,
- /// Used for HRTBs
- generic_params: Vec<GenericParamDef>,
- modifier: TraitBoundModifier,
- },
- Outlives(String),
-}
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum TraitBoundModifier {
- None,
- Maybe,
- MaybeConst,
-}
-
-#[serde(rename_all = "snake_case")]
-#[serde(tag = "kind", content = "inner")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum Type {
- /// Structs, enums, and traits
- ResolvedPath {
- name: String,
- id: Id,
- args: Option<Box<GenericArgs>>,
- param_names: Vec<GenericBound>,
- },
- /// Parameterized types
- Generic(String),
- /// Fixed-size numeric types (plus int/usize/float), char, arrays, slices, and tuples
- Primitive(String),
- /// `extern "ABI" fn`
- FunctionPointer(Box<FunctionPointer>),
- /// `(String, u32, Box<usize>)`
- Tuple(Vec<Type>),
- /// `[u32]`
- Slice(Box<Type>),
- /// [u32; 15]
- Array {
- #[serde(rename = "type")]
- type_: Box<Type>,
- len: String,
- },
- /// `impl TraitA + TraitB + ...`
- ImplTrait(Vec<GenericBound>),
- /// `!`
- Never,
- /// `_`
- Infer,
- /// `*mut u32`, `*u8`, etc.
- RawPointer {
- mutable: bool,
- #[serde(rename = "type")]
- type_: Box<Type>,
- },
- /// `&'a mut String`, `&str`, etc.
- BorrowedRef {
- lifetime: Option<String>,
- mutable: bool,
- #[serde(rename = "type")]
- type_: Box<Type>,
- },
- /// `<Type as Trait>::Name` or associated types like `T::Item` where `T: Iterator`
- QualifiedPath {
- name: String,
- self_type: Box<Type>,
- #[serde(rename = "trait")]
- trait_: Box<Type>,
- },
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct FunctionPointer {
- pub is_unsafe: bool,
- pub generic_params: Vec<GenericParamDef>,
- pub decl: FnDecl,
- pub abi: String,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct FnDecl {
- pub inputs: Vec<(String, Type)>,
- pub output: Option<Type>,
- pub c_variadic: bool,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Trait {
- pub is_auto: bool,
- pub is_unsafe: bool,
- pub items: Vec<Id>,
- pub generics: Generics,
- pub bounds: Vec<GenericBound>,
- pub implementors: Vec<Id>,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct TraitAlias {
- pub generics: Generics,
- pub params: Vec<GenericBound>,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Impl {
- pub is_unsafe: bool,
- pub generics: Generics,
- pub provided_trait_methods: Vec<String>,
- #[serde(rename = "trait")]
- pub trait_: Option<Type>,
- #[serde(rename = "for")]
- pub for_: Type,
- pub items: Vec<Id>,
- pub negative: bool,
- pub synthetic: bool,
- pub blanket_impl: Option<Type>,
-}
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Import {
- /// The full path being imported.
- pub span: String,
- /// May be different from the last segment of `source` when renaming imports:
- /// `use source as name;`
- pub name: String,
- /// The ID of the item being imported.
- pub id: Option<Id>, // FIXME is this actually ever None?
- /// Whether this import uses a glob: `use source::*;`
- pub glob: bool,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct ProcMacro {
- pub kind: MacroKind,
- pub helpers: Vec<String>,
-}
-
-#[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub enum MacroKind {
- /// A bang macro `foo!()`.
- Bang,
- /// An attribute macro `#[foo]`.
- Attr,
- /// A derive macro `#[derive(Foo)]`
- Derive,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Typedef {
- #[serde(rename = "type")]
- pub type_: Type,
- pub generics: Generics,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct OpaqueTy {
- pub bounds: Vec<GenericBound>,
- pub generics: Generics,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
-pub struct Static {
- #[serde(rename = "type")]
- pub type_: Type,
- pub mutable: bool,
- pub expr: String,
-}