1111use Span ;
1212
1313use rustc_errors as errors;
14- use syntax_pos:: MultiSpan ;
1514
1615/// An enum representing a diagnostic level.
17- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356 " ) ]
16+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140 " ) ]
1817#[ derive( Copy , Clone , Debug ) ]
1918#[ non_exhaustive]
2019pub enum Level {
@@ -28,57 +27,105 @@ pub enum Level {
2827 Help ,
2928}
3029
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+
3158/// A structure representing a diagnostic message and associated children
3259/// messages.
33- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356 " ) ]
60+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140 " ) ]
3461#[ derive( Clone , Debug ) ]
3562pub struct Diagnostic {
3663 level : Level ,
3764 message : String ,
38- span : Option < Span > ,
65+ spans : Vec < Span > ,
3966 children : Vec < Diagnostic >
4067}
4168
4269macro_rules! diagnostic_child_methods {
4370 ( $spanned: ident, $regular: ident, $level: expr) => (
4471 /// 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) ) ;
4979 self
5080 }
5181
5282 /// Add a new child diagnostic message to `self` with the level
5383 /// 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 " ) ]
5585 pub fn $regular<T : Into <String >>( mut self , message: T ) -> Diagnostic {
5686 self . children. push( Diagnostic :: new( $level, message) ) ;
5787 self
5888 }
5989 )
6090}
6191
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" ) ]
62107impl Diagnostic {
63108 /// 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 " ) ]
65110 pub fn new < T : Into < String > > ( level : Level , message : T ) -> Diagnostic {
66111 Diagnostic {
67112 level : level,
68113 message : message. into ( ) ,
69- span : None ,
114+ spans : vec ! [ ] ,
70115 children : vec ! [ ]
71116 }
72117 }
73118
74119 /// 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+ {
78125 Diagnostic {
79126 level : level,
80127 message : message. into ( ) ,
81- span : Some ( span ) ,
128+ spans : spans . into_spans ( ) ,
82129 children : vec ! [ ]
83130 }
84131 }
@@ -89,25 +136,62 @@ impl Diagnostic {
89136 diagnostic_child_methods ! ( span_help, help, Level :: Help ) ;
90137
91138 /// Returns the diagnostic `level` for `self`.
92- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356 " ) ]
139+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140 " ) ]
93140 pub fn level ( & self ) -> Level {
94141 self . level
95142 }
96143
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+
97180 /// Emit the diagnostic.
98- #[ unstable( feature = "proc_macro_diagnostic" , issue = "38356 " ) ]
181+ #[ unstable( feature = "proc_macro_diagnostic" , issue = "54140 " ) ]
99182 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+
100188 let level = self . level . to_internal ( ) ;
101189 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 ) ) ;
106191
107192 for child in self . children {
108- let span = child. span . map_or ( MultiSpan :: new ( ) , |s| s. 0 . into ( ) ) ;
109193 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 ) ;
111195 }
112196
113197 :: __internal:: with_sess ( move |sess, _| {
0 commit comments