pluralize, CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle,
};
+use log::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
+use rustc_span::hygiene::{ExpnKind, MacroKind};
use std::borrow::Cow;
use std::cmp::{max, min, Reverse};
use std::io;
if call_sp != *sp && !always_backtrace {
before_after.push((*sp, call_sp));
}
- let backtrace_len = sp.macro_backtrace().len();
- for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() {
+ let macro_backtrace: Vec<_> = sp.macro_backtrace().collect();
+ let backtrace_len = macro_backtrace.len();
+ for (i, trace) in macro_backtrace.iter().rev().enumerate() {
// Only show macro locations that are local
// and display them like a span_note
- if trace.def_site_span.is_dummy() {
+ if trace.def_site.is_dummy() {
continue;
}
if always_backtrace {
new_labels.push((
- trace.def_site_span,
+ trace.def_site,
format!(
"in this expansion of `{}`{}",
- trace.macro_decl_name,
+ trace.kind.descr(),
if backtrace_len > 2 {
// if backtrace_len == 1 it'll be pointed
// at by "in this macro invocation"
));
}
// Check to make sure we're not in any <*macros>
- if !sm.span_to_filename(trace.def_site_span).is_macros()
- && !trace.macro_decl_name.starts_with("desugaring of ")
- && !trace.macro_decl_name.starts_with("#[")
+ if !sm.span_to_filename(trace.def_site).is_macros()
+ && matches!(trace.kind, ExpnKind::Macro(MacroKind::Bang, _))
|| always_backtrace
{
new_labels.push((
continue;
}
if sm.span_to_filename(sp_label.span.clone()).is_macros() && !always_backtrace {
- let v = sp_label.span.macro_backtrace();
- if let Some(use_site) = v.last() {
- before_after.push((sp_label.span.clone(), use_site.call_site.clone()));
+ if let Some(use_site) = sp_label.span.macro_backtrace().last() {
+ before_after.push((sp_label.span, use_site.call_site));
}
}
}
fn emit_diagnostic(&mut self, _: &Diagnostic) {}
}
-/// maximum number of lines we will print for each error; arbitrary.
+/// Maximum number of lines we will print for each error; arbitrary.
pub const MAX_HIGHLIGHT_LINES: usize = 6;
-/// maximum number of suggestions to be shown
+/// Maximum number of lines we will print for a multiline suggestion; arbitrary.
+///
+/// This should be replaced with a more involved mechanism to output multiline suggestions that
+/// more closely mimmics the regular diagnostic output, where irrelevant code lines are elided.
+pub const MAX_SUGGESTION_HIGHLIGHT_LINES: usize = 6;
+/// Maximum number of suggestions to be shown
///
/// Arbitrary, but taken from trait import suggestion limit
pub const MAX_SUGGESTIONS: usize = 4;
let level_str = level.to_string();
// The failure note level itself does not provide any useful diagnostic information
if *level != Level::FailureNote && !level_str.is_empty() {
- buffer.append(0, &level_str, Style::Level(level.clone()));
+ buffer.append(0, &level_str, Style::Level(*level));
}
// only render error codes, not lint codes
if let Some(DiagnosticId::Error(ref code)) = *code {
- buffer.append(0, "[", Style::Level(level.clone()));
- buffer.append(0, &code, Style::Level(level.clone()));
- buffer.append(0, "]", Style::Level(level.clone()));
+ buffer.append(0, "[", Style::Level(*level));
+ buffer.append(0, &code, Style::Level(*level));
+ buffer.append(0, "]", Style::Level(*level));
}
if *level != Level::FailureNote && !level_str.is_empty() {
buffer.append(0, ": ", header_style);
} else if self.ui_testing {
140
} else {
- term_size::dimensions()
+ termize::dimensions()
.map(|(w, _)| w.saturating_sub(code_offset))
.unwrap_or(std::usize::MAX)
};
// Render the suggestion message
let level_str = level.to_string();
if !level_str.is_empty() {
- buffer.append(0, &level_str, Style::Level(level.clone()));
+ buffer.append(0, &level_str, Style::Level(*level));
buffer.append(0, ": ", Style::HeaderMsg);
}
self.msg_to_buffer(
draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1);
let mut line_pos = 0;
let mut lines = complete.lines();
- for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
+ for line in lines.by_ref().take(MAX_SUGGESTION_HIGHLIGHT_LINES) {
// Print the span column to avoid confusion
buffer.puts(
row_num,
/// Whether the original and suggested code are visually similar enough to warrant extra wording.
pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
// FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode.
- let found = sm.span_to_snippet(sp).unwrap();
+ let found = match sm.span_to_snippet(sp) {
+ Ok(snippet) => snippet,
+ Err(e) => {
+ warn!("Invalid span {:?}. Err={:?}", sp, e);
+ return false;
+ }
+ };
let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z'];
// All the chars that differ in capitalization are confusable (above):
let confusable = found