@@ -32,8 +32,6 @@ use serialize::{Encodable, Decodable, Encoder, Decoder};
3232
3333use ast:: Name ;
3434
35- use errors:: emitter:: MAX_HIGHLIGHT_LINES ;
36-
3735// _____________________________________________________________________________
3836// Pos, BytePos, CharPos
3937//
@@ -132,13 +130,21 @@ pub struct Span {
132130 pub expn_id : ExpnId
133131}
134132
135- /// Spans are converted to MultiSpans just before error reporting, either automatically,
136- /// generated by line grouping, or manually constructed.
137- /// In the latter case care should be taken to ensure that spans are ordered, disjoint,
138- /// and point into the same FileMap.
133+ /// A collection of spans. Each span can optionally have an associated
134+ /// label. The spans do not have to be disjoint or have any other
135+ /// particular relationship: in fact, they can even be from distinct
136+ /// files. When the error is reported, the text referenced by the
137+ /// spans will be printed, with highlights or labels in the
138+ /// appropriate places.
139139#[ derive( Clone ) ]
140140pub struct MultiSpan {
141- pub spans : Vec < Span >
141+ pub spans : Vec < SpanString >
142+ }
143+
144+ #[ derive( Clone , Debug ) ]
145+ pub struct SpanString {
146+ pub span : Span ,
147+ pub label : Option < String > ,
142148}
143149
144150pub const DUMMY_SP : Span = Span { lo : BytePos ( 0 ) , hi : BytePos ( 0 ) , expn_id : NO_EXPANSION } ;
@@ -284,55 +290,28 @@ impl MultiSpan {
284290 MultiSpan { spans : Vec :: new ( ) }
285291 }
286292
293+ pub fn from_labels ( vec : Vec < ( Span , String ) > ) -> MultiSpan {
294+ MultiSpan {
295+ spans : vec. into_iter ( )
296+ . map ( |( span, string) | SpanString {
297+ span : span,
298+ label : Some ( string)
299+ } )
300+ . collect ( )
301+ }
302+ }
303+
287304 pub fn to_span_bounds ( & self ) -> Span {
288305 assert ! ( !self . spans. is_empty( ) ) ;
289- let Span { lo, expn_id, .. } = * self . spans . first ( ) . unwrap ( ) ;
290- let Span { hi, .. } = * self . spans . last ( ) . unwrap ( ) ;
306+ let Span { lo, expn_id, .. } = self . spans . first ( ) . unwrap ( ) . span ;
307+ let Span { hi, .. } = self . spans . last ( ) . unwrap ( ) . span ;
291308 Span { lo : lo, hi : hi, expn_id : expn_id }
292309 }
293-
294- /// Merges or inserts the given span into itself.
295- pub fn push_merge ( & mut self , mut sp : Span ) {
296- let mut idx_merged = None ;
297-
298- for idx in 0 .. {
299- let cur = match self . spans . get ( idx) {
300- Some ( s) => * s,
301- None => break ,
302- } ;
303- // Try to merge with a contained Span
304- if let Some ( union) = cur. merge ( sp) {
305- self . spans [ idx] = union;
306- sp = union;
307- idx_merged = Some ( idx) ;
308- break ;
309- }
310- // Or insert into the first sorted position
311- if sp. hi <= cur. lo {
312- self . spans . insert ( idx, sp) ;
313- idx_merged = Some ( idx) ;
314- break ;
315- }
316- }
317- if let Some ( idx) = idx_merged {
318- // Merge with spans trailing the insertion/merging position
319- while ( idx + 1 ) < self . spans . len ( ) {
320- if let Some ( union) = self . spans [ idx + 1 ] . merge ( sp) {
321- self . spans [ idx] = union;
322- self . spans . remove ( idx + 1 ) ;
323- } else {
324- break ;
325- }
326- }
327- } else {
328- self . spans . push ( sp) ;
329- }
330- }
331310}
332311
333312impl From < Span > for MultiSpan {
334313 fn from ( span : Span ) -> MultiSpan {
335- MultiSpan { spans : vec ! [ span] }
314+ MultiSpan { spans : vec ! [ SpanString { span: span , label : None } ] }
336315 }
337316}
338317
@@ -1156,53 +1135,6 @@ impl CodeMap {
11561135 }
11571136 }
11581137
1159- /// Groups and sorts spans by lines into `MultiSpan`s, where `push` adds them to their group,
1160- /// specifying the unification behaviour for overlapping spans.
1161- /// Spans overflowing a line are put into their own one-element-group.
1162- pub fn custom_group_spans < F > ( & self , mut spans : Vec < Span > , push : F ) -> Vec < MultiSpan >
1163- where F : Fn ( & mut MultiSpan , Span )
1164- {
1165- spans. sort_by ( |a, b| a. lo . cmp ( & b. lo ) ) ;
1166- let mut groups = Vec :: < MultiSpan > :: new ( ) ;
1167- let mut overflowing = vec ! [ ] ;
1168- let mut prev_expn = ExpnId ( !2u32 ) ;
1169- let mut prev_file = !0usize ;
1170- let mut prev_line = !0usize ;
1171- let mut err_size = 0 ;
1172-
1173- for sp in spans {
1174- let line = self . lookup_char_pos ( sp. lo ) . line ;
1175- let line_hi = self . lookup_char_pos ( sp. hi ) . line ;
1176- if line != line_hi {
1177- overflowing. push ( sp. into ( ) ) ;
1178- continue
1179- }
1180- let file = self . lookup_filemap_idx ( sp. lo ) ;
1181-
1182- if err_size < MAX_HIGHLIGHT_LINES && sp. expn_id == prev_expn && file == prev_file {
1183- // `push` takes care of sorting, trimming, and merging
1184- push ( & mut groups. last_mut ( ) . unwrap ( ) , sp) ;
1185- if line != prev_line {
1186- err_size += 1 ;
1187- }
1188- } else {
1189- groups. push ( sp. into ( ) ) ;
1190- err_size = 1 ;
1191- }
1192- prev_expn = sp. expn_id ;
1193- prev_file = file;
1194- prev_line = line;
1195- }
1196- groups. extend ( overflowing) ;
1197- groups
1198- }
1199-
1200- /// Groups and sorts spans by lines into `MultiSpan`s, merging overlapping spans.
1201- /// Spans overflowing a line are put into their own one-element-group.
1202- pub fn group_spans ( & self , spans : Vec < Span > ) -> Vec < MultiSpan > {
1203- self . custom_group_spans ( spans, |msp, sp| msp. push_merge ( sp) )
1204- }
1205-
12061138 pub fn get_filemap ( & self , filename : & str ) -> Rc < FileMap > {
12071139 for fm in self . files . borrow ( ) . iter ( ) {
12081140 if filename == fm. name {
@@ -1719,62 +1651,4 @@ r"blork2.rs:2:1: 2:12
17191651" ;
17201652 assert_eq ! ( sstr, res_str) ;
17211653 }
1722-
1723- #[ test]
1724- fn t13 ( ) {
1725- // Test that collecting multiple spans into line-groups works correctly
1726- let cm = CodeMap :: new ( ) ;
1727- let inp = "_aaaaa__bbb\n vv\n w\n x\n y\n z\n cccccc__ddddee__" ;
1728- let sp1 = " ~~~~~ \n \n \n \n \n \n " ;
1729- let sp2 = " \n \n \n \n \n ~\n " ;
1730- let sp3 = " ~~~\n ~~\n \n \n \n \n " ;
1731- let sp4 = " \n \n \n \n \n \n ~~~~~~ " ;
1732- let sp5 = " \n \n \n \n \n \n ~~~~ " ;
1733- let sp6 = " \n \n \n \n \n \n ~~~~ " ;
1734- let sp_merge = " \n \n \n \n \n \n ~~~~~~ " ;
1735- let sp7 = " \n ~\n \n \n \n \n " ;
1736- let sp8 = " \n \n ~\n \n \n \n " ;
1737- let sp9 = " \n \n \n ~\n \n \n " ;
1738- let sp10 = " \n \n \n \n ~\n \n " ;
1739-
1740- let span = |sp, expected| {
1741- let sp = span_from_selection ( inp, sp) ;
1742- assert_eq ! ( & cm. span_to_snippet( sp) . unwrap( ) , expected) ;
1743- sp
1744- } ;
1745-
1746- cm. new_filemap_and_lines ( "blork.rs" , inp) ;
1747- let sp1 = span ( sp1, "aaaaa" ) ;
1748- let sp2 = span ( sp2, "z" ) ;
1749- let sp3 = span ( sp3, "bbb\n vv" ) ;
1750- let sp4 = span ( sp4, "cccccc" ) ;
1751- let sp5 = span ( sp5, "dddd" ) ;
1752- let sp6 = span ( sp6, "ddee" ) ;
1753- let sp7 = span ( sp7, "v" ) ;
1754- let sp8 = span ( sp8, "w" ) ;
1755- let sp9 = span ( sp9, "x" ) ;
1756- let sp10 = span ( sp10, "y" ) ;
1757- let sp_merge = span ( sp_merge, "ddddee" ) ;
1758-
1759- let spans = vec ! [ sp5, sp2, sp4, sp9, sp10, sp7, sp3, sp8, sp1, sp6] ;
1760-
1761- macro_rules! check_next {
1762- ( $groups: expr, $expected: expr) => ( {
1763- let actual = $groups. next( ) . map( |g|& g. spans[ ..] ) ;
1764- let expected = $expected;
1765- println!( "actual:\n {:?}\n " , actual) ;
1766- println!( "expected:\n {:?}\n " , expected) ;
1767- assert_eq!( actual, expected. as_ref( ) . map( |x|& x[ ..] ) ) ;
1768- } ) ;
1769- }
1770-
1771- let _groups = cm. group_spans ( spans. clone ( ) ) ;
1772- let it = & mut _groups. iter ( ) ;
1773-
1774- check_next ! ( it, Some ( [ sp1, sp7, sp8, sp9, sp10, sp2] ) ) ;
1775- // New group because we're exceeding MAX_HIGHLIGHT_LINES
1776- check_next ! ( it, Some ( [ sp4, sp_merge] ) ) ;
1777- check_next ! ( it, Some ( [ sp3] ) ) ;
1778- check_next ! ( it, None :: <[ Span ; 0 ] >) ;
1779- }
17801654}
0 commit comments