@@ -44,6 +44,8 @@ use serialize::{Encodable, Decodable, Encoder, Decoder};
4444extern crate serialize;
4545extern crate serialize as rustc_serialize; // used by deriving
4646
47+ extern crate unicode_width;
48+
4749pub mod hygiene;
4850pub use hygiene:: { SyntaxContext , ExpnInfo , ExpnFormat , NameAndSpan , CompilerDesugaringKind } ;
4951
@@ -494,6 +496,63 @@ pub struct MultiByteChar {
494496 pub bytes : usize ,
495497}
496498
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+
497556/// The state of the lazy external source loading mechanism of a FileMap.
498557#[ derive( PartialEq , Eq , Clone ) ]
499558pub enum ExternalSource {
@@ -552,11 +611,13 @@ pub struct FileMap {
552611 pub lines : RefCell < Vec < BytePos > > ,
553612 /// Locations of multi-byte characters in the source code
554613 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 > > ,
555616}
556617
557618impl Encodable for FileMap {
558619 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| {
560621 s. emit_struct_field ( "name" , 0 , |s| self . name . encode ( s) ) ?;
561622 s. emit_struct_field ( "name_was_remapped" , 1 , |s| self . name_was_remapped . encode ( s) ) ?;
562623 s. emit_struct_field ( "src_hash" , 6 , |s| self . src_hash . encode ( s) ) ?;
@@ -610,6 +671,9 @@ impl Encodable for FileMap {
610671 } ) ?;
611672 s. emit_struct_field ( "multibyte_chars" , 5 , |s| {
612673 ( * 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)
613677 } )
614678 } )
615679 }
@@ -618,7 +682,7 @@ impl Encodable for FileMap {
618682impl Decodable for FileMap {
619683 fn decode < D : Decoder > ( d : & mut D ) -> Result < FileMap , D :: Error > {
620684
621- d. read_struct ( "FileMap" , 6 , |d| {
685+ d. read_struct ( "FileMap" , 8 , |d| {
622686 let name: String = d. read_struct_field ( "name" , 0 , |d| Decodable :: decode ( d) ) ?;
623687 let name_was_remapped: bool =
624688 d. read_struct_field ( "name_was_remapped" , 1 , |d| Decodable :: decode ( d) ) ?;
@@ -657,6 +721,8 @@ impl Decodable for FileMap {
657721 } ) ?;
658722 let multibyte_chars: Vec < MultiByteChar > =
659723 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) ) ?;
660726 Ok ( FileMap {
661727 name,
662728 name_was_remapped,
@@ -671,7 +737,8 @@ impl Decodable for FileMap {
671737 src_hash,
672738 external_src : RefCell :: new ( ExternalSource :: AbsentOk ) ,
673739 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)
675742 } )
676743 } )
677744 }
@@ -709,6 +776,7 @@ impl FileMap {
709776 end_pos : Pos :: from_usize ( end_pos) ,
710777 lines : RefCell :: new ( Vec :: new ( ) ) ,
711778 multibyte_chars : RefCell :: new ( Vec :: new ( ) ) ,
779+ non_narrow_chars : RefCell :: new ( Vec :: new ( ) ) ,
712780 }
713781 }
714782
@@ -798,6 +866,23 @@ impl FileMap {
798866 self . multibyte_chars . borrow_mut ( ) . push ( mbc) ;
799867 }
800868
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+
801886 pub fn is_real_file ( & self ) -> bool {
802887 !( self . name . starts_with ( "<" ) &&
803888 self . name . ends_with ( ">" ) )
@@ -944,7 +1029,9 @@ pub struct Loc {
9441029 /// The (1-based) line number
9451030 pub line : usize ,
9461031 /// 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 ,
9481035}
9491036
9501037/// A source code location used as the result of lookup_char_pos_adj
0 commit comments