diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 79eaabe31e86b..8c14d1bbe8f8a 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -105,7 +105,7 @@ r##"
Switch tab
Go to active search result
-
+
+
+ / -
Collapse/expand all sections
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 88e1f780d0342..eb59c57603aae 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2498,7 +2498,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, if !foreign.is_empty() { write!(w, " -

+

Implementations on Foreign Types

")?; @@ -3591,7 +3591,8 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { let mut links = HashSet::new(); let ret = v.iter() .filter_map(|i| if let Some(ref i) = i.inner_impl().trait_ { - let out = format!("{:#}", i).replace("<", "<").replace(">", ">"); + let i_display = format!("{:#}", i); + let out = Escape(&i_display); let encoded = small_url_encode(&format!("{:#}", i)); let generated = format!("{}", encoded, out); if !links.contains(&generated) && links.insert(generated.clone()) { @@ -3617,11 +3618,12 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { fn sidebar_struct(fmt: &mut fmt::Formatter, it: &clean::Item, s: &clean::Struct) -> fmt::Result { let mut sidebar = String::new(); + let fields = get_struct_fields_name(&s.fields); - if s.fields.iter() - .any(|f| if let clean::StructFieldItem(..) = f.inner { true } else { false }) { + if !fields.is_empty() { if let doctree::Plain = s.struct_type { - sidebar.push_str("
  • Fields
  • "); + sidebar.push_str(&format!("Fields\ +
    {}
    ", fields)); } } @@ -3633,40 +3635,122 @@ fn sidebar_struct(fmt: &mut fmt::Formatter, it: &clean::Item, Ok(()) } +fn extract_for_impl_name(item: &clean::Item) -> Option<(String, String)> { + match item.inner { + clean::ItemEnum::ImplItem(ref i) => { + if let Some(ref trait_) = i.trait_ { + Some((format!("{:#}", i.for_), format!("{:#}", trait_))) + } else { + None + } + }, + _ => None, + } +} + fn sidebar_trait(fmt: &mut fmt::Formatter, it: &clean::Item, t: &clean::Trait) -> fmt::Result { let mut sidebar = String::new(); - let has_types = t.items.iter().any(|m| m.is_associated_type()); - let has_consts = t.items.iter().any(|m| m.is_associated_const()); - let has_required = t.items.iter().any(|m| m.is_ty_method()); - let has_provided = t.items.iter().any(|m| m.is_method()); + let types = t.items + .iter() + .filter_map(|m| { + match m.name { + Some(ref name) if m.is_associated_type() => { + Some(format!("{name}", + name=name)) + } + _ => None, + } + }) + .collect::(); + let consts = t.items + .iter() + .filter_map(|m| { + match m.name { + Some(ref name) if m.is_associated_const() => { + Some(format!("{name}", + name=name)) + } + _ => None, + } + }) + .collect::(); + let required = t.items + .iter() + .filter_map(|m| { + match m.name { + Some(ref name) if m.is_ty_method() => { + Some(format!("{name}", + name=name)) + } + _ => None, + } + }) + .collect::(); + let provided = t.items + .iter() + .filter_map(|m| { + match m.name { + Some(ref name) if m.is_method() => { + Some(format!("{name}", name=name)) + } + _ => None, + } + }) + .collect::(); - if has_types { - sidebar.push_str("
  • Associated Types
  • "); + if !types.is_empty() { + sidebar.push_str(&format!("\ + Associated Types
    {}
    ", + types)); } - if has_consts { - sidebar.push_str("
  • Associated Constants
  • "); + if !consts.is_empty() { + sidebar.push_str(&format!("\ + Associated Constants
    {}
    ", + consts)); } - if has_required { - sidebar.push_str("
  • Required Methods
  • "); + if !required.is_empty() { + sidebar.push_str(&format!("\ + Required Methods
    {}
    ", + required)); } - if has_provided { - sidebar.push_str("
  • Provided Methods
  • "); + if !provided.is_empty() { + sidebar.push_str(&format!("\ + Provided Methods
    {}
    ", + provided)); } let c = cache(); if let Some(implementors) = c.implementors.get(&it.def_id) { - if implementors.iter().any(|i| i.impl_.for_.def_id() - .map_or(false, |d| !c.paths.contains_key(&d))) - { - sidebar.push_str("
  • \ - Implementations on Foreign Types
  • "); - } - } - - sidebar.push_str("
  • Implementors
  • "); + let res = implementors.iter() + .filter(|i| i.impl_.for_.def_id() + .map_or(false, |d| !c.paths.contains_key(&d))) + .filter_map(|i| { + if let Some(item) = implementor2item(&c, i) { + match extract_for_impl_name(&item) { + Some((ref name, ref url)) => { + Some(format!("{}", + small_url_encode(url), + Escape(name))) + } + _ => None, + } + } else { + None + } + }) + .collect::(); + if !res.is_empty() { + sidebar.push_str(&format!("\ + Implementations on Foreign Types
    {}
    ", + res)); + } + } + + sidebar.push_str("Implementors"); sidebar.push_str(&sidebar_assoc_items(it)); @@ -3693,13 +3777,29 @@ fn sidebar_typedef(fmt: &mut fmt::Formatter, it: &clean::Item, Ok(()) } +fn get_struct_fields_name(fields: &[clean::Item]) -> String { + fields.iter() + .filter(|f| if let clean::StructFieldItem(..) = f.inner { + true + } else { + false + }) + .filter_map(|f| match f.name { + Some(ref name) => Some(format!("\ + {name}", name=name)), + _ => None, + }) + .collect() +} + fn sidebar_union(fmt: &mut fmt::Formatter, it: &clean::Item, u: &clean::Union) -> fmt::Result { let mut sidebar = String::new(); + let fields = get_struct_fields_name(&u.fields); - if u.fields.iter() - .any(|f| if let clean::StructFieldItem(..) = f.inner { true } else { false }) { - sidebar.push_str("
  • Fields
  • "); + if !fields.is_empty() { + sidebar.push_str(&format!("Fields\ +
    {}
    ", fields)); } sidebar.push_str(&sidebar_assoc_items(it)); @@ -3714,8 +3814,16 @@ fn sidebar_enum(fmt: &mut fmt::Formatter, it: &clean::Item, e: &clean::Enum) -> fmt::Result { let mut sidebar = String::new(); - if !e.variants.is_empty() { - sidebar.push_str("
  • Variants
  • "); + let variants = e.variants.iter() + .filter_map(|v| match v.name { + Some(ref name) => Some(format!("{name}\ + ", name = name)), + _ => None, + }) + .collect::(); + if !variants.is_empty() { + sidebar.push_str(&format!("Variants\ +
    {}
    ", variants)); } sidebar.push_str(&sidebar_assoc_items(it)); diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index b1120e0af3894..1d9bfa260bf5b 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -213,6 +213,7 @@ break; case "+": + case "-": ev.preventDefault(); toggleAllDocs(); break; diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 398a692f8df5e..599b032b63030 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -582,13 +582,14 @@ body.blur > :not(#help) { display: block; margin-top: -1px; } -#help dd { margin: 5px 33px; } +#help dd { margin: 5px 35px; } #help .infos { padding-left: 0; } #help h1, #help h2 { margin-top: 0; } #help > div div { width: 50%; float: left; padding: 20px; + padding-left: 17px; } .stab { diff --git a/src/libstd/env.rs b/src/libstd/env.rs index f81adad3ebebf..457c6e1409d3c 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -671,6 +671,10 @@ pub struct ArgsOs { inner: sys::args::Args } /// set to arbitrary text, and may not even exist. This means this property should /// not be relied upon for security purposes. /// +/// On Unix systems shell usually expands unquoted arguments with glob patterns +/// (such as `*` and `?`). On Windows this is not done, and such arguments are +/// passed as-is. +/// /// # Panics /// /// The returned iterator will panic during iteration if any argument to the diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index d23cae40cfaff..15f858bca1643 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -20,7 +20,9 @@ use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; use sys::platform::fs::MetadataExt as UnixMetadataExt; -/// Unix-specific extensions to `File` +/// Unix-specific extensions to [`File`]. +/// +/// [`File`]: ../../../../std/fs/struct.File.html #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { /// Reads a number of bytes starting from a given offset. @@ -515,19 +517,79 @@ impl MetadataExt for fs::Metadata { fn blocks(&self) -> u64 { self.st_blocks() } } -/// Add special unix types (block/char device, fifo and socket) +/// Add support for special unix types (block/char device, fifo and socket). #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. + /// + /// # Examples + /// + /// ``` + /// use std::fs; + /// use std::os::unix::fs::FileTypeExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("block_device_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_block_device()); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_block_device(&self) -> bool; /// Returns whether this file type is a char device. + /// + /// # Examples + /// + /// ``` + /// use std::fs; + /// use std::os::unix::fs::FileTypeExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("char_device_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_char_device()); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_char_device(&self) -> bool; /// Returns whether this file type is a fifo. + /// + /// # Examples + /// + /// ``` + /// use std::fs; + /// use std::os::unix::fs::FileTypeExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("fifo_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_fifo()); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_fifo(&self) -> bool; /// Returns whether this file type is a socket. + /// + /// # Examples + /// + /// ``` + /// use std::fs; + /// use std::os::unix::fs::FileTypeExt; + /// + /// # use std::io; + /// # fn f() -> io::Result<()> { + /// let meta = fs::metadata("unix.socket")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_socket()); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_socket(&self) -> bool; } @@ -540,7 +602,9 @@ impl FileTypeExt for fs::FileType { fn is_socket(&self) -> bool { self.as_inner().is(libc::S_IFSOCK) } } -/// Unix-specific extension methods for `fs::DirEntry` +/// Unix-specific extension methods for [`fs::DirEntry`]. +/// +/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html #[stable(feature = "dir_entry_ext", since = "1.1.0")] pub trait DirEntryExt { /// Returns the underlying `d_ino` field in the contained `dirent` @@ -600,7 +664,9 @@ pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> } #[stable(feature = "dir_builder", since = "1.6.0")] -/// An extension trait for `fs::DirBuilder` for unix-specific options. +/// An extension trait for [`fs::DirBuilder`] for unix-specific options. +/// +/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html pub trait DirBuilderExt { /// Sets the mode to create new directories with. This option defaults to /// 0o777. diff --git a/src/test/rustdoc/sidebar-items.rs b/src/test/rustdoc/sidebar-items.rs new file mode 100644 index 0000000000000..9be40441e9d4f --- /dev/null +++ b/src/test/rustdoc/sidebar-items.rs @@ -0,0 +1,59 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +// @has foo/trait.Foo.html +// @has - '//*[@class="sidebar-title"][@href="#required-methods"]' 'Required Methods' +// @has - '//*[@class="sidebar-links"]/a' 'bar' +// @has - '//*[@class="sidebar-title"][@href="#provided-methods"]' 'Provided Methods' +// @has - '//*[@class="sidebar-links"]/a' 'foo' +// @has - '//*[@class="sidebar-title"][@href="#associated-const"]' 'Associated Constants' +// @has - '//*[@class="sidebar-links"]/a' 'BAR' +// @has - '//*[@class="sidebar-title"][@href="#associated-types"]' 'Associated Types' +// @has - '//*[@class="sidebar-links"]/a' 'Output' +pub trait Foo { + const BAR: u32 = 0; + type Output: ?Sized; + + fn foo() {} + fn bar() -> Self::Output; +} + +// @has foo/struct.Bar.html +// @has - '//*[@class="sidebar-title"][@href="#fields"]' 'Fields' +// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f"]' 'f' +// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.u"]' 'u' +// @!has - '//*[@class="sidebar-links"]/a' 'w' +pub struct Bar { + pub f: u32, + pub u: u32, + w: u32, +} + +// @has foo/enum.En.html +// @has - '//*[@class="sidebar-title"][@href="#variants"]' 'Variants' +// @has - '//*[@class="sidebar-links"]/a' 'foo' +// @has - '//*[@class="sidebar-links"]/a' 'bar' +pub enum En { + foo, + bar, +} + +// @has foo/union.MyUnion.html +// @has - '//*[@class="sidebar-title"][@href="#fields"]' 'Fields' +// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f1"]' 'f1' +// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f2"]' 'f2' +// @!has - '//*[@class="sidebar-links"]/a' 'w' +pub union MyUnion { + pub f1: u32, + pub f2: f32, + w: u32, +}