@@ -21,10 +21,11 @@ pub use self::ExpnFormat::*;
21
21
22
22
use std:: cell:: { Cell , RefCell } ;
23
23
use std:: ops:: { Add , Sub } ;
24
- use std:: path:: Path ;
24
+ use std:: path:: { Path , PathBuf } ;
25
25
use std:: rc:: Rc ;
26
26
use std:: cmp;
27
27
28
+ use std:: env;
28
29
use std:: { fmt, fs} ;
29
30
use std:: io:: { self , Read } ;
30
31
@@ -508,6 +509,8 @@ pub struct FileMap {
508
509
/// originate from files has names between angle brackets by convention,
509
510
/// e.g. `<anon>`
510
511
pub name : FileName ,
512
+ /// The absolute path of the file that the source came from.
513
+ pub abs_path : Option < FileName > ,
511
514
/// The complete source code
512
515
pub src : Option < Rc < String > > ,
513
516
/// The start position of this source in the CodeMap
@@ -522,11 +525,12 @@ pub struct FileMap {
522
525
523
526
impl Encodable for FileMap {
524
527
fn encode < S : Encoder > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > {
525
- s. emit_struct ( "FileMap" , 5 , |s| {
528
+ s. emit_struct ( "FileMap" , 6 , |s| {
526
529
s. emit_struct_field ( "name" , 0 , |s| self . name . encode ( s) ) ?;
527
- s. emit_struct_field ( "start_pos" , 1 , |s| self . start_pos . encode ( s) ) ?;
528
- s. emit_struct_field ( "end_pos" , 2 , |s| self . end_pos . encode ( s) ) ?;
529
- s. emit_struct_field ( "lines" , 3 , |s| {
530
+ s. emit_struct_field ( "abs_path" , 1 , |s| self . abs_path . encode ( s) ) ?;
531
+ s. emit_struct_field ( "start_pos" , 2 , |s| self . start_pos . encode ( s) ) ?;
532
+ s. emit_struct_field ( "end_pos" , 3 , |s| self . end_pos . encode ( s) ) ?;
533
+ s. emit_struct_field ( "lines" , 4 , |s| {
530
534
let lines = self . lines . borrow ( ) ;
531
535
// store the length
532
536
s. emit_u32 ( lines. len ( ) as u32 ) ?;
@@ -572,7 +576,7 @@ impl Encodable for FileMap {
572
576
573
577
Ok ( ( ) )
574
578
} ) ?;
575
- s. emit_struct_field ( "multibyte_chars" , 4 , |s| {
579
+ s. emit_struct_field ( "multibyte_chars" , 5 , |s| {
576
580
( * self . multibyte_chars . borrow ( ) ) . encode ( s)
577
581
} )
578
582
} )
@@ -582,11 +586,13 @@ impl Encodable for FileMap {
582
586
impl Decodable for FileMap {
583
587
fn decode < D : Decoder > ( d : & mut D ) -> Result < FileMap , D :: Error > {
584
588
585
- d. read_struct ( "FileMap" , 5 , |d| {
589
+ d. read_struct ( "FileMap" , 6 , |d| {
586
590
let name: String = d. read_struct_field ( "name" , 0 , |d| Decodable :: decode ( d) ) ?;
587
- let start_pos: BytePos = d. read_struct_field ( "start_pos" , 1 , |d| Decodable :: decode ( d) ) ?;
588
- let end_pos: BytePos = d. read_struct_field ( "end_pos" , 2 , |d| Decodable :: decode ( d) ) ?;
589
- let lines: Vec < BytePos > = d. read_struct_field ( "lines" , 3 , |d| {
591
+ let abs_path: Option < String > =
592
+ d. read_struct_field ( "abs_path" , 1 , |d| Decodable :: decode ( d) ) ?;
593
+ let start_pos: BytePos = d. read_struct_field ( "start_pos" , 2 , |d| Decodable :: decode ( d) ) ?;
594
+ let end_pos: BytePos = d. read_struct_field ( "end_pos" , 3 , |d| Decodable :: decode ( d) ) ?;
595
+ let lines: Vec < BytePos > = d. read_struct_field ( "lines" , 4 , |d| {
590
596
let num_lines: u32 = Decodable :: decode ( d) ?;
591
597
let mut lines = Vec :: with_capacity ( num_lines as usize ) ;
592
598
@@ -615,9 +621,10 @@ impl Decodable for FileMap {
615
621
Ok ( lines)
616
622
} ) ?;
617
623
let multibyte_chars: Vec < MultiByteChar > =
618
- d. read_struct_field ( "multibyte_chars" , 4 , |d| Decodable :: decode ( d) ) ?;
624
+ d. read_struct_field ( "multibyte_chars" , 5 , |d| Decodable :: decode ( d) ) ?;
619
625
Ok ( FileMap {
620
626
name : name,
627
+ abs_path : abs_path,
621
628
start_pos : start_pos,
622
629
end_pos : end_pos,
623
630
src : None ,
@@ -703,6 +710,9 @@ pub trait FileLoader {
703
710
/// Query the existence of a file.
704
711
fn file_exists ( & self , path : & Path ) -> bool ;
705
712
713
+ /// Return an absolute path to a file, if possible.
714
+ fn abs_path ( & self , path : & Path ) -> Option < PathBuf > ;
715
+
706
716
/// Read the contents of an UTF-8 file into memory.
707
717
fn read_file ( & self , path : & Path ) -> io:: Result < String > ;
708
718
}
@@ -715,6 +725,16 @@ impl FileLoader for RealFileLoader {
715
725
fs:: metadata ( path) . is_ok ( )
716
726
}
717
727
728
+ fn abs_path ( & self , path : & Path ) -> Option < PathBuf > {
729
+ if path. is_absolute ( ) {
730
+ Some ( path. to_path_buf ( ) )
731
+ } else {
732
+ env:: current_dir ( )
733
+ . ok ( )
734
+ . map ( |cwd| cwd. join ( path) )
735
+ }
736
+ }
737
+
718
738
fn read_file ( & self , path : & Path ) -> io:: Result < String > {
719
739
let mut src = String :: new ( ) ;
720
740
fs:: File :: open ( path) ?. read_to_string ( & mut src) ?;
@@ -755,7 +775,8 @@ impl CodeMap {
755
775
756
776
pub fn load_file ( & self , path : & Path ) -> io:: Result < Rc < FileMap > > {
757
777
let src = self . file_loader . read_file ( path) ?;
758
- Ok ( self . new_filemap ( path. to_str ( ) . unwrap ( ) . to_string ( ) , src) )
778
+ let abs_path = self . file_loader . abs_path ( path) . map ( |p| p. to_str ( ) . unwrap ( ) . to_string ( ) ) ;
779
+ Ok ( self . new_filemap ( path. to_str ( ) . unwrap ( ) . to_string ( ) , abs_path, src) )
759
780
}
760
781
761
782
fn next_start_pos ( & self ) -> usize {
@@ -770,7 +791,8 @@ impl CodeMap {
770
791
771
792
/// Creates a new filemap without setting its line information. If you don't
772
793
/// intend to set the line information yourself, you should use new_filemap_and_lines.
773
- pub fn new_filemap ( & self , filename : FileName , mut src : String ) -> Rc < FileMap > {
794
+ pub fn new_filemap ( & self , filename : FileName , abs_path : Option < FileName > ,
795
+ mut src : String ) -> Rc < FileMap > {
774
796
let start_pos = self . next_start_pos ( ) ;
775
797
let mut files = self . files . borrow_mut ( ) ;
776
798
@@ -783,6 +805,7 @@ impl CodeMap {
783
805
784
806
let filemap = Rc :: new ( FileMap {
785
807
name : filename,
808
+ abs_path : abs_path,
786
809
src : Some ( Rc :: new ( src) ) ,
787
810
start_pos : Pos :: from_usize ( start_pos) ,
788
811
end_pos : Pos :: from_usize ( end_pos) ,
@@ -796,8 +819,11 @@ impl CodeMap {
796
819
}
797
820
798
821
/// Creates a new filemap and sets its line information.
799
- pub fn new_filemap_and_lines ( & self , filename : & str , src : & str ) -> Rc < FileMap > {
800
- let fm = self . new_filemap ( filename. to_string ( ) , src. to_owned ( ) ) ;
822
+ pub fn new_filemap_and_lines ( & self , filename : & str , abs_path : Option < & str > ,
823
+ src : & str ) -> Rc < FileMap > {
824
+ let fm = self . new_filemap ( filename. to_string ( ) ,
825
+ abs_path. map ( |s| s. to_owned ( ) ) ,
826
+ src. to_owned ( ) ) ;
801
827
let mut byte_pos: u32 = fm. start_pos . 0 ;
802
828
for line in src. lines ( ) {
803
829
// register the start of this line
@@ -816,6 +842,7 @@ impl CodeMap {
816
842
/// information for things inlined from other crates.
817
843
pub fn new_imported_filemap ( & self ,
818
844
filename : FileName ,
845
+ abs_path : Option < FileName > ,
819
846
source_len : usize ,
820
847
mut file_local_lines : Vec < BytePos > ,
821
848
mut file_local_multibyte_chars : Vec < MultiByteChar > )
@@ -836,6 +863,7 @@ impl CodeMap {
836
863
837
864
let filemap = Rc :: new ( FileMap {
838
865
name : filename,
866
+ abs_path : abs_path,
839
867
src : None ,
840
868
start_pos : start_pos,
841
869
end_pos : end_pos,
@@ -1422,6 +1450,7 @@ mod tests {
1422
1450
fn t1 ( ) {
1423
1451
let cm = CodeMap :: new ( ) ;
1424
1452
let fm = cm. new_filemap ( "blork.rs" . to_string ( ) ,
1453
+ None ,
1425
1454
"first line.\n second line" . to_string ( ) ) ;
1426
1455
fm. next_line ( BytePos ( 0 ) ) ;
1427
1456
// Test we can get lines with partial line info.
@@ -1438,6 +1467,7 @@ mod tests {
1438
1467
fn t2 ( ) {
1439
1468
let cm = CodeMap :: new ( ) ;
1440
1469
let fm = cm. new_filemap ( "blork.rs" . to_string ( ) ,
1470
+ None ,
1441
1471
"first line.\n second line" . to_string ( ) ) ;
1442
1472
// TESTING *REALLY* BROKEN BEHAVIOR:
1443
1473
fm. next_line ( BytePos ( 0 ) ) ;
@@ -1448,10 +1478,13 @@ mod tests {
1448
1478
fn init_code_map ( ) -> CodeMap {
1449
1479
let cm = CodeMap :: new ( ) ;
1450
1480
let fm1 = cm. new_filemap ( "blork.rs" . to_string ( ) ,
1481
+ None ,
1451
1482
"first line.\n second line" . to_string ( ) ) ;
1452
1483
let fm2 = cm. new_filemap ( "empty.rs" . to_string ( ) ,
1484
+ None ,
1453
1485
"" . to_string ( ) ) ;
1454
1486
let fm3 = cm. new_filemap ( "blork2.rs" . to_string ( ) ,
1487
+ None ,
1455
1488
"first line.\n second line" . to_string ( ) ) ;
1456
1489
1457
1490
fm1. next_line ( BytePos ( 0 ) ) ;
@@ -1514,8 +1547,10 @@ mod tests {
1514
1547
// € is a three byte utf8 char.
1515
1548
let fm1 =
1516
1549
cm. new_filemap ( "blork.rs" . to_string ( ) ,
1550
+ None ,
1517
1551
"fir€st €€€€ line.\n second line" . to_string ( ) ) ;
1518
1552
let fm2 = cm. new_filemap ( "blork2.rs" . to_string ( ) ,
1553
+ None ,
1519
1554
"first line€€.\n € second line" . to_string ( ) ) ;
1520
1555
1521
1556
fm1. next_line ( BytePos ( 0 ) ) ;
@@ -1583,7 +1618,7 @@ mod tests {
1583
1618
let cm = CodeMap :: new ( ) ;
1584
1619
let inputtext = "aaaaa\n bbbbBB\n CCC\n DDDDDddddd\n eee\n " ;
1585
1620
let selection = " \n ~~\n ~~~\n ~~~~~ \n \n " ;
1586
- cm. new_filemap_and_lines ( "blork.rs" , inputtext) ;
1621
+ cm. new_filemap_and_lines ( "blork.rs" , None , inputtext) ;
1587
1622
let span = span_from_selection ( inputtext, selection) ;
1588
1623
1589
1624
// check that we are extracting the text we thought we were extracting
0 commit comments