From 98450757e5fa18ee0be9213d2830c9363b0f5fd3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 6 Jul 2020 12:53:44 -0700 Subject: [PATCH 1/8] Revert "Remove "important traits" feature" This reverts commit 1244ced9580b942926afc06815e0691cf3f4a846. --- src/doc/rustdoc/src/unstable-features.md | 21 ++++ .../src/language-features/doc-spotlight.md | 30 ++++++ src/librustc_feature/active.rs | 3 + src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/mod.rs | 2 + src/librustdoc/clean/types.rs | 1 + src/librustdoc/html/format.rs | 12 +++ src/librustdoc/html/render.rs | 87 ++++++++++++++++- src/librustdoc/html/static/main.js | 28 ++++++ src/librustdoc/html/static/rustdoc.css | 96 ++++++++++++++++++- src/librustdoc/html/static/themes/dark.css | 33 +++++++ src/librustdoc/html/static/themes/light.css | 33 +++++++ src/test/rustdoc/doc-spotlight.rs | 36 +++++++ .../feature-gate-doc_spotlight.rs | 4 + .../feature-gate-doc_spotlight.stderr | 12 +++ 15 files changed, 393 insertions(+), 9 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/doc-spotlight.md create mode 100644 src/test/rustdoc/doc-spotlight.rs create mode 100644 src/test/ui/feature-gates/feature-gate-doc_spotlight.rs create mode 100644 src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index eea674f2b84b9..d16c2a9d0342c 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -150,6 +150,27 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg]. [unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html [issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781 +### Adding your trait to the "Important Traits" dialog + +Rustdoc keeps a list of a few traits that are believed to be "fundamental" to a given type when +implemented on it. These traits are intended to be the primary interface for their types, and are +often the only thing available to be documented on their types. For this reason, Rustdoc will track +when a given type implements one of these traits and call special attention to it when a function +returns one of these types. This is the "Important Traits" dialog, visible as a circle-i button next +to the function, which, when clicked, shows the dialog. + +In the standard library, the traits that qualify for inclusion are `Iterator`, `io::Read`, and +`io::Write`. However, rather than being implemented as a hard-coded list, these traits have a +special marker attribute on them: `#[doc(spotlight)]`. This means that you could apply this +attribute to your own trait to include it in the "Important Traits" dialog in documentation. + +The `#[doc(spotlight)]` attribute currently requires the `#![feature(doc_spotlight)]` feature gate. +For more information, see [its chapter in the Unstable Book][unstable-spotlight] and [its tracking +issue][issue-spotlight]. + +[unstable-spotlight]: ../unstable-book/language-features/doc-spotlight.html +[issue-spotlight]: https://github.com/rust-lang/rust/issues/45040 + ### Exclude certain dependencies from documentation The standard library uses several dependencies which, in turn, use several types and traits from the diff --git a/src/doc/unstable-book/src/language-features/doc-spotlight.md b/src/doc/unstable-book/src/language-features/doc-spotlight.md new file mode 100644 index 0000000000000..8117755fef1c8 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/doc-spotlight.md @@ -0,0 +1,30 @@ +# `doc_spotlight` + +The tracking issue for this feature is: [#45040] + +The `doc_spotlight` feature allows the use of the `spotlight` parameter to the `#[doc]` attribute, +to "spotlight" a specific trait on the return values of functions. Adding a `#[doc(spotlight)]` +attribute to a trait definition will make rustdoc print extra information for functions which return +a type that implements that trait. This attribute is applied to the `Iterator`, `io::Read`, and +`io::Write` traits in the standard library. + +You can do this on your own traits, like this: + +``` +#![feature(doc_spotlight)] + +#[doc(spotlight)] +pub trait MyTrait {} + +pub struct MyStruct; +impl MyTrait for MyStruct {} + +/// The docs for this function will have an extra line about `MyStruct` implementing `MyTrait`, +/// without having to write that yourself! +pub fn my_fn() -> MyStruct { MyStruct } +``` + +This feature was originally implemented in PR [#45039]. + +[#45040]: https://github.com/rust-lang/rust/issues/45040 +[#45039]: https://github.com/rust-lang/rust/pull/45039 diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 0da3693af4fb6..d7c310a8b4c8b 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -368,6 +368,9 @@ declare_features! ( /// Allows `#[doc(masked)]`. (active, doc_masked, "1.21.0", Some(44027), None), + /// Allows `#[doc(spotlight)]`. + (active, doc_spotlight, "1.22.0", Some(45040), None), + /// Allows `#[doc(include = "some-file")]`. (active, external_doc, "1.22.0", Some(44732), None), diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 78628b198a3c3..1387389981d26 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -12,7 +12,7 @@ use rustc_metadata::creader::LoadedMacro; use rustc_middle::ty; use rustc_mir::const_eval::is_min_const_fn; use rustc_span::hygiene::MacroKind; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use crate::clean::{self, GetDefId, ToSource, TypeKind}; @@ -194,6 +194,7 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait { let generics = (cx.tcx.generics_of(did), predicates).clean(cx); let generics = filter_non_trait_generics(did, generics); let (generics, supertrait_bounds) = separate_supertrait_bounds(generics); + let is_spotlight = load_attrs(cx, did).clean(cx).has_doc_flag(sym::spotlight); let is_auto = cx.tcx.trait_is_auto(did); clean::Trait { auto: auto_trait, @@ -201,6 +202,7 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait { generics, items: trait_items, bounds: supertrait_bounds, + is_spotlight, is_auto, } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 03d6853494cfc..8a4ee91df405f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1007,6 +1007,7 @@ impl Clean for hir::FnRetTy<'_> { impl Clean for doctree::Trait<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let attrs = self.attrs.clean(cx); + let is_spotlight = attrs.has_doc_flag(sym::spotlight); Item { name: Some(self.name.clean(cx)), attrs, @@ -1021,6 +1022,7 @@ impl Clean for doctree::Trait<'_> { items: self.items.iter().map(|ti| ti.clean(cx)).collect(), generics: self.generics.clean(cx), bounds: self.bounds.clean(cx), + is_spotlight, is_auto: self.is_auto.clean(cx), }), } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index c9ae67ded0a3f..5f6d9ecc0476d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -995,6 +995,7 @@ pub struct Trait { pub items: Vec, pub generics: Generics, pub bounds: Vec, + pub is_spotlight: bool, pub is_auto: bool, } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index a453a8b3dcb2a..0d8284029afc7 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -63,10 +63,22 @@ impl Buffer { Buffer { for_html: false, buffer: String::new() } } + crate fn is_empty(&self) -> bool { + self.buffer.is_empty() + } + crate fn into_inner(self) -> String { self.buffer } + crate fn insert_str(&mut self, idx: usize, s: &str) { + self.buffer.insert_str(idx, s); + } + + crate fn push_str(&mut self, s: &str) { + self.buffer.push_str(s); + } + // Intended for consumption by write! and writeln! (std::fmt) but without // the fmt::Result return type imposed by fmt::Write (and avoiding the trait // import). diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9fa3f6cc39610..940d7e87a183b 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2410,7 +2410,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func f.generics.print() ) .len(); - write!(w, "
");
+    write!(w, "{}
", render_spotlight_traits(it));
     render_attributes(w, it, false);
     write!(
         w,
@@ -2612,7 +2612,12 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
         let name = m.name.as_ref().unwrap();
         let item_type = m.type_();
         let id = cx.derive_id(format!("{}.{}", item_type, name));
-        write!(w, "

", id = id); + write!( + w, + "

{extra}", + extra = render_spotlight_traits(m), + id = id + ); render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl); write!(w, ""); render_stability_since(w, m, t); @@ -3559,6 +3564,76 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool { } } +fn render_spotlight_traits(item: &clean::Item) -> String { + match item.inner { + clean::FunctionItem(clean::Function { ref decl, .. }) + | clean::TyMethodItem(clean::TyMethod { ref decl, .. }) + | clean::MethodItem(clean::Method { ref decl, .. }) + | clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => spotlight_decl(decl), + _ => String::new(), + } +} + +fn spotlight_decl(decl: &clean::FnDecl) -> String { + let mut out = Buffer::html(); + let mut trait_ = String::new(); + + if let Some(did) = decl.output.def_id() { + let c = cache(); + if let Some(impls) = c.impls.get(&did) { + for i in impls { + let impl_ = i.inner_impl(); + if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) { + if out.is_empty() { + out.push_str(&format!( + "

Important traits for {}

\ + ", + impl_.for_.print() + )); + trait_.push_str(&impl_.for_.print().to_string()); + } + + //use the "where" class here to make it small + out.push_str(&format!( + "{}", + impl_.print() + )); + let t_did = impl_.trait_.def_id().unwrap(); + for it in &impl_.items { + if let clean::TypedefItem(ref tydef, _) = it.inner { + out.push_str(" "); + assoc_type( + &mut out, + it, + &[], + Some(&tydef.type_), + AssocItemLink::GotoSource(t_did, &FxHashSet::default()), + "", + ); + out.push_str(";"); + } + } + } + } + } + } + + if !out.is_empty() { + out.insert_str( + 0, + &format!( + "
ⓘ\ + Important traits for {}
\ +
", + trait_ + ), + ); + out.push_str("
"); + } + + out.into_inner() +} + fn render_impl( w: &mut Buffer, cx: &Context, @@ -3665,12 +3740,14 @@ fn render_impl( (true, " hidden") }; match item.inner { - clean::MethodItem(clean::Method { .. }) - | clean::TyMethodItem(clean::TyMethod { .. }) => { + clean::MethodItem(clean::Method { ref decl, .. }) + | clean::TyMethodItem(clean::TyMethod { ref decl, .. }) => { // Only render when the method is not static or we allow static methods if render_method_item { let id = cx.derive_id(format!("{}.{}", item_type, name)); - write!(w, "

", id, item_type, extra_class); + write!(w, "

", id, item_type, extra_class); + write!(w, "{}", spotlight_decl(decl)); + write!(w, ""); render_assoc_item(w, item, link.anchor(&id), ItemType::Impl); write!(w, ""); render_stability_since_raw(w, item.stable_since(), outer_version); diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 336c691ac1c24..524a841e098b7 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -365,6 +365,7 @@ function defocusSearchBar() { function handleEscape(ev) { var help = getHelpElement(); var search = getSearchElement(); + hideModal(); if (hasClass(help, "hidden") === false) { displayHelp(false, ev, help); } else if (hasClass(search, "hidden") === false) { @@ -397,6 +398,7 @@ function defocusSearchBar() { case "s": case "S": displayHelp(false, ev); + hideModal(); ev.preventDefault(); focusSearchBar(); break; @@ -409,6 +411,7 @@ function defocusSearchBar() { case "?": if (ev.shiftKey) { + hideModal(); displayHelp(true, ev); } break; @@ -2636,6 +2639,31 @@ function defocusSearchBar() { }); }()); + function showModal(content) { + var modal = document.createElement("div"); + modal.id = "important"; + addClass(modal, "modal"); + modal.innerHTML = "
✕" + + "
" + content + + "
"; + document.getElementsByTagName("body")[0].appendChild(modal); + document.getElementById("modal-close").onclick = hideModal; + modal.onclick = hideModal; + } + + function hideModal() { + var modal = document.getElementById("important"); + if (modal) { + modal.parentNode.removeChild(modal); + } + } + + onEachLazy(document.getElementsByClassName("important-traits"), function(e) { + e.onclick = function() { + showModal(e.lastElementChild.innerHTML); + }; + }); + // In the search display, allows to switch between tabs. function printTab(nb) { if (nb === 0 || nb === 1 || nb === 2) { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 15a0c76ceeafb..3b2a28a0f5e45 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -146,9 +146,12 @@ code, pre, a.test-arrow { border-radius: 3px; padding: 0 0.1em; } -.docblock pre code, .docblock-short pre code { +.docblock pre code, .docblock-short pre code, .docblock code.spotlight { padding: 0; } +.docblock code.spotlight :last-child { + padding-bottom: 0.6em; +} pre { padding: 14px; } @@ -523,7 +526,7 @@ h4 > code, h3 > code, .invisible > code { font-size: 0.8em; } -.content .methods > div { +.content .methods > div:not(.important-traits) { margin-left: 40px; margin-bottom: 15px; } @@ -1098,7 +1101,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { font-size: 20px; } -.tooltip .tooltiptext { +.important-traits .tooltip .tooltiptext { border: 1px solid; font-weight: normal; } @@ -1144,6 +1147,17 @@ pre.rust { font-size: 16px; } +.important-traits { + cursor: pointer; + z-index: 2; +} + +h4 > .important-traits { + position: absolute; + left: -44px; + top: 2px; +} + #all-types { text-align: center; border: 1px solid; @@ -1370,6 +1384,12 @@ pre.rust { z-index: 1; } + h4 > .important-traits { + position: absolute; + left: -22px; + top: 24px; + } + #titles > div > div.count { float: left; width: 100%; @@ -1472,12 +1492,82 @@ pre.rust { } } +.modal { + position: fixed; + width: 100vw; + height: 100vh; + z-index: 10000; + top: 0; + left: 0; +} + +.modal-content { + display: block; + max-width: 60%; + min-width: 200px; + padding: 8px; + top: 40%; + position: absolute; + left: 50%; + transform: translate(-50%, -40%); + border: 1px solid; + border-radius: 4px; + border-top-right-radius: 0; +} + +.modal-content > .docblock { + margin: 0; +} + h3.important { margin: 0; margin-bottom: 13px; font-size: 19px; } +.modal-content > .docblock > code.content { + margin: 0; + padding: 0; + font-size: 20px; +} + +.modal-content > .close { + position: absolute; + font-weight: 900; + right: -25px; + top: -1px; + font-size: 18px; + width: 25px; + padding-right: 2px; + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; + text-align: center; + border: 1px solid; + border-right: 0; + cursor: pointer; +} + +.modal-content > .whiter { + height: 25px; + position: absolute; + width: 3px; + right: -2px; + top: 0px; +} + +#main > div.important-traits { + position: absolute; + left: -24px; + margin-top: 16px; +} + +.content > .methods > .method > div.important-traits { + position: absolute; + font-weight: 400; + left: -42px; + margin-top: 2px; +} + kbd { display: inline-block; padding: 3px 5px; diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 41dcb5c24507c..daa5ccf34bb18 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -337,6 +337,12 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: transparent black transparent transparent; } +.important-traits .tooltip .tooltiptext { + background-color: white; + color: black; + border-color: black; +} + #titles > div:not(.selected) { background-color: #252525; border-top-color: #252525; @@ -350,6 +356,33 @@ pre.ignore:hover, .information:hover + pre.ignore { color: #888; } +.modal { + background-color: rgba(0,0,0,0.3); +} + +.modal-content { + background-color: #272727; + border-color: #999; +} + +.modal-content > .close { + background-color: #272727; + border-color: #999; +} + +.modal-content > .close:hover { + background-color: #ff1f1f; + color: white; +} + +.modal-content > .whiter { + background-color: #272727; +} + +.modal-content > .close:hover + .whiter { + background-color: #ff1f1f; +} + @media (max-width: 700px) { .sidebar-menu { background-color: #505050; diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 386fe2398e63a..aa7df01dc02b3 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -331,6 +331,12 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: transparent black transparent transparent; } +.important-traits .tooltip .tooltiptext { + background-color: white; + color: black; + border-color: black; +} + #titles > div:not(.selected) { background-color: #e6e6e6; border-top-color: #e6e6e6; @@ -344,6 +350,33 @@ pre.ignore:hover, .information:hover + pre.ignore { color: #888; } +.modal { + background-color: rgba(0,0,0,0.3); +} + +.modal-content { + background-color: #eee; + border-color: #999; +} + +.modal-content > .close { + background-color: #eee; + border-color: #999; +} + +.modal-content > .close:hover { + background-color: #ff1f1f; + color: white; +} + +.modal-content > .whiter { + background-color: #eee; +} + +.modal-content > .close:hover + .whiter { + background-color: #ff1f1f; +} + @media (max-width: 700px) { .sidebar-menu { background-color: #F1F1F1; diff --git a/src/test/rustdoc/doc-spotlight.rs b/src/test/rustdoc/doc-spotlight.rs new file mode 100644 index 0000000000000..ddd46c3c2155f --- /dev/null +++ b/src/test/rustdoc/doc-spotlight.rs @@ -0,0 +1,36 @@ +#![feature(doc_spotlight)] + +pub struct Wrapper { + inner: T, +} + +impl SomeTrait for Wrapper {} + +#[doc(spotlight)] +pub trait SomeTrait { + // @has doc_spotlight/trait.SomeTrait.html + // @has - '//code[@class="content"]' 'impl SomeTrait for Wrapper' + fn wrap_me(self) -> Wrapper where Self: Sized { + Wrapper { + inner: self, + } + } +} + +pub struct SomeStruct; +impl SomeTrait for SomeStruct {} + +impl SomeStruct { + // @has doc_spotlight/struct.SomeStruct.html + // @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct' + // @has - '//code[@class="content"]' 'impl SomeTrait for Wrapper' + pub fn new() -> SomeStruct { + SomeStruct + } +} + +// @has doc_spotlight/fn.bare_fn.html +// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct' +pub fn bare_fn() -> SomeStruct { + SomeStruct +} diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs b/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs new file mode 100644 index 0000000000000..452b45b34456b --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs @@ -0,0 +1,4 @@ +#[doc(spotlight)] //~ ERROR: `#[doc(spotlight)]` is experimental +trait SomeTrait {} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr new file mode 100644 index 0000000000000..010d74054a412 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr @@ -0,0 +1,12 @@ +error[E0658]: `#[doc(spotlight)]` is experimental + --> $DIR/feature-gate-doc_spotlight.rs:1:1 + | +LL | #[doc(spotlight)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #45040 for more information + = help: add `#![feature(doc_spotlight)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 3cecd6003b3eb15168421084a27223596517899c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 6 Jul 2020 12:54:33 -0700 Subject: [PATCH 2/8] Revert "Remove spotlight usage" This reverts commit 13c6d5819aae3c0de6a90e7f17ea967bf4487cbb. --- src/libcore/future/future.rs | 1 + src/libcore/iter/traits/iterator.rs | 1 + src/libcore/lib.rs | 1 + src/librustc_ast_passes/feature_gate.rs | 1 + src/librustc_span/symbol.rs | 2 ++ src/libstd/io/mod.rs | 2 ++ src/libstd/lib.rs | 1 + 7 files changed, 9 insertions(+) diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index abf461338d80a..733ebdc0e97f2 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -24,6 +24,7 @@ use crate::task::{Context, Poll}; /// `.await` the value. /// /// [`Waker`]: ../task/struct.Waker.html +#[doc(spotlight)] #[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] #[lang = "future_trait"] diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index ce4be973140e5..692eed80c0252 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -92,6 +92,7 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} label = "`{Self}` is not an iterator", message = "`{Self}` is not an iterator" )] +#[doc(spotlight)] #[must_use = "iterators are lazy and do nothing unless consumed"] pub trait Iterator { /// The type of the elements being iterated over. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 88991dea7d43e..c2dc3e5985f34 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -96,6 +96,7 @@ #![feature(custom_inner_attributes)] #![feature(decl_macro)] #![feature(doc_cfg)] +#![cfg_attr(not(bootstrap), feature(doc_spotlight))] #![feature(duration_consts_2)] #![feature(extern_types)] #![feature(fundamental)] diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index a7b0c9cf81be6..b424c8afb3471 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -253,6 +253,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { include => external_doc cfg => doc_cfg masked => doc_masked + spotlight => doc_spotlight alias => doc_alias keyword => doc_keyword ); diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 75f588918a020..ccb6ccb57fa40 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -400,6 +400,7 @@ symbols! { doc_cfg, doc_keyword, doc_masked, + doc_spotlight, doctest, document_private_items, dotdot_in_tuple_patterns, @@ -968,6 +969,7 @@ symbols! { soft, specialization, speed, + spotlight, sqrtf32, sqrtf64, sse4a_target_feature, diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 717d2868abf98..d5af4f25102d1 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -499,6 +499,7 @@ where /// [`&str`]: ../../std/primitive.str.html /// [slice]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] +#[doc(spotlight)] pub trait Read { /// Pull some bytes from this source into the specified buffer, returning /// how many bytes were read. @@ -1261,6 +1262,7 @@ impl Initializer { /// /// [`write_all`]: #method.write_all #[stable(feature = "rust1", since = "1.0.0")] +#[doc(spotlight)] pub trait Write { /// Write a buffer into this writer, returning how many bytes were written. /// diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 4fd5e238eea11..cbc24009a949a 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -261,6 +261,7 @@ #![feature(doc_cfg)] #![feature(doc_keyword)] #![feature(doc_masked)] +#![cfg_attr(not(bootstrap), feature(doc_spotlight))] #![feature(dropck_eyepatch)] #![feature(duration_constants)] #![feature(exact_size_is_empty)] From c90fb7185a5febb00b7f8ccb49abceacd41bad6e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 6 Jul 2020 14:13:47 -0700 Subject: [PATCH 3/8] Move spotlight next to the return type --- src/librustdoc/html/render.rs | 34 +++++++++----------------- src/librustdoc/html/static/rustdoc.css | 16 ++---------- 2 files changed, 14 insertions(+), 36 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 940d7e87a183b..1a96656b6f23c 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2410,12 +2410,12 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func f.generics.print() ) .len(); - write!(w, "{}
", render_spotlight_traits(it));
+    write!(w, "
");
     render_attributes(w, it, false);
     write!(
         w,
         "{vis}{constness}{asyncness}{unsafety}{abi}fn \
-           {name}{generics}{decl}{where_clause}
", + {name}{generics}{decl}{spotlight}{where_clause}
", vis = it.visibility.print_with_space(), constness = f.header.constness.print_with_space(), asyncness = f.header.asyncness.print_with_space(), @@ -2425,7 +2425,8 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func generics = f.generics.print(), where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true }, decl = Function { decl: &f.decl, header_len, indent: 0, asyncness: f.header.asyncness } - .print() + .print(), + spotlight = spotlight_decl(&f.decl), ); document(w, cx, it) } @@ -2614,9 +2615,8 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait) let id = cx.derive_id(format!("{}.{}", item_type, name)); write!( w, - "

{extra}", - extra = render_spotlight_traits(m), - id = id + "

", + id = id, ); render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl); write!(w, ""); @@ -2931,7 +2931,7 @@ fn render_assoc_item( write!( w, "{}{}{}{}{}{}{}fn {name}\ - {generics}{decl}{where_clause}", + {generics}{decl}{spotlight}{where_clause}", if parent == ItemType::Trait { " " } else { "" }, meth.visibility.print_with_space(), header.constness.print_with_space(), @@ -2943,6 +2943,7 @@ fn render_assoc_item( name = name, generics = g.print(), decl = Function { decl: d, header_len, indent, asyncness: header.asyncness }.print(), + spotlight = spotlight_decl(&d), where_clause = WhereClause { gens: g, indent, end_newline } ) } @@ -3564,16 +3565,6 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool { } } -fn render_spotlight_traits(item: &clean::Item) -> String { - match item.inner { - clean::FunctionItem(clean::Function { ref decl, .. }) - | clean::TyMethodItem(clean::TyMethod { ref decl, .. }) - | clean::MethodItem(clean::Method { ref decl, .. }) - | clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => spotlight_decl(decl), - _ => String::new(), - } -} - fn spotlight_decl(decl: &clean::FnDecl) -> String { let mut out = Buffer::html(); let mut trait_ = String::new(); @@ -3622,13 +3613,13 @@ fn spotlight_decl(decl: &clean::FnDecl) -> String { out.insert_str( 0, &format!( - "
ⓘ\ + "
ⓘ\ Important traits for {}
\
", trait_ ), ); - out.push_str("
"); + out.push_str("
"); } out.into_inner() @@ -3740,13 +3731,12 @@ fn render_impl( (true, " hidden") }; match item.inner { - clean::MethodItem(clean::Method { ref decl, .. }) - | clean::TyMethodItem(clean::TyMethod { ref decl, .. }) => { + clean::MethodItem(clean::Method { .. }) + | clean::TyMethodItem(clean::TyMethod { .. }) => { // Only render when the method is not static or we allow static methods if render_method_item { let id = cx.derive_id(format!("{}.{}", item_type, name)); write!(w, "

", id, item_type, extra_class); - write!(w, "{}", spotlight_decl(decl)); write!(w, ""); render_assoc_item(w, item, link.anchor(&id), ItemType::Impl); write!(w, ""); diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 3b2a28a0f5e45..b780cf5dafb49 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1082,7 +1082,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { font-size: 16px; } -.tooltip:hover .tooltiptext { +.important-traits:hover .tooltiptext { display: inline; } @@ -1150,6 +1150,7 @@ pre.rust { .important-traits { cursor: pointer; z-index: 2; + margin-left: 5px; } h4 > .important-traits { @@ -1555,19 +1556,6 @@ h3.important { top: 0px; } -#main > div.important-traits { - position: absolute; - left: -24px; - margin-top: 16px; -} - -.content > .methods > .method > div.important-traits { - position: absolute; - font-weight: 400; - left: -42px; - margin-top: 2px; -} - kbd { display: inline-block; padding: 3px 5px; From 734afb48300ad840118c2a6d140ec8bfeecf866e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 6 Jul 2020 17:18:04 -0700 Subject: [PATCH 4/8] Make spotlight show on hover This makes the spotlight show on hover instead of click. Clicks can be used to persist it, which is also what's used on mobile. --- src/librustdoc/html/render.rs | 16 +-- src/librustdoc/html/static/main.js | 21 +--- src/librustdoc/html/static/rustdoc.css | 104 ++++++++------------ src/librustdoc/html/static/themes/dark.css | 34 +------ src/librustdoc/html/static/themes/light.css | 34 +------ 5 files changed, 53 insertions(+), 156 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1a96656b6f23c..3f49420492eda 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2613,11 +2613,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait) let name = m.name.as_ref().unwrap(); let item_type = m.type_(); let id = cx.derive_id(format!("{}.{}", item_type, name)); - write!( - w, - "

", - id = id, - ); + write!(w, "

", id = id,); render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl); write!(w, ""); render_stability_since(w, m, t); @@ -3612,14 +3608,10 @@ fn spotlight_decl(decl: &clean::FnDecl) -> String { if !out.is_empty() { out.insert_str( 0, - &format!( - "
ⓘ\ - Important traits for {}
\ -
", - trait_ - ), + "
" + ); - out.push_str("
"); + out.push_str("
"); } out.into_inner() diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 524a841e098b7..fcbcae096fccd 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2639,28 +2639,13 @@ function defocusSearchBar() { }); }()); - function showModal(content) { - var modal = document.createElement("div"); - modal.id = "important"; - addClass(modal, "modal"); - modal.innerHTML = "
✕" + - "
" + content + - "
"; - document.getElementsByTagName("body")[0].appendChild(modal); - document.getElementById("modal-close").onclick = hideModal; - modal.onclick = hideModal; - } - - function hideModal() { - var modal = document.getElementById("important"); - if (modal) { - modal.parentNode.removeChild(modal); - } + function showImportantTraits(content) { + let list = content.classList } onEachLazy(document.getElementsByClassName("important-traits"), function(e) { e.onclick = function() { - showModal(e.lastElementChild.innerHTML); + e.getElementsByClassName('important-traits-tooltiptext')[0].classList.toggle("force-tooltip") }; }); diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index b780cf5dafb49..bc7507f9af8fc 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1082,10 +1082,6 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { font-size: 16px; } -.important-traits:hover .tooltiptext { - display: inline; -} - .tooltip .tooltiptext::after { content: " "; position: absolute; @@ -1101,9 +1097,46 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { font-size: 20px; } -.important-traits .tooltip .tooltiptext { - border: 1px solid; - font-weight: normal; +.important-traits-tooltip { + display: inline-block; + cursor: pointer; +} + +.important-traits:hover .important-traits-tooltiptext, +.important-traits .important-traits-tooltiptext.force-tooltip { + display: inline-block; +} + +.important-traits .important-traits-tooltiptext { + display: none; + padding: 5px 3px 3px 3px; + border-radius: 6px; + margin-left: 5px; + z-index: 10; + font-size: 16px; + cursor: default; + position: absolute; + /* Themes will override the color here, + but it's necessary to make it opaque */ + background-color: #eee; + border: 1px solid #999; +} + +.important-traits-tooltip::after { + /* The margin on the tooltip does not capture hover events, + this extends the area of hover enough so that mouse hover is not + lost when moving the mouse to the tooltip */ + content: "\00a0\00a0\00a0"; +} + +.important-traits .important, .important-traits .docblock { + margin: 0; +} + +.important-traits .docblock code.content{ + margin: 0; + padding: 0; + font-size: 20px; } pre.rust { @@ -1493,69 +1526,12 @@ h4 > .important-traits { } } -.modal { - position: fixed; - width: 100vw; - height: 100vh; - z-index: 10000; - top: 0; - left: 0; -} - -.modal-content { - display: block; - max-width: 60%; - min-width: 200px; - padding: 8px; - top: 40%; - position: absolute; - left: 50%; - transform: translate(-50%, -40%); - border: 1px solid; - border-radius: 4px; - border-top-right-radius: 0; -} - -.modal-content > .docblock { - margin: 0; -} - h3.important { margin: 0; margin-bottom: 13px; font-size: 19px; } -.modal-content > .docblock > code.content { - margin: 0; - padding: 0; - font-size: 20px; -} - -.modal-content > .close { - position: absolute; - font-weight: 900; - right: -25px; - top: -1px; - font-size: 18px; - width: 25px; - padding-right: 2px; - border-top-right-radius: 5px; - border-bottom-right-radius: 5px; - text-align: center; - border: 1px solid; - border-right: 0; - cursor: pointer; -} - -.modal-content > .whiter { - height: 25px; - position: absolute; - width: 3px; - right: -2px; - top: 0px; -} - kbd { display: inline-block; padding: 3px 5px; diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index daa5ccf34bb18..cdfe01f216df3 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -337,10 +337,9 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: transparent black transparent transparent; } -.important-traits .tooltip .tooltiptext { - background-color: white; - color: black; - border-color: black; +.important-traits-tooltiptext { + background-color: #111 !important; + border-color: #777 !important; } #titles > div:not(.selected) { @@ -356,33 +355,6 @@ pre.ignore:hover, .information:hover + pre.ignore { color: #888; } -.modal { - background-color: rgba(0,0,0,0.3); -} - -.modal-content { - background-color: #272727; - border-color: #999; -} - -.modal-content > .close { - background-color: #272727; - border-color: #999; -} - -.modal-content > .close:hover { - background-color: #ff1f1f; - color: white; -} - -.modal-content > .whiter { - background-color: #272727; -} - -.modal-content > .close:hover + .whiter { - background-color: #ff1f1f; -} - @media (max-width: 700px) { .sidebar-menu { background-color: #505050; diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index aa7df01dc02b3..8ffb935a37851 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -331,10 +331,9 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: transparent black transparent transparent; } -.important-traits .tooltip .tooltiptext { - background-color: white; - color: black; - border-color: black; +.important-traits-tooltiptext { + background-color: #eee !important; + border-color: #999 !important; } #titles > div:not(.selected) { @@ -350,33 +349,6 @@ pre.ignore:hover, .information:hover + pre.ignore { color: #888; } -.modal { - background-color: rgba(0,0,0,0.3); -} - -.modal-content { - background-color: #eee; - border-color: #999; -} - -.modal-content > .close { - background-color: #eee; - border-color: #999; -} - -.modal-content > .close:hover { - background-color: #ff1f1f; - color: white; -} - -.modal-content > .whiter { - background-color: #eee; -} - -.modal-content > .close:hover + .whiter { - background-color: #ff1f1f; -} - @media (max-width: 700px) { .sidebar-menu { background-color: #F1F1F1; From ae6c7e6f406fa5129c865f3af4414ff6e0bfe739 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 15 Jul 2020 08:58:10 -0700 Subject: [PATCH 5/8] Review comments for JS --- src/librustdoc/html/static/main.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index fcbcae096fccd..082f9cca064f1 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -365,7 +365,6 @@ function defocusSearchBar() { function handleEscape(ev) { var help = getHelpElement(); var search = getSearchElement(); - hideModal(); if (hasClass(help, "hidden") === false) { displayHelp(false, ev, help); } else if (hasClass(search, "hidden") === false) { @@ -398,7 +397,6 @@ function defocusSearchBar() { case "s": case "S": displayHelp(false, ev); - hideModal(); ev.preventDefault(); focusSearchBar(); break; @@ -411,7 +409,6 @@ function defocusSearchBar() { case "?": if (ev.shiftKey) { - hideModal(); displayHelp(true, ev); } break; @@ -2639,13 +2636,10 @@ function defocusSearchBar() { }); }()); - function showImportantTraits(content) { - let list = content.classList - } - onEachLazy(document.getElementsByClassName("important-traits"), function(e) { e.onclick = function() { - e.getElementsByClassName('important-traits-tooltiptext')[0].classList.toggle("force-tooltip") + this.getElementsByClassName('important-traits-tooltiptext')[0] + .classList.toggle("force-tooltip"); }; }); From 0625b2981351f93e7d0cd7e207a52e5605d2816b Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 15 Jul 2020 09:13:18 -0700 Subject: [PATCH 6/8] Add Ayu theme for spotlight --- src/librustdoc/html/static/themes/ayu.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index bc21c28750fd8..ae273c5dc397c 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -394,6 +394,11 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: transparent #314559 transparent transparent; } +.important-traits-tooltiptext { + background-color: #314559 !important; + border-color: #5c6773 !important; +} + #titles > div.selected { background-color: #141920 !important; border-bottom: 1px solid #ffb44c !important; From a474b272f5bccd955afad5935c8e3cefc4aa88e4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 15 Jul 2020 09:29:34 -0700 Subject: [PATCH 7/8] Remove !important on border-color and background-color --- src/librustdoc/html/static/rustdoc.css | 5 +---- src/librustdoc/html/static/themes/ayu.css | 4 ++-- src/librustdoc/html/static/themes/dark.css | 4 ++-- src/librustdoc/html/static/themes/light.css | 4 ++-- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index bc7507f9af8fc..5b336c3751528 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1116,10 +1116,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { font-size: 16px; cursor: default; position: absolute; - /* Themes will override the color here, - but it's necessary to make it opaque */ - background-color: #eee; - border: 1px solid #999; + border: 1px solid; } .important-traits-tooltip::after { diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index ae273c5dc397c..b436997da5816 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -395,8 +395,8 @@ pre.ignore:hover, .information:hover + pre.ignore { } .important-traits-tooltiptext { - background-color: #314559 !important; - border-color: #5c6773 !important; + background-color: #314559; + border-color: #5c6773; } #titles > div.selected { diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index cdfe01f216df3..f4ca67f8540a9 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -338,8 +338,8 @@ pre.ignore:hover, .information:hover + pre.ignore { } .important-traits-tooltiptext { - background-color: #111 !important; - border-color: #777 !important; + background-color: #111; + border-color: #777; } #titles > div:not(.selected) { diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 8ffb935a37851..b5a0ba4775c24 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -332,8 +332,8 @@ pre.ignore:hover, .information:hover + pre.ignore { } .important-traits-tooltiptext { - background-color: #eee !important; - border-color: #999 !important; + background-color: #eee; + border-color: #999; } #titles > div:not(.selected) { From c621a54eeb71248927dff8ac0c76f279cf756f28 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 16 Jul 2020 09:01:30 -0700 Subject: [PATCH 8/8] Don't position:relative on all pres We need it for run buttons (https://github.com/rust-lang/rust/pull/44671), but not function defs --- src/librustdoc/html/static/rustdoc.css | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 5b336c3751528..f5551446bf220 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1136,8 +1136,13 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { font-size: 20px; } -pre.rust { +/* Example code has the "Run" button that + needs to be positioned relative to the pre */ +pre.rust.rust-example-rendered { position: relative; +} + +pre.rust { tab-size: 4; -moz-tab-size: 4; }