Use translatable diagnostics in rustc_const_eval
This commit is contained in:
parent
642c92e630
commit
4f83717cf7
93 changed files with 2375 additions and 1123 deletions
|
@ -14,6 +14,8 @@ use syn::Token;
|
|||
use syn::{parse_quote, spanned::Spanned, Attribute, Meta, Path, Type};
|
||||
use synstructure::{BindingInfo, Structure, VariantInfo};
|
||||
|
||||
use super::utils::SubdiagnosticVariant;
|
||||
|
||||
/// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub(crate) enum DiagnosticDeriveKind {
|
||||
|
@ -150,19 +152,19 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
|||
fn parse_subdiag_attribute(
|
||||
&self,
|
||||
attr: &Attribute,
|
||||
) -> Result<Option<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
|
||||
let Some((subdiag, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
|
||||
) -> Result<Option<(SubdiagnosticKind, Path, bool)>, DiagnosticDeriveError> {
|
||||
let Some(subdiag) = SubdiagnosticVariant::from_attr(attr, self)? else {
|
||||
// Some attributes aren't errors - like documentation comments - but also aren't
|
||||
// subdiagnostics.
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag {
|
||||
if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag.kind {
|
||||
throw_invalid_attr!(attr, |diag| diag
|
||||
.help("consider creating a `Subdiagnostic` instead"));
|
||||
}
|
||||
|
||||
let slug = slug.unwrap_or_else(|| match subdiag {
|
||||
let slug = subdiag.slug.unwrap_or_else(|| match subdiag.kind {
|
||||
SubdiagnosticKind::Label => parse_quote! { _subdiag::label },
|
||||
SubdiagnosticKind::Note => parse_quote! { _subdiag::note },
|
||||
SubdiagnosticKind::Help => parse_quote! { _subdiag::help },
|
||||
|
@ -171,7 +173,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
|||
SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
|
||||
});
|
||||
|
||||
Ok(Some((subdiag, slug)))
|
||||
Ok(Some((subdiag.kind, slug, subdiag.no_span)))
|
||||
}
|
||||
|
||||
/// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct
|
||||
|
@ -229,7 +231,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
|||
return Ok(tokens);
|
||||
}
|
||||
|
||||
let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
|
||||
let Some((subdiag, slug, _no_span)) = self.parse_subdiag_attribute(attr)? else {
|
||||
// Some attributes aren't errors - like documentation comments - but also aren't
|
||||
// subdiagnostics.
|
||||
return Ok(quote! {});
|
||||
|
@ -380,7 +382,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
|||
_ => (),
|
||||
}
|
||||
|
||||
let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
|
||||
let Some((subdiag, slug, _no_span)) = self.parse_subdiag_attribute(attr)? else {
|
||||
// Some attributes aren't errors - like documentation comments - but also aren't
|
||||
// subdiagnostics.
|
||||
return Ok(quote! {});
|
||||
|
|
|
@ -14,6 +14,8 @@ use quote::{format_ident, quote};
|
|||
use syn::{spanned::Spanned, Attribute, Meta, MetaList, Path};
|
||||
use synstructure::{BindingInfo, Structure, VariantInfo};
|
||||
|
||||
use super::utils::SubdiagnosticVariant;
|
||||
|
||||
/// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
|
||||
pub(crate) struct SubdiagnosticDeriveBuilder {
|
||||
diag: syn::Ident,
|
||||
|
@ -180,11 +182,13 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
|
|||
}
|
||||
|
||||
impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||
fn identify_kind(&mut self) -> Result<Vec<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
|
||||
fn identify_kind(
|
||||
&mut self,
|
||||
) -> Result<Vec<(SubdiagnosticKind, Path, bool)>, DiagnosticDeriveError> {
|
||||
let mut kind_slugs = vec![];
|
||||
|
||||
for attr in self.variant.ast().attrs {
|
||||
let Some((kind, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
|
||||
let Some(SubdiagnosticVariant { kind, slug, no_span }) = SubdiagnosticVariant::from_attr(attr, self)? else {
|
||||
// Some attributes aren't errors - like documentation comments - but also aren't
|
||||
// subdiagnostics.
|
||||
continue;
|
||||
|
@ -202,7 +206,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
|||
);
|
||||
};
|
||||
|
||||
kind_slugs.push((kind, slug));
|
||||
kind_slugs.push((kind, slug, no_span));
|
||||
}
|
||||
|
||||
Ok(kind_slugs)
|
||||
|
@ -487,7 +491,8 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
|||
}
|
||||
};
|
||||
|
||||
let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect();
|
||||
let kind_stats: KindsStatistics =
|
||||
kind_slugs.iter().map(|(kind, _slug, _no_span)| kind).collect();
|
||||
|
||||
let init = if kind_stats.has_multipart_suggestion {
|
||||
quote! { let mut suggestions = Vec::new(); }
|
||||
|
@ -508,13 +513,17 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
|||
let diag = &self.parent.diag;
|
||||
let f = &self.parent.f;
|
||||
let mut calls = TokenStream::new();
|
||||
for (kind, slug) in kind_slugs {
|
||||
for (kind, slug, no_span) in kind_slugs {
|
||||
let message = format_ident!("__message");
|
||||
calls.extend(
|
||||
quote! { let #message = #f(#diag, crate::fluent_generated::#slug.into()); },
|
||||
);
|
||||
|
||||
let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
|
||||
let name = format_ident!(
|
||||
"{}{}",
|
||||
if span_field.is_some() && !no_span { "span_" } else { "" },
|
||||
kind
|
||||
);
|
||||
let call = match kind {
|
||||
SubdiagnosticKind::Suggestion {
|
||||
suggestion_kind,
|
||||
|
@ -566,7 +575,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
if let Some(span) = span_field {
|
||||
if let Some(span) = span_field && !no_span {
|
||||
quote! { #diag.#name(#span, #message); }
|
||||
} else {
|
||||
quote! { #diag.#name(#message); }
|
||||
|
|
|
@ -597,14 +597,20 @@ pub(super) enum SubdiagnosticKind {
|
|||
},
|
||||
}
|
||||
|
||||
impl SubdiagnosticKind {
|
||||
/// Constructs a `SubdiagnosticKind` from a field or type attribute such as `#[note]`,
|
||||
/// `#[error(parser::add_paren)]` or `#[suggestion(code = "...")]`. Returns the
|
||||
pub(super) struct SubdiagnosticVariant {
|
||||
pub(super) kind: SubdiagnosticKind,
|
||||
pub(super) slug: Option<Path>,
|
||||
pub(super) no_span: bool,
|
||||
}
|
||||
|
||||
impl SubdiagnosticVariant {
|
||||
/// Constructs a `SubdiagnosticVariant` from a field or type attribute such as `#[note]`,
|
||||
/// `#[error(parser::add_paren, no_span)]` or `#[suggestion(code = "...")]`. Returns the
|
||||
/// `SubdiagnosticKind` and the diagnostic slug, if specified.
|
||||
pub(super) fn from_attr(
|
||||
attr: &Attribute,
|
||||
fields: &impl HasFieldMap,
|
||||
) -> Result<Option<(SubdiagnosticKind, Option<Path>)>, DiagnosticDeriveError> {
|
||||
) -> Result<Option<SubdiagnosticVariant>, DiagnosticDeriveError> {
|
||||
// Always allow documentation comments.
|
||||
if is_doc_comment(attr) {
|
||||
return Ok(None);
|
||||
|
@ -679,7 +685,7 @@ impl SubdiagnosticKind {
|
|||
| SubdiagnosticKind::Help
|
||||
| SubdiagnosticKind::Warn
|
||||
| SubdiagnosticKind::MultipartSuggestion { .. } => {
|
||||
return Ok(Some((kind, None)));
|
||||
return Ok(Some(SubdiagnosticVariant { kind, slug: None, no_span: false }));
|
||||
}
|
||||
SubdiagnosticKind::Suggestion { .. } => {
|
||||
throw_span_err!(span, "suggestion without `code = \"...\"`")
|
||||
|
@ -696,11 +702,14 @@ impl SubdiagnosticKind {
|
|||
|
||||
let mut first = true;
|
||||
let mut slug = None;
|
||||
let mut no_span = false;
|
||||
|
||||
list.parse_nested_meta(|nested| {
|
||||
if nested.input.is_empty() || nested.input.peek(Token![,]) {
|
||||
if first {
|
||||
slug = Some(nested.path);
|
||||
} else if nested.path.is_ident("no_span") {
|
||||
no_span = true;
|
||||
} else {
|
||||
span_err(nested.input.span().unwrap(), "a diagnostic slug must be the first argument to the attribute").emit();
|
||||
}
|
||||
|
@ -775,19 +784,19 @@ impl SubdiagnosticKind {
|
|||
(_, SubdiagnosticKind::Suggestion { .. }) => {
|
||||
span_err(path_span, "invalid nested attribute")
|
||||
.help(
|
||||
"only `style`, `code` and `applicability` are valid nested attributes",
|
||||
"only `no_span`, `style`, `code` and `applicability` are valid nested attributes",
|
||||
)
|
||||
.emit();
|
||||
has_errors = true;
|
||||
}
|
||||
(_, SubdiagnosticKind::MultipartSuggestion { .. }) => {
|
||||
span_err(path_span, "invalid nested attribute")
|
||||
.help("only `style` and `applicability` are valid nested attributes")
|
||||
.help("only `no_span`, `style` and `applicability` are valid nested attributes")
|
||||
.emit();
|
||||
has_errors = true;
|
||||
}
|
||||
_ => {
|
||||
span_err(path_span, "invalid nested attribute").emit();
|
||||
span_err(path_span, "only `no_span` is a valid nested attribute").emit();
|
||||
has_errors = true;
|
||||
}
|
||||
}
|
||||
|
@ -831,7 +840,7 @@ impl SubdiagnosticKind {
|
|||
| SubdiagnosticKind::Warn => {}
|
||||
}
|
||||
|
||||
Ok(Some((kind, slug)))
|
||||
Ok(Some(SubdiagnosticVariant { kind, slug, no_span }))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue