Skip to content

Commit

Permalink
Rustdoc-Json: More accurate struct type.
Browse files Browse the repository at this point in the history
Closes #101489
  • Loading branch information
aDotInTheVoid committed Sep 7, 2022
1 parent 78a891d commit 1c8de17
Show file tree
Hide file tree
Showing 15 changed files with 118 additions and 71 deletions.
8 changes: 5 additions & 3 deletions src/etc/check_missing_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,11 @@ def check_type(ty):
work_list |= set(item["inner"]["items"]) - visited
elif item["kind"] == "struct":
check_generics(item["inner"]["generics"])
work_list |= (
set(item["inner"]["fields"]) | set(item["inner"]["impls"])
) - visited
work_list |= set(item["inner"]["impls"]) - visited
if "tuple" in item["inner"]["kind"]:
work_list |= set(filter(None, item["inner"]["kind"]["tuple"])) - visited
elif "plain" in item["inner"]["kind"]:
work_list |= set(item["inner"]["kind"]["plain"]["fields"]) - visited
elif item["kind"] == "struct_field":
check_type(item["inner"])
elif item["kind"] == "enum":
Expand Down
36 changes: 11 additions & 25 deletions src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,11 +304,19 @@ impl FromWithTcx<clean::Struct> for Struct {
fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
let fields_stripped = struct_.has_stripped_entries();
let clean::Struct { struct_type, generics, fields } = struct_;

let kind = match struct_type {
CtorKind::Fn => StructKind::Tuple(ids_keeping_stripped(fields, tcx)),
CtorKind::Const => {
assert!(fields.is_empty());
StructKind::Unit
}
CtorKind::Fictive => StructKind::Plain { fields: ids(fields, tcx), fields_stripped },
};

Struct {
struct_type: from_ctor_kind(struct_type),
kind,
generics: generics.into_tcx(tcx),
fields_stripped,
fields: ids(fields, tcx),
impls: Vec::new(), // Added in JsonRenderer::item
}
}
Expand All @@ -327,14 +335,6 @@ impl FromWithTcx<clean::Union> for Union {
}
}

pub(crate) fn from_ctor_kind(struct_type: CtorKind) -> StructType {
match struct_type {
CtorKind::Fictive => StructType::Plain,
CtorKind::Fn => StructType::Tuple,
CtorKind::Const => StructType::Unit,
}
}

pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> Header {
Header {
async_: header.is_async(),
Expand Down Expand Up @@ -644,20 +644,6 @@ impl FromWithTcx<clean::Enum> for Enum {
}
}

impl FromWithTcx<clean::VariantStruct> for Struct {
fn from_tcx(struct_: clean::VariantStruct, tcx: TyCtxt<'_>) -> Self {
let fields_stripped = struct_.has_stripped_entries();
let clean::VariantStruct { struct_type, fields } = struct_;
Struct {
struct_type: from_ctor_kind(struct_type),
generics: Generics { params: vec![], where_predicates: vec![] },
fields_stripped,
fields: ids(fields, tcx),
impls: Vec::new(),
}
}
}

impl FromWithTcx<clean::Variant> for Variant {
fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
use clean::Variant::*;
Expand Down
42 changes: 30 additions & 12 deletions src/rustdoc-json-types/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::path::PathBuf;
use serde::{Deserialize, Serialize};

/// rustdoc format-version.
pub const FORMAT_VERSION: u32 = 20;
pub const FORMAT_VERSION: u32 = 21;

/// 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
Expand Down Expand Up @@ -289,13 +289,39 @@ pub struct Union {

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Struct {
pub struct_type: StructType,
pub kind: StructKind,
pub generics: Generics,
pub fields_stripped: bool,
pub fields: Vec<Id>,
pub impls: Vec<Id>,
}

#[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<Option<Id>>),
/// A struct with nammed fields.
///
/// ```rust
/// pub struct PlainStruct { x: i32 }
/// pub struct EmptyPlainStruct {}
/// ```
Plain { fields: Vec<Id>, fields_stripped: bool },
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Enum {
pub generics: Generics,
Expand Down Expand Up @@ -357,14 +383,6 @@ pub struct Discriminant {
pub value: String,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum StructType {
Plain,
Tuple,
Unit,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Header {
#[serde(rename = "const")]
Expand Down
4 changes: 1 addition & 3 deletions src/rustdoc-json-types/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ use super::*;
#[test]
fn test_struct_info_roundtrip() {
let s = ItemEnum::Struct(Struct {
struct_type: StructType::Plain,
generics: Generics { params: vec![], where_predicates: vec![] },
fields_stripped: false,
fields: vec![],
kind: StructKind::Plain { fields: vec![], fields_stripped: false },
impls: vec![],
});

Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc-json/nested.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub mod l1 {
pub mod l3 {

// @is "$.index[*][?(@.name=='L4')].kind" \"struct\"
// @is "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\"
// @is "$.index[*][?(@.name=='L4')].inner.kind" \"unit\"
// @set l4_id = "$.index[*][?(@.name=='L4')].id"
// @ismany "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id
pub struct L4;
Expand Down
11 changes: 11 additions & 0 deletions src/test/rustdoc-json/structs/plain_all_pub.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pub struct Demo {
pub x: i32,
pub y: i32,
}

// @set x = "$.index[*][?(@.name=='x')].id"
// @set y = "$.index[*][?(@.name=='y')].id"
// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[1]" $y
// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 2
// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" false
11 changes: 11 additions & 0 deletions src/test/rustdoc-json/structs/plain_doc_hidden.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pub struct Demo {
pub x: i32,
#[doc(hidden)]
pub y: i32,
}

// @set x = "$.index[*][?(@.name=='x')].id"
// @!has "$.index[*][?(@.name=='y')].id"
// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 1
// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" true
9 changes: 4 additions & 5 deletions src/test/rustdoc-json/structs/plain_empty.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// @has "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\"
// @has "$.index[*][?(@.name=='PlainEmpty')].kind" \"struct\"
// @has "$.index[*][?(@.name=='PlainEmpty')].inner.struct_type" \"plain\"
// @has "$.index[*][?(@.name=='PlainEmpty')].inner.fields_stripped" false
// @has "$.index[*][?(@.name=='PlainEmpty')].inner.fields" []
// @is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\"
// @is "$.index[*][?(@.name=='PlainEmpty')].kind" \"struct\"
// @is "$.index[*][?(@.name=='PlainEmpty')].inner.kind.plain.fields_stripped" false
// @is "$.index[*][?(@.name=='PlainEmpty')].inner.kind.plain.fields" []
pub struct PlainEmpty {}
9 changes: 9 additions & 0 deletions src/test/rustdoc-json/structs/plain_pub_priv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub struct Demo {
pub x: i32,
y: i32,
}

// @set x = "$.index[*][?(@.name=='x')].id"
// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 1
// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" true
7 changes: 3 additions & 4 deletions src/test/rustdoc-json/structs/tuple.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// @has "$.index[*][?(@.name=='Tuple')].visibility" \"public\"
// @has "$.index[*][?(@.name=='Tuple')].kind" \"struct\"
// @has "$.index[*][?(@.name=='Tuple')].inner.struct_type" \"tuple\"
// @has "$.index[*][?(@.name=='Tuple')].inner.fields_stripped" true
// @is "$.index[*][?(@.name=='Tuple')].visibility" \"public\"
// @is "$.index[*][?(@.name=='Tuple')].kind" \"struct\"
// @is "$.index[*][?(@.name=='Tuple')].inner.kind.tuple" '[null, null]'
pub struct Tuple(u32, String);
2 changes: 2 additions & 0 deletions src/test/rustdoc-json/structs/tuple_empty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @is "$.index[*][?(@.name=='TupleUnit')].inner.kind.tuple" []
pub struct TupleUnit();
13 changes: 13 additions & 0 deletions src/test/rustdoc-json/structs/tuple_pub_priv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pub struct Demo(
i32,
/// field
pub i32,
#[doc(hidden)] i32,
);

// @set field = "$.index[*][?(@.docs=='field')].id"

// @is "$.index[*][?(@.name=='Demo')].inner.kind.tuple[0]" null
// @is "$.index[*][?(@.name=='Demo')].inner.kind.tuple[1]" $field
// @is "$.index[*][?(@.name=='Demo')].inner.kind.tuple[2]" null
// @count "$.index[*][?(@.name=='Demo')].inner.kind.tuple[*]" 3
7 changes: 3 additions & 4 deletions src/test/rustdoc-json/structs/unit.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// @has "$.index[*][?(@.name=='Unit')].visibility" \"public\"
// @has "$.index[*][?(@.name=='Unit')].kind" \"struct\"
// @has "$.index[*][?(@.name=='Unit')].inner.struct_type" \"unit\"
// @has "$.index[*][?(@.name=='Unit')].inner.fields" []
// @is "$.index[*][?(@.name=='Unit')].visibility" \"public\"
// @is "$.index[*][?(@.name=='Unit')].kind" \"struct\"
// @is "$.index[*][?(@.name=='Unit')].inner.kind" \"unit\"
pub struct Unit;
16 changes: 8 additions & 8 deletions src/test/rustdoc-json/structs/with_generics.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::collections::HashMap;

// @has "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\"
// @has "$.index[*][?(@.name=='WithGenerics')].kind" \"struct\"
// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].name" \"T\"
// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].kind.type"
// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].name" \"U\"
// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].kind.type"
// @has "$.index[*][?(@.name=='WithGenerics')].inner.struct_type" \"plain\"
// @has "$.index[*][?(@.name=='WithGenerics')].inner.fields_stripped" true
// @is "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\"
// @is "$.index[*][?(@.name=='WithGenerics')].kind" \"struct\"
// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].name" \"T\"
// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].kind.type.bounds" []
// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].name" \"U\"
// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].kind.type.bounds" []
// @is "$.index[*][?(@.name=='WithGenerics')].inner.kind.plain.fields_stripped" true
// @is "$.index[*][?(@.name=='WithGenerics')].inner.kind.plain.fields" []
pub struct WithGenerics<T, U> {
stuff: Vec<T>,
things: HashMap<U, U>,
Expand Down
12 changes: 6 additions & 6 deletions src/test/rustdoc-json/structs/with_primitives.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// @has "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
// @has "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\"
// @has "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\"
// @has "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" []
// @has "$.index[*][?(@.name=='WithPrimitives')].inner.struct_type" \"plain\"
// @has "$.index[*][?(@.name=='WithPrimitives')].inner.fields_stripped" true
// @is "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
// @is "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\"
// @is "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\"
// @is "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" []
// @is "$.index[*][?(@.name=='WithPrimitives')].inner.kind.plain.fields_stripped" true
// @is "$.index[*][?(@.name=='WithPrimitives')].inner.kind.plain.fields" []
pub struct WithPrimitives<'a> {
num: u32,
s: &'a str,
Expand Down

0 comments on commit 1c8de17

Please sign in to comment.