diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 0207fcda9e880..3978f10367db0 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2992,7 +2992,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { fn item_constant(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, c: &clean::Constant) -> fmt::Result { write!(w, "
")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w, "{vis}const \
                {name}: {typ}
", vis = VisSpace(&it.visibility), @@ -3004,7 +3004,7 @@ fn item_constant(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, fn item_static(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, s: &clean::Static) -> fmt::Result { write!(w, "
")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w, "{vis}static {mutability}\
                {name}: {typ}
", vis = VisSpace(&it.visibility), @@ -3027,7 +3027,7 @@ fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, f.generics ).len(); write!(w, "{}
", render_spotlight_traits(it)?)?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w,
            "{vis}{constness}{unsafety}{asyncness}{abi}fn \
            {name}{generics}{decl}{where_clause}
", @@ -3116,7 +3116,7 @@ fn item_trait( // Output the trait definition wrap_into_docblock(w, |w| { write!(w, "
")?;
-        render_attributes(w, it)?;
+        render_attributes(w, it, true)?;
         write!(w, "{}{}{}trait {}{}{}",
                VisSpace(&it.visibility),
                UnsafetySpace(t.unsafety),
@@ -3379,8 +3379,10 @@ fn assoc_const(w: &mut fmt::Formatter<'_>,
                it: &clean::Item,
                ty: &clean::Type,
                _default: Option<&String>,
-               link: AssocItemLink<'_>) -> fmt::Result {
-    write!(w, "{}const {}: {}",
+               link: AssocItemLink<'_>,
+               extra: &str) -> fmt::Result {
+    write!(w, "{}{}const {}: {}",
+           extra,
            VisSpace(&it.visibility),
            naive_assoc_href(it, link),
            it.name.as_ref().unwrap(),
@@ -3391,8 +3393,10 @@ fn assoc_const(w: &mut fmt::Formatter<'_>,
 fn assoc_type(w: &mut W, it: &clean::Item,
                              bounds: &[clean::GenericBound],
                              default: Option<&clean::Type>,
-                             link: AssocItemLink<'_>) -> fmt::Result {
-    write!(w, "type {}",
+                             link: AssocItemLink<'_>,
+                             extra: &str) -> fmt::Result {
+    write!(w, "{}type {}",
+           extra,
            naive_assoc_href(it, link),
            it.name.as_ref().unwrap())?;
     if !bounds.is_empty() {
@@ -3469,7 +3473,7 @@ fn render_assoc_item(w: &mut fmt::Formatter<'_>,
         } else {
             (0, true)
         };
-        render_attributes(w, meth)?;
+        render_attributes(w, meth, false)?;
         write!(w, "{}{}{}{}{}{}{}fn {name}\
                    {generics}{decl}{where_clause}",
                if parent == ItemType::Trait { "    " } else { "" },
@@ -3503,10 +3507,12 @@ fn render_assoc_item(w: &mut fmt::Formatter<'_>,
             method(w, item, m.header, &m.generics, &m.decl, link, parent)
         }
         clean::AssociatedConstItem(ref ty, ref default) => {
-            assoc_const(w, item, ty, default.as_ref(), link)
+            assoc_const(w, item, ty, default.as_ref(), link,
+                        if parent == ItemType::Trait { "    " } else { "" })
         }
         clean::AssociatedTypeItem(ref bounds, ref default) => {
-            assoc_type(w, item, bounds, default.as_ref(), link)
+            assoc_type(w, item, bounds, default.as_ref(), link,
+                       if parent == ItemType::Trait { "    " } else { "" })
         }
         _ => panic!("render_assoc_item called on non-associated-item")
     }
@@ -3516,7 +3522,7 @@ fn item_struct(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
                s: &clean::Struct) -> fmt::Result {
     wrap_into_docblock(w, |w| {
         write!(w, "
")?;
-        render_attributes(w, it)?;
+        render_attributes(w, it, true)?;
         render_struct(w,
                       it,
                       Some(&s.generics),
@@ -3567,7 +3573,7 @@ fn item_union(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
                s: &clean::Union) -> fmt::Result {
     wrap_into_docblock(w, |w| {
         write!(w, "
")?;
-        render_attributes(w, it)?;
+        render_attributes(w, it, true)?;
         render_union(w,
                      it,
                      Some(&s.generics),
@@ -3612,7 +3618,7 @@ fn item_enum(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
              e: &clean::Enum) -> fmt::Result {
     wrap_into_docblock(w, |w| {
         write!(w, "
")?;
-        render_attributes(w, it)?;
+        render_attributes(w, it, true)?;
         write!(w, "{}enum {}{}{}",
                VisSpace(&it.visibility),
                it.name.as_ref().unwrap(),
@@ -3773,7 +3779,15 @@ const ATTRIBUTE_WHITELIST: &'static [Symbol] = &[
     sym::non_exhaustive
 ];
 
-fn render_attributes(w: &mut dyn fmt::Write, it: &clean::Item) -> fmt::Result {
+// The `top` parameter is used when generating the item declaration to ensure it doesn't have a
+// left padding. For example:
+//
+// #[foo] <----- "top" attribute
+// struct Foo {
+//     #[bar] <---- not "top" attribute
+//     bar: usize,
+// }
+fn render_attributes(w: &mut dyn fmt::Write, it: &clean::Item, top: bool) -> fmt::Result {
     let mut attrs = String::new();
 
     for attr in &it.attrs.other_attrs {
@@ -3785,7 +3799,8 @@ fn render_attributes(w: &mut dyn fmt::Write, it: &clean::Item) -> fmt::Result {
         }
     }
     if attrs.len() > 0 {
-        write!(w, "
{}
", &attrs)?; + write!(w, "
{}
", + if top { " top-attr" } else { "" }, &attrs)?; } Ok(()) } @@ -4118,7 +4133,8 @@ fn spotlight_decl(decl: &clean::FnDecl) -> Result { out.push_str(" "); assoc_type(&mut out, it, &[], Some(&tydef.type_), - AssocItemLink::GotoSource(t_did, &FxHashSet::default()))?; + AssocItemLink::GotoSource(t_did, &FxHashSet::default()), + "")?; out.push_str(";"); } } @@ -4158,7 +4174,8 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt if let clean::TypedefItem(ref tydef, _) = it.inner { write!(w, " ")?; assoc_type(w, it, &vec![], Some(&tydef.type_), - AssocItemLink::Anchor(None))?; + AssocItemLink::Anchor(None), + "")?; write!(w, ";")?; } } @@ -4228,7 +4245,7 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

", id, item_type, extra_class)?; write!(w, "", ns_id)?; - assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?; + assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id), "")?; write!(w, "

")?; } clean::AssociatedConstItem(ref ty, ref default) => { @@ -4236,7 +4253,7 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

", id, item_type, extra_class)?; write!(w, "", ns_id)?; - assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?; + assoc_const(w, item, ty, default.as_ref(), link.anchor(&id), "")?; write!(w, "")?; render_stability_since_raw(w, item.stable_since(), outer_version)?; if let Some(l) = (Item { cx, item }).src_href() { @@ -4250,7 +4267,7 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

", id, item_type, extra_class)?; write!(w, "", ns_id)?; - assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?; + assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id), "")?; write!(w, "

")?; } clean::StrippedItem(..) => return Ok(()), @@ -4338,7 +4355,7 @@ fn item_existential( t: &clean::Existential, ) -> fmt::Result { write!(w, "
")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w, "existential type {}{}{where_clause}: {bounds};
", it.name.as_ref().unwrap(), t.generics, @@ -4357,7 +4374,7 @@ fn item_existential( fn item_trait_alias(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, t: &clean::TraitAlias) -> fmt::Result { write!(w, "
")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w, "trait {}{}{} = {};
", it.name.as_ref().unwrap(), t.generics, @@ -4376,7 +4393,7 @@ fn item_trait_alias(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, fn item_typedef(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, t: &clean::Typedef) -> fmt::Result { write!(w, "
")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w, "type {}{}{where_clause} = {type_};
", it.name.as_ref().unwrap(), t.generics, @@ -4394,7 +4411,7 @@ fn item_typedef(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, fn item_foreign_type(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item) -> fmt::Result { writeln!(w, "
extern {{")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(
         w,
         "    {}type {};\n}}
", diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 85ab0855f05e9..72a01a49bc66d 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2325,7 +2325,11 @@ if (!DOMTokenList.prototype.remove) { } var attributesToggle = createToggleWrapper(createSimpleToggle(false)); onEachLazy(main.getElementsByClassName("attributes"), function(i_e) { - i_e.parentNode.insertBefore(attributesToggle.cloneNode(true), i_e); + var attr_tog = attributesToggle.cloneNode(true); + if (hasClass(i_e, "top-attr") === true) { + addClass(attr_tog, "top-attr"); + } + i_e.parentNode.insertBefore(attr_tog, i_e); itemAttributesFunc(i_e); }); diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 880b824335517..522b6d60a18d8 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1587,10 +1587,10 @@ div.name.expand::before { } /* This part is to fix the "Expand attributes" part in the type declaration. */ -.type-decl > pre > :first-child { +.type-decl > pre > .toggle-wrapper.toggle-attributes.top-attr { margin-left: 0 !important; } -.type-decl > pre > :nth-child(2) { +.type-decl > pre > .docblock.attributes.top-attr { margin-left: 1.8em !important; } .type-decl > pre > .toggle-attributes { diff --git a/src/test/rustdoc/attributes.rs b/src/test/rustdoc/attributes.rs index eb0e3f065c7b3..6ecdad3ec0000 100644 --- a/src/test/rustdoc/attributes.rs +++ b/src/test/rustdoc/attributes.rs @@ -8,8 +8,8 @@ pub extern "C" fn f() {} #[export_name = "bar"] pub extern "C" fn g() {} -// @has foo/enum.Foo.html '//*[@class="docblock attributes"]' '#[repr(i64)]' -// @has foo/enum.Foo.html '//*[@class="docblock attributes"]' '#[must_use]' +// @has foo/enum.Foo.html '//*[@class="docblock attributes top-attr"]' '#[repr(i64)]' +// @has foo/enum.Foo.html '//*[@class="docblock attributes top-attr"]' '#[must_use]' #[repr(i64)] #[must_use] pub enum Foo {