Allow nesting subdiagnostics
This commit is contained in:
parent
5646b65cf5
commit
c88bb6c011
@ -71,6 +71,7 @@ pub(crate) fn into_tokens(self, mut structure: Structure<'_>) -> TokenStream {
|
||||
span_field: None,
|
||||
applicability: None,
|
||||
has_suggestion_parts: false,
|
||||
has_subdiagnostic: false,
|
||||
is_enum,
|
||||
};
|
||||
builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
|
||||
@ -133,6 +134,10 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||
/// during finalization if still `false`.
|
||||
has_suggestion_parts: bool,
|
||||
|
||||
/// Set to true when a `#[subdiagnostic]` field is encountered, used to suppress the error
|
||||
/// emitted when no subdiagnostic kinds are specified on the variant itself.
|
||||
has_subdiagnostic: bool,
|
||||
|
||||
/// Set to true when this variant is an enum variant rather than just the body of a struct.
|
||||
is_enum: bool,
|
||||
}
|
||||
@ -373,6 +378,13 @@ fn generate_field_code_inner_path(
|
||||
|
||||
Ok(quote! {})
|
||||
}
|
||||
"subdiagnostic" => {
|
||||
let f = &self.parent.f;
|
||||
let diag = &self.parent.diag;
|
||||
let binding = &info.binding;
|
||||
self.has_subdiagnostic = true;
|
||||
Ok(quote! { #binding.add_to_diag_with(#diag, #f); })
|
||||
}
|
||||
_ => {
|
||||
let mut span_attrs = vec![];
|
||||
if kind_stats.has_multipart_suggestion {
|
||||
@ -480,18 +492,6 @@ fn generate_field_code_inner_list(
|
||||
|
||||
pub(crate) fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
|
||||
let kind_slugs = self.identify_kind()?;
|
||||
if kind_slugs.is_empty() {
|
||||
if self.is_enum {
|
||||
// It's okay for a variant to not be a subdiagnostic at all..
|
||||
return Ok(quote! {});
|
||||
} else {
|
||||
// ..but structs should always be _something_.
|
||||
throw_span_err!(
|
||||
self.variant.ast().ident.span().unwrap(),
|
||||
"subdiagnostic kind not specified"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let kind_stats: KindsStatistics =
|
||||
kind_slugs.iter().map(|(kind, _slug, _no_span)| kind).collect();
|
||||
@ -510,6 +510,19 @@ pub(crate) fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveErro
|
||||
.map(|binding| self.generate_field_attr_code(binding, kind_stats))
|
||||
.collect();
|
||||
|
||||
if kind_slugs.is_empty() {
|
||||
if self.is_enum {
|
||||
// It's okay for a variant to not be a subdiagnostic at all..
|
||||
return Ok(quote! {});
|
||||
} else if !self.has_subdiagnostic {
|
||||
// ..but structs should always be _something_.
|
||||
throw_span_err!(
|
||||
self.variant.ast().ident.span().unwrap(),
|
||||
"subdiagnostic kind not specified"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let span_field = self.span_field.value_ref();
|
||||
|
||||
let diag = &self.parent.diag;
|
||||
|
@ -144,6 +144,7 @@ pub fn extension(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
help,
|
||||
note,
|
||||
warning,
|
||||
subdiagnostic,
|
||||
suggestion,
|
||||
suggestion_short,
|
||||
suggestion_hidden,
|
||||
|
@ -827,3 +827,13 @@ struct PrimarySpanOnVec {
|
||||
//~| NOTE there must be exactly one primary span
|
||||
sub: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
struct NestedParent {
|
||||
#[subdiagnostic]
|
||||
single_sub: A,
|
||||
#[subdiagnostic]
|
||||
option_sub: Option<A>,
|
||||
#[subdiagnostic]
|
||||
vec_sub: Vec<A>,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user