• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 mod diagnostic;
2 mod diagnostic_builder;
3 mod error;
4 mod subdiagnostic;
5 mod utils;
6 
7 use diagnostic::{DiagnosticDerive, LintDiagnosticDerive};
8 use proc_macro2::TokenStream;
9 use quote::format_ident;
10 use subdiagnostic::SubdiagnosticDeriveBuilder;
11 use synstructure::Structure;
12 
13 /// Implements `#[derive(Diagnostic)]`, which allows for errors to be specified as a struct,
14 /// independent from the actual diagnostics emitting code.
15 ///
16 /// ```ignore (rust)
17 /// # extern crate rustc_errors;
18 /// # use rustc_errors::Applicability;
19 /// # extern crate rustc_span;
20 /// # use rustc_span::{symbol::Ident, Span};
21 /// # extern crate rust_middle;
22 /// # use rustc_middle::ty::Ty;
23 /// #[derive(Diagnostic)]
24 /// #[diag(borrowck_move_out_of_borrow, code = "E0505")]
25 /// pub struct MoveOutOfBorrowError<'tcx> {
26 ///     pub name: Ident,
27 ///     pub ty: Ty<'tcx>,
28 ///     #[primary_span]
29 ///     #[label]
30 ///     pub span: Span,
31 ///     #[label(first_borrow_label)]
32 ///     pub first_borrow_span: Span,
33 ///     #[suggestion(code = "{name}.clone()")]
34 ///     pub clone_sugg: Option<(Span, Applicability)>
35 /// }
36 /// ```
37 ///
38 /// ```fluent
39 /// move_out_of_borrow = cannot move out of {$name} because it is borrowed
40 ///     .label = cannot move out of borrow
41 ///     .first_borrow_label = `{$ty}` first borrowed here
42 ///     .suggestion = consider cloning here
43 /// ```
44 ///
45 /// Then, later, to emit the error:
46 ///
47 /// ```ignore (rust)
48 /// sess.emit_err(MoveOutOfBorrowError {
49 ///     expected,
50 ///     actual,
51 ///     span,
52 ///     first_borrow_span,
53 ///     clone_sugg: Some(suggestion, Applicability::MachineApplicable),
54 /// });
55 /// ```
56 ///
57 /// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`:
58 /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html>
session_diagnostic_derive(s: Structure<'_>) -> TokenStream59 pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
60     DiagnosticDerive::new(format_ident!("diag"), format_ident!("handler"), s).into_tokens()
61 }
62 
63 /// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct,
64 /// independent from the actual lint emitting code.
65 ///
66 /// ```ignore (rust)
67 /// #[derive(LintDiagnostic)]
68 /// #[diag(lint_atomic_ordering_invalid_fail_success)]
69 /// pub struct AtomicOrderingInvalidLint {
70 ///     method: Symbol,
71 ///     success_ordering: Symbol,
72 ///     fail_ordering: Symbol,
73 ///     #[label(fail_label)]
74 ///     fail_order_arg_span: Span,
75 ///     #[label(success_label)]
76 ///     #[suggestion(
77 ///         code = "std::sync::atomic::Ordering::{success_suggestion}",
78 ///         applicability = "maybe-incorrect"
79 ///     )]
80 ///     success_order_arg_span: Span,
81 /// }
82 /// ```
83 ///
84 /// ```fluent
85 /// lint_atomic_ordering_invalid_fail_success = `{$method}`'s success ordering must be at least as strong as its failure ordering
86 ///     .fail_label = `{$fail_ordering}` failure ordering
87 ///     .success_label = `{$success_ordering}` success ordering
88 ///     .suggestion = consider using `{$success_suggestion}` success ordering instead
89 /// ```
90 ///
91 /// Then, later, to emit the error:
92 ///
93 /// ```ignore (rust)
94 /// cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg_span, AtomicOrderingInvalidLint {
95 ///     method,
96 ///     success_ordering,
97 ///     fail_ordering,
98 ///     fail_order_arg_span,
99 ///     success_order_arg_span,
100 /// });
101 /// ```
102 ///
103 /// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`:
104 /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference>
lint_diagnostic_derive(s: Structure<'_>) -> TokenStream105 pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
106     LintDiagnosticDerive::new(format_ident!("diag"), s).into_tokens()
107 }
108 
109 /// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and
110 /// suggestions to be specified as a structs or enums, independent from the actual diagnostics
111 /// emitting code or diagnostic derives.
112 ///
113 /// ```ignore (rust)
114 /// #[derive(Subdiagnostic)]
115 /// pub enum ExpectedIdentifierLabel<'tcx> {
116 ///     #[label(expected_identifier)]
117 ///     WithoutFound {
118 ///         #[primary_span]
119 ///         span: Span,
120 ///     }
121 ///     #[label(expected_identifier_found)]
122 ///     WithFound {
123 ///         #[primary_span]
124 ///         span: Span,
125 ///         found: String,
126 ///     }
127 /// }
128 ///
129 /// #[derive(Subdiagnostic)]
130 /// #[suggestion(style = "verbose",parser::raw_identifier)]
131 /// pub struct RawIdentifierSuggestion<'tcx> {
132 ///     #[primary_span]
133 ///     span: Span,
134 ///     #[applicability]
135 ///     applicability: Applicability,
136 ///     ident: Ident,
137 /// }
138 /// ```
139 ///
140 /// ```fluent
141 /// parser_expected_identifier = expected identifier
142 ///
143 /// parser_expected_identifier_found = expected identifier, found {$found}
144 ///
145 /// parser_raw_identifier = escape `{$ident}` to use it as an identifier
146 /// ```
147 ///
148 /// Then, later, to add the subdiagnostic:
149 ///
150 /// ```ignore (rust)
151 /// diag.subdiagnostic(ExpectedIdentifierLabel::WithoutFound { span });
152 ///
153 /// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident });
154 /// ```
session_subdiagnostic_derive(s: Structure<'_>) -> TokenStream155 pub fn session_subdiagnostic_derive(s: Structure<'_>) -> TokenStream {
156     SubdiagnosticDeriveBuilder::new().into_tokens(s)
157 }
158