Skip to content

Commit

Permalink
Auto merge of #50541 - QuietMisdreavus:rustdoc-errors, r=GuillaumeGomez
Browse files Browse the repository at this point in the history
rustdoc: replace most (e)println! statements with structured warnings/errors

Turns out, the rustc diagnostic handler doesn't need a whole lot of setup that we weren't already doing. For errors that occur outside a "dealing with source code" context, we can just use the format/color config we were already parsing and make up a `Handler` that we can emit structured warnings/errors from. So i did that. This will make it way easier to test things with `rustdoc-ui` tests, since those require the JSON error output. (In fact, this PR is a yak shave for a different one where i was trying to do just that. `>_>`)
  • Loading branch information
bors committed May 16, 2018
2 parents e44fc6c + c3fd12f commit 3c31e17
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 122 deletions.
85 changes: 53 additions & 32 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,57 @@ impl DocAccessLevels for AccessLevels<DefId> {
}
}

/// Creates a new diagnostic `Handler` that can be used to emit warnings and errors.
///
/// If the given `error_format` is `ErrorOutputType::Json` and no `CodeMap` is given, a new one
/// will be created for the handler.
pub fn new_handler(error_format: ErrorOutputType, codemap: Option<Lrc<codemap::CodeMap>>)
-> errors::Handler
{
// rustdoc doesn't override (or allow to override) anything from this that is relevant here, so
// stick to the defaults
let sessopts = config::basic_options();
let emitter: Box<dyn Emitter + sync::Send> = match error_format {
ErrorOutputType::HumanReadable(color_config) => Box::new(
EmitterWriter::stderr(
color_config,
codemap.map(|cm| cm as _),
false,
sessopts.debugging_opts.teach,
).ui_testing(sessopts.debugging_opts.ui_testing)
),
ErrorOutputType::Json(pretty) => {
let codemap = codemap.unwrap_or_else(
|| Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping())));
Box::new(
JsonEmitter::stderr(
None,
codemap,
pretty,
sessopts.debugging_opts.suggestion_applicability,
).ui_testing(sessopts.debugging_opts.ui_testing)
)
},
ErrorOutputType::Short(color_config) => Box::new(
EmitterWriter::stderr(
color_config,
codemap.map(|cm| cm as _),
true,
false)
),
};

errors::Handler::with_emitter_and_flags(
emitter,
errors::HandlerFlags {
can_emit_warnings: true,
treat_err_as_bug: false,
external_macro_backtrace: false,
..Default::default()
},
)
}

pub fn run_core(search_paths: SearchPaths,
cfgs: Vec<String>,
externs: config::Externs,
Expand Down Expand Up @@ -159,41 +210,11 @@ pub fn run_core(search_paths: SearchPaths,
},
error_format,
edition,
..config::basic_options().clone()
..config::basic_options()
};
driver::spawn_thread_pool(sessopts, move |sessopts| {
let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()));
let emitter: Box<dyn Emitter + sync::Send> = match error_format {
ErrorOutputType::HumanReadable(color_config) => Box::new(
EmitterWriter::stderr(
color_config,
Some(codemap.clone()),
false,
sessopts.debugging_opts.teach,
).ui_testing(sessopts.debugging_opts.ui_testing)
),
ErrorOutputType::Json(pretty) => Box::new(
JsonEmitter::stderr(
None,
codemap.clone(),
pretty,
sessopts.debugging_opts.suggestion_applicability,
).ui_testing(sessopts.debugging_opts.ui_testing)
),
ErrorOutputType::Short(color_config) => Box::new(
EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false)
),
};

let diagnostic_handler = errors::Handler::with_emitter_and_flags(
emitter,
errors::HandlerFlags {
can_emit_warnings: true,
treat_err_as_bug: false,
external_macro_backtrace: false,
..Default::default()
},
);
let diagnostic_handler = new_handler(error_format, Some(codemap.clone()));

let mut sess = session::build_session_(
sessopts, cpath, diagnostic_handler, codemap,
Expand Down
25 changes: 14 additions & 11 deletions src/librustdoc/externalfiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use std::fs;
use std::path::Path;
use std::str;
use errors;
use html::markdown::Markdown;

#[derive(Clone)]
Expand All @@ -28,23 +29,23 @@ pub struct ExternalHtml {

impl ExternalHtml {
pub fn load(in_header: &[String], before_content: &[String], after_content: &[String],
md_before_content: &[String], md_after_content: &[String])
md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler)
-> Option<ExternalHtml> {
load_external_files(in_header)
load_external_files(in_header, diag)
.and_then(|ih|
load_external_files(before_content)
load_external_files(before_content, diag)
.map(|bc| (ih, bc))
)
.and_then(|(ih, bc)|
load_external_files(md_before_content)
load_external_files(md_before_content, diag)
.map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[]))))
)
.and_then(|(ih, bc)|
load_external_files(after_content)
load_external_files(after_content, diag)
.map(|ac| (ih, bc, ac))
)
.and_then(|(ih, bc, ac)|
load_external_files(md_after_content)
load_external_files(md_after_content, diag)
.map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[]))))
)
.map(|(ih, bc, ac)|
Expand All @@ -62,28 +63,30 @@ pub enum LoadStringError {
BadUtf8,
}

pub fn load_string<P: AsRef<Path>>(file_path: P) -> Result<String, LoadStringError> {
pub fn load_string<P: AsRef<Path>>(file_path: P, diag: &errors::Handler)
-> Result<String, LoadStringError>
{
let file_path = file_path.as_ref();
let contents = match fs::read(file_path) {
Ok(bytes) => bytes,
Err(e) => {
eprintln!("error reading `{}`: {}", file_path.display(), e);
diag.struct_err(&format!("error reading `{}`: {}", file_path.display(), e)).emit();
return Err(LoadStringError::ReadFail);
}
};
match str::from_utf8(&contents) {
Ok(s) => Ok(s.to_string()),
Err(_) => {
eprintln!("error reading `{}`: not UTF-8", file_path.display());
diag.struct_err(&format!("error reading `{}`: not UTF-8", file_path.display())).emit();
Err(LoadStringError::BadUtf8)
}
}
}

fn load_external_files(names: &[String]) -> Option<String> {
fn load_external_files(names: &[String], diag: &errors::Handler) -> Option<String> {
let mut out = String::new();
for name in names {
let s = match load_string(name) {
let s = match load_string(name, diag) {
Ok(s) => s,
Err(_) => return None,
};
Expand Down
Loading

0 comments on commit 3c31e17

Please sign in to comment.