| 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) |
| } |