Bring attention to suggestions when the only difference is capitalization

This commit is contained in:
Esteban Küber
2019-10-13 21:48:39 -07:00
parent 898f36c83c
commit 4bb771615e
38 changed files with 121 additions and 71 deletions
@@ -49,6 +49,10 @@ fn emit_diagnostic(&mut self, db: &Diagnostic) {
&suggestions);
}
fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>> {
self.source_map.as_ref()
}
fn should_show_explain(&self) -> bool {
!self.short_message
}
+28 -4
View File
@@ -192,6 +192,8 @@ fn should_show_explain(&self) -> bool {
true
}
fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>>;
/// Formats the substitutions of the primary_span
///
/// The are a lot of conditions to this method, but in short:
@@ -204,7 +206,7 @@ fn should_show_explain(&self) -> bool {
/// we return the original `primary_span` and the original suggestions.
fn primary_span_formatted<'a>(
&mut self,
db: &'a Diagnostic
db: &'a Diagnostic,
) -> (MultiSpan, &'a [CodeSuggestion]) {
let mut primary_span = db.span.clone();
if let Some((sugg, rest)) = db.suggestions.split_first() {
@@ -234,7 +236,20 @@ fn primary_span_formatted<'a>(
format!("help: {}", sugg.msg)
} else {
// Show the default suggestion text with the substitution
format!("help: {}: `{}`", sugg.msg, substitution)
format!(
"help: {}{}: `{}`",
sugg.msg,
if self.source_map().as_ref().map(|sm| substitution.to_lowercase() == sm
.span_to_snippet(sugg.substitutions[0].parts[0].span)
.unwrap()
.to_lowercase()).unwrap_or(false)
{
" (notice the capitalization)"
} else {
""
},
substitution,
)
};
primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg);
@@ -382,6 +397,10 @@ fn fix_multispan_in_std_macros(&self,
}
impl Emitter for EmitterWriter {
fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>> {
self.sm.as_ref()
}
fn emit_diagnostic(&mut self, db: &Diagnostic) {
let mut children = db.children.clone();
let (mut primary_span, suggestions) = self.primary_span_formatted(&db);
@@ -1461,7 +1480,9 @@ fn emit_suggestion_default(
let suggestions = suggestion.splice_lines(&**sm);
let mut row_num = 2;
for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) {
let mut notice_capitalization = false;
for (complete, parts, only_capitalization) in suggestions.iter().take(MAX_SUGGESTIONS) {
notice_capitalization |= only_capitalization;
// Only show underline if the suggestion spans a single line and doesn't cover the
// entirety of the code output. If you have multiple replacements in the same line
// of code, show the underline.
@@ -1552,7 +1573,10 @@ fn emit_suggestion_default(
}
if suggestions.len() > MAX_SUGGESTIONS {
let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS);
buffer.puts(row_num, 0, &msg, Style::NoStyle);
buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle);
} else if notice_capitalization {
let msg = "notice the capitalization difference";
buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle);
}
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
Ok(())
+21 -11
View File
@@ -37,13 +37,16 @@
mod styled_buffer;
mod lock;
use syntax_pos::{BytePos,
Loc,
FileLinesResult,
SourceFile,
FileName,
MultiSpan,
Span};
use syntax_pos::{
BytePos,
FileLinesResult,
FileName,
Loc,
MultiSpan,
SourceFile,
Span,
SpanSnippetError,
};
/// Indicates the confidence in the correctness of a suggestion.
///
@@ -147,6 +150,7 @@ pub trait SourceMapper {
fn lookup_char_pos(&self, pos: BytePos) -> Loc;
fn span_to_lines(&self, sp: Span) -> FileLinesResult;
fn span_to_string(&self, sp: Span) -> String;
fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError>;
fn span_to_filename(&self, sp: Span) -> FileName;
fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span>;
fn call_span_if_macro(&self, sp: Span) -> Span;
@@ -155,9 +159,12 @@ pub trait SourceMapper {
}
impl CodeSuggestion {
/// Returns the assembled code suggestions and whether they should be shown with an underline.
pub fn splice_lines(&self, cm: &SourceMapperDyn)
-> Vec<(String, Vec<SubstitutionPart>)> {
/// Returns the assembled code suggestions, whether they should be shown with an underline
/// and whether the substitution only differs in capitalization.
pub fn splice_lines(
&self,
cm: &SourceMapperDyn,
) -> Vec<(String, Vec<SubstitutionPart>, bool)> {
use syntax_pos::{CharPos, Pos};
fn push_trailing(buf: &mut String,
@@ -232,6 +239,8 @@ fn push_trailing(buf: &mut String,
prev_hi = cm.lookup_char_pos(part.span.hi());
prev_line = fm.get_line(prev_hi.line - 1);
}
let only_capitalization = buf.clone().to_lowercase()
== cm.span_to_snippet(bounding_span).unwrap().to_lowercase();
// if the replacement already ends with a newline, don't print the next line
if !buf.ends_with('\n') {
push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None);
@@ -240,7 +249,8 @@ fn push_trailing(buf: &mut String,
while buf.ends_with('\n') {
buf.pop();
}
(buf, substitution.parts)
(buf, substitution.parts, only_capitalization)
}).collect()
}
}