@@ -16,7 +16,7 @@ use url::Url;
16
16
17
17
use self :: hygiene:: MarkData ;
18
18
pub use self :: hygiene:: { Mark , SyntaxContext } ;
19
- use crate :: { rustc_data_structures:: stable_hasher:: StableHasher , sync:: Lrc } ;
19
+ use crate :: { cache :: CacheCell , rustc_data_structures:: stable_hasher:: StableHasher , sync:: Lrc } ;
20
20
21
21
mod analyze_source_file;
22
22
pub mod hygiene;
@@ -825,14 +825,10 @@ pub struct SourceFile {
825
825
pub start_pos : BytePos ,
826
826
/// The end position of this source in the `SourceMap`
827
827
pub end_pos : BytePos ,
828
- /// Locations of lines beginnings in the source code
829
- pub lines : Vec < BytePos > ,
830
- /// Locations of multi-byte characters in the source code
831
- pub multibyte_chars : Vec < MultiByteChar > ,
832
- /// Width of characters that are not narrow in the source code
833
- pub non_narrow_chars : Vec < NonNarrowChar > ,
834
828
/// A hash of the filename, used for speeding up the incr. comp. hashing.
835
829
pub name_hash : u128 ,
830
+
831
+ lazy : CacheCell < SourceFileAnalysis > ,
836
832
}
837
833
838
834
#[ cfg_attr(
@@ -849,8 +845,6 @@ pub struct SourceFileAnalysis {
849
845
pub multibyte_chars : Vec < MultiByteChar > ,
850
846
/// Width of characters that are not narrow in the source code
851
847
pub non_narrow_chars : Vec < NonNarrowChar > ,
852
- /// A hash of the filename, used for speeding up the incr. comp. hashing.
853
- pub name_hash : u128 ,
854
848
}
855
849
856
850
impl fmt:: Debug for SourceFile {
@@ -904,9 +898,6 @@ impl SourceFile {
904
898
} ;
905
899
let end_pos = start_pos. to_usize ( ) + src. len ( ) ;
906
900
907
- let ( lines, multibyte_chars, non_narrow_chars) =
908
- analyze_source_file:: analyze_source_file ( & src[ ..] , start_pos) ;
909
-
910
901
SourceFile {
911
902
name,
912
903
name_was_remapped,
@@ -916,17 +907,16 @@ impl SourceFile {
916
907
src_hash,
917
908
start_pos,
918
909
end_pos : SmallPos :: from_usize ( end_pos) ,
919
- lines,
920
- multibyte_chars,
921
- non_narrow_chars,
922
910
name_hash,
911
+ lazy : CacheCell :: new ( ) ,
923
912
}
924
913
}
925
914
926
915
/// Return the BytePos of the beginning of the current line.
927
916
pub fn line_begin_pos ( & self , pos : BytePos ) -> BytePos {
928
917
let line_index = self . lookup_line ( pos) . unwrap ( ) ;
929
- self . lines [ line_index]
918
+ let analysis = self . analyze ( ) ;
919
+ analysis. lines [ line_index]
930
920
}
931
921
932
922
/// Get a line from the list of pre-computed line-beginnings.
@@ -944,7 +934,8 @@ impl SourceFile {
944
934
}
945
935
946
936
let begin = {
947
- let line = self . lines . get ( line_number) ?;
937
+ let analysis = self . analyze ( ) ;
938
+ let line = analysis. lines . get ( line_number) ?;
948
939
let begin: BytePos = * line - self . start_pos ;
949
940
begin. to_usize ( )
950
941
} ;
@@ -961,20 +952,22 @@ impl SourceFile {
961
952
}
962
953
963
954
pub fn count_lines ( & self ) -> usize {
964
- self . lines . len ( )
955
+ let analysis = self . analyze ( ) ;
956
+ analysis. lines . len ( )
965
957
}
966
958
967
959
/// Find the line containing the given position. The return value is the
968
960
/// index into the `lines` array of this SourceFile, not the 1-based line
969
961
/// number. If the `source_file` is empty or the position is located before
970
962
/// the first line, `None` is returned.
971
963
pub fn lookup_line ( & self , pos : BytePos ) -> Option < usize > {
972
- if self . lines . is_empty ( ) {
964
+ let analysis = self . analyze ( ) ;
965
+ if analysis. lines . is_empty ( ) {
973
966
return None ;
974
967
}
975
968
976
- let line_index = lookup_line ( & self . lines [ .. ] , pos) ;
977
- assert ! ( line_index < self . lines. len( ) as isize ) ;
969
+ let line_index = lookup_line ( & analysis . lines , pos) ;
970
+ assert ! ( line_index < analysis . lines. len( ) as isize ) ;
978
971
if line_index >= 0 {
979
972
Some ( line_index as usize )
980
973
} else {
@@ -987,18 +980,32 @@ impl SourceFile {
987
980
return ( self . start_pos , self . end_pos ) ;
988
981
}
989
982
990
- assert ! ( line_index < self . lines. len( ) ) ;
991
- if line_index == ( self . lines . len ( ) - 1 ) {
992
- ( self . lines [ line_index] , self . end_pos )
983
+ let analysis = self . analyze ( ) ;
984
+
985
+ assert ! ( line_index < analysis. lines. len( ) ) ;
986
+ if line_index == ( analysis. lines . len ( ) - 1 ) {
987
+ ( analysis. lines [ line_index] , self . end_pos )
993
988
} else {
994
- ( self . lines [ line_index] , self . lines [ line_index + 1 ] )
989
+ ( analysis . lines [ line_index] , analysis . lines [ line_index + 1 ] )
995
990
}
996
991
}
997
992
998
993
#[ inline]
999
994
pub fn contains ( & self , byte_pos : BytePos ) -> bool {
1000
995
byte_pos >= self . start_pos && byte_pos <= self . end_pos
1001
996
}
997
+
998
+ pub fn analyze ( & self ) -> & SourceFileAnalysis {
999
+ self . lazy . get_or_init ( || {
1000
+ let ( lines, multibyte_chars, non_narrow_chars) =
1001
+ analyze_source_file:: analyze_source_file ( & self . src [ ..] , self . start_pos ) ;
1002
+ SourceFileAnalysis {
1003
+ lines,
1004
+ multibyte_chars,
1005
+ non_narrow_chars,
1006
+ }
1007
+ } )
1008
+ }
1002
1009
}
1003
1010
1004
1011
/// Remove utf-8 BOM if any.
0 commit comments