Implement a Method to Seal DiagInner
's Suggestions
This commit is contained in:
parent
adaff5368b
commit
741005792e
13 changed files with 102 additions and 53 deletions
|
@ -48,7 +48,7 @@ impl Emitter for AnnotateSnippetEmitter {
|
|||
fn emit_diagnostic(&mut self, mut diag: DiagInner) {
|
||||
let fluent_args = to_fluent_args(diag.args.iter());
|
||||
|
||||
let mut suggestions = diag.suggestions.unwrap_or(vec![]);
|
||||
let mut suggestions = diag.suggestions.unwrap_tag();
|
||||
self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);
|
||||
|
||||
self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
|
||||
|
|
|
@ -19,13 +19,9 @@ use crate::snippet::Style;
|
|||
use crate::{
|
||||
CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level,
|
||||
MultiSpan, StashKey, SubdiagMessage, Substitution, SubstitutionPart, SuggestionStyle,
|
||||
Suggestions,
|
||||
};
|
||||
|
||||
/// Error type for `DiagInner`'s `suggestions` field, indicating that
|
||||
/// `.disable_suggestions()` was called on the `DiagInner`.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
|
||||
pub struct SuggestionsDisabled;
|
||||
|
||||
/// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of
|
||||
/// `DiagArg` are converted to `FluentArgs` (consuming the collection) at the start of diagnostic
|
||||
/// emission.
|
||||
|
@ -296,7 +292,7 @@ pub struct DiagInner {
|
|||
pub code: Option<ErrCode>,
|
||||
pub span: MultiSpan,
|
||||
pub children: Vec<Subdiag>,
|
||||
pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
|
||||
pub suggestions: Suggestions,
|
||||
pub args: DiagArgMap,
|
||||
|
||||
/// This is not used for highlighting or rendering any error message. Rather, it can be used
|
||||
|
@ -325,7 +321,7 @@ impl DiagInner {
|
|||
code: None,
|
||||
span: MultiSpan::new(),
|
||||
children: vec![],
|
||||
suggestions: Ok(vec![]),
|
||||
suggestions: Suggestions::Enabled(vec![]),
|
||||
args: Default::default(),
|
||||
sort_span: DUMMY_SP,
|
||||
is_lint: None,
|
||||
|
@ -409,7 +405,7 @@ impl DiagInner {
|
|||
&Option<ErrCode>,
|
||||
&MultiSpan,
|
||||
&[Subdiag],
|
||||
&Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
|
||||
&Suggestions,
|
||||
Vec<(&DiagArgName, &DiagArgValue)>,
|
||||
&Option<IsLint>,
|
||||
) {
|
||||
|
@ -823,16 +819,32 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Disallow attaching suggestions this diagnostic.
|
||||
/// Disallow attaching suggestions to this diagnostic.
|
||||
/// Any suggestions attached e.g. with the `span_suggestion_*` methods
|
||||
/// (before and after the call to `disable_suggestions`) will be ignored.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn disable_suggestions(&mut self) -> &mut Self {
|
||||
self.suggestions = Err(SuggestionsDisabled);
|
||||
self.suggestions = Suggestions::Disabled;
|
||||
self
|
||||
}
|
||||
|
||||
/// Helper for pushing to `self.suggestions`, if available (not disable).
|
||||
/// Prevent new suggestions from being added to this diagnostic.
|
||||
///
|
||||
/// Suggestions added before the call to `.seal_suggestions()` will be preserved
|
||||
/// and new suggestions will be ignored.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn seal_suggestions(&mut self) -> &mut Self {
|
||||
if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
|
||||
let suggestions_slice = std::mem::take(suggestions).into_boxed_slice();
|
||||
self.suggestions = Suggestions::Sealed(suggestions_slice);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Helper for pushing to `self.suggestions`.
|
||||
///
|
||||
/// A new suggestion is added if suggestions are enabled for this diagnostic.
|
||||
/// Otherwise, they are ignored.
|
||||
#[rustc_lint_diagnostics]
|
||||
fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
|
||||
for subst in &suggestion.substitutions {
|
||||
|
@ -846,7 +858,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
}
|
||||
}
|
||||
|
||||
if let Ok(suggestions) = &mut self.suggestions {
|
||||
if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
|
||||
suggestions.push(suggestion);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -498,7 +498,7 @@ impl Emitter for HumanEmitter {
|
|||
fn emit_diagnostic(&mut self, mut diag: DiagInner) {
|
||||
let fluent_args = to_fluent_args(diag.args.iter());
|
||||
|
||||
let mut suggestions = diag.suggestions.unwrap_or(vec![]);
|
||||
let mut suggestions = diag.suggestions.unwrap_tag();
|
||||
self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);
|
||||
|
||||
self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
|
||||
|
|
|
@ -33,7 +33,8 @@ use crate::emitter::{
|
|||
use crate::registry::Registry;
|
||||
use crate::translation::{to_fluent_args, Translate};
|
||||
use crate::{
|
||||
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, Subdiag, TerminalUrl,
|
||||
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, Subdiag, Suggestions,
|
||||
TerminalUrl,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -292,7 +293,7 @@ impl Diagnostic {
|
|||
/// Converts from `rustc_errors::DiagInner` to `Diagnostic`.
|
||||
fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic {
|
||||
let args = to_fluent_args(diag.args.iter());
|
||||
let sugg = diag.suggestions.iter().flatten().map(|sugg| {
|
||||
let sugg_to_diag = |sugg: &CodeSuggestion| {
|
||||
let translated_message =
|
||||
je.translate_message(&sugg.msg, &args).map_err(Report::new).unwrap();
|
||||
Diagnostic {
|
||||
|
@ -303,7 +304,12 @@ impl Diagnostic {
|
|||
children: vec![],
|
||||
rendered: None,
|
||||
}
|
||||
});
|
||||
};
|
||||
let sugg = match &diag.suggestions {
|
||||
Suggestions::Enabled(suggestions) => suggestions.iter().map(sugg_to_diag),
|
||||
Suggestions::Sealed(suggestions) => suggestions.iter().map(sugg_to_diag),
|
||||
Suggestions::Disabled => [].iter().map(sugg_to_diag),
|
||||
};
|
||||
|
||||
// generate regular command line output and store it in the json
|
||||
|
||||
|
|
|
@ -126,6 +126,41 @@ impl SuggestionStyle {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents the help messages seen on a diagnostic.
|
||||
#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
|
||||
pub enum Suggestions {
|
||||
/// Indicates that new suggestions can be added or removed from this diagnostic.
|
||||
///
|
||||
/// `DiagInner`'s new_* methods initialize the `suggestions` field with
|
||||
/// this variant. Also, this is the default variant for `Suggestions`.
|
||||
Enabled(Vec<CodeSuggestion>),
|
||||
/// Indicates that suggestions cannot be added or removed from this diagnostic.
|
||||
///
|
||||
/// Gets toggled when `.seal_suggestions()` is called on the `DiagInner`.
|
||||
Sealed(Box<[CodeSuggestion]>),
|
||||
/// Indicates that no suggestion is available for this diagnostic.
|
||||
///
|
||||
/// Gets toggled when `.disable_suggestions()` is called on the `DiagInner`.
|
||||
Disabled,
|
||||
}
|
||||
|
||||
impl Suggestions {
|
||||
/// Returns the underlying list of suggestions.
|
||||
pub fn unwrap_tag(self) -> Vec<CodeSuggestion> {
|
||||
match self {
|
||||
Suggestions::Enabled(suggestions) => suggestions,
|
||||
Suggestions::Sealed(suggestions) => suggestions.into_vec(),
|
||||
Suggestions::Disabled => Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Suggestions {
|
||||
fn default() -> Self {
|
||||
Self::Enabled(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
|
||||
pub struct CodeSuggestion {
|
||||
/// Each substitute can have multiple variants due to multiple
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue