Skip to content

Commit fe7ed38

Browse files
Correctly handle line comments in attributes and generate extern crates
outside of wrapping function
1 parent 1240a7d commit fe7ed38

File tree

5 files changed

+89
-11
lines changed

5 files changed

+89
-11
lines changed

src/librustdoc/doctest/make.rs

+32-7
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,24 @@ impl DocTestBuilder {
176176

177177
// Now push any outer attributes from the example, assuming they
178178
// are intended to be crate attributes.
179-
prog.push_str(&self.crate_attrs);
180-
prog.push_str(&self.maybe_crate_attrs);
181-
prog.push_str(&self.crates);
179+
if !self.crate_attrs.is_empty() {
180+
prog.push_str(&self.crate_attrs);
181+
if !self.crate_attrs.ends_with('\n') {
182+
prog.push('\n');
183+
}
184+
}
185+
if !self.maybe_crate_attrs.is_empty() {
186+
prog.push_str(&self.maybe_crate_attrs);
187+
if !self.maybe_crate_attrs.ends_with('\n') {
188+
prog.push('\n');
189+
}
190+
}
191+
if !self.crates.is_empty() {
192+
prog.push_str(&self.crates);
193+
if !self.crates.ends_with('\n') {
194+
prog.push('\n');
195+
}
196+
}
182197

183198
// Don't inject `extern crate std` because it's already injected by the
184199
// compiler.
@@ -338,7 +353,8 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
338353
info: &mut ParseSourceInfo,
339354
crate_name: &Option<&str>,
340355
is_top_level: bool,
341-
) {
356+
) -> bool {
357+
let mut is_crate = false;
342358
if !info.has_global_allocator
343359
&& item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator)
344360
{
@@ -354,12 +370,13 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
354370
if let Some(ref body) = fn_item.body {
355371
for stmt in &body.stmts {
356372
if let StmtKind::Item(ref item) = stmt.kind {
357-
check_item(item, info, crate_name, false)
373+
is_crate |= check_item(item, info, crate_name, false);
358374
}
359375
}
360376
}
361377
}
362378
ast::ItemKind::ExternCrate(original) => {
379+
is_crate = true;
363380
if !info.found_extern_crate
364381
&& let Some(crate_name) = crate_name
365382
{
@@ -374,6 +391,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
374391
}
375392
_ => {}
376393
}
394+
is_crate
377395
}
378396

379397
let mut prev_span_hi = None;
@@ -412,8 +430,11 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
412430
}
413431
}
414432
for stmt in &body.stmts {
433+
let mut is_crate = false;
415434
match stmt.kind {
416-
StmtKind::Item(ref item) => check_item(&item, &mut info, crate_name, true),
435+
StmtKind::Item(ref item) => {
436+
is_crate = check_item(&item, &mut info, crate_name, true);
437+
}
417438
StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => {
418439
cancel_error_count(&psess);
419440
return Err(());
@@ -458,7 +479,11 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
458479
&mut prev_span_hi,
459480
);
460481
}
461-
push_to_s(&mut info.everything_else, source, span, &mut prev_span_hi);
482+
if !is_crate {
483+
push_to_s(&mut info.everything_else, source, span, &mut prev_span_hi);
484+
} else {
485+
push_to_s(&mut info.crates, source, span, &mut prev_span_hi);
486+
}
462487
}
463488
Ok(info)
464489
}

src/librustdoc/doctest/tests.rs

+27-3
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ fn make_test_manual_extern_crate() {
127127
use asdf::qwop;
128128
assert_eq!(2+2, 4);";
129129
let expected = "#![allow(unused)]
130-
fn main() {
131130
extern crate asdf;
131+
fn main() {
132132
use asdf::qwop;
133133
assert_eq!(2+2, 4);
134134
}"
@@ -144,8 +144,8 @@ fn make_test_manual_extern_crate_with_macro_use() {
144144
use asdf::qwop;
145145
assert_eq!(2+2, 4);";
146146
let expected = "#![allow(unused)]
147-
fn main() {
148147
#[macro_use] extern crate asdf;
148+
fn main() {
149149
use asdf::qwop;
150150
assert_eq!(2+2, 4);
151151
}"
@@ -197,6 +197,7 @@ fn make_test_crate_attrs() {
197197
assert_eq!(2+2, 4);";
198198
let expected = "#![allow(unused)]
199199
#![feature(sick_rad)]
200+
200201
fn main() {
201202
assert_eq!(2+2, 4);
202203
}"
@@ -277,10 +278,10 @@ fn make_test_issues_33731() {
277278
assert_eq!(asdf::foo, 4);";
278279

279280
let expected = "#![allow(unused)]
281+
extern crate hella_qwop;
280282
#[allow(unused_extern_crates)]
281283
extern crate r#asdf;
282284
fn main() {
283-
extern crate hella_qwop;
284285
assert_eq!(asdf::foo, 4);
285286
}"
286287
.to_string();
@@ -401,3 +402,26 @@ fn check_split_args() {
401402
compare("a\n\t \rb", &["a", "b"]);
402403
compare("a\n\t1 \rb", &["a", "1", "b"]);
403404
}
405+
406+
#[test]
407+
fn comment_in_attrs() {
408+
// if input already has a fn main, it should insert a space before it
409+
let opts = default_global_opts("");
410+
let input = "\
411+
#![feature(rustdoc_internals)]
412+
#![allow(internal_features)]
413+
#![doc(rust_logo)]
414+
//! This crate has the Rust(tm) branding on it.";
415+
let expected = "\
416+
#![allow(unused)]
417+
#![feature(rustdoc_internals)]
418+
#![allow(internal_features)]
419+
#![doc(rust_logo)]
420+
//! This crate has the Rust(tm) branding on it.
421+
fn main() {
422+
423+
}"
424+
.to_string();
425+
let (output, len) = make_test(input, None, false, &opts, None);
426+
assert_eq!((output, len), (expected, 2));
427+
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ check-pass
2+
//@ compile-flags:--test --test-args=--test-threads=1
3+
//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
4+
//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
5+
6+
// This test ensures that crate imports are placed outside of the `main` function
7+
// so they work all the time (even in 2015 edition).
8+
9+
/// ```rust
10+
/// #![feature(test)]
11+
///
12+
/// extern crate test;
13+
/// use test::Bencher;
14+
///
15+
/// #[bench]
16+
/// fn bench_xor_1000_ints(b: &mut Bencher) {
17+
/// b.iter(|| {
18+
/// (0..1000).fold(0, |old, new| old ^ new);
19+
/// });
20+
/// }
21+
/// ```
22+
///
23+
pub fn foo() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
running 1 test
3+
test $DIR/extern-crate.rs - foo (line 9) ... ok
4+
5+
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
6+

tests/rustdoc/playground.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@
2424
2525
//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' ""
2626
//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' ""
27-
//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' ""
27+
//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' ""

0 commit comments

Comments
 (0)