@@ -16,6 +16,7 @@ use std::io;
1616pub use std:: path:: { Path , PathBuf } ;
1717use std:: sync:: Arc ;
1818
19+ #[ derive( Debug ) ]
1920struct FileId {
2021 name : FilePath ,
2122 /// Hash value of `self.name`.
@@ -24,11 +25,9 @@ struct FileId {
2425
2526impl FileId {
2627 fn new ( name : & Path ) -> FileId {
27- let hash = hash ( name) ;
28- Self {
29- name : FilePath :: new ( name) ,
30- hash,
31- }
28+ let name = FilePath :: new ( name) ;
29+ let hash = hash ( & name) ;
30+ Self { name, hash }
3231 }
3332}
3433
@@ -58,7 +57,10 @@ struct UniqueSource {
5857impl fmt:: Debug for UniqueSource {
5958 /// Custom implementation to avoid large contents strings.
6059 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
61- write ! ( f, "Source {{file_name: {:?}}}" , self . file_name( ) )
60+ f. debug_struct ( stringify ! ( UniqueSource ) )
61+ . field ( stringify ! ( file_id) , & self . file_id )
62+ . field ( stringify ! ( contents) , & "..." )
63+ . finish ( )
6264 }
6365}
6466
@@ -102,13 +104,11 @@ impl UniqueSource {
102104/// A thread-safe reference to a source file.
103105/// Multiple objects of this type can refer to the same source.
104106#[ derive( Debug , Clone ) ]
105- pub struct Source {
106- source : Arc < UniqueSource > ,
107- }
107+ pub struct Source ( Arc < UniqueSource > ) ;
108108
109109impl PartialEq for Source {
110110 fn eq ( & self , other : & Self ) -> bool {
111- self . source . file_id == other. source . file_id
111+ self . 0 . file_id == other. 0 . file_id
112112 }
113113}
114114
@@ -120,15 +120,15 @@ impl PartialOrd for Source {
120120
121121impl Ord for Source {
122122 fn cmp ( & self , other : & Source ) -> std:: cmp:: Ordering {
123- self . source . file_name ( ) . cmp ( other. file_name ( ) )
123+ self . file_name ( ) . cmp ( other. file_name ( ) )
124124 }
125125}
126126
127127impl Eq for Source { }
128128
129129impl Hash for Source {
130130 fn hash < H : Hasher > ( & self , hasher : & mut H ) {
131- hasher. write_u64 ( self . source . file_id . hash )
131+ hasher. write_u64 ( self . 0 . file_id . hash )
132132 }
133133}
134134
@@ -138,34 +138,28 @@ impl Source {
138138 /// Note: For differing values of `contents`, the value of `file_name`
139139 /// *must* differ as well.
140140 pub fn inline ( file_name : & Path , contents : & str ) -> Source {
141- Source {
142- source : Arc :: new ( UniqueSource :: inline ( file_name, contents) ) ,
143- }
141+ Source ( Arc :: new ( UniqueSource :: inline ( file_name, contents) ) )
144142 }
145143
146144 pub fn from_latin1_file ( file_name : & Path ) -> io:: Result < Source > {
147- Ok ( Source {
148- source : Arc :: new ( UniqueSource :: from_latin1_file ( file_name) ?) ,
149- } )
145+ Ok ( Source ( Arc :: new ( UniqueSource :: from_latin1_file ( file_name) ?) ) )
150146 }
151147
152148 #[ cfg( test) ]
153149 pub fn from_contents ( file_name : & Path , contents : Contents ) -> Source {
154- Source {
155- source : Arc :: new ( UniqueSource :: from_contents ( file_name, contents) ) ,
156- }
150+ Source ( Arc :: new ( UniqueSource :: from_contents ( file_name, contents) ) )
157151 }
158152
159153 pub fn contents ( & self ) -> RwLockReadGuard < ' _ , Contents > {
160- self . source . contents ( )
154+ self . 0 . contents ( )
161155 }
162156
163157 pub fn file_name ( & self ) -> & Path {
164- self . source . file_name ( )
158+ self . 0 . file_name ( )
165159 }
166160
167161 pub ( crate ) fn file_path ( & self ) -> & FilePath {
168- self . source . file_path ( )
162+ self . 0 . file_path ( )
169163 }
170164
171165 pub fn pos ( & self , start : Position , end : Position ) -> SrcPos {
@@ -176,7 +170,7 @@ impl Source {
176170 }
177171
178172 pub fn change ( & self , range : Option < & Range > , content : & str ) {
179- let mut contents = self . source . contents . write ( ) ;
173+ let mut contents = self . 0 . contents . write ( ) ;
180174 if let Some ( range) = range {
181175 contents. change ( range, content) ;
182176 } else {
@@ -528,36 +522,44 @@ impl<T: HasSrcPos> HasSource for T {
528522 }
529523}
530524
531- /// A wrapper arround a PathBuf that ensures the path is canoninicalized
532- # [ derive ( PartialEq , Eq , Hash , Clone ) ]
533- pub ( crate ) struct FilePath {
534- path : PathBuf ,
535- }
525+ /// A wrapper around a PathBuf that ensures the path is absolute and simplified.
526+ ///
527+ /// This struct can be used similar to a [PathBuf], i.e., dereferencing it will return a [Path]
528+ # [ derive ( PartialEq , Eq , Hash , Clone , Debug ) ]
529+ pub ( crate ) struct FilePath ( PathBuf ) ;
536530
537531impl std:: ops:: Deref for FilePath {
538532 type Target = Path ;
539533 fn deref ( & self ) -> & Self :: Target {
540- & self . path
534+ & self . 0
541535 }
542536}
543537
544538impl FilePath {
545539 pub fn new ( path : & Path ) -> Self {
546- let path = match dunce:: canonicalize ( path) {
547- Ok ( path) => path,
540+ // In tests, when using inline files, paths are used that do not point to an existing file.
541+ // In this case, we simply want to preserve the name without changing it.
542+ if cfg ! ( test) && !path. exists ( ) {
543+ return Self ( path. to_owned ( ) ) ;
544+ }
545+ // It would also be possible to use dunce::canonicalize here instead of path::absolute
546+ // and dunce::simplify, but dunce::canonicalize resolves symlinks
547+ // which we don't want (see issue #327)
548+ let path = match std:: path:: absolute ( path) {
549+ // dunce::simplified converts UNC paths to regular paths.
550+ // UNC paths have caused issues when a file was mounted on a network drive.
551+ // Related issue: #115
552+ Ok ( path) => dunce:: simplified ( & path) . to_owned ( ) ,
548553 Err ( err) => {
549- if !cfg ! ( test) {
550- eprintln ! (
551- "Could not create absolute path {}: {:?}" ,
552- path. to_string_lossy( ) ,
553- err
554- ) ;
555- }
554+ eprintln ! (
555+ "Could not create absolute path {}: {:?}" ,
556+ path. to_string_lossy( ) ,
557+ err
558+ ) ;
556559 path. to_owned ( )
557560 }
558561 } ;
559-
560- Self { path }
562+ Self ( path)
561563 }
562564}
563565
0 commit comments