Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle notable trait popup differently #91431

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,6 @@ impl Buffer {
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);
}
Expand Down
3 changes: 3 additions & 0 deletions src/librustdoc/html/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1439,6 +1439,8 @@ fn init_id_map() -> FxHashMap<String, usize> {
let mut map = FxHashMap::default();
// This is the list of IDs used in Javascript.
map.insert("help".to_owned(), 1);
// This is the ID used to generate the notable traits popup in Javascript.
map.insert("notable-traits-tooltiptext".to_owned(), 1);
// This is the list of IDs used in HTML generated in Rust (including the ones
// used in tera template files).
map.insert("mainThemeStyle".to_owned(), 1);
Expand All @@ -1458,6 +1460,7 @@ fn init_id_map() -> FxHashMap<String, usize> {
map.insert("sidebar-vars".to_owned(), 1);
map.insert("copy-path".to_owned(), 1);
map.insert("TOC".to_owned(), 1);
map.insert("notable-traits".to_owned(), 1);
// This is the list of IDs used by rustdoc sections (but still generated by
// rustdoc).
map.insert("fields".to_owned(), 1);
Expand Down
13 changes: 9 additions & 4 deletions src/librustdoc/html/render/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ crate struct SharedContext<'tcx> {
crate cache: Cache,

crate call_locations: AllCallLocations,
/// The key is the notable trait text and the value is its index (we add it in the DOM so the
/// JS knows which notable trait to pick).
crate notable_traits: RefCell<FxHashMap<(String, String), usize>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you absolutely sure this needs a RefCell?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now at least it does unfortunately...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I didn't notice this is in the SharedContext.

}

impl SharedContext<'_> {
Expand Down Expand Up @@ -493,6 +496,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
span_correspondance_map: matches,
cache,
call_locations,
notable_traits: RefCell::new(Default::default()),
};

// Add the default themes to the `Vec` of stylepaths
Expand Down Expand Up @@ -549,7 +553,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {

fn after_krate(&mut self) -> Result<(), Error> {
let crate_name = self.tcx().crate_name(LOCAL_CRATE);
let final_file = self.dst.join(&*crate_name.as_str()).join("all.html");
let crate_name = crate_name.as_str();
let crate_name: &str = &*crate_name;
let final_file = self.dst.join(crate_name).join("all.html");
let settings_file = self.dst.join("settings.html");

let mut root_path = self.dst.to_str().expect("invalid path").to_owned();
Expand Down Expand Up @@ -618,10 +624,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
self.shared.fs.write(settings_file, v)?;
if let Some(ref redirections) = self.shared.redirections {
if !redirections.borrow().is_empty() {
let redirect_map_path =
self.dst.join(&*crate_name.as_str()).join("redirect-map.json");
let redirect_map_path = self.dst.join(crate_name).join("redirect-map.json");
let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
self.shared.ensure_dir(&self.dst.join(&*crate_name.as_str()))?;
self.shared.ensure_dir(&self.dst.join(crate_name))?;
self.shared.fs.write(redirect_map_path, paths)?;
}
}
Expand Down
55 changes: 38 additions & 17 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ mod write_shared;
crate use self::context::*;
crate use self::span_map::{collect_spans_and_sources, LinkFromSrc};

use std::collections::hash_map::Entry;
use std::collections::VecDeque;
use std::default::Default;
use std::fmt;
Expand Down Expand Up @@ -1241,7 +1242,8 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
}

fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
let mut out = Buffer::html();
let mut out_for = Buffer::html();
let mut out_content = Buffer::html();

if let Some((did, ty)) = decl.output.as_return().and_then(|t| Some((t.def_id(cx.cache())?, t)))
{
Expand All @@ -1258,29 +1260,38 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
let trait_did = trait_.def_id();

if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable) {
if out.is_empty() {
if out_for.is_empty() {
write!(
&mut out,
"<div class=\"notable\">Notable traits for {}</div>\
<code class=\"content\">",
impl_.for_.print(cx)
&mut out_for,
"{}",
impl_.for_.print(cx),
// "<div class=\"notable\">Notable traits for {}</div>\
// <code class=\"content\">",
);
}

//use the "where" class here to make it small
write!(
&mut out,
&mut out_content,
"<span class=\"where fmt-newline\">{}</span>",
impl_.print(false, cx)
);
for it in &impl_.items {
if let clean::TypedefItem(ref tydef, _) = *it.kind {
out.push_str("<span class=\"where fmt-newline\"> ");
out_content.push_str("<span class=\"where fmt-newline\"> ");
let empty_set = FxHashSet::default();
let src_link =
AssocItemLink::GotoSource(trait_did.into(), &empty_set);
assoc_type(&mut out, it, &[], Some(&tydef.type_), src_link, "", cx);
out.push_str(";</span>");
assoc_type(
&mut out_content,
it,
&[],
Some(&tydef.type_),
src_link,
"",
cx,
);
out_content.push_str(";</span>");
}
}
}
Expand All @@ -1289,16 +1300,26 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
}
}

if !out.is_empty() {
out.insert_str(
0,
"<span class=\"notable-traits\"><span class=\"notable-traits-tooltip\">ⓘ\
<div class=\"notable-traits-tooltiptext\"><span class=\"docblock\">",
if !out_for.is_empty() && !out_content.is_empty() {
let mut notable_traits = cx.shared.notable_traits.borrow_mut();

let out_for = out_for.into_inner();
let out_content = out_content.into_inner();
let nb_notable = notable_traits.len();
let index = match notable_traits.entry((out_for, out_content)) {
Entry::Occupied(o) => *o.get(),
Entry::Vacant(v) => {
v.insert(nb_notable);
nb_notable
}
};
return format!(
"<span class=\"notable-traits\"><span class=\"notable-traits-tooltip\" data-index={}>ⓘ</span></span>",
index
);
out.push_str("</code></span></div></span></span>");
}

out.into_inner()
String::new()
}

#[derive(Clone, Copy, Debug)]
Expand Down
17 changes: 17 additions & 0 deletions src/librustdoc/html/render/print_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,23 @@ pub(super) fn print_item(
unreachable!();
}
}
// We now write down all the notable traits DOM in one place that will be used by JS after.
let mut notable_traits = cx.shared.notable_traits.borrow_mut();
if !notable_traits.is_empty() {
let mut notables = notable_traits.drain().collect::<Vec<_>>();
notables.sort_by(|(_, pos1), (_, pos2)| pos1.cmp(pos2));
buf.write_str("<div id=\"notable-traits\" class=\"code-header\">");
for notable in notables {
buf.write_str(&format!(
"<div class=\"notable-traits-tooltiptext\">\
<div class=\"notable\">Notable traits for {}</div>\
<code class=\"content\">{}</code>\
</div>",
notable.0.0, notable.0.1
));
}
buf.write_str("</div>");
}
}

/// For large structs, enums, unions, etc, determine whether to hide their fields
Expand Down
20 changes: 9 additions & 11 deletions src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -1268,20 +1268,13 @@ h3.variant {
cursor: pointer;
}

.notable-traits:hover .notable-traits-tooltiptext,
.notable-traits .notable-traits-tooltiptext.force-tooltip {
display: inline-block;
}

.notable-traits .notable-traits-tooltiptext {
display: none;
.notable-traits-tooltiptext {
padding: 5px 3px 3px 3px;
border-radius: 6px;
margin-left: 5px;
z-index: 10;
font-size: 16px;
cursor: default;
position: absolute;
border: 1px solid;
}

Expand All @@ -1296,17 +1289,22 @@ h3.variant {
margin: 0;
}

.notable-traits .notable {
.notable-traits-tooltiptext .notable {
margin: 0;
margin-bottom: 13px;
font-size: 19px;
font-weight: 600;
}
#notable-traits .notable-traits-tooltiptext {
display: none;
position: absolute;
}

.notable-traits .docblock code.content{
.notable-traits-tooltiptext code.content{
margin: 0;
padding: 0;
font-size: 20px;
font-weight: 600;
}

/* Example code has the "Run" button that needs to be positioned relative to the pre */
Expand Down Expand Up @@ -1965,7 +1963,7 @@ details.rustdoc-toggle[open] > summary.hideme::after {
margin-top: 0;
}

.notable-traits .notable-traits-tooltiptext {
.notable-traits {
left: 0;
top: 100%;
}
Expand Down
46 changes: 39 additions & 7 deletions src/librustdoc/html/static/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ function hideThemeButtonState() {
if (!searchState.input) {
return;
}

function loadScript(url) {
var script = document.createElement('script');
script.src = url;
Expand Down Expand Up @@ -910,13 +911,6 @@ function hideThemeButtonState() {
});
});

onEachLazy(document.getElementsByClassName("notable-traits"), function(e) {
e.onclick = function() {
this.getElementsByClassName('notable-traits-tooltiptext')[0]
.classList.toggle("force-tooltip");
};
});

var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
if (sidebar_menu) {
sidebar_menu.onclick = function() {
Expand Down Expand Up @@ -1010,6 +1004,44 @@ function hideThemeButtonState() {
onHashChange(null);
window.addEventListener("hashchange", onHashChange);
searchState.setup();

//
// Handling the notable traits popup.
//
function showNotableTraitPopup(elem) {
if (elem === window.currentNotableElem) {
window.currentNotablePopup.style.display = "";
window.currentNotableElem = null;
return;
} else if (window.currentNotablePopup) {
window.currentNotablePopup.style.display = "";
}
var elemRect = elem.getBoundingClientRect();
var containerRect = main.getBoundingClientRect();

var index = elem.getAttribute("data-index");
var notableTraitContainer = document.getElementById("notable-traits");
var notable = notableTraitContainer.children[parseInt(index)];

notable.style.top = (elemRect.top - containerRect.top) + "px";
// In here, if the "i" is too much on the right, better put the popup on its left.
if (elem.offsetLeft > main.offsetWidth / 2) {
notable.style.left = "";
notable.style.right = (main.offsetWidth - elem.offsetLeft + 2) + "px";
} else {
notable.style.right = "";
notable.style.left = (elem.offsetLeft + 12) + "px";
}
notable.style.display = "block";
window.currentNotableElem = elem;
window.currentNotablePopup = notable;
}

onEachLazy(document.getElementsByClassName("notable-traits-tooltip"), function(e) {
e.onclick = function() {
showNotableTraitPopup(this);
};
});
}());

(function () {
Expand Down