blob: c0512e86bbcb43569fef06802fbfc2500c452955 [file] [log] [blame] [edit]
mod diagnostic;
mod diagnostic_builder;
mod error;
mod message;
mod msg_macro;
mod subdiagnostic;
mod utils;
use diagnostic::{DiagnosticDerive, LintDiagnosticDerive};
pub(super) use msg_macro::msg_macro;
use proc_macro2::TokenStream;
use subdiagnostic::SubdiagnosticDerive;
use synstructure::Structure;
/// Implements `#[derive(Diagnostic)]`, which allows for errors to be specified as a struct,
/// independent from the actual diagnostics emitting code.
///
/// ```ignore (rust)
/// # extern crate rustc_errors;
/// # use rustc_errors::Applicability;
/// # extern crate rustc_span;
/// # use rustc_span::{Ident, Span};
/// # extern crate rust_middle;
/// # use rustc_middle::ty::Ty;
/// #[derive(Diagnostic)]
/// #[diag("this is an example message", code = E0123)]
/// pub(crate) struct ExampleError<'tcx> {
/// pub name: Ident,
/// pub ty: Ty<'tcx>,
/// #[primary_span]
/// #[label("with a label")]
/// pub span: Span,
/// #[label("with a label")]
/// pub other_span: Span,
/// #[suggestion("with a suggestion", code = "{name}.clone()")]
/// pub opt_sugg: Option<(Span, Applicability)>,
/// }
/// ```
///
/// Then, later, to emit the error:
///
/// ```ignore (rust)
/// sess.emit_err(ExampleError {
/// name, ty, span, other_span, opt_sugg
/// });
/// ```
///
/// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`:
/// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html>
pub(super) fn diagnostic_derive(s: Structure<'_>) -> TokenStream {
DiagnosticDerive::new(s).into_tokens()
}
/// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct,
/// independent from the actual lint emitting code.
///
/// ```ignore (rust)
/// #[derive(LintDiagnostic)]
/// #[diag("unused attribute")]
/// pub(crate) struct UnusedAttribute {
/// #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")]
/// pub this: Span,
/// #[note("attribute also specified here")]
/// pub other: Span,
/// #[warning(
/// "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
/// )]
/// pub warning: bool,
/// }
/// ```
///
/// Then, later, to emit the error:
///
/// ```ignore (rust)
/// cx.emit_span_lint(UNUSED_ATTRIBUTES, span, UnusedAttribute {
/// ...
/// });
/// ```
///
/// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`:
/// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference>
pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
LintDiagnosticDerive::new(s).into_tokens()
}
/// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and
/// suggestions to be specified as a structs or enums, independent from the actual diagnostics
/// emitting code or diagnostic derives.
///
/// ```ignore (rust)
/// #[derive(Subdiagnostic)]
/// pub(crate) enum BuiltinUnusedDocCommentSub {
/// #[help("use `//` for a plain comment")]
/// PlainHelp,
/// #[help("use `/* */` for a plain comment")]
/// BlockHelp,
/// }
/// ```
/// Then, later, use the subdiagnostic in a diagnostic:
///
/// ```ignore (rust)
/// #[derive(LintDiagnostic)]
/// #[diag("unused doc comment")]
/// pub(crate) struct BuiltinUnusedDocComment<'a> {
/// pub kind: &'a str,
/// #[label("rustdoc does not generate documentation for {$kind}")]
/// pub label: Span,
/// #[subdiagnostic]
/// pub sub: BuiltinUnusedDocCommentSub,
/// }
/// ```
pub(super) fn subdiagnostic_derive(s: Structure<'_>) -> TokenStream {
SubdiagnosticDerive::new().into_tokens(s)
}