From cef78b6eaa560e2857ce2721668e37bd22437eb4 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 9 May 2016 10:55:30 +0200 Subject: [PATCH] rustdoc: do not panic all the way when lexing a source snippet fails Currently, the libsyntax lexer panics on invalid source, which makes rustdoc panic when trying to highlight it. I assume there are efforts underway to make the lexer panic-free, but until this is done this should be an acceptable workaround. Note that the panic is still printed like normal as "thread X panicked, run with RUST_BACKTRACE=1 ...", so I added the printout below to make it seem less like a fatal error. I didn't touch `render_inner_with_highlighting` below, as it is currently unused. It returns a Result whose Err type would have to be changed if it was to support lexer errors. Fixes: #30032 --- src/librustdoc/html/highlight.rs | 33 ++++++++++++++++++++------------ src/test/rustdoc/issue-30032.rs | 18 +++++++++++++++++ 2 files changed, 39 insertions(+), 12 deletions(-) create mode 100644 src/test/rustdoc/issue-30032.rs diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 7ccf51a462953..d015e1b1e5500 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -24,6 +24,7 @@ use html::escape::Escape; use std::fmt::Display; use std::io; +use std::panic::catch_unwind; use std::io::prelude::*; use syntax::codemap::{CodeMap, Span}; @@ -34,20 +35,28 @@ use syntax::parse; /// Highlights `src`, returning the HTML output. pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>) -> String { debug!("highlighting: ================\n{}\n==============", src); - let sess = parse::ParseSess::new(); - let fm = sess.codemap().new_filemap("".to_string(), src.to_string()); - - let mut out = Vec::new(); - write_header(class, id, &mut out).unwrap(); - let mut classifier = Classifier::new(lexer::StringReader::new(&sess.span_diagnostic, fm), - sess.codemap()); - if let Err(_) = classifier.write_source(&mut out) { - return format!("
{}
", src); + // As long as the lexer panics... + let result = catch_unwind(|| { + let sess = parse::ParseSess::new(); + let fm = sess.codemap().new_filemap("".to_string(), src.to_string()); + let mut out = Vec::new(); + write_header(class, id, &mut out).unwrap(); + let mut classifier = Classifier::new(lexer::StringReader::new(&sess.span_diagnostic, fm), + sess.codemap()); + classifier.write_source(&mut out).unwrap(); + write_footer(&mut out).unwrap(); + out + }); + match result { + // catches both panics from the lexer and the unwrap()s + Err(_) => { + println!("warning: error during source highlighting (see above), \ + passing source through unhighlighted"); + format!("
{}
", src) + }, + Ok(out) => String::from_utf8_lossy(&out[..]).into_owned(), } - - write_footer(&mut out).unwrap(); - String::from_utf8_lossy(&out[..]).into_owned() } /// Highlights `src`, returning the HTML output. Returns only the inner html to diff --git a/src/test/rustdoc/issue-30032.rs b/src/test/rustdoc/issue-30032.rs new file mode 100644 index 0000000000000..309d22161e058 --- /dev/null +++ b/src/test/rustdoc/issue-30032.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This used to panic due to the invalid source, so just checking for +// existence of the output file is enough. + +// @has issue_30032/fn.main.html +/// ```ignore +/// let invalid = 'abc'; +/// ``` +pub fn main() {}