@@ -24,6 +24,8 @@ use std::io;
24
24
use std:: rc:: Rc ;
25
25
use term;
26
26
27
+ /// Emitter trait for emitting errors. Do not implement this directly:
28
+ /// implement `CoreEmitter` instead.
27
29
pub trait Emitter {
28
30
/// Emit a standalone diagnostic message.
29
31
fn emit ( & mut self , span : & MultiSpan , msg : & str , code : Option < & str > , lvl : Level ) ;
@@ -32,27 +34,44 @@ pub trait Emitter {
32
34
fn emit_struct ( & mut self , db : & DiagnosticBuilder ) ;
33
35
}
34
36
35
- /// A core trait that can only handle very simple messages: those
36
- /// without spans or any real structure. Used only in specific contexts.
37
- pub trait RudimentaryEmitter {
38
- fn emit_rudimentary ( & mut self , msg : & str , code : Option < & str > , lvl : Level ) ;
37
+ pub trait CoreEmitter {
38
+ fn emit_message ( & mut self ,
39
+ rsp : & RenderSpan ,
40
+ msg : & str ,
41
+ code : Option < & str > ,
42
+ lvl : Level ,
43
+ is_header : bool ) ;
39
44
}
40
45
41
- impl < T : RudimentaryEmitter > Emitter for T {
46
+ impl < T : CoreEmitter > Emitter for T {
42
47
fn emit ( & mut self ,
43
48
msp : & MultiSpan ,
44
49
msg : & str ,
45
50
code : Option < & str > ,
46
51
lvl : Level ) {
47
- assert ! ( msp. primary_span( ) . is_none( ) , "Rudimenatry emitters can't handle spans" ) ;
48
- self . emit_rudimentary ( msg, code, lvl) ;
52
+ self . emit_message ( & FullSpan ( msp. clone ( ) ) ,
53
+ msg,
54
+ code,
55
+ lvl,
56
+ true ) ;
49
57
}
50
58
51
59
fn emit_struct ( & mut self , db : & DiagnosticBuilder ) {
52
- self . emit ( & db. span , & db. message , db. code . as_ref ( ) . map ( |s| & * * s) , db. level ) ;
60
+ self . emit_message ( & FullSpan ( db. span . clone ( ) ) ,
61
+ & db. message ,
62
+ db. code . as_ref ( ) . map ( |s| & * * s) ,
63
+ db. level ,
64
+ true ) ;
53
65
for child in & db. children {
54
- assert ! ( child. render_span. is_none( ) , "Rudimentary emitters can't handle render spans" ) ;
55
- self . emit ( & child. span , & child. message , None , child. level ) ;
66
+ let render_span = child. render_span
67
+ . clone ( )
68
+ . unwrap_or_else (
69
+ || FullSpan ( child. span . clone ( ) ) ) ;
70
+ self . emit_message ( & render_span,
71
+ & child. message ,
72
+ None ,
73
+ child. level ,
74
+ false ) ;
56
75
}
57
76
}
58
77
}
@@ -83,11 +102,14 @@ pub struct BasicEmitter {
83
102
dst : Destination ,
84
103
}
85
104
86
- impl RudimentaryEmitter for BasicEmitter {
87
- fn emit_rudimentary ( & mut self ,
88
- msg : & str ,
89
- code : Option < & str > ,
90
- lvl : Level ) {
105
+ impl CoreEmitter for BasicEmitter {
106
+ fn emit_message ( & mut self ,
107
+ _rsp : & RenderSpan ,
108
+ msg : & str ,
109
+ code : Option < & str > ,
110
+ lvl : Level ,
111
+ _is_header : bool ) {
112
+ // we ignore the span as we have no access to a codemap at this point
91
113
if let Err ( e) = print_diagnostic ( & mut self . dst , "" , lvl, msg, code) {
92
114
panic ! ( "failed to print diagnostics: {:?}" , e) ;
93
115
}
@@ -112,28 +134,16 @@ pub struct EmitterWriter {
112
134
first : bool ,
113
135
}
114
136
115
- impl Emitter for EmitterWriter {
116
- fn emit ( & mut self ,
117
- msp : & MultiSpan ,
118
- msg : & str ,
119
- code : Option < & str > ,
120
- lvl : Level ) {
121
- self . emit_multispan ( msp, msg, code, lvl, true ) ;
122
- }
123
-
124
- fn emit_struct ( & mut self , db : & DiagnosticBuilder ) {
125
- self . emit_multispan ( & db. span , & db. message ,
126
- db. code . as_ref ( ) . map ( |s| & * * s) , db. level , true ) ;
127
-
128
- for child in & db. children {
129
- match child. render_span {
130
- Some ( ref sp) =>
131
- self . emit_renderspan ( sp, & child. message ,
132
- child. level ) ,
133
- None =>
134
- self . emit_multispan ( & child. span ,
135
- & child. message , None , child. level , false ) ,
136
- }
137
+ impl CoreEmitter for EmitterWriter {
138
+ fn emit_message ( & mut self ,
139
+ rsp : & RenderSpan ,
140
+ msg : & str ,
141
+ code : Option < & str > ,
142
+ lvl : Level ,
143
+ is_header : bool ) {
144
+ match self . emit_message_ ( rsp, msg, code, lvl, is_header) {
145
+ Ok ( ( ) ) => { }
146
+ Err ( e) => panic ! ( "failed to emit error: {}" , e)
137
147
}
138
148
}
139
149
}
@@ -173,83 +183,56 @@ impl EmitterWriter {
173
183
EmitterWriter { dst : Raw ( dst) , registry : registry, cm : code_map, first : true }
174
184
}
175
185
176
- fn emit_multispan ( & mut self ,
177
- span : & MultiSpan ,
178
- msg : & str ,
179
- code : Option < & str > ,
180
- lvl : Level ,
181
- is_header : bool ) {
186
+ fn emit_message_ ( & mut self ,
187
+ rsp : & RenderSpan ,
188
+ msg : & str ,
189
+ code : Option < & str > ,
190
+ lvl : Level ,
191
+ is_header : bool )
192
+ -> io:: Result < ( ) > {
182
193
if is_header {
183
194
if self . first {
184
195
self . first = false ;
185
196
} else {
186
- match write ! ( self . dst, "\n " ) {
187
- Ok ( _) => { }
188
- Err ( e) => {
189
- panic ! ( "failed to print diagnostics: {:?}" , e)
190
- }
191
- }
197
+ write ! ( self . dst, "\n " ) ?;
192
198
}
193
199
}
194
200
195
- let error = match span. primary_span ( ) {
196
- Some ( COMMAND_LINE_SP ) => {
197
- self . emit_ ( & FileLine ( span. clone ( ) ) , msg, code, lvl)
198
- }
199
- Some ( DUMMY_SP ) | None => {
200
- print_diagnostic ( & mut self . dst , "" , lvl, msg, code)
201
- }
202
- Some ( _) => {
203
- self . emit_ ( & FullSpan ( span. clone ( ) ) , msg, code, lvl)
204
- }
205
- } ;
206
-
207
- if let Err ( e) = error {
208
- panic ! ( "failed to print diagnostics: {:?}" , e) ;
209
- }
210
- }
211
-
212
- fn emit_renderspan ( & mut self , sp : & RenderSpan , msg : & str , lvl : Level ) {
213
- if let Err ( e) = self . emit_ ( sp, msg, None , lvl) {
214
- panic ! ( "failed to print diagnostics: {:?}" , e) ;
215
- }
216
- }
217
-
218
- fn emit_ ( & mut self ,
219
- rsp : & RenderSpan ,
220
- msg : & str ,
221
- code : Option < & str > ,
222
- lvl : Level )
223
- -> io:: Result < ( ) > {
224
- let msp = rsp. span ( ) ;
225
- let primary_span = msp. primary_span ( ) ;
226
-
227
201
match code {
228
202
Some ( code) if self . registry . as_ref ( )
229
- . and_then ( |registry| registry. find_description ( code) ) . is_some ( ) =>
230
- {
203
+ . and_then ( |registry| registry. find_description ( code) )
204
+ . is_some ( ) => {
231
205
let code_with_explain = String :: from ( "--explain " ) + code;
232
206
print_diagnostic ( & mut self . dst , "" , lvl, msg, Some ( & code_with_explain) ) ?
233
207
}
234
- _ => print_diagnostic ( & mut self . dst , "" , lvl, msg, code) ?
208
+ _ => {
209
+ print_diagnostic ( & mut self . dst , "" , lvl, msg, code) ?
210
+ }
235
211
}
236
212
213
+ // Watch out for various nasty special spans; don't try to
214
+ // print any filename or anything for those.
215
+ match rsp. span ( ) . primary_span ( ) {
216
+ Some ( COMMAND_LINE_SP ) | Some ( DUMMY_SP ) => {
217
+ return Ok ( ( ) ) ;
218
+ }
219
+ _ => { }
220
+ }
221
+
222
+ // Otherwise, print out the snippet etc as needed.
237
223
match * rsp {
238
- FullSpan ( _ ) => {
224
+ FullSpan ( ref msp ) => {
239
225
self . highlight_lines ( msp, lvl) ?;
240
- if let Some ( primary_span) = primary_span {
226
+ if let Some ( primary_span) = msp . primary_span ( ) {
241
227
self . print_macro_backtrace ( primary_span) ?;
242
228
}
243
229
}
244
230
Suggestion ( ref suggestion) => {
245
231
self . highlight_suggestion ( suggestion) ?;
246
- if let Some ( primary_span) = primary_span {
232
+ if let Some ( primary_span) = rsp . span ( ) . primary_span ( ) {
247
233
self . print_macro_backtrace ( primary_span) ?;
248
234
}
249
235
}
250
- FileLine ( ..) => {
251
- // no source text in this case!
252
- }
253
236
}
254
237
255
238
Ok ( ( ) )
0 commit comments