diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 10b6c9850ae..67502ab8e15 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -12,7 +12,8 @@ use std::fs; use std::path::Path; use std::str; use errors; -use html::markdown::Markdown; +use syntax::feature_gate::UnstableFeatures; +use html::markdown::{ErrorCodes, Markdown}; #[derive(Clone)] pub struct ExternalHtml { @@ -31,6 +32,7 @@ impl ExternalHtml { pub fn load(in_header: &[String], before_content: &[String], after_content: &[String], md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler) -> Option { + let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); load_external_files(in_header, diag) .and_then(|ih| load_external_files(before_content, diag) @@ -38,7 +40,7 @@ impl ExternalHtml { ) .and_then(|(ih, bc)| load_external_files(md_before_content, diag) - .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[])))) + .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[], codes)))) ) .and_then(|(ih, bc)| load_external_files(after_content, diag) @@ -46,7 +48,7 @@ impl ExternalHtml { ) .and_then(|(ih, bc, ac)| load_external_files(md_after_content, diag) - .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[])))) + .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[], codes)))) ) .map(|(ih, bc, ac)| ExternalHtml { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 54fd041fb00..f65211f97be 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -18,10 +18,10 @@ //! ``` //! #![feature(rustc_private)] //! -//! use rustdoc::html::markdown::Markdown; +//! use rustdoc::html::markdown::{Markdown, ErrorCodes}; //! //! let s = "My *markdown* _text_"; -//! let html = format!("{}", Markdown(s, &[])); +//! let html = format!("{}", Markdown(s, &[], ErrorCodes::Yes)); //! // ... something using html //! ``` @@ -35,7 +35,6 @@ use std::borrow::Cow; use std::ops::Range; use std::str; -use syntax::feature_gate::UnstableFeatures; use html::render::derive_id; use html::toc::TocBuilder; use html::highlight; @@ -48,15 +47,37 @@ use pulldown_cmark::{Options, OPTION_ENABLE_FOOTNOTES, OPTION_ENABLE_TABLES}; /// formatted, this struct will emit the HTML corresponding to the rendered /// version of the contained markdown string. /// The second parameter is a list of link replacements -pub struct Markdown<'a>(pub &'a str, pub &'a [(String, String)]); +pub struct Markdown<'a>(pub &'a str, pub &'a [(String, String)], pub ErrorCodes); /// A unit struct like `Markdown`, that renders the markdown with a /// table of contents. -pub struct MarkdownWithToc<'a>(pub &'a str); +pub struct MarkdownWithToc<'a>(pub &'a str, pub ErrorCodes); /// A unit struct like `Markdown`, that renders the markdown escaping HTML tags. -pub struct MarkdownHtml<'a>(pub &'a str); +pub struct MarkdownHtml<'a>(pub &'a str, pub ErrorCodes); /// A unit struct like `Markdown`, that renders only the first paragraph. pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]); +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum ErrorCodes { + Yes, + No, +} + +impl ErrorCodes { + pub fn from(b: bool) -> Self { + match b { + true => ErrorCodes::Yes, + false => ErrorCodes::No, + } + } + + pub fn as_bool(self) -> bool { + match self { + ErrorCodes::Yes => true, + ErrorCodes::No => false, + } + } +} + /// Controls whether a line will be hidden or shown in HTML output. /// /// All lines are used in documentation tests. @@ -127,14 +148,14 @@ thread_local!(pub static PLAYGROUND: RefCell, String)>> = /// Adds syntax highlighting and playground Run buttons to rust code blocks. struct CodeBlocks<'a, I: Iterator>> { inner: I, - check_error_codes: bool, + check_error_codes: ErrorCodes, } impl<'a, I: Iterator>> CodeBlocks<'a, I> { - fn new(iter: I) -> Self { + fn new(iter: I, error_codes: ErrorCodes) -> Self { CodeBlocks { inner: iter, - check_error_codes: UnstableFeatures::from_environment().is_nightly_build(), + check_error_codes: error_codes, } } } @@ -476,9 +497,8 @@ impl fmt::Display for TestableCodeError { } pub fn find_testable_code( - doc: &str, tests: &mut test::Collector + doc: &str, tests: &mut test::Collector, error_codes: ErrorCodes, ) -> Result<(), TestableCodeError> { - let is_nightly = UnstableFeatures::from_environment().is_nightly_build(); let mut parser = Parser::new(doc); let mut prev_offset = 0; let mut nb_lines = 0; @@ -489,7 +509,7 @@ pub fn find_testable_code( let block_info = if s.is_empty() { LangString::all_false() } else { - LangString::parse(&*s, is_nightly) + LangString::parse(&*s, error_codes) }; if !block_info.rust { continue @@ -570,7 +590,8 @@ impl LangString { } } - fn parse(string: &str, allow_error_code_check: bool) -> LangString { + fn parse(string: &str, allow_error_code_check: ErrorCodes) -> LangString { + let allow_error_code_check = allow_error_code_check.as_bool(); let mut seen_rust_tags = false; let mut seen_other_tags = false; let mut data = LangString::all_false(); @@ -620,7 +641,7 @@ impl LangString { impl<'a> fmt::Display for Markdown<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let Markdown(md, links) = *self; + let Markdown(md, links, codes) = *self; // This is actually common enough to special-case if md.is_empty() { return Ok(()) } @@ -645,7 +666,7 @@ impl<'a> fmt::Display for Markdown<'a> { CodeBlocks::new( LinkReplacer::new( HeadingLinks::new(p, None), - links)))); + links), codes))); fmt.write_str(&s) } @@ -653,7 +674,7 @@ impl<'a> fmt::Display for Markdown<'a> { impl<'a> fmt::Display for MarkdownWithToc<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let MarkdownWithToc(md) = *self; + let MarkdownWithToc(md, codes) = *self; let mut opts = Options::empty(); opts.insert(OPTION_ENABLE_TABLES); @@ -665,8 +686,12 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> { let mut toc = TocBuilder::new(); - html::push_html(&mut s, - Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, Some(&mut toc))))); + { + let p = HeadingLinks::new(p, Some(&mut toc)); + let p = CodeBlocks::new(p, codes); + let p = Footnotes::new(p); + html::push_html(&mut s, p); + } write!(fmt, "", toc.into_toc())?; @@ -676,7 +701,7 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> { impl<'a> fmt::Display for MarkdownHtml<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let MarkdownHtml(md) = *self; + let MarkdownHtml(md, codes) = *self; // This is actually common enough to special-case if md.is_empty() { return Ok(()) } @@ -694,8 +719,10 @@ impl<'a> fmt::Display for MarkdownHtml<'a> { let mut s = String::with_capacity(md.len() * 3 / 2); - html::push_html(&mut s, - Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, None)))); + let p = HeadingLinks::new(p, None); + let p = CodeBlocks::new(p, codes); + let p = Footnotes::new(p); + html::push_html(&mut s, p); fmt.write_str(&s) } @@ -830,7 +857,7 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option>)> { #[cfg(test)] mod tests { - use super::{LangString, Markdown, MarkdownHtml}; + use super::{ErrorCodes, LangString, Markdown, MarkdownHtml}; use super::plain_summary_line; use html::render::reset_ids; @@ -839,7 +866,7 @@ mod tests { fn t(s: &str, should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool, compile_fail: bool, allow_fail: bool, error_codes: Vec) { - assert_eq!(LangString::parse(s, true), LangString { + assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString { should_panic, no_run, ignore, @@ -878,14 +905,14 @@ mod tests { #[test] fn issue_17736() { let markdown = "# title"; - Markdown(markdown, &[]).to_string(); + Markdown(markdown, &[], ErrorCodes::Yes).to_string(); reset_ids(true); } #[test] fn test_header() { fn t(input: &str, expect: &str) { - let output = Markdown(input, &[]).to_string(); + let output = Markdown(input, &[], ErrorCodes::Yes).to_string(); assert_eq!(output, expect, "original: {}", input); reset_ids(true); } @@ -907,7 +934,7 @@ mod tests { #[test] fn test_header_ids_multiple_blocks() { fn t(input: &str, expect: &str) { - let output = Markdown(input, &[]).to_string(); + let output = Markdown(input, &[], ErrorCodes::Yes).to_string(); assert_eq!(output, expect, "original: {}", input); } @@ -948,7 +975,7 @@ mod tests { #[test] fn test_markdown_html_escape() { fn t(input: &str, expect: &str) { - let output = MarkdownHtml(input).to_string(); + let output = MarkdownHtml(input, ErrorCodes::Yes).to_string(); assert_eq!(output, expect, "original: {}", input); } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 24a9bf416e4..b9b058cb548 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -56,6 +56,7 @@ use externalfiles::ExternalHtml; use serialize::json::{ToJson, Json, as_json}; use syntax::ast; use syntax::codemap::FileName; +use syntax::feature_gate::UnstableFeatures; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; @@ -72,7 +73,7 @@ use html::format::{GenericBounds, WhereClause, href, AbiSpace}; use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace}; use html::format::fmt_impl_for_trait_page; use html::item_type::ItemType; -use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine}; +use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes}; use html::{highlight, layout}; use minifier; @@ -99,6 +100,7 @@ pub struct Context { /// real location of an item. This is used to allow external links to /// publicly reused items to redirect to the right location. pub render_redirect_pages: bool, + pub codes: ErrorCodes, pub shared: Arc, } @@ -581,6 +583,7 @@ pub fn run(mut krate: clean::Crate, current: Vec::new(), dst, render_redirect_pages: false, + codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()), shared: Arc::new(scx), }; @@ -2221,13 +2224,14 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re fn render_markdown(w: &mut fmt::Formatter, md_text: &str, links: Vec<(String, String)>, - prefix: &str,) + prefix: &str, + codes: ErrorCodes) -> fmt::Result { - write!(w, "
{}{}
", prefix, Markdown(md_text, &links)) + write!(w, "
{}{}
", prefix, Markdown(md_text, &links, codes)) } fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink, - prefix: &str) -> fmt::Result { + prefix: &str, codes: ErrorCodes) -> fmt::Result { if let Some(s) = item.doc_value() { let markdown = if s.contains('\n') { format!("{} [Read more]({})", @@ -2235,7 +2239,7 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin } else { plain_summary_line(Some(s)).to_string() }; - render_markdown(w, &markdown, item.links(), prefix)?; + render_markdown(w, &markdown, item.links(), prefix, codes)?; } else if !prefix.is_empty() { write!(w, "
{}
", prefix)?; } @@ -2261,7 +2265,7 @@ fn document_full(w: &mut fmt::Formatter, item: &clean::Item, cx: &Context, prefix: &str) -> fmt::Result { if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) { debug!("Doc block: =====\n{}\n=====", s); - render_markdown(w, &*s, item.links(), prefix)?; + render_markdown(w, &*s, item.links(), prefix, cx.codes)?; } else if !prefix.is_empty() { write!(w, "
{}
", prefix)?; } @@ -2508,6 +2512,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec { let mut stability = vec![]; + let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); if let Some(stab) = item.stability.as_ref() { let deprecated_reason = if show_reason && !stab.deprecated_reason.is_empty() { @@ -2521,14 +2526,11 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) }; @@ -2559,7 +2561,9 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", unstable_extra, - MarkdownHtml(&stab.unstable_reason)); + MarkdownHtml( + &stab.unstable_reason, + error_codes)); stability.push(format!("
{}
", text)); } @@ -2582,11 +2586,11 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) } @@ -3811,7 +3815,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi write!(w, "")?; if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) { write!(w, "
{}
", - Markdown(&*dox, &i.impl_item.links()))?; + Markdown(&*dox, &i.impl_item.links(), cx.codes))?; } } @@ -3897,7 +3901,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } else if show_def_docs { // In case the item isn't documented, // provide short documentation from the trait. - document_short(w, it, link, &prefix)?; + document_short(w, it, link, &prefix, cx.codes)?; } } } else { @@ -3909,7 +3913,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } else { document_stability(w, cx, item)?; if show_def_docs { - document_short(w, item, link, &prefix)?; + document_short(w, item, link, &prefix, cx.codes)?; } } } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 4d1eae1470f..97a3b2c1ea0 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -19,6 +19,7 @@ use testing; use rustc::session::search_paths::SearchPaths; use rustc::session::config::{Externs, CodegenOptions}; use syntax::codemap::DUMMY_SP; +use syntax::feature_gate::UnstableFeatures; use syntax::edition::Edition; use externalfiles::{ExternalHtml, LoadStringError, load_string}; @@ -26,7 +27,7 @@ use externalfiles::{ExternalHtml, LoadStringError, load_string}; use html::render::reset_ids; use html::escape::Escape; use html::markdown; -use html::markdown::{Markdown, MarkdownWithToc, find_testable_code}; +use html::markdown::{ErrorCodes, Markdown, MarkdownWithToc, find_testable_code}; use test::{TestOptions, Collector}; /// Separate any lines at the start of the file that begin with `# ` or `%`. @@ -88,10 +89,11 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches, reset_ids(false); + let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); let text = if include_toc { - MarkdownWithToc(text).to_string() + MarkdownWithToc(text, error_codes).to_string() } else { - Markdown(text, &[]).to_string() + Markdown(text, &[], error_codes).to_string() }; let err = write!( @@ -157,7 +159,8 @@ pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, Some(PathBuf::from(input)), linker, edition); collector.set_position(DUMMY_SP); - let res = find_testable_code(&input_str, &mut collector); + let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); + let res = find_testable_code(&input_str, &mut collector, codes); if let Err(err) = res { diag.span_warn(DUMMY_SP, &err.to_string()); } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 9723b452800..650a2408aa6 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -42,7 +42,7 @@ use errors; use errors::emitter::ColorConfig; use clean::Attributes; -use html::markdown::{self, LangString}; +use html::markdown::{self, ErrorCodes, LangString}; #[derive(Clone, Default)] pub struct TestOptions { @@ -145,7 +145,8 @@ pub fn run(input_path: &Path, let mut hir_collector = HirCollector { sess: &sess, collector: &mut collector, - map: &map + map: &map, + codes: ErrorCodes::from(sess.opts.unstable_features.is_nightly_build()), }; hir_collector.visit_testable("".to_string(), &krate.attrs, |this| { intravisit::walk_crate(this, krate); @@ -662,7 +663,8 @@ impl Collector { struct HirCollector<'a, 'hir: 'a> { sess: &'a session::Session, collector: &'a mut Collector, - map: &'a hir::map::Map<'hir> + map: &'a hir::map::Map<'hir>, + codes: ErrorCodes, } impl<'a, 'hir> HirCollector<'a, 'hir> { @@ -688,7 +690,7 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { // anything else, this will combine them for us if let Some(doc) = attrs.collapsed_doc_value() { self.collector.set_position(attrs.span.unwrap_or(DUMMY_SP)); - let res = markdown::find_testable_code(&doc, self.collector); + let res = markdown::find_testable_code(&doc, self.collector, self.codes); if let Err(err) = res { self.sess.diagnostic().span_warn(attrs.span.unwrap_or(DUMMY_SP), &err.to_string()); diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index e72f90554d3..79c5be125b3 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -24,7 +24,7 @@ use std::path::PathBuf; use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata}; -use rustdoc::html::markdown::{Markdown, PLAYGROUND}; +use rustdoc::html::markdown::{Markdown, ErrorCodes, PLAYGROUND}; use rustc_serialize::json; enum OutputFormat { @@ -100,7 +100,7 @@ impl Formatter for HTMLFormatter { // Description rendered as markdown. match info.description { - Some(ref desc) => write!(output, "{}", Markdown(desc, &[]))?, + Some(ref desc) => write!(output, "{}", Markdown(desc, &[], ErrorCodes::Yes))?, None => write!(output, "

No description.

\n")?, }