Correctly handle doctests with invalid AST
This commit is contained in:
parent
59a9e0986d
commit
7ec3cabe17
@ -635,7 +635,7 @@ fn drop(&mut self) {
|
||||
cmd.current_dir(run_directory);
|
||||
}
|
||||
|
||||
let result = if rustdoc_options.nocapture {
|
||||
let result = if is_multiple_tests || rustdoc_options.nocapture {
|
||||
cmd.status().map(|status| process::Output {
|
||||
status,
|
||||
stdout: Vec::new(),
|
||||
@ -801,10 +801,15 @@ fn add_test(&mut self, scraped_test: ScrapedDoctest) {
|
||||
);
|
||||
|
||||
let edition = scraped_test.edition(&self.rustdoc_options);
|
||||
let doctest =
|
||||
DocTest::new(&scraped_test.text, Some(&self.opts.crate_name), edition, Some(test_id));
|
||||
let doctest = DocTest::new(
|
||||
&scraped_test.text,
|
||||
Some(&self.opts.crate_name),
|
||||
edition,
|
||||
self.can_merge_doctests,
|
||||
Some(test_id),
|
||||
);
|
||||
let is_standalone = !self.can_merge_doctests
|
||||
|| doctest.failed_ast
|
||||
|| !doctest.can_be_merged
|
||||
|| scraped_test.langstr.compile_fail
|
||||
|| scraped_test.langstr.test_harness
|
||||
|| scraped_test.langstr.standalone
|
||||
|
@ -26,6 +26,7 @@ pub(crate) struct DocTest {
|
||||
pub(crate) everything_else: String,
|
||||
pub(crate) test_id: Option<String>,
|
||||
pub(crate) failed_ast: bool,
|
||||
pub(crate) can_be_merged: bool,
|
||||
}
|
||||
|
||||
impl DocTest {
|
||||
@ -33,6 +34,7 @@ pub(crate) fn new(
|
||||
source: &str,
|
||||
crate_name: Option<&str>,
|
||||
edition: Edition,
|
||||
can_merge_doctests: bool,
|
||||
// If `test_id` is `None`, it means we're generating code for a code example "run" link.
|
||||
test_id: Option<String>,
|
||||
) -> Self {
|
||||
@ -49,6 +51,7 @@ pub(crate) fn new(
|
||||
&crates,
|
||||
edition,
|
||||
&mut supports_color,
|
||||
can_merge_doctests,
|
||||
)
|
||||
else {
|
||||
// If the parser panicked due to a fatal error, pass the test code through unchanged.
|
||||
@ -62,6 +65,7 @@ pub(crate) fn new(
|
||||
already_has_extern_crate: false,
|
||||
test_id,
|
||||
failed_ast: true,
|
||||
can_be_merged: false,
|
||||
};
|
||||
};
|
||||
Self {
|
||||
@ -72,7 +76,10 @@ pub(crate) fn new(
|
||||
everything_else,
|
||||
already_has_extern_crate,
|
||||
test_id,
|
||||
failed_ast,
|
||||
failed_ast: false,
|
||||
// If the AST returned an error, we don't want this doctest to be merged with the
|
||||
// others.
|
||||
can_be_merged: !failed_ast,
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,6 +92,11 @@ pub(crate) fn generate_unique_doctest(
|
||||
opts: &GlobalTestOptions,
|
||||
crate_name: Option<&str>,
|
||||
) -> (String, usize) {
|
||||
if self.failed_ast {
|
||||
// If the AST failed to compile, no need to go generate a complete doctest, the error
|
||||
// will be better this way.
|
||||
return (test_code.to_string(), 0);
|
||||
}
|
||||
let mut line_offset = 0;
|
||||
let mut prog = String::new();
|
||||
let everything_else = self.everything_else.trim();
|
||||
@ -323,6 +335,7 @@ fn check_for_main_and_extern_crate(
|
||||
crates: &str,
|
||||
edition: Edition,
|
||||
supports_color: &mut bool,
|
||||
can_merge_doctests: bool,
|
||||
) -> Result<(Option<Span>, bool, bool), FatalError> {
|
||||
let result = rustc_driver::catch_fatal_errors(|| {
|
||||
rustc_span::create_session_if_not_set_then(edition, |_| {
|
||||
@ -340,7 +353,7 @@ fn check_for_main_and_extern_crate(
|
||||
);
|
||||
// No need to double-check this if the "merged doctests" feature isn't enabled (so
|
||||
// before the 2024 edition).
|
||||
if edition >= Edition::Edition2024 && parsing_result != ParsingResult::Ok {
|
||||
if can_merge_doctests && parsing_result != ParsingResult::Ok {
|
||||
// If we found an AST error, we want to ensure it's because of an expression being
|
||||
// used outside of a function.
|
||||
//
|
||||
@ -525,5 +538,5 @@ enum PartitionState {
|
||||
debug!("crates:\n{crates}");
|
||||
debug!("after:\n{after}");
|
||||
|
||||
(before, after, crates)
|
||||
(before, after.trim().to_owned(), crates)
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ fn make_test(
|
||||
test_id: Option<&str>,
|
||||
) -> (String, usize) {
|
||||
let doctest =
|
||||
DocTest::new(test_code, crate_name, DEFAULT_EDITION, test_id.map(|s| s.to_string()));
|
||||
DocTest::new(test_code, crate_name, DEFAULT_EDITION, false, test_id.map(|s| s.to_string()));
|
||||
let (code, line_offset) =
|
||||
doctest.generate_unique_doctest(test_code, dont_insert_main, opts, crate_name);
|
||||
(code, line_offset)
|
||||
|
@ -297,7 +297,7 @@ fn next(&mut self) -> Option<Self::Item> {
|
||||
attrs: vec![],
|
||||
args_file: PathBuf::new(),
|
||||
};
|
||||
let doctest = doctest::DocTest::new(&test, krate, edition, None);
|
||||
let doctest = doctest::DocTest::new(&test, krate, edition, false, None);
|
||||
let (test, _) = doctest.generate_unique_doctest(&test, false, &opts, krate);
|
||||
let channel = if test.contains("#![feature(") { "&version=nightly" } else { "" };
|
||||
|
||||
|
20
tests/rustdoc-ui/doctest/wrong-ast-2024.rs
Normal file
20
tests/rustdoc-ui/doctest/wrong-ast-2024.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//@ compile-flags:--test --test-args=--test-threads=1 -Zunstable-options --edition 2024
|
||||
//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
|
||||
//@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
|
||||
//@ normalize-stdout-test "wrong-ast.rs:\d+:\d+" -> "wrong-ast.rs:$$LINE:$$COL"
|
||||
//@ failure-status: 101
|
||||
|
||||
/// ```
|
||||
/// /* plop
|
||||
/// ```
|
||||
pub fn one() {}
|
||||
|
||||
/// ```
|
||||
/// } mod __doctest_1 { fn main() {
|
||||
/// ```
|
||||
pub fn two() {}
|
||||
|
||||
/// ```should_panic
|
||||
/// panic!()
|
||||
/// ```
|
||||
pub fn three() {}
|
35
tests/rustdoc-ui/doctest/wrong-ast-2024.stdout
Normal file
35
tests/rustdoc-ui/doctest/wrong-ast-2024.stdout
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
running 2 tests
|
||||
test $DIR/wrong-ast-2024.rs - one (line 7) ... FAILED
|
||||
test $DIR/wrong-ast-2024.rs - two (line 12) ... FAILED
|
||||
|
||||
failures:
|
||||
|
||||
---- $DIR/wrong-ast-2024.rs - one (line 7) stdout ----
|
||||
error[E0758]: unterminated block comment
|
||||
--> $DIR/wrong-ast-2024.rs:8:1
|
||||
|
|
||||
LL | /* plop
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0758`.
|
||||
Couldn't compile the test.
|
||||
---- $DIR/wrong-ast-2024.rs - two (line 12) stdout ----
|
||||
error: unexpected closing delimiter: `}`
|
||||
--> $DIR/wrong-ast-2024.rs:13:1
|
||||
|
|
||||
LL | } mod __doctest_1 { fn main() {
|
||||
| ^ unexpected closing delimiter
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Couldn't compile the test.
|
||||
|
||||
failures:
|
||||
$DIR/wrong-ast-2024.rs - one (line 7)
|
||||
$DIR/wrong-ast-2024.rs - two (line 12)
|
||||
|
||||
test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
|
||||
|
20
tests/rustdoc-ui/doctest/wrong-ast.rs
Normal file
20
tests/rustdoc-ui/doctest/wrong-ast.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//@ compile-flags:--test --test-args=--test-threads=1
|
||||
//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
|
||||
//@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
|
||||
//@ normalize-stdout-test "wrong-ast.rs:\d+:\d+" -> "wrong-ast.rs:$$LINE:$$COL"
|
||||
//@ failure-status: 101
|
||||
|
||||
/// ```
|
||||
/// /* plop
|
||||
/// ```
|
||||
pub fn one() {}
|
||||
|
||||
/// ```
|
||||
/// } mod __doctest_1 { fn main() {
|
||||
/// ```
|
||||
pub fn two() {}
|
||||
|
||||
/// ```should_panic
|
||||
/// panic!()
|
||||
/// ```
|
||||
pub fn three() {}
|
36
tests/rustdoc-ui/doctest/wrong-ast.stdout
Normal file
36
tests/rustdoc-ui/doctest/wrong-ast.stdout
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
running 3 tests
|
||||
test $DIR/wrong-ast.rs - one (line 7) ... FAILED
|
||||
test $DIR/wrong-ast.rs - three (line 17) ... ok
|
||||
test $DIR/wrong-ast.rs - two (line 12) ... FAILED
|
||||
|
||||
failures:
|
||||
|
||||
---- $DIR/wrong-ast.rs - one (line 7) stdout ----
|
||||
error[E0758]: unterminated block comment
|
||||
--> $DIR/wrong-ast.rs:$LINE:$COL
|
||||
|
|
||||
LL | /* plop
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0758`.
|
||||
Couldn't compile the test.
|
||||
---- $DIR/wrong-ast.rs - two (line 12) stdout ----
|
||||
error: unexpected closing delimiter: `}`
|
||||
--> $DIR/wrong-ast.rs:$LINE:$COL
|
||||
|
|
||||
LL | } mod __doctest_1 { fn main() {
|
||||
| ^ unexpected closing delimiter
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Couldn't compile the test.
|
||||
|
||||
failures:
|
||||
$DIR/wrong-ast.rs - one (line 7)
|
||||
$DIR/wrong-ast.rs - two (line 12)
|
||||
|
||||
test result: FAILED. 1 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
|
||||
|
Loading…
Reference in New Issue
Block a user