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

Lines changed: 18 additions & 6 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 10 additions & 2 deletions
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

Lines changed: 11 additions & 2 deletions
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

Lines changed: 1 addition & 1 deletion
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' '[]'
Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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> {}
Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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() {}

0 commit comments

Comments
 (0)