Skip to content

Commit 59bd4fa

Browse files
Add is_inner information to rustdoc-json-types
1 parent f6690a1 commit 59bd4fa

20 files changed

+77
-48
lines changed

src/librustdoc/clean/types.rs

+18-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::{fmt, iter};
55

66
use arrayvec::ArrayVec;
77
use rustc_abi::{ExternAbi, VariantIdx};
8+
use rustc_ast::AttrStyle;
89
use rustc_attr_parsing::{AttributeKind, ConstStability, Deprecation, Stability, StableSince};
910
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
1011
use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -759,13 +760,20 @@ impl Item {
759760
Some(tcx.visibility(def_id))
760761
}
761762

762-
pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Vec<String> {
763+
/// Returns a Vec of stringified attributes with a boolean set to `true` if it's an inner
764+
/// attribute.
765+
pub(crate) fn attributes(
766+
&self,
767+
tcx: TyCtxt<'_>,
768+
cache: &Cache,
769+
is_json: bool,
770+
) -> Vec<(bool, String)> {
763771
const ALLOWED_ATTRIBUTES: &[Symbol] =
764772
&[sym::export_name, sym::link_section, sym::no_mangle, sym::non_exhaustive];
765773

766774
use rustc_abi::IntegerType;
767775

768-
let mut attrs: Vec<String> = self
776+
let mut attrs: Vec<(bool, String)> = self
769777
.attrs
770778
.other_attrs
771779
.iter()
@@ -786,15 +794,19 @@ impl Item {
786794
// because it isn't public API.
787795
None
788796
}
789-
_ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)),
797+
_ => Some((
798+
attr.opt_style() == Some(AttrStyle::Inner),
799+
rustc_hir_pretty::attribute_to_string(&tcx, attr),
800+
)),
790801
}
791802
} else if attr.has_any_name(ALLOWED_ATTRIBUTES) {
792-
Some(
803+
Some((
804+
attr.opt_style() == Some(AttrStyle::Inner),
793805
rustc_hir_pretty::attribute_to_string(&tcx, attr)
794806
.replace("\\\n", "")
795807
.replace('\n', "")
796808
.replace(" ", " "),
797-
)
809+
))
798810
} else {
799811
None
800812
}
@@ -860,7 +872,7 @@ impl Item {
860872
out.push(&int_s);
861873
}
862874
if !out.is_empty() {
863-
attrs.push(format!("#[repr({})]", out.join(", ")));
875+
attrs.push((false, format!("#[repr({})]", out.join(", "))));
864876
}
865877
}
866878
attrs

src/librustdoc/html/render/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1194,7 +1194,7 @@ fn render_assoc_item(
11941194
// a whitespace prefix and newline.
11951195
fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> impl fmt::Display {
11961196
fmt::from_fn(move |f| {
1197-
for a in it.attributes(cx.tcx(), cx.cache(), false) {
1197+
for (_, a) in it.attributes(cx.tcx(), cx.cache(), false) {
11981198
writeln!(f, "{prefix}{a}")?;
11991199
}
12001200
Ok(())
@@ -1204,7 +1204,7 @@ fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) ->
12041204
// When an attribute is rendered inside a <code> tag, it is formatted using
12051205
// a div to produce a newline after it.
12061206
fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) {
1207-
for attr in it.attributes(cx.tcx(), cx.cache(), false) {
1207+
for (_, attr) in it.attributes(cx.tcx(), cx.cache(), false) {
12081208
write!(w, "<div class=\"code-attribute\">{attr}</div>").unwrap();
12091209
}
12101210
}

src/librustdoc/json/conversions.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@ impl JsonRenderer<'_> {
4040
})
4141
.collect();
4242
let docs = item.opt_doc_value();
43-
let attrs = item.attributes(self.tcx, self.cache(), true);
43+
let attrs = item
44+
.attributes(self.tcx, self.cache(), true)
45+
.into_iter()
46+
.map(|(is_inner, content)| Attribute { is_inner, content })
47+
.collect::<Vec<_>>();
4448
let span = item.span(self.tcx);
4549
let visibility = item.visibility(self.tcx);
4650
let clean::ItemInner { name, item_id, .. } = *item.inner;
@@ -767,7 +771,11 @@ impl FromClean<clean::ProcMacro> for ProcMacro {
767771
fn from_clean(mac: clean::ProcMacro, _renderer: &JsonRenderer<'_>) -> Self {
768772
ProcMacro {
769773
kind: from_macro_kind(mac.kind),
770-
helpers: mac.helpers.iter().map(|x| x.to_string()).collect(),
774+
helpers: mac
775+
.helpers
776+
.iter()
777+
.map(|x| Attribute { is_inner: false, content: x.to_string() })
778+
.collect(),
771779
}
772780
}
773781
}

src/rustdoc-json-types/lib.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,15 @@ pub struct ItemSummary {
152152
pub kind: ItemKind,
153153
}
154154

155+
/// An attribute (like `#[inline]`).
156+
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)]
157+
pub struct Attribute {
158+
/// Whether it is an inner (`#![]`) or an outer attribute (`#[]`).
159+
pub is_inner: bool,
160+
/// The content of the attribute.
161+
pub content: String,
162+
}
163+
155164
/// Anything that can hold documentation - modules, structs, enums, functions, traits, etc.
156165
///
157166
/// The `Item` data type holds fields that can apply to any of these,
@@ -193,7 +202,7 @@ pub struct Item {
193202
///
194203
/// As an internal implementation detail subject to change, this debug-printing format
195204
/// is currently equivalent to the HIR pretty-printing of parsed attributes.
196-
pub attrs: Vec<String>,
205+
pub attrs: Vec<Attribute>,
197206
/// Information about the item’s deprecation, if present.
198207
pub deprecation: Option<Deprecation>,
199208
/// The type-specific fields describing this item.
@@ -1301,7 +1310,7 @@ pub struct ProcMacro {
13011310
/// Some(T),
13021311
/// }
13031312
/// ```
1304-
pub helpers: Vec<String>,
1313+
pub helpers: Vec<Attribute>,
13051314
}
13061315

13071316
/// The way a [`ProcMacro`] is declared to be used.

tests/rustdoc-json/attrs/automatically_derived.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ impl Default for Manual {
99
}
1010
}
1111

12-
//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Derive" && @.inner.impl.trait.path == "Default")].attrs' '["#[automatically_derived]"]'
12+
//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Derive" && @.inner.impl.trait.path == "Default")].attrs' '[{"content": "#[automatically_derived]", "is_inner": false}]'
1313
//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Manual" && @.inner.impl.trait.path == "Default")].attrs' '[]'
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@ edition: 2021
22
#![no_std]
33

4-
//@ is "$.index[?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]'
4+
//@ is "$.index[?(@.name=='example')].attrs" '[{"content": "#[export_name = \"altered\"]", "is_inner": false}]'
55
#[export_name = "altered"]
66
pub extern "C" fn example() {}

tests/rustdoc-json/attrs/export_name_2024.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
// The representation of `#[unsafe(export_name = ..)]` in rustdoc in edition 2024
55
// is still `#[export_name = ..]` without the `unsafe` attribute wrapper.
66

7-
//@ is "$.index[?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]'
7+
//@ is "$.index[?(@.name=='example')].attrs" '[{"content": "#[export_name = \"altered\"]", "is_inner": false}]'
88
#[unsafe(export_name = "altered")]
99
pub extern "C" fn example() {}

tests/rustdoc-json/attrs/must_use.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#![no_std]
22

3-
//@ is "$.index[?(@.name=='example')].attrs" '["#[must_use]"]'
3+
//@ is "$.index[?(@.name=='example')].attrs" '[{"content": "#[must_use]", "is_inner": false}]'
44
#[must_use]
55
pub fn example() -> impl Iterator<Item = i64> {}
66

7-
//@ is "$.index[?(@.name=='explicit_message')].attrs" '["#[must_use = \"does nothing if you do not use it\"]"]'
7+
//@ is "$.index[?(@.name=='explicit_message')].attrs" '[{"content": "#[must_use = \"does nothing if you do not use it\"]", "is_inner": false}]'
88
#[must_use = "does nothing if you do not use it"]
99
pub fn explicit_message() -> impl Iterator<Item = i64> {}
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@ edition: 2021
22
#![no_std]
33

4-
//@ is "$.index[?(@.name=='example')].attrs" '["#[no_mangle]"]'
4+
//@ is "$.index[?(@.name=='example')].attrs" '[{"content": "#[no_mangle]", "is_inner": false}]'
55
#[no_mangle]
66
pub extern "C" fn example() {}

tests/rustdoc-json/attrs/no_mangle_2024.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
// The representation of `#[unsafe(no_mangle)]` in rustdoc in edition 2024
55
// is still `#[no_mangle]` without the `unsafe` attribute wrapper.
66

7-
//@ is "$.index[?(@.name=='example')].attrs" '["#[no_mangle]"]'
7+
//@ is "$.index[?(@.name=='example')].attrs" '[{"content": "#[no_mangle]", "is_inner": false}]'
88
#[unsafe(no_mangle)]
99
pub extern "C" fn example() {}

tests/rustdoc-json/attrs/non_exhaustive.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
#![no_std]
22

3-
//@ is "$.index[?(@.name=='MyEnum')].attrs" '["#[non_exhaustive]"]'
3+
//@ is "$.index[?(@.name=='MyEnum')].attrs" '[{"content": "#[non_exhaustive]", "is_inner": false}]'
44
#[non_exhaustive]
55
pub enum MyEnum {
66
First,
77
}
88

99
pub enum NonExhaustiveVariant {
10-
//@ is "$.index[?(@.name=='Variant')].attrs" '["#[non_exhaustive]"]'
10+
//@ is "$.index[?(@.name=='Variant')].attrs" '[{"content": "#[non_exhaustive]", "is_inner": false}]'
1111
#[non_exhaustive]
1212
Variant(i64),
1313
}
1414

15-
//@ is "$.index[?(@.name=='MyStruct')].attrs" '["#[non_exhaustive]"]'
15+
//@ is "$.index[?(@.name=='MyStruct')].attrs" '[{"content": "#[non_exhaustive]", "is_inner": false}]'
1616
#[non_exhaustive]
1717
pub struct MyStruct {
1818
pub x: i64,

tests/rustdoc-json/attrs/repr_align.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![no_std]
22

3-
//@ is "$.index[?(@.name=='Aligned')].attrs" '["#[repr(align(4))]"]'
3+
//@ is "$.index[?(@.name=='Aligned')].attrs" '[{"content": "#[repr(align(4))]", "is_inner": false}]'
44
#[repr(align(4))]
55
pub struct Aligned {
66
a: i8,

tests/rustdoc-json/attrs/repr_c.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
#![no_std]
22

3-
//@ is "$.index[?(@.name=='ReprCStruct')].attrs" '["#[repr(C)]"]'
3+
//@ is "$.index[?(@.name=='ReprCStruct')].attrs" '[{"content": "#[repr(C)]", "is_inner": false}]'
44
#[repr(C)]
55
pub struct ReprCStruct(pub i64);
66

7-
//@ is "$.index[?(@.name=='ReprCEnum')].attrs" '["#[repr(C)]"]'
7+
//@ is "$.index[?(@.name=='ReprCEnum')].attrs" '[{"content": "#[repr(C)]", "is_inner": false}]'
88
#[repr(C)]
99
pub enum ReprCEnum {
1010
First,
1111
}
1212

13-
//@ is "$.index[?(@.name=='ReprCUnion')].attrs" '["#[repr(C)]"]'
13+
//@ is "$.index[?(@.name=='ReprCUnion')].attrs" '[{"content": "#[repr(C)]", "is_inner": false}]'
1414
#[repr(C)]
1515
pub union ReprCUnion {
1616
pub left: i64,

tests/rustdoc-json/attrs/repr_combination.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -3,76 +3,76 @@
33
// Combinations of `#[repr(..)]` attributes.
44
// Rustdoc JSON emits normalized output, regardless of the original source.
55

6-
//@ is "$.index[?(@.name=='ReprCI8')].attrs" '["#[repr(C, i8)]"]'
6+
//@ is "$.index[?(@.name=='ReprCI8')].attrs" '[{"content": "#[repr(C, i8)]", "is_inner": false}]'
77
#[repr(C, i8)]
88
pub enum ReprCI8 {
99
First,
1010
}
1111

12-
//@ is "$.index[?(@.name=='SeparateReprCI16')].attrs" '["#[repr(C, i16)]"]'
12+
//@ is "$.index[?(@.name=='SeparateReprCI16')].attrs" '[{"content": "#[repr(C, i16)]", "is_inner": false}]'
1313
#[repr(C)]
1414
#[repr(i16)]
1515
pub enum SeparateReprCI16 {
1616
First,
1717
}
1818

19-
//@ is "$.index[?(@.name=='ReversedReprCUsize')].attrs" '["#[repr(C, usize)]"]'
19+
//@ is "$.index[?(@.name=='ReversedReprCUsize')].attrs" '[{"content": "#[repr(C, usize)]", "is_inner": false}]'
2020
#[repr(usize, C)]
2121
pub enum ReversedReprCUsize {
2222
First,
2323
}
2424

25-
//@ is "$.index[?(@.name=='ReprCPacked')].attrs" '["#[repr(C, packed(1))]"]'
25+
//@ is "$.index[?(@.name=='ReprCPacked')].attrs" '[{"content": "#[repr(C, packed(1))]", "is_inner": false}]'
2626
#[repr(C, packed)]
2727
pub struct ReprCPacked {
2828
a: i8,
2929
b: i64,
3030
}
3131

32-
//@ is "$.index[?(@.name=='SeparateReprCPacked')].attrs" '["#[repr(C, packed(2))]"]'
32+
//@ is "$.index[?(@.name=='SeparateReprCPacked')].attrs" '[{"content": "#[repr(C, packed(2))]", "is_inner": false}]'
3333
#[repr(C)]
3434
#[repr(packed(2))]
3535
pub struct SeparateReprCPacked {
3636
a: i8,
3737
b: i64,
3838
}
3939

40-
//@ is "$.index[?(@.name=='ReversedReprCPacked')].attrs" '["#[repr(C, packed(2))]"]'
40+
//@ is "$.index[?(@.name=='ReversedReprCPacked')].attrs" '[{"content": "#[repr(C, packed(2))]", "is_inner": false}]'
4141
#[repr(packed(2), C)]
4242
pub struct ReversedReprCPacked {
4343
a: i8,
4444
b: i64,
4545
}
4646

47-
//@ is "$.index[?(@.name=='ReprCAlign')].attrs" '["#[repr(C, align(16))]"]'
47+
//@ is "$.index[?(@.name=='ReprCAlign')].attrs" '[{"content": "#[repr(C, align(16))]", "is_inner": false}]'
4848
#[repr(C, align(16))]
4949
pub struct ReprCAlign {
5050
a: i8,
5151
b: i64,
5252
}
5353

54-
//@ is "$.index[?(@.name=='SeparateReprCAlign')].attrs" '["#[repr(C, align(2))]"]'
54+
//@ is "$.index[?(@.name=='SeparateReprCAlign')].attrs" '[{"content": "#[repr(C, align(2))]", "is_inner": false}]'
5555
#[repr(C)]
5656
#[repr(align(2))]
5757
pub struct SeparateReprCAlign {
5858
a: i8,
5959
b: i64,
6060
}
6161

62-
//@ is "$.index[?(@.name=='ReversedReprCAlign')].attrs" '["#[repr(C, align(2))]"]'
62+
//@ is "$.index[?(@.name=='ReversedReprCAlign')].attrs" '[{"content": "#[repr(C, align(2))]", "is_inner": false}]'
6363
#[repr(align(2), C)]
6464
pub struct ReversedReprCAlign {
6565
a: i8,
6666
b: i64,
6767
}
6868

69-
//@ is "$.index[?(@.name=='AlignedExplicitRepr')].attrs" '["#[repr(C, align(16), isize)]"]'
69+
//@ is "$.index[?(@.name=='AlignedExplicitRepr')].attrs" '[{"content": "#[repr(C, align(16), isize)]", "is_inner": false}]'
7070
#[repr(C, align(16), isize)]
7171
pub enum AlignedExplicitRepr {
7272
First,
7373
}
7474

75-
//@ is "$.index[?(@.name=='ReorderedAlignedExplicitRepr')].attrs" '["#[repr(C, align(16), isize)]"]'
75+
//@ is "$.index[?(@.name=='ReorderedAlignedExplicitRepr')].attrs" '[{"content": "#[repr(C, align(16), isize)]", "is_inner": false}]'
7676
#[repr(isize, C, align(16))]
7777
pub enum ReorderedAlignedExplicitRepr {
7878
First,

tests/rustdoc-json/attrs/repr_int_enum.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
#![no_std]
22

3-
//@ is "$.index[?(@.name=='I8')].attrs" '["#[repr(i8)]"]'
3+
//@ is "$.index[?(@.name=='I8')].attrs" '[{"content": "#[repr(i8)]", "is_inner": false}]'
44
#[repr(i8)]
55
pub enum I8 {
66
First,
77
}
88

9-
//@ is "$.index[?(@.name=='I32')].attrs" '["#[repr(i32)]"]'
9+
//@ is "$.index[?(@.name=='I32')].attrs" '[{"content": "#[repr(i32)]", "is_inner": false}]'
1010
#[repr(i32)]
1111
pub enum I32 {
1212
First,
1313
}
1414

15-
//@ is "$.index[?(@.name=='Usize')].attrs" '["#[repr(usize)]"]'
15+
//@ is "$.index[?(@.name=='Usize')].attrs" '[{"content": "#[repr(usize)]", "is_inner": false}]'
1616
#[repr(usize)]
1717
pub enum Usize {
1818
First,

tests/rustdoc-json/attrs/repr_packed.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
// Note the normalization:
44
// `#[repr(packed)]` in source becomes `#[repr(packed(1))]` in rustdoc JSON.
55
//
6-
//@ is "$.index[?(@.name=='Packed')].attrs" '["#[repr(packed(1))]"]'
6+
//@ is "$.index[?(@.name=='Packed')].attrs" '[{"content": "#[repr(packed(1))]", "is_inner": false}]'
77
#[repr(packed)]
88
pub struct Packed {
99
a: i8,
1010
b: i64,
1111
}
1212

13-
//@ is "$.index[?(@.name=='PackedAligned')].attrs" '["#[repr(packed(4))]"]'
13+
//@ is "$.index[?(@.name=='PackedAligned')].attrs" '[{"content": "#[repr(packed(4))]", "is_inner": false}]'
1414
#[repr(packed(4))]
1515
pub struct PackedAligned {
1616
a: i8,

tests/rustdoc-json/attrs/repr_transparent.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// Here, the non-1-ZST field is public.
1111
// We expect `#[repr(transparent)]` in the attributes.
1212
//
13-
//@ is "$.index[?(@.name=='Transparent')].attrs" '["#[repr(transparent)]"]'
13+
//@ is "$.index[?(@.name=='Transparent')].attrs" '[{"content": "#[repr(transparent)]", "is_inner": false}]'
1414
#[repr(transparent)]
1515
pub struct Transparent(pub i64);
1616

@@ -24,7 +24,7 @@ pub struct TransparentNonPub(i64);
2424
// Only 1-ZST fields here, and one of them is public.
2525
// We expect `#[repr(transparent)]` in the attributes.
2626
//
27-
//@ is "$.index[?(@.name=='AllZst')].attrs" '["#[repr(transparent)]"]'
27+
//@ is "$.index[?(@.name=='AllZst')].attrs" '[{"content": "#[repr(transparent)]", "is_inner": false}]'
2828
#[repr(transparent)]
2929
pub struct AllZst<'a>(pub core::marker::PhantomData<&'a ()>, ());
3030

tests/rustdoc-json/enums/discriminant/struct.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#[repr(i32)]
2-
//@ is "$.index[?(@.name=='Foo')].attrs" '["#[repr(i32)]"]'
2+
//@ is "$.index[?(@.name=='Foo')].attrs" '[{"content": "#[repr(i32)]", "is_inner": false}]'
33
pub enum Foo {
44
//@ is "$.index[?(@.name=='Struct')].inner.variant.discriminant" null
55
//@ count "$.index[?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0

0 commit comments

Comments
 (0)