11
11
use Span ;
12
12
13
13
use rustc_errors as errors;
14
- use syntax_pos:: MultiSpan ;
15
14
16
15
/// An enum representing a diagnostic level.
17
- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356 " ) ]
16
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140 " ) ]
18
17
#[ derive( Copy , Clone , Debug ) ]
19
18
#[ non_exhaustive]
20
19
pub enum Level {
@@ -28,57 +27,105 @@ pub enum Level {
28
27
Help ,
29
28
}
30
29
30
+ /// Trait implemented by types that can be converted into a set of `Span`s.
31
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
32
+ pub trait MultiSpan {
33
+ /// Converts `self` into a `Vec<Span>`.
34
+ fn into_spans ( self ) -> Vec < Span > ;
35
+ }
36
+
37
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
38
+ impl MultiSpan for Span {
39
+ fn into_spans ( self ) -> Vec < Span > {
40
+ vec ! [ self ]
41
+ }
42
+ }
43
+
44
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
45
+ impl MultiSpan for Vec < Span > {
46
+ fn into_spans ( self ) -> Vec < Span > {
47
+ self
48
+ }
49
+ }
50
+
51
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
52
+ impl < ' a > MultiSpan for & ' a [ Span ] {
53
+ fn into_spans ( self ) -> Vec < Span > {
54
+ self . to_vec ( )
55
+ }
56
+ }
57
+
31
58
/// A structure representing a diagnostic message and associated children
32
59
/// messages.
33
- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356 " ) ]
60
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140 " ) ]
34
61
#[ derive( Clone , Debug ) ]
35
62
pub struct Diagnostic {
36
63
level : Level ,
37
64
message : String ,
38
- span : Option < Span > ,
65
+ spans : Vec < Span > ,
39
66
children : Vec < Diagnostic >
40
67
}
41
68
42
69
macro_rules! diagnostic_child_methods {
43
70
( $spanned: ident, $regular: ident, $level: expr) => (
44
71
/// Add a new child diagnostic message to `self` with the level
45
- /// identified by this methods name with the given `span` and `message`.
46
- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356" ) ]
47
- pub fn $spanned<T : Into <String >>( mut self , span: Span , message: T ) -> Diagnostic {
48
- self . children. push( Diagnostic :: spanned( span, $level, message) ) ;
72
+ /// identified by this method's name with the given `spans` and
73
+ /// `message`.
74
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
75
+ pub fn $spanned<S , T >( mut self , spans: S , message: T ) -> Diagnostic
76
+ where S : MultiSpan , T : Into <String >
77
+ {
78
+ self . children. push( Diagnostic :: spanned( spans, $level, message) ) ;
49
79
self
50
80
}
51
81
52
82
/// Add a new child diagnostic message to `self` with the level
53
83
/// identified by this method's name with the given `message`.
54
- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356 " ) ]
84
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140 " ) ]
55
85
pub fn $regular<T : Into <String >>( mut self , message: T ) -> Diagnostic {
56
86
self . children. push( Diagnostic :: new( $level, message) ) ;
57
87
self
58
88
}
59
89
)
60
90
}
61
91
92
+ /// Iterator over the children diagnostics of a `Diagnostic`.
93
+ #[ derive( Debug , Clone ) ]
94
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
95
+ pub struct Children < ' a > ( :: std:: slice:: Iter < ' a , Diagnostic > ) ;
96
+
97
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
98
+ impl < ' a > Iterator for Children < ' a > {
99
+ type Item = & ' a Diagnostic ;
100
+
101
+ fn next ( & mut self ) -> Option < Self :: Item > {
102
+ self . 0 . next ( )
103
+ }
104
+ }
105
+
106
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
62
107
impl Diagnostic {
63
108
/// Create a new diagnostic with the given `level` and `message`.
64
- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356 " ) ]
109
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140 " ) ]
65
110
pub fn new < T : Into < String > > ( level : Level , message : T ) -> Diagnostic {
66
111
Diagnostic {
67
112
level : level,
68
113
message : message. into ( ) ,
69
- span : None ,
114
+ spans : vec ! [ ] ,
70
115
children : vec ! [ ]
71
116
}
72
117
}
73
118
74
119
/// Create a new diagnostic with the given `level` and `message` pointing to
75
- /// the given `span`.
76
- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356" ) ]
77
- pub fn spanned < T : Into < String > > ( span : Span , level : Level , message : T ) -> Diagnostic {
120
+ /// the given set of `spans`.
121
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
122
+ pub fn spanned < S , T > ( spans : S , level : Level , message : T ) -> Diagnostic
123
+ where S : MultiSpan , T : Into < String >
124
+ {
78
125
Diagnostic {
79
126
level : level,
80
127
message : message. into ( ) ,
81
- span : Some ( span ) ,
128
+ spans : spans . into_spans ( ) ,
82
129
children : vec ! [ ]
83
130
}
84
131
}
@@ -89,25 +136,62 @@ impl Diagnostic {
89
136
diagnostic_child_methods ! ( span_help, help, Level :: Help ) ;
90
137
91
138
/// Returns the diagnostic `level` for `self`.
92
- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356 " ) ]
139
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140 " ) ]
93
140
pub fn level ( & self ) -> Level {
94
141
self . level
95
142
}
96
143
144
+ /// Sets the level in `self` to `level`.
145
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
146
+ pub fn set_level ( & mut self , level : Level ) {
147
+ self . level = level;
148
+ }
149
+
150
+ /// Returns the message in `self`.
151
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
152
+ pub fn message ( & self ) -> & str {
153
+ & self . message
154
+ }
155
+
156
+ /// Sets the message in `self` to `message`.
157
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
158
+ pub fn set_message < T : Into < String > > ( & mut self , message : T ) {
159
+ self . message = message. into ( ) ;
160
+ }
161
+
162
+ /// Returns the `Span`s in `self`.
163
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
164
+ pub fn spans ( & self ) -> & [ Span ] {
165
+ & self . spans
166
+ }
167
+
168
+ /// Sets the `Span`s in `self` to `spans`.
169
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
170
+ pub fn set_spans < S : MultiSpan > ( & mut self , spans : S ) {
171
+ self . spans = spans. into_spans ( ) ;
172
+ }
173
+
174
+ /// Returns an iterator over the children diagnostics of `self`.
175
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140" ) ]
176
+ pub fn children ( & self ) -> Children {
177
+ Children ( self . children . iter ( ) )
178
+ }
179
+
97
180
/// Emit the diagnostic.
98
- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356 " ) ]
181
+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140 " ) ]
99
182
pub fn emit ( self ) {
183
+ fn to_internal ( spans : Vec < Span > ) -> :: syntax_pos:: MultiSpan {
184
+ let spans: Vec < _ > = spans. into_iter ( ) . map ( |s| s. 0 ) . collect ( ) ;
185
+ :: syntax_pos:: MultiSpan :: from_spans ( spans)
186
+ }
187
+
100
188
let level = self . level . to_internal ( ) ;
101
189
let mut diag = errors:: Diagnostic :: new ( level, & * self . message ) ;
102
-
103
- if let Some ( span) = self . span {
104
- diag. set_span ( span. 0 ) ;
105
- }
190
+ diag. set_span ( to_internal ( self . spans ) ) ;
106
191
107
192
for child in self . children {
108
- let span = child. span . map_or ( MultiSpan :: new ( ) , |s| s. 0 . into ( ) ) ;
109
193
let level = child. level . to_internal ( ) ;
110
- diag. sub ( level, & * child. message , span , None ) ;
194
+ diag. sub ( level, & * child. message , to_internal ( child . spans ) , None ) ;
111
195
}
112
196
113
197
:: __internal:: with_sess ( move |sess, _| {
0 commit comments