//! 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 rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use std::path::PathBuf; /// rustdoc format-version. pub const FORMAT_VERSION: u32 = 27; /// 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, PartialEq, Eq, Serialize, Deserialize)] 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, /// 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, /// Maps IDs to fully qualified paths and other info helpful for generating links. pub paths: FxHashMap, /// Maps `crate_id` of items to a crate name and html_root_url if it exists. pub external_crates: FxHashMap, /// 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, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct ExternalCrate { pub name: String, pub html_root_url: Option, } /// 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, PartialEq, Eq, Hash, Serialize, Deserialize)] 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`). /// /// Note that items can appear in multiple paths, and the one chosen is implementation /// defined. Currently, this is the full path to where the item was defined. Eg /// [`String`] is currently `["alloc", "string", "String"]` and [`HashMap`][`std::collections::HashMap`] /// is `["std", "collections", "hash", "map", "HashMap"]`, but this is subject to change. pub path: Vec, /// Whether this item is a struct, trait, macro, etc. pub kind: ItemKind, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] 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, /// The source location of this item (absent if it came from a macro expansion or inline /// assembly). pub span: Option, /// 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, /// 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, /// Stringified versions of the attributes on this item (e.g. `"#[inline]"`) pub attrs: Vec, pub deprecation: Option, pub inner: ItemEnum, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] 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, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Deprecation { pub since: Option, pub note: Option, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] 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, }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct DynTrait { /// All the traits implemented. One of them is the vtable, and the rest must be auto traits. pub traits: Vec, /// The lifetime of the whole dyn object /// ```text /// dyn Debug + 'static /// ^^^^^^^ /// | /// this part /// ``` pub lifetime: Option, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] /// A trait and potential HRTBs pub struct PolyTrait { #[serde(rename = "trait")] pub trait_: Path, /// Used for Higher-Rank Trait Bounds (HRTBs) /// ```text /// dyn for<'a> Fn() -> &'a i32" /// ^^^^^^^ /// | /// this part /// ``` pub generic_params: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum GenericArgs { /// <'a, 32, B: Copy, C = u32> AngleBracketed { args: Vec, bindings: Vec }, /// Fn(A, B) -> C Parenthesized { inputs: Vec, output: Option }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum GenericArg { Lifetime(String), Type(Type), Const(Constant), Infer, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Constant { #[serde(rename = "type")] pub type_: Type, pub expr: String, pub value: Option, pub is_literal: bool, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct TypeBinding { pub name: String, pub args: GenericArgs, pub binding: TypeBindingKind, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum TypeBindingKind { Equality(Term), Constraint(Vec), } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Id(pub String); #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum ItemKind { Module, ExternCrate, Import, Struct, StructField, Union, Enum, Variant, Function, TypeAlias, OpaqueTy, Constant, Trait, TraitAlias, Impl, Static, ForeignType, Macro, ProcAttribute, ProcDerive, AssocConst, AssocType, Primitive, Keyword, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum ItemEnum { Module(Module), ExternCrate { name: String, rename: Option, }, Import(Import), Union(Union), Struct(Struct), StructField(Type), Enum(Enum), Variant(Variant), Function(Function), Trait(Trait), TraitAlias(TraitAlias), Impl(Impl), TypeAlias(TypeAlias), OpaqueTy(OpaqueTy), Constant(Constant), Static(Static), /// `type`s from an extern block ForeignType, /// Declarative macro_rules! macro Macro(String), ProcMacro(ProcMacro), Primitive(Primitive), AssocConst { #[serde(rename = "type")] type_: Type, /// e.g. `const X: usize = 5;` default: Option, }, AssocType { generics: Generics, bounds: Vec, /// e.g. `type X = usize;` default: Option, }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Module { pub is_crate: bool, pub items: Vec, /// If `true`, this module is not part of the public API, but it contains /// items that are re-exported as public API. pub is_stripped: bool, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Union { pub generics: Generics, pub fields_stripped: bool, pub fields: Vec, pub impls: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Struct { pub kind: StructKind, pub generics: Generics, pub impls: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum StructKind { /// A struct with no fields and no parentheses. /// /// ```rust /// pub struct Unit; /// ``` Unit, /// A struct with unnamed fields. /// /// ```rust /// pub struct TupleStruct(i32); /// pub struct EmptyTupleStruct(); /// ``` /// /// All [`Id`]'s will point to [`ItemEnum::StructField`]. Private and /// `#[doc(hidden)]` fields will be given as `None` Tuple(Vec>), /// A struct with nammed fields. /// /// ```rust /// pub struct PlainStruct { x: i32 } /// pub struct EmptyPlainStruct {} /// ``` Plain { fields: Vec, fields_stripped: bool }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Enum { pub generics: Generics, pub variants_stripped: bool, pub variants: Vec, pub impls: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Variant { /// Whether the variant is plain, a tuple-like, or struct-like. Contains the fields. pub kind: VariantKind, /// The discriminant, if explicitly specified. pub discriminant: Option, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum VariantKind { /// A variant with no parentheses /// /// ```rust /// enum Demo { /// PlainVariant, /// PlainWithDiscriminant = 1, /// } /// ``` Plain, /// A variant with unnamed fields. /// /// Unlike most of json, `#[doc(hidden)]` fields will be given as `None` /// instead of being omitted, because order matters. /// /// ```rust /// enum Demo { /// TupleVariant(i32), /// EmptyTupleVariant(), /// } /// ``` Tuple(Vec>), /// A variant with named fields. /// /// ```rust /// enum Demo { /// StructVariant { x: i32 }, /// EmptyStructVariant {}, /// } /// ``` Struct { fields: Vec, fields_stripped: bool }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Discriminant { /// The expression that produced the discriminant. /// /// Unlike `value`, this preserves the original formatting (eg suffixes, /// hexadecimal, and underscores), making it unsuitable to be machine /// interpreted. /// /// In some cases, when the value is to complex, this may be `"{ _ }"`. /// When this occurs is unstable, and may change without notice. pub expr: String, /// The numerical value of the discriminant. Stored as a string due to /// JSON's poor support for large integers, and the fact that it would need /// to store from [`i128::MIN`] to [`u128::MAX`]. pub value: String, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Header { #[serde(rename = "const")] pub const_: bool, #[serde(rename = "unsafe")] pub unsafe_: bool, #[serde(rename = "async")] pub async_: bool, pub abi: Abi, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Abi { // We only have a concrete listing here for stable ABI's because their are so many // See rustc_ast_passes::feature_gate::PostExpansionVisitor::check_abi for the list Rust, C { unwind: bool }, Cdecl { unwind: bool }, Stdcall { unwind: bool }, Fastcall { unwind: bool }, Aapcs { unwind: bool }, Win64 { unwind: bool }, SysV64 { unwind: bool }, System { unwind: bool }, Other(String), } /// Represents a function (including methods and other associated functions) #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Function { pub decl: FnDecl, pub generics: Generics, pub header: Header, pub has_body: bool, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Generics { pub params: Vec, pub where_predicates: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct GenericParamDef { pub name: String, pub kind: GenericParamDefKind, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum GenericParamDefKind { Lifetime { outlives: Vec, }, Type { bounds: Vec, default: Option, /// This is normally `false`, which means that this generic parameter is /// declared in the Rust source text. /// /// If it is `true`, this generic parameter has been introduced by the /// compiler behind the scenes. /// /// # Example /// /// Consider /// /// ```ignore (pseudo-rust) /// pub fn f(_: impl Trait) {} /// ``` /// /// The compiler will transform this behind the scenes to /// /// ```ignore (pseudo-rust) /// pub fn f(_: impl Trait) {} /// ``` /// /// In this example, the generic parameter named `impl Trait` (and which /// is bound by `Trait`) is synthetic, because it was not originally in /// the Rust source text. synthetic: bool, }, Const { #[serde(rename = "type")] type_: Type, default: Option, }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum WherePredicate { BoundPredicate { #[serde(rename = "type")] type_: Type, bounds: Vec, /// Used for Higher-Rank Trait Bounds (HRTBs) /// ```text /// where for<'a> &'a T: Iterator," /// ^^^^^^^ /// | /// this part /// ``` generic_params: Vec, }, RegionPredicate { lifetime: String, bounds: Vec, }, EqPredicate { lhs: Type, rhs: Term, }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum GenericBound { TraitBound { #[serde(rename = "trait")] trait_: Path, /// Used for Higher-Rank Trait Bounds (HRTBs) /// ```text /// where F: for<'a, 'b> Fn(&'a u8, &'b u8) /// ^^^^^^^^^^^ /// | /// this part /// ``` generic_params: Vec, modifier: TraitBoundModifier, }, Outlives(String), } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum TraitBoundModifier { None, Maybe, MaybeConst, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum Term { Type(Type), Constant(Constant), } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum Type { /// Structs, enums, and unions ResolvedPath(Path), DynTrait(DynTrait), /// Parameterized types Generic(String), /// Built in numeric (i*, u*, f*) types, bool, and char Primitive(String), /// `extern "ABI" fn` FunctionPointer(Box), /// `(String, u32, Box)` Tuple(Vec), /// `[u32]` Slice(Box), /// [u32; 15] Array { #[serde(rename = "type")] type_: Box, len: String, }, /// `impl TraitA + TraitB + ...` ImplTrait(Vec), /// `_` Infer, /// `*mut u32`, `*u8`, etc. RawPointer { mutable: bool, #[serde(rename = "type")] type_: Box, }, /// `&'a mut String`, `&str`, etc. BorrowedRef { lifetime: Option, mutable: bool, #[serde(rename = "type")] type_: Box, }, /// Associated types like `::Name` and `T::Item` where /// `T: Iterator` or inherent associated types like `Struct::Name`. QualifiedPath { name: String, args: Box, self_type: Box, /// `None` iff this is an *inherent* associated type. #[serde(rename = "trait")] trait_: Option, }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Path { pub name: String, pub id: Id, /// Generic arguments to the type /// ```test /// std::borrow::Cow<'static, str> /// ^^^^^^^^^^^^^^ /// | /// this part /// ``` pub args: Option>, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct FunctionPointer { pub decl: FnDecl, /// Used for Higher-Rank Trait Bounds (HRTBs) /// ```text /// for<'c> fn(val: &'c i32) -> i32 /// ^^^^^^^ /// | /// this part /// ``` pub generic_params: Vec, pub header: Header, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct FnDecl { /// List of argument names and their type. /// /// Note that not all names will be valid identifiers, as some of /// them may be patterns. pub inputs: Vec<(String, Type)>, pub output: Option, pub c_variadic: bool, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Trait { pub is_auto: bool, pub is_unsafe: bool, pub items: Vec, pub generics: Generics, pub bounds: Vec, pub implementations: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct TraitAlias { pub generics: Generics, pub params: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Impl { pub is_unsafe: bool, pub generics: Generics, pub provided_trait_methods: Vec, #[serde(rename = "trait")] pub trait_: Option, #[serde(rename = "for")] pub for_: Type, pub items: Vec, pub negative: bool, pub synthetic: bool, pub blanket_impl: Option, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub struct Import { /// The full path being imported. pub source: 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. Will be `None` in case of re-exports of primitives: /// ```rust /// pub use i32 as my_i32; /// ``` pub id: Option, /// Whether this import uses a glob: `use source::*;` pub glob: bool, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct ProcMacro { pub kind: MacroKind, pub helpers: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum MacroKind { /// A bang macro `foo!()`. Bang, /// An attribute macro `#[foo]`. Attr, /// A derive macro `#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]` Derive, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct TypeAlias { #[serde(rename = "type")] pub type_: Type, pub generics: Generics, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct OpaqueTy { pub bounds: Vec, pub generics: Generics, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Static { #[serde(rename = "type")] pub type_: Type, pub mutable: bool, pub expr: String, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Primitive { pub name: String, pub impls: Vec, } #[cfg(test)] mod tests;