@@ -44,6 +44,8 @@ use serialize::{Encodable, Decodable, Encoder, Decoder};
44
44
extern crate serialize;
45
45
extern crate serialize as rustc_serialize; // used by deriving
46
46
47
+ extern crate unicode_width;
48
+
47
49
pub mod hygiene;
48
50
pub use hygiene:: { SyntaxContext , ExpnInfo , ExpnFormat , NameAndSpan , CompilerDesugaringKind } ;
49
51
@@ -494,6 +496,63 @@ pub struct MultiByteChar {
494
496
pub bytes : usize ,
495
497
}
496
498
499
+ /// Identifies an offset of a non-narrow character in a FileMap
500
+ #[ derive( Copy , Clone , RustcEncodable , RustcDecodable , Eq , PartialEq ) ]
501
+ pub enum NonNarrowChar {
502
+ /// Represents a zero-width character
503
+ ZeroWidth ( BytePos ) ,
504
+ /// Represents a wide (fullwidth) character
505
+ Wide ( BytePos ) ,
506
+ }
507
+
508
+ impl NonNarrowChar {
509
+ fn new ( pos : BytePos , width : usize ) -> Self {
510
+ match width {
511
+ 0 => NonNarrowChar :: ZeroWidth ( pos) ,
512
+ 2 => NonNarrowChar :: Wide ( pos) ,
513
+ _ => panic ! ( "width {} given for non-narrow character" , width) ,
514
+ }
515
+ }
516
+
517
+ /// Returns the absolute offset of the character in the CodeMap
518
+ pub fn pos ( & self ) -> BytePos {
519
+ match * self {
520
+ NonNarrowChar :: ZeroWidth ( p) |
521
+ NonNarrowChar :: Wide ( p) => p,
522
+ }
523
+ }
524
+
525
+ /// Returns the width of the character, 0 (zero-width) or 2 (wide)
526
+ pub fn width ( & self ) -> usize {
527
+ match * self {
528
+ NonNarrowChar :: ZeroWidth ( _) => 0 ,
529
+ NonNarrowChar :: Wide ( _) => 2 ,
530
+ }
531
+ }
532
+ }
533
+
534
+ impl Add < BytePos > for NonNarrowChar {
535
+ type Output = Self ;
536
+
537
+ fn add ( self , rhs : BytePos ) -> Self {
538
+ match self {
539
+ NonNarrowChar :: ZeroWidth ( pos) => NonNarrowChar :: ZeroWidth ( pos + rhs) ,
540
+ NonNarrowChar :: Wide ( pos) => NonNarrowChar :: Wide ( pos + rhs) ,
541
+ }
542
+ }
543
+ }
544
+
545
+ impl Sub < BytePos > for NonNarrowChar {
546
+ type Output = Self ;
547
+
548
+ fn sub ( self , rhs : BytePos ) -> Self {
549
+ match self {
550
+ NonNarrowChar :: ZeroWidth ( pos) => NonNarrowChar :: ZeroWidth ( pos - rhs) ,
551
+ NonNarrowChar :: Wide ( pos) => NonNarrowChar :: Wide ( pos - rhs) ,
552
+ }
553
+ }
554
+ }
555
+
497
556
/// The state of the lazy external source loading mechanism of a FileMap.
498
557
#[ derive( PartialEq , Eq , Clone ) ]
499
558
pub enum ExternalSource {
@@ -552,11 +611,13 @@ pub struct FileMap {
552
611
pub lines : RefCell < Vec < BytePos > > ,
553
612
/// Locations of multi-byte characters in the source code
554
613
pub multibyte_chars : RefCell < Vec < MultiByteChar > > ,
614
+ /// Width of characters that are not narrow in the source code
615
+ pub non_narrow_chars : RefCell < Vec < NonNarrowChar > > ,
555
616
}
556
617
557
618
impl Encodable for FileMap {
558
619
fn encode < S : Encoder > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > {
559
- s. emit_struct ( "FileMap" , 7 , |s| {
620
+ s. emit_struct ( "FileMap" , 8 , |s| {
560
621
s. emit_struct_field ( "name" , 0 , |s| self . name . encode ( s) ) ?;
561
622
s. emit_struct_field ( "name_was_remapped" , 1 , |s| self . name_was_remapped . encode ( s) ) ?;
562
623
s. emit_struct_field ( "src_hash" , 6 , |s| self . src_hash . encode ( s) ) ?;
@@ -610,6 +671,9 @@ impl Encodable for FileMap {
610
671
} ) ?;
611
672
s. emit_struct_field ( "multibyte_chars" , 5 , |s| {
612
673
( * self . multibyte_chars . borrow ( ) ) . encode ( s)
674
+ } ) ?;
675
+ s. emit_struct_field ( "non_narrow_chars" , 7 , |s| {
676
+ ( * self . non_narrow_chars . borrow ( ) ) . encode ( s)
613
677
} )
614
678
} )
615
679
}
@@ -618,7 +682,7 @@ impl Encodable for FileMap {
618
682
impl Decodable for FileMap {
619
683
fn decode < D : Decoder > ( d : & mut D ) -> Result < FileMap , D :: Error > {
620
684
621
- d. read_struct ( "FileMap" , 6 , |d| {
685
+ d. read_struct ( "FileMap" , 8 , |d| {
622
686
let name: String = d. read_struct_field ( "name" , 0 , |d| Decodable :: decode ( d) ) ?;
623
687
let name_was_remapped: bool =
624
688
d. read_struct_field ( "name_was_remapped" , 1 , |d| Decodable :: decode ( d) ) ?;
@@ -657,6 +721,8 @@ impl Decodable for FileMap {
657
721
} ) ?;
658
722
let multibyte_chars: Vec < MultiByteChar > =
659
723
d. read_struct_field ( "multibyte_chars" , 5 , |d| Decodable :: decode ( d) ) ?;
724
+ let non_narrow_chars: Vec < NonNarrowChar > =
725
+ d. read_struct_field ( "non_narrow_chars" , 7 , |d| Decodable :: decode ( d) ) ?;
660
726
Ok ( FileMap {
661
727
name,
662
728
name_was_remapped,
@@ -671,7 +737,8 @@ impl Decodable for FileMap {
671
737
src_hash,
672
738
external_src : RefCell :: new ( ExternalSource :: AbsentOk ) ,
673
739
lines : RefCell :: new ( lines) ,
674
- multibyte_chars : RefCell :: new ( multibyte_chars)
740
+ multibyte_chars : RefCell :: new ( multibyte_chars) ,
741
+ non_narrow_chars : RefCell :: new ( non_narrow_chars)
675
742
} )
676
743
} )
677
744
}
@@ -709,6 +776,7 @@ impl FileMap {
709
776
end_pos : Pos :: from_usize ( end_pos) ,
710
777
lines : RefCell :: new ( Vec :: new ( ) ) ,
711
778
multibyte_chars : RefCell :: new ( Vec :: new ( ) ) ,
779
+ non_narrow_chars : RefCell :: new ( Vec :: new ( ) ) ,
712
780
}
713
781
}
714
782
@@ -798,6 +866,23 @@ impl FileMap {
798
866
self . multibyte_chars . borrow_mut ( ) . push ( mbc) ;
799
867
}
800
868
869
+ pub fn record_width ( & self , pos : BytePos , ch : char ) {
870
+ let width = match ch {
871
+ '\t' | '\n' =>
872
+ // Tabs will consume one column.
873
+ // Make newlines take one column so that displayed spans can point them.
874
+ 1 ,
875
+ ch =>
876
+ // Assume control characters are zero width.
877
+ // FIXME: How can we decide between `width` and `width_cjk`?
878
+ unicode_width:: UnicodeWidthChar :: width ( ch) . unwrap_or ( 0 ) ,
879
+ } ;
880
+ // Only record non-narrow characters.
881
+ if width != 1 {
882
+ self . non_narrow_chars . borrow_mut ( ) . push ( NonNarrowChar :: new ( pos, width) ) ;
883
+ }
884
+ }
885
+
801
886
pub fn is_real_file ( & self ) -> bool {
802
887
!( self . name . starts_with ( "<" ) &&
803
888
self . name . ends_with ( ">" ) )
@@ -944,7 +1029,9 @@ pub struct Loc {
944
1029
/// The (1-based) line number
945
1030
pub line : usize ,
946
1031
/// The (0-based) column offset
947
- pub col : CharPos
1032
+ pub col : CharPos ,
1033
+ /// The (0-based) column offset when displayed
1034
+ pub col_display : usize ,
948
1035
}
949
1036
950
1037
/// A source code location used as the result of lookup_char_pos_adj
0 commit comments