mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-17 06:26:55 +00:00
errors: introduce DiagnosticMessage
Introduce a `DiagnosticMessage` type that will enable diagnostic messages to be simple strings or Fluent identifiers. `DiagnosticMessage` is now used in the implementation of the standard `DiagnosticBuilder` APIs. Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
a22cf2af05
commit
8c684563a5
@ -1708,13 +1708,13 @@ impl SharedEmitter {
|
||||
impl Emitter for SharedEmitter {
|
||||
fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
|
||||
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
||||
msg: diag.message(),
|
||||
msg: diag.message().to_string(),
|
||||
code: diag.code.clone(),
|
||||
lvl: diag.level(),
|
||||
})));
|
||||
for child in &diag.children {
|
||||
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
||||
msg: child.message(),
|
||||
msg: child.message().to_string(),
|
||||
code: None,
|
||||
lvl: child.level,
|
||||
})));
|
||||
|
@ -41,7 +41,7 @@ impl Emitter for AnnotateSnippetEmitterWriter {
|
||||
|
||||
self.emit_messages_default(
|
||||
&diag.level,
|
||||
diag.message(),
|
||||
diag.message().to_string(),
|
||||
&diag.code,
|
||||
&primary_span,
|
||||
&children,
|
||||
|
@ -18,6 +18,34 @@ use std::hash::{Hash, Hasher};
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
|
||||
pub struct SuggestionsDisabled;
|
||||
|
||||
/// Abstraction over a message in a diagnostic to support both translatable and non-translatable
|
||||
/// diagnostic messages.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
|
||||
pub enum DiagnosticMessage {
|
||||
/// Non-translatable diagnostic message.
|
||||
Str(String),
|
||||
/// Identifier for a Fluent message corresponding to the diagnostic message.
|
||||
FluentIdentifier(String),
|
||||
}
|
||||
|
||||
impl DiagnosticMessage {
|
||||
/// Convert `DiagnosticMessage` to a `&str`.
|
||||
pub fn as_str(&self) -> &str {
|
||||
match self {
|
||||
DiagnosticMessage::Str(msg) => msg,
|
||||
DiagnosticMessage::FluentIdentifier(..) => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert `DiagnosticMessage` to an owned `String`.
|
||||
pub fn to_string(self) -> String {
|
||||
match self {
|
||||
DiagnosticMessage::Str(msg) => msg,
|
||||
DiagnosticMessage::FluentIdentifier(..) => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[derive(Clone, Debug, Encodable, Decodable)]
|
||||
pub struct Diagnostic {
|
||||
@ -25,7 +53,7 @@ pub struct Diagnostic {
|
||||
// outside of what methods in this crate themselves allow.
|
||||
crate level: Level,
|
||||
|
||||
pub message: Vec<(String, Style)>,
|
||||
pub message: Vec<(DiagnosticMessage, Style)>,
|
||||
pub code: Option<DiagnosticId>,
|
||||
pub span: MultiSpan,
|
||||
pub children: Vec<SubDiagnostic>,
|
||||
@ -52,7 +80,7 @@ pub enum DiagnosticId {
|
||||
#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
|
||||
pub struct SubDiagnostic {
|
||||
pub level: Level,
|
||||
pub message: Vec<(String, Style)>,
|
||||
pub message: Vec<(DiagnosticMessage, Style)>,
|
||||
pub span: MultiSpan,
|
||||
pub render_span: Option<MultiSpan>,
|
||||
}
|
||||
@ -112,7 +140,7 @@ impl Diagnostic {
|
||||
pub fn new_with_code(level: Level, code: Option<DiagnosticId>, message: &str) -> Self {
|
||||
Diagnostic {
|
||||
level,
|
||||
message: vec![(message.to_owned(), Style::NoStyle)],
|
||||
message: vec![(DiagnosticMessage::Str(message.to_owned()), Style::NoStyle)],
|
||||
code,
|
||||
span: MultiSpan::new(),
|
||||
children: vec![],
|
||||
@ -465,7 +493,7 @@ impl Diagnostic {
|
||||
.map(|(span, snippet)| SubstitutionPart { snippet, span })
|
||||
.collect(),
|
||||
}],
|
||||
msg: msg.to_owned(),
|
||||
msg: DiagnosticMessage::Str(msg.to_owned()),
|
||||
style,
|
||||
applicability,
|
||||
tool_metadata: Default::default(),
|
||||
@ -493,7 +521,7 @@ impl Diagnostic {
|
||||
.map(|(span, snippet)| SubstitutionPart { snippet, span })
|
||||
.collect(),
|
||||
}],
|
||||
msg: msg.to_owned(),
|
||||
msg: DiagnosticMessage::Str(msg.to_owned()),
|
||||
style: SuggestionStyle::CompletelyHidden,
|
||||
applicability,
|
||||
tool_metadata: Default::default(),
|
||||
@ -548,7 +576,7 @@ impl Diagnostic {
|
||||
substitutions: vec![Substitution {
|
||||
parts: vec![SubstitutionPart { snippet: suggestion, span: sp }],
|
||||
}],
|
||||
msg: msg.to_owned(),
|
||||
msg: DiagnosticMessage::Str(msg.to_owned()),
|
||||
style,
|
||||
applicability,
|
||||
tool_metadata: Default::default(),
|
||||
@ -591,7 +619,7 @@ impl Diagnostic {
|
||||
.collect();
|
||||
self.push_suggestion(CodeSuggestion {
|
||||
substitutions,
|
||||
msg: msg.to_owned(),
|
||||
msg: DiagnosticMessage::Str(msg.to_owned()),
|
||||
style: SuggestionStyle::ShowCode,
|
||||
applicability,
|
||||
tool_metadata: Default::default(),
|
||||
@ -616,7 +644,7 @@ impl Diagnostic {
|
||||
.collect(),
|
||||
})
|
||||
.collect(),
|
||||
msg: msg.to_owned(),
|
||||
msg: DiagnosticMessage::Str(msg.to_owned()),
|
||||
style: SuggestionStyle::ShowCode,
|
||||
applicability,
|
||||
tool_metadata: Default::default(),
|
||||
@ -698,7 +726,7 @@ impl Diagnostic {
|
||||
) {
|
||||
self.push_suggestion(CodeSuggestion {
|
||||
substitutions: vec![],
|
||||
msg: msg.to_owned(),
|
||||
msg: DiagnosticMessage::Str(msg.to_owned()),
|
||||
style: SuggestionStyle::CompletelyHidden,
|
||||
applicability,
|
||||
tool_metadata: ToolMetadata::new(tool_metadata),
|
||||
@ -733,15 +761,15 @@ impl Diagnostic {
|
||||
}
|
||||
|
||||
pub fn set_primary_message<M: Into<String>>(&mut self, msg: M) -> &mut Self {
|
||||
self.message[0] = (msg.into(), Style::NoStyle);
|
||||
self.message[0] = (DiagnosticMessage::Str(msg.into()), Style::NoStyle);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn message(&self) -> String {
|
||||
self.message.iter().map(|i| i.0.as_str()).collect::<String>()
|
||||
pub fn message(&self) -> DiagnosticMessage {
|
||||
DiagnosticMessage::Str(self.message.iter().map(|i| i.0.as_str()).collect::<String>())
|
||||
}
|
||||
|
||||
pub fn styled_message(&self) -> &Vec<(String, Style)> {
|
||||
pub fn styled_message(&self) -> &Vec<(DiagnosticMessage, Style)> {
|
||||
&self.message
|
||||
}
|
||||
|
||||
@ -758,7 +786,7 @@ impl Diagnostic {
|
||||
) {
|
||||
let sub = SubDiagnostic {
|
||||
level,
|
||||
message: vec![(message.to_owned(), Style::NoStyle)],
|
||||
message: vec![(DiagnosticMessage::Str(message.to_owned()), Style::NoStyle)],
|
||||
span,
|
||||
render_span,
|
||||
};
|
||||
@ -770,10 +798,11 @@ impl Diagnostic {
|
||||
fn sub_with_highlights(
|
||||
&mut self,
|
||||
level: Level,
|
||||
message: Vec<(String, Style)>,
|
||||
mut message: Vec<(String, Style)>,
|
||||
span: MultiSpan,
|
||||
render_span: Option<MultiSpan>,
|
||||
) {
|
||||
let message = message.drain(..).map(|m| (DiagnosticMessage::Str(m.0), m.1)).collect();
|
||||
let sub = SubDiagnostic { level, message, span, render_span };
|
||||
self.children.push(sub);
|
||||
}
|
||||
@ -783,7 +812,7 @@ impl Diagnostic {
|
||||
&self,
|
||||
) -> (
|
||||
&Level,
|
||||
&Vec<(String, Style)>,
|
||||
&Vec<(DiagnosticMessage, Style)>,
|
||||
&Option<DiagnosticId>,
|
||||
&MultiSpan,
|
||||
&Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
|
||||
@ -816,11 +845,11 @@ impl PartialEq for Diagnostic {
|
||||
}
|
||||
|
||||
impl SubDiagnostic {
|
||||
pub fn message(&self) -> String {
|
||||
self.message.iter().map(|i| i.0.as_str()).collect::<String>()
|
||||
pub fn message(&self) -> DiagnosticMessage {
|
||||
DiagnosticMessage::Str(self.message.iter().map(|i| i.0.as_str()).collect::<String>())
|
||||
}
|
||||
|
||||
pub fn styled_message(&self) -> &Vec<(String, Style)> {
|
||||
pub fn styled_message(&self) -> &Vec<(DiagnosticMessage, Style)> {
|
||||
&self.message
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ use rustc_span::{MultiSpan, SourceFile, Span};
|
||||
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
|
||||
use crate::styled_buffer::StyledBuffer;
|
||||
use crate::{
|
||||
CodeSuggestion, Diagnostic, DiagnosticId, Handler, Level, SubDiagnostic, SubstitutionHighlight,
|
||||
SuggestionStyle,
|
||||
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Handler, Level, SubDiagnostic,
|
||||
SubstitutionHighlight, SuggestionStyle,
|
||||
};
|
||||
|
||||
use rustc_lint_defs::pluralize;
|
||||
@ -236,7 +236,7 @@ pub trait Emitter {
|
||||
// don't display multipart suggestions as labels
|
||||
sugg.substitutions[0].parts.len() == 1 &&
|
||||
// don't display long messages as labels
|
||||
sugg.msg.split_whitespace().count() < 10 &&
|
||||
sugg.msg.as_str().split_whitespace().count() < 10 &&
|
||||
// don't display multiline suggestions as labels
|
||||
!sugg.substitutions[0].parts[0].snippet.contains('\n') &&
|
||||
![
|
||||
@ -252,12 +252,12 @@ pub trait Emitter {
|
||||
let msg = if substitution.is_empty() || sugg.style.hide_inline() {
|
||||
// This substitution is only removal OR we explicitly don't want to show the
|
||||
// code inline (`hide_inline`). Therefore, we don't show the substitution.
|
||||
format!("help: {}", sugg.msg)
|
||||
format!("help: {}", sugg.msg.as_str())
|
||||
} else {
|
||||
// Show the default suggestion text with the substitution
|
||||
format!(
|
||||
"help: {}{}: `{}`",
|
||||
sugg.msg,
|
||||
sugg.msg.as_str(),
|
||||
if self
|
||||
.source_map()
|
||||
.map(|sm| is_case_difference(
|
||||
@ -333,7 +333,7 @@ pub trait Emitter {
|
||||
|
||||
children.push(SubDiagnostic {
|
||||
level: Level::Note,
|
||||
message: vec![(msg, Style::NoStyle)],
|
||||
message: vec![(DiagnosticMessage::Str(msg), Style::NoStyle)],
|
||||
span: MultiSpan::new(),
|
||||
render_span: None,
|
||||
});
|
||||
@ -1176,7 +1176,7 @@ impl EmitterWriter {
|
||||
fn msg_to_buffer(
|
||||
&self,
|
||||
buffer: &mut StyledBuffer,
|
||||
msg: &[(String, Style)],
|
||||
msg: &[(DiagnosticMessage, Style)],
|
||||
padding: usize,
|
||||
label: &str,
|
||||
override_style: Option<Style>,
|
||||
@ -1229,6 +1229,7 @@ impl EmitterWriter {
|
||||
// very *weird* formats
|
||||
// see?
|
||||
for &(ref text, ref style) in msg.iter() {
|
||||
let text = text.as_str();
|
||||
let lines = text.split('\n').collect::<Vec<_>>();
|
||||
if lines.len() > 1 {
|
||||
for (i, line) in lines.iter().enumerate() {
|
||||
@ -1247,7 +1248,7 @@ impl EmitterWriter {
|
||||
fn emit_message_default(
|
||||
&mut self,
|
||||
msp: &MultiSpan,
|
||||
msg: &[(String, Style)],
|
||||
msg: &[(DiagnosticMessage, Style)],
|
||||
code: &Option<DiagnosticId>,
|
||||
level: &Level,
|
||||
max_line_num_len: usize,
|
||||
@ -1287,6 +1288,7 @@ impl EmitterWriter {
|
||||
label_width += 2;
|
||||
}
|
||||
for &(ref text, _) in msg.iter() {
|
||||
let text = text.as_str();
|
||||
// Account for newlines to align output to its label.
|
||||
for (line, text) in normalize_whitespace(text).lines().enumerate() {
|
||||
buffer.append(
|
||||
@ -1852,7 +1854,7 @@ impl EmitterWriter {
|
||||
fn emit_messages_default(
|
||||
&mut self,
|
||||
level: &Level,
|
||||
message: &[(String, Style)],
|
||||
message: &[(DiagnosticMessage, Style)],
|
||||
code: &Option<DiagnosticId>,
|
||||
span: &MultiSpan,
|
||||
children: &[SubDiagnostic],
|
||||
|
@ -346,7 +346,7 @@ struct UnusedExterns<'a, 'b, 'c> {
|
||||
impl Diagnostic {
|
||||
fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic {
|
||||
let sugg = diag.suggestions.iter().flatten().map(|sugg| Diagnostic {
|
||||
message: sugg.msg.clone(),
|
||||
message: sugg.msg.clone().to_string(),
|
||||
code: None,
|
||||
level: "help",
|
||||
spans: DiagnosticSpan::from_suggestion(sugg, je),
|
||||
@ -385,7 +385,7 @@ impl Diagnostic {
|
||||
let output = String::from_utf8(output).unwrap();
|
||||
|
||||
Diagnostic {
|
||||
message: diag.message(),
|
||||
message: diag.message().to_string(),
|
||||
code: DiagnosticCode::map_opt_string(diag.code.clone(), je),
|
||||
level: diag.level.to_str(),
|
||||
spans: DiagnosticSpan::from_multispan(&diag.span, je),
|
||||
@ -402,7 +402,7 @@ impl Diagnostic {
|
||||
|
||||
fn from_sub_diagnostic(diag: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic {
|
||||
Diagnostic {
|
||||
message: diag.message(),
|
||||
message: diag.message().to_string(),
|
||||
code: None,
|
||||
level: diag.level.to_str(),
|
||||
spans: diag
|
||||
|
@ -145,7 +145,7 @@ pub struct CodeSuggestion {
|
||||
/// ]
|
||||
/// ```
|
||||
pub substitutions: Vec<Substitution>,
|
||||
pub msg: String,
|
||||
pub msg: DiagnosticMessage,
|
||||
/// Visual representation of this suggestion.
|
||||
pub style: SuggestionStyle,
|
||||
/// Whether or not the suggestion is approximate
|
||||
@ -400,7 +400,9 @@ impl fmt::Display for ExplicitBug {
|
||||
|
||||
impl error::Error for ExplicitBug {}
|
||||
|
||||
pub use diagnostic::{Diagnostic, DiagnosticId, DiagnosticStyledString, SubDiagnostic};
|
||||
pub use diagnostic::{
|
||||
Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, SubDiagnostic,
|
||||
};
|
||||
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
|
||||
use std::backtrace::Backtrace;
|
||||
|
||||
|
@ -68,17 +68,18 @@ fn emit_frag_parse_err(
|
||||
arm_span: Span,
|
||||
kind: AstFragmentKind,
|
||||
) {
|
||||
if parser.token == token::Eof && e.message().ends_with(", found `<eof>`") {
|
||||
// FIXME(davidtwco): avoid depending on the error message text
|
||||
if parser.token == token::Eof && e.message().as_str().ends_with(", found `<eof>`") {
|
||||
if !e.span.is_dummy() {
|
||||
// early end of macro arm (#52866)
|
||||
e.replace_span_with(parser.sess.source_map().next_point(parser.token.span));
|
||||
}
|
||||
let msg = &e.message[0];
|
||||
e.message[0] = (
|
||||
format!(
|
||||
rustc_errors::DiagnosticMessage::Str(format!(
|
||||
"macro expansion ends with an incomplete expression: {}",
|
||||
msg.0.replace(", found `<eof>`", ""),
|
||||
),
|
||||
msg.0.as_str().replace(", found `<eof>`", ""),
|
||||
)),
|
||||
msg.1,
|
||||
);
|
||||
}
|
||||
|
@ -1010,7 +1010,8 @@ impl<'a> Parser<'a> {
|
||||
let current_qual_sp = self.prev_token.span;
|
||||
let current_qual_sp = current_qual_sp.to(sp_start);
|
||||
if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) {
|
||||
if err.message() == "expected `{`, found keyword `unsafe`" {
|
||||
// FIXME(davidtwco): avoid depending on the error message text
|
||||
if err.message().as_str() == "expected `{`, found keyword `unsafe`" {
|
||||
let invalid_qual_sp = self.token.uninterpolated_span();
|
||||
let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap();
|
||||
|
||||
|
@ -780,7 +780,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
if has_custom_message {
|
||||
err.note(&msg);
|
||||
} else {
|
||||
err.message = vec![(msg, Style::NoStyle)];
|
||||
err.message =
|
||||
vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)];
|
||||
}
|
||||
if snippet.starts_with('&') {
|
||||
// This is already a literal borrow and the obligation is failing
|
||||
|
@ -176,7 +176,7 @@ struct BufferEmitter {
|
||||
impl Emitter for BufferEmitter {
|
||||
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
|
||||
let mut buffer = self.buffer.borrow_mut();
|
||||
buffer.messages.push(format!("error from rustc: {}", diag.message[0].0));
|
||||
buffer.messages.push(format!("error from rustc: {}", diag.message[0].0.as_str()));
|
||||
if diag.is_error() {
|
||||
buffer.has_errors = true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user