macros: add diagnostic derive for lints
`SessionDiagnostic` isn't suitable for use on lints as whether or not it creates an error or a warning is decided at compile-time by the macro, whereas lints decide this at runtime based on the location of the lint being reported (as it will depend on the user's `allow`/`deny` attributes, etc). Re-using most of the machinery for `SessionDiagnostic`, this macro introduces a `LintDiagnostic` derive which implements a `DecorateLint` trait, taking a `LintDiagnosticBuilder` and adding to the lint according to the diagnostic struct.
This commit is contained in:
parent
7f9d8480d6
commit
9d864c8d56
12 changed files with 847 additions and 614 deletions
|
@ -1,4 +1,4 @@
|
|||
use crate::diagnostics::error::{span_err, throw_span_err, SessionDiagnosticDeriveError};
|
||||
use crate::diagnostics::error::{span_err, throw_span_err, DiagnosticDeriveError};
|
||||
use proc_macro::Span;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote, ToTokens};
|
||||
|
@ -34,7 +34,7 @@ pub(crate) fn type_is_unit(ty: &Type) -> bool {
|
|||
pub(crate) fn report_type_error(
|
||||
attr: &Attribute,
|
||||
ty_name: &str,
|
||||
) -> Result<!, SessionDiagnosticDeriveError> {
|
||||
) -> Result<!, DiagnosticDeriveError> {
|
||||
let name = attr.path.segments.last().unwrap().ident.to_string();
|
||||
let meta = attr.parse_meta()?;
|
||||
|
||||
|
@ -59,7 +59,7 @@ fn report_error_if_not_applied_to_ty(
|
|||
info: &FieldInfo<'_>,
|
||||
path: &[&str],
|
||||
ty_name: &str,
|
||||
) -> Result<(), SessionDiagnosticDeriveError> {
|
||||
) -> Result<(), DiagnosticDeriveError> {
|
||||
if !type_matches_path(&info.ty, path) {
|
||||
report_type_error(attr, ty_name)?;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ fn report_error_if_not_applied_to_ty(
|
|||
pub(crate) fn report_error_if_not_applied_to_applicability(
|
||||
attr: &Attribute,
|
||||
info: &FieldInfo<'_>,
|
||||
) -> Result<(), SessionDiagnosticDeriveError> {
|
||||
) -> Result<(), DiagnosticDeriveError> {
|
||||
report_error_if_not_applied_to_ty(
|
||||
attr,
|
||||
info,
|
||||
|
@ -84,7 +84,7 @@ pub(crate) fn report_error_if_not_applied_to_applicability(
|
|||
pub(crate) fn report_error_if_not_applied_to_span(
|
||||
attr: &Attribute,
|
||||
info: &FieldInfo<'_>,
|
||||
) -> Result<(), SessionDiagnosticDeriveError> {
|
||||
) -> Result<(), DiagnosticDeriveError> {
|
||||
report_error_if_not_applied_to_ty(attr, info, &["rustc_span", "Span"], "`Span`")
|
||||
}
|
||||
|
||||
|
@ -166,10 +166,12 @@ pub(crate) struct FieldInfo<'a> {
|
|||
/// Small helper trait for abstracting over `Option` fields that contain a value and a `Span`
|
||||
/// for error reporting if they are set more than once.
|
||||
pub(crate) trait SetOnce<T> {
|
||||
fn set_once(&mut self, value: T);
|
||||
fn set_once(&mut self, _: (T, Span));
|
||||
|
||||
fn value(self) -> Option<T>;
|
||||
}
|
||||
|
||||
impl<T> SetOnce<(T, Span)> for Option<(T, Span)> {
|
||||
impl<T> SetOnce<T> for Option<(T, Span)> {
|
||||
fn set_once(&mut self, (value, span): (T, Span)) {
|
||||
match self {
|
||||
None => {
|
||||
|
@ -182,6 +184,10 @@ impl<T> SetOnce<(T, Span)> for Option<(T, Span)> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn value(self) -> Option<T> {
|
||||
self.map(|(v, _)| v)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait HasFieldMap {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue