Skip to content

Commit 902460d

Browse files
Add line number and filename in error message
1 parent 230234f commit 902460d

File tree

2 files changed

+55
-6
lines changed

2 files changed

+55
-6
lines changed

src/librustdoc/markdown.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
154154
let mut opts = TestOptions::default();
155155
opts.no_crate_inject = true;
156156
let mut collector = Collector::new(input.to_string(), cfgs, libs, externs,
157-
true, opts, maybe_sysroot);
157+
true, opts, maybe_sysroot, &input_str, "input".to_string());
158158
find_testable_code(&input_str, &mut collector);
159159
test_args.insert(0, "rustdoctest".to_string());
160160
testing::test_main(&test_args, collector.tests);

src/librustdoc/test.rs

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::collections::HashMap;
1112
use std::env;
1213
use std::ffi::OsString;
14+
use std::fs::File;
1315
use std::io::prelude::*;
1416
use std::io;
1517
use std::path::PathBuf;
@@ -96,13 +98,24 @@ pub fn run(input: &str,
9698
link::find_crate_name(None, &hir_forest.krate().attrs, &input)
9799
});
98100
let opts = scrape_test_config(hir_forest.krate());
101+
let filename = input_path.to_str().unwrap_or("").to_owned();
102+
let mut f = match File::open(input_path) {
103+
Ok(f) => f,
104+
_ => return 1,
105+
};
106+
let mut file_content = String::new();
107+
if let Err(_) = f.read_to_string(&mut file_content) {
108+
return 1;
109+
}
99110
let mut collector = Collector::new(crate_name,
100111
cfgs,
101112
libs,
102113
externs,
103114
false,
104115
opts,
105-
maybe_sysroot);
116+
maybe_sysroot,
117+
&file_content,
118+
filename);
106119

107120
{
108121
let dep_graph = DepGraph::new(false);
@@ -162,11 +175,12 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
162175
should_panic: bool, no_run: bool, as_test_harness: bool,
163176
compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
164177
maybe_sysroot: Option<PathBuf>,
165-
original: &str) {
178+
original: &str, line_number: u32, filename: &str) {
166179
// the test harness wants its own `main` & top level functions, so
167180
// never wrap the test in `fn main() { ... }`
168181
let new_test = maketest(test, Some(cratename), as_test_harness, opts);
169-
let test = format!("```{}\n{}\n```\n", original, test);
182+
let test = format!("Error on {}:{}\n\n```{}\n{}\n```\n",
183+
filename, line_number, original, test);
170184
let input = config::Input::Str {
171185
name: driver::anon_src(),
172186
input: new_test.to_owned(),
@@ -389,11 +403,27 @@ pub struct Collector {
389403
cratename: String,
390404
opts: TestOptions,
391405
maybe_sysroot: Option<PathBuf>,
406+
code_blocks: HashMap<String, Vec<u32>>,
407+
filename: String,
392408
}
393409

394410
impl Collector {
395411
pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
396-
use_headers: bool, opts: TestOptions, maybe_sysroot: Option<PathBuf>) -> Collector {
412+
use_headers: bool, opts: TestOptions, maybe_sysroot: Option<PathBuf>,
413+
file_content: &str, filename: String) -> Collector {
414+
let mut line_number = 1;
415+
let mut block_lines = HashMap::new();
416+
for (pos, block) in file_content.split("```").enumerate() {
417+
if (pos & 1) != 0 {
418+
let key = format!("{}", block.replace("/// ", "").replace("//!", ""));
419+
if !block_lines.contains_key(&key) {
420+
block_lines.insert(key.clone(), Vec::new());
421+
}
422+
block_lines.get_mut(&key).unwrap().push(line_number);
423+
}
424+
line_number += block.lines().count() as u32 - 1;
425+
}
426+
397427
Collector {
398428
tests: Vec::new(),
399429
names: Vec::new(),
@@ -406,7 +436,22 @@ impl Collector {
406436
cratename: cratename,
407437
opts: opts,
408438
maybe_sysroot: maybe_sysroot,
439+
code_blocks: block_lines,
440+
filename: filename,
441+
}
442+
}
443+
444+
fn get_line_from_key(&mut self, key: &String) -> u32 {
445+
let (line, need_removal) = if let Some(l) = self.code_blocks.get_mut(key) {
446+
let need_removal = l.len() > 1;
447+
(l.pop().unwrap_or(1), need_removal)
448+
} else {
449+
return 1;
450+
};
451+
if need_removal {
452+
self.code_blocks.remove(key);
409453
}
454+
line
410455
}
411456

412457
pub fn add_test(&mut self, test: String,
@@ -427,6 +472,8 @@ impl Collector {
427472
let opts = self.opts.clone();
428473
let maybe_sysroot = self.maybe_sysroot.clone();
429474
debug!("Creating test {}: {}", name, test);
475+
let line_number = self.get_line_from_key(&format!("{}\n{}\n", original, test));
476+
let filename = self.filename.clone();
430477
self.tests.push(testing::TestDescAndFn {
431478
desc: testing::TestDesc {
432479
name: testing::DynTestName(name),
@@ -453,7 +500,9 @@ impl Collector {
453500
error_codes,
454501
&opts,
455502
maybe_sysroot,
456-
&original)
503+
&original,
504+
line_number,
505+
&filename)
457506
})
458507
} {
459508
Ok(()) => (),

0 commit comments

Comments
 (0)