Skip to content

Commit 20a5aa3

Browse files
set the default edition when pre-parsing a doctest
1 parent a19cf18 commit 20a5aa3

File tree

8 files changed

+84
-53
lines changed

8 files changed

+84
-53
lines changed

src/librustdoc/config.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -386,27 +386,28 @@ impl Options {
386386
}
387387
}
388388

389+
let edition = matches.opt_str("edition").unwrap_or("2015".to_string());
390+
let edition = match edition.parse() {
391+
Ok(e) => e,
392+
Err(_) => {
393+
diag.struct_err("could not parse edition").emit();
394+
return Err(1);
395+
}
396+
};
397+
389398
let mut id_map = html::markdown::IdMap::new();
390399
id_map.populate(html::render::initial_ids());
391400
let external_html = match ExternalHtml::load(
392401
&matches.opt_strs("html-in-header"),
393402
&matches.opt_strs("html-before-content"),
394403
&matches.opt_strs("html-after-content"),
395404
&matches.opt_strs("markdown-before-content"),
396-
&matches.opt_strs("markdown-after-content"), &diag, &mut id_map) {
405+
&matches.opt_strs("markdown-after-content"),
406+
&diag, &mut id_map, edition) {
397407
Some(eh) => eh,
398408
None => return Err(3),
399409
};
400410

401-
let edition = matches.opt_str("edition").unwrap_or("2015".to_string());
402-
let edition = match edition.parse() {
403-
Ok(e) => e,
404-
Err(_) => {
405-
diag.struct_err("could not parse edition").emit();
406-
return Err(1);
407-
}
408-
};
409-
410411
match matches.opt_str("r").as_ref().map(|s| &**s) {
411412
Some("rust") | None => {}
412413
Some(s) => {

src/librustdoc/externalfiles.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::path::Path;
33
use std::str;
44
use errors;
55
use crate::syntax::feature_gate::UnstableFeatures;
6+
use crate::syntax::edition::Edition;
67
use crate::html::markdown::{IdMap, ErrorCodes, Markdown};
78

89
use std::cell::RefCell;
@@ -23,7 +24,7 @@ pub struct ExternalHtml {
2324
impl ExternalHtml {
2425
pub fn load(in_header: &[String], before_content: &[String], after_content: &[String],
2526
md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler,
26-
id_map: &mut IdMap)
27+
id_map: &mut IdMap, edition: Edition)
2728
-> Option<ExternalHtml> {
2829
let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
2930
load_external_files(in_header, diag)
@@ -34,7 +35,8 @@ impl ExternalHtml {
3435
.and_then(|(ih, bc)|
3536
load_external_files(md_before_content, diag)
3637
.map(|m_bc| (ih,
37-
format!("{}{}", bc, Markdown(&m_bc, &[], RefCell::new(id_map), codes))))
38+
format!("{}{}", bc, Markdown(&m_bc, &[], RefCell::new(id_map),
39+
codes, edition))))
3840
)
3941
.and_then(|(ih, bc)|
4042
load_external_files(after_content, diag)
@@ -43,7 +45,8 @@ impl ExternalHtml {
4345
.and_then(|(ih, bc, ac)|
4446
load_external_files(md_after_content, diag)
4547
.map(|m_ac| (ih, bc,
46-
format!("{}{}", ac, Markdown(&m_ac, &[], RefCell::new(id_map), codes))))
48+
format!("{}{}", ac, Markdown(&m_ac, &[], RefCell::new(id_map),
49+
codes, edition))))
4750
)
4851
.map(|(ih, bc, ac)|
4952
ExternalHtml {

src/librustdoc/html/markdown.rs

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,21 @@ fn opts() -> Options {
4242
/// A unit struct which has the `fmt::Display` trait implemented. When
4343
/// formatted, this struct will emit the HTML corresponding to the rendered
4444
/// version of the contained markdown string.
45-
/// The second parameter is a list of link replacements
45+
///
46+
/// The second parameter is a list of link replacements.
47+
///
48+
/// The third is the current list of used header IDs.
49+
///
50+
/// The fourth is whether to allow the use of explicit error codes in doctest lang strings.
51+
///
52+
/// The fifth is what default edition to use when parsing doctests (to add a `fn main`).
4653
pub struct Markdown<'a>(
47-
pub &'a str, pub &'a [(String, String)], pub RefCell<&'a mut IdMap>, pub ErrorCodes);
54+
pub &'a str, pub &'a [(String, String)], pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition);
4855
/// A unit struct like `Markdown`, that renders the markdown with a
4956
/// table of contents.
50-
pub struct MarkdownWithToc<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
57+
pub struct MarkdownWithToc<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition);
5158
/// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
52-
pub struct MarkdownHtml<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
59+
pub struct MarkdownHtml<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition);
5360
/// A unit struct like `Markdown`, that renders only the first paragraph.
5461
pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]);
5562

@@ -146,13 +153,15 @@ thread_local!(pub static PLAYGROUND: RefCell<Option<(Option<String>, String)>> =
146153
struct CodeBlocks<'a, I: Iterator<Item = Event<'a>>> {
147154
inner: I,
148155
check_error_codes: ErrorCodes,
156+
edition: Edition,
149157
}
150158

151159
impl<'a, I: Iterator<Item = Event<'a>>> CodeBlocks<'a, I> {
152-
fn new(iter: I, error_codes: ErrorCodes) -> Self {
160+
fn new(iter: I, error_codes: ErrorCodes, edition: Edition) -> Self {
153161
CodeBlocks {
154162
inner: iter,
155163
check_error_codes: error_codes,
164+
edition,
156165
}
157166
}
158167
}
@@ -177,6 +186,9 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
177186
return event;
178187
}
179188

189+
let explicit_edition = edition.is_some();
190+
let edition = edition.unwrap_or(self.edition);
191+
180192
let mut origtext = String::new();
181193
for event in &mut self.inner {
182194
match event {
@@ -202,22 +214,14 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
202214
.collect::<Vec<Cow<'_, str>>>().join("\n");
203215
let krate = krate.as_ref().map(|s| &**s);
204216
let (test, _) = test::make_test(&test, krate, false,
205-
&Default::default());
217+
&Default::default(), edition);
206218
let channel = if test.contains("#![feature(") {
207219
"&amp;version=nightly"
208220
} else {
209221
""
210222
};
211223

212-
let edition_string = if let Some(e @ Edition::Edition2018) = edition {
213-
format!("&amp;edition={}{}", e,
214-
if channel == "&amp;version=nightly" { "" }
215-
else { "&amp;version=nightly" })
216-
} else if let Some(e) = edition {
217-
format!("&amp;edition={}", e)
218-
} else {
219-
"".to_owned()
220-
};
224+
let edition_string = format!("&amp;edition={}", edition);
221225

222226
// These characters don't need to be escaped in a URI.
223227
// FIXME: use a library function for percent encoding.
@@ -247,8 +251,8 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
247251
Some(("This example is not tested".to_owned(), "ignore"))
248252
} else if compile_fail {
249253
Some(("This example deliberately fails to compile".to_owned(), "compile_fail"))
250-
} else if let Some(e) = edition {
251-
Some((format!("This code runs with edition {}", e), "edition"))
254+
} else if explicit_edition {
255+
Some((format!("This code runs with edition {}", edition), "edition"))
252256
} else {
253257
None
254258
};
@@ -259,7 +263,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
259263
Some(&format!("rust-example-rendered{}",
260264
if ignore { " ignore" }
261265
else if compile_fail { " compile_fail" }
262-
else if edition.is_some() { " edition " }
266+
else if explicit_edition { " edition " }
263267
else { "" })),
264268
playground_button.as_ref().map(String::as_str),
265269
Some((s1.as_str(), s2))));
@@ -270,7 +274,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
270274
Some(&format!("rust-example-rendered{}",
271275
if ignore { " ignore" }
272276
else if compile_fail { " compile_fail" }
273-
else if edition.is_some() { " edition " }
277+
else if explicit_edition { " edition " }
274278
else { "" })),
275279
playground_button.as_ref().map(String::as_str),
276280
None));
@@ -659,7 +663,7 @@ impl LangString {
659663

660664
impl<'a> fmt::Display for Markdown<'a> {
661665
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
662-
let Markdown(md, links, ref ids, codes) = *self;
666+
let Markdown(md, links, ref ids, codes, edition) = *self;
663667
let mut ids = ids.borrow_mut();
664668

665669
// This is actually common enough to special-case
@@ -678,7 +682,7 @@ impl<'a> fmt::Display for Markdown<'a> {
678682

679683
let p = HeadingLinks::new(p, None, &mut ids);
680684
let p = LinkReplacer::new(p, links);
681-
let p = CodeBlocks::new(p, codes);
685+
let p = CodeBlocks::new(p, codes, edition);
682686
let p = Footnotes::new(p);
683687
html::push_html(&mut s, p);
684688

@@ -688,7 +692,7 @@ impl<'a> fmt::Display for Markdown<'a> {
688692

689693
impl<'a> fmt::Display for MarkdownWithToc<'a> {
690694
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
691-
let MarkdownWithToc(md, ref ids, codes) = *self;
695+
let MarkdownWithToc(md, ref ids, codes, edition) = *self;
692696
let mut ids = ids.borrow_mut();
693697

694698
let p = Parser::new_ext(md, opts());
@@ -699,7 +703,7 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> {
699703

700704
{
701705
let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
702-
let p = CodeBlocks::new(p, codes);
706+
let p = CodeBlocks::new(p, codes, edition);
703707
let p = Footnotes::new(p);
704708
html::push_html(&mut s, p);
705709
}
@@ -712,7 +716,7 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> {
712716

713717
impl<'a> fmt::Display for MarkdownHtml<'a> {
714718
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
715-
let MarkdownHtml(md, ref ids, codes) = *self;
719+
let MarkdownHtml(md, ref ids, codes, edition) = *self;
716720
let mut ids = ids.borrow_mut();
717721

718722
// This is actually common enough to special-case
@@ -728,7 +732,7 @@ impl<'a> fmt::Display for MarkdownHtml<'a> {
728732
let mut s = String::with_capacity(md.len() * 3 / 2);
729733

730734
let p = HeadingLinks::new(p, None, &mut ids);
731-
let p = CodeBlocks::new(p, codes);
735+
let p = CodeBlocks::new(p, codes, edition);
732736
let p = Footnotes::new(p);
733737
html::push_html(&mut s, p);
734738

src/librustdoc/html/render.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ use std::rc::Rc;
4747
use errors;
4848
use serialize::json::{ToJson, Json, as_json};
4949
use syntax::ast;
50+
use syntax::edition::Edition;
5051
use syntax::ext::base::MacroKind;
5152
use syntax::source_map::FileName;
5253
use syntax::feature_gate::UnstableFeatures;
@@ -107,6 +108,8 @@ struct Context {
107108
/// publicly reused items to redirect to the right location.
108109
pub render_redirect_pages: bool,
109110
pub codes: ErrorCodes,
111+
/// The default edition used to parse doctests.
112+
pub edition: Edition,
110113
/// The map used to ensure all generated 'id=' attributes are unique.
111114
id_map: Rc<RefCell<IdMap>>,
112115
pub shared: Arc<SharedContext>,
@@ -513,7 +516,8 @@ pub fn run(mut krate: clean::Crate,
513516
options: RenderOptions,
514517
passes: FxHashSet<String>,
515518
renderinfo: RenderInfo,
516-
diag: &errors::Handler) -> Result<(), Error> {
519+
diag: &errors::Handler,
520+
edition: Edition) -> Result<(), Error> {
517521
// need to save a copy of the options for rendering the index page
518522
let md_opts = options.clone();
519523
let RenderOptions {
@@ -603,6 +607,7 @@ pub fn run(mut krate: clean::Crate,
603607
dst,
604608
render_redirect_pages: false,
605609
codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()),
610+
edition,
606611
id_map: Rc::new(RefCell::new(id_map)),
607612
shared: Arc::new(scx),
608613
};
@@ -1127,7 +1132,7 @@ themePicker.onblur = handleThemeButtonsBlur;
11271132
md_opts.output = cx.dst.clone();
11281133
md_opts.external_html = (*cx.shared).layout.external_html.clone();
11291134

1130-
crate::markdown::render(index_page, md_opts, diag);
1135+
crate::markdown::render(index_page, md_opts, diag, cx.edition);
11311136
} else {
11321137
let dst = cx.dst.join("index.html");
11331138
let mut w = BufWriter::new(try_err!(File::create(&dst), &dst));
@@ -2552,7 +2557,7 @@ fn render_markdown(w: &mut fmt::Formatter<'_>,
25522557
if is_hidden { " hidden" } else { "" },
25532558
prefix,
25542559
Markdown(md_text, &links, RefCell::new(&mut ids),
2555-
cx.codes))
2560+
cx.codes, cx.edition))
25562561
}
25572562

25582563
fn document_short(
@@ -2917,7 +2922,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
29172922

29182923
if let Some(note) = note {
29192924
let mut ids = cx.id_map.borrow_mut();
2920-
let html = MarkdownHtml(&note, RefCell::new(&mut ids), error_codes);
2925+
let html = MarkdownHtml(&note, RefCell::new(&mut ids), error_codes, cx.edition);
29212926
message.push_str(&format!(": {}", html));
29222927
}
29232928
stability.push(format!("<div class='stab deprecated'>{}</div>", message));
@@ -2966,7 +2971,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
29662971
message = format!(
29672972
"<details><summary>{}</summary>{}</details>",
29682973
message,
2969-
MarkdownHtml(&unstable_reason, RefCell::new(&mut ids), error_codes)
2974+
MarkdownHtml(&unstable_reason, RefCell::new(&mut ids), error_codes, cx.edition)
29702975
);
29712976
}
29722977

@@ -4179,7 +4184,8 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt
41794184
if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
41804185
let mut ids = cx.id_map.borrow_mut();
41814186
write!(w, "<div class='docblock'>{}</div>",
4182-
Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids), cx.codes))?;
4187+
Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids),
4188+
cx.codes, cx.edition))?;
41834189
}
41844190
}
41854191

src/librustdoc/lib.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,15 +391,19 @@ fn main_args(args: &[String]) -> i32 {
391391
match (options.should_test, options.markdown_input()) {
392392
(true, true) => return markdown::test(options, &diag),
393393
(true, false) => return test::run(options),
394-
(false, true) => return markdown::render(options.input, options.render_options, &diag),
394+
(false, true) => return markdown::render(options.input,
395+
options.render_options,
396+
&diag,
397+
options.edition),
395398
(false, false) => {}
396399
}
397400

398401
// need to move these items separately because we lose them by the time the closure is called,
399402
// but we can't crates the Handler ahead of time because it's not Send
400403
let diag_opts = (options.error_format,
401404
options.debugging_options.treat_err_as_bug,
402-
options.debugging_options.ui_testing);
405+
options.debugging_options.ui_testing,
406+
options.edition);
403407
let show_coverage = options.show_coverage;
404408
rust_input(options, move |out| {
405409
if show_coverage {
@@ -410,14 +414,15 @@ fn main_args(args: &[String]) -> i32 {
410414

411415
let Output { krate, passes, renderinfo, renderopts } = out;
412416
info!("going to format");
413-
let (error_format, treat_err_as_bug, ui_testing) = diag_opts;
417+
let (error_format, treat_err_as_bug, ui_testing, edition) = diag_opts;
414418
let diag = core::new_handler(error_format, None, treat_err_as_bug, ui_testing);
415419
match html::render::run(
416420
krate,
417421
renderopts,
418422
passes.into_iter().collect(),
419423
renderinfo,
420424
&diag,
425+
edition,
421426
) {
422427
Ok(_) => rustc_driver::EXIT_SUCCESS,
423428
Err(e) => {

src/librustdoc/markdown.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::cell::RefCell;
55

66
use errors;
77
use testing;
8+
use syntax::edition::Edition;
89
use syntax::source_map::DUMMY_SP;
910
use syntax::feature_gate::UnstableFeatures;
1011

@@ -36,7 +37,12 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) {
3637

3738
/// Render `input` (e.g., "foo.md") into an HTML file in `output`
3839
/// (e.g., output = "bar" => "bar/foo.html").
39-
pub fn render(input: PathBuf, options: RenderOptions, diag: &errors::Handler) -> i32 {
40+
pub fn render(
41+
input: PathBuf,
42+
options: RenderOptions,
43+
diag: &errors::Handler,
44+
edition: Edition
45+
) -> i32 {
4046
let mut output = options.output;
4147
output.push(input.file_stem().unwrap());
4248
output.set_extension("html");
@@ -76,9 +82,9 @@ pub fn render(input: PathBuf, options: RenderOptions, diag: &errors::Handler) ->
7682
let mut ids = IdMap::new();
7783
let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
7884
let text = if !options.markdown_no_toc {
79-
MarkdownWithToc(text, RefCell::new(&mut ids), error_codes).to_string()
85+
MarkdownWithToc(text, RefCell::new(&mut ids), error_codes, edition).to_string()
8086
} else {
81-
Markdown(text, &[], RefCell::new(&mut ids), error_codes).to_string()
87+
Markdown(text, &[], RefCell::new(&mut ids), error_codes, edition).to_string()
8288
};
8389

8490
let err = write!(

0 commit comments

Comments
 (0)