From 017bfc361170d43fb9f93e6fed535e1719a680b4 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Mon, 5 Mar 2018 16:05:38 -0600 Subject: [PATCH 1/2] expose #[target_feature] attributes in rustdoc --- src/librustdoc/clean/cfg.rs | 40 +++++++++++++++++++++++++++++++++++-- src/librustdoc/clean/mod.rs | 13 ++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 5cac2d1bbe7..c228f54217d 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -138,7 +138,7 @@ impl Cfg { /// Renders the configuration for human display, as a short HTML description. pub(crate) fn render_short_html(&self) -> String { - let mut msg = Html(self).to_string(); + let mut msg = ShortHtml(self).to_string(); if self.should_capitalize_first_letter() { if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) { msg[i .. i+1].make_ascii_uppercase(); @@ -149,7 +149,13 @@ impl Cfg { /// Renders the configuration for long display, as a long HTML description. pub(crate) fn render_long_html(&self) -> String { - let mut msg = format!("This is supported on {}", Html(self)); + let on = if self.should_use_with_in_description() { + "with" + } else { + "on" + }; + + let mut msg = format!("This is supported {} {}", on, Html(self)); if self.should_append_only_to_description() { msg.push_str(" only"); } @@ -180,6 +186,13 @@ impl Cfg { } } } + + fn should_use_with_in_description(&self) -> bool { + match *self { + Cfg::Cfg(ref name, _) if name == &"target_feature" => true, + _ => false, + } + } } impl ops::Not for Cfg { @@ -376,6 +389,8 @@ impl<'a> fmt::Display for Html<'a> { }, ("target_endian", Some(endian)) => return write!(fmt, "{}-endian", endian), ("target_pointer_width", Some(bits)) => return write!(fmt, "{}-bit", bits), + ("target_feature", Some(feat)) => + return write!(fmt, "target feature {}", feat), _ => "", }; if !human_readable.is_empty() { @@ -390,6 +405,19 @@ impl<'a> fmt::Display for Html<'a> { } } +struct ShortHtml<'a>(&'a Cfg); + +impl<'a> fmt::Display for ShortHtml<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self.0 { + Cfg::Cfg(ref name, Some(ref vendor)) if name == &"target_feature" => { + write!(fmt, "{}", vendor) + }, + ref cfg => write!(fmt, "{}", Html(cfg)), + } + } +} + #[cfg(test)] mod test { use super::Cfg; @@ -824,6 +852,10 @@ mod test { ).render_short_html(), "(Debug-assertions enabled or Windows) and Unix" ); + assert_eq!( + name_value_cfg("target_feature", "sse2").render_short_html(), + "sse2" + ); }) } @@ -898,6 +930,10 @@ mod test { "This is supported on (debug-assertions enabled or Windows) and Unix\ only." ); + assert_eq!( + name_value_cfg("target_feature", "sse2").render_long_html(), + "This is supported with target feature sse2 only." + ); }) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ff281a53ab7..d6897617d55 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -828,6 +828,19 @@ impl Attributes { }) }).collect(); + // treat #[target_feature(enable = "feat")] attributes as if they were + // #[doc(cfg(target_feature = "feat"))] attributes as well + for attr in attrs.lists("target_feature") { + if attr.check_name("enable") { + if let Some(feat) = attr.value_str() { + let meta = attr::mk_name_value_item_str("target_feature".into(), feat); + if let Ok(feat_cfg) = Cfg::parse(&meta) { + cfg &= feat_cfg; + } + } + } + } + Attributes { doc_strings, other_attrs, From b3fb0d10f03fe7d8f2eaa705a972b0f45e1723db Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Wed, 21 Mar 2018 19:57:10 -0500 Subject: [PATCH 2/2] add target_feature items to doc_cfg rustdoc test --- src/test/rustdoc/doc-cfg.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/test/rustdoc/doc-cfg.rs b/src/test/rustdoc/doc-cfg.rs index 8499e5c741e..ea8a13b034b 100644 --- a/src/test/rustdoc/doc-cfg.rs +++ b/src/test/rustdoc/doc-cfg.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(doc_cfg)] +#![feature(target_feature, cfg_target_feature)] // @has doc_cfg/struct.Portable.html // @!has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' '' @@ -45,3 +46,26 @@ pub mod unix_only { fn unix_and_arm_only_function() {} } } + +// tagging a function with `#[target_feature]` creates a doc(cfg(target_feature)) node for that +// item as well + +// the portability header is different on the module view versus the full view +// @has doc_cfg/index.html +// @matches - '//*[@class=" module-item"]//*[@class="stab portability"]' '\Aavx\Z' + +// @has doc_cfg/fn.uses_target_feature.html +// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \ +// 'This is supported with target feature avx only.' +#[target_feature(enable = "avx")] +pub unsafe fn uses_target_feature() { + content::should::be::irrelevant(); +} + +// @has doc_cfg/fn.uses_cfg_target_feature.html +// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \ +// 'This is supported with target feature avx only.' +#[doc(cfg(target_feature = "avx"))] +pub fn uses_cfg_target_feature() { + uses_target_feature(); +}