diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index c692babfacc4..b2a366ec5beb 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -21,9 +21,11 @@ pub use self::MacroFormat::*; use std::cell::RefCell; use std::ops::{Add, Sub}; +use std::path::Path; use std::rc::Rc; -use std::fmt; +use std::{fmt, fs}; +use std::io::{self, Read}; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -527,6 +529,29 @@ impl FileMap { } } +/// An abstraction over the fs operations used by the Parser. +pub trait FileLoader { + /// Query the existence of a file. + fn file_exists(&self, path: &Path) -> bool; + + /// Read the contents of an UTF-8 file into memory. + fn read_file(&self, path: &Path) -> io::Result; +} + +/// A FileLoader that uses std::fs to load real files. +pub struct RealFileLoader; + +impl FileLoader for RealFileLoader { + fn file_exists(&self, path: &Path) -> bool { + fs::metadata(path).is_ok() + } + + fn read_file(&self, path: &Path) -> io::Result { + let mut src = String::new(); + try!(try!(fs::File::open(path)).read_to_string(&mut src)); + Ok(src) + } +} // _____________________________________________________________________________ // CodeMap @@ -534,7 +559,8 @@ impl FileMap { pub struct CodeMap { pub files: RefCell>>, - expansions: RefCell> + expansions: RefCell>, + file_loader: Box } impl CodeMap { @@ -542,9 +568,27 @@ impl CodeMap { CodeMap { files: RefCell::new(Vec::new()), expansions: RefCell::new(Vec::new()), + file_loader: Box::new(RealFileLoader) } } + pub fn with_file_loader(file_loader: Box) -> CodeMap { + CodeMap { + files: RefCell::new(Vec::new()), + expansions: RefCell::new(Vec::new()), + file_loader: file_loader + } + } + + pub fn file_exists(&self, path: &Path) -> bool { + self.file_loader.file_exists(path) + } + + pub fn load_file(&self, path: &Path) -> io::Result> { + let src = try!(self.file_loader.read_file(path)); + Ok(self.new_filemap(path.to_str().unwrap().to_string(), src)) + } + pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc { let mut files = self.files.borrow_mut(); let start_pos = match files.last() { diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 3d27363d6ff2..68574560533f 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -19,7 +19,6 @@ use ptr::P; use str::char_at; use std::cell::RefCell; -use std::fs::File; use std::io::Read; use std::iter; use std::path::{Path, PathBuf}; @@ -220,17 +219,18 @@ pub fn new_parser_from_tts<'a>(sess: &'a ParseSess, /// Given a session and a path and an optional span (for error reporting), /// add the path to the session's codemap and return the new filemap. -pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option) - -> Rc { - let mut contents = String::new(); - if let Err(e) = File::open(path).and_then(|mut f| f.read_to_string(&mut contents)) { - let msg = format!("couldn't read {:?}: {}", path.display(), e); - match spanopt { - Some(sp) => panic!(sess.span_diagnostic.span_fatal(sp, &msg)), - None => sess.span_diagnostic.handler().fatal(&msg) +fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option) + -> Rc { + match sess.codemap().load_file(path) { + Ok(filemap) => filemap, + Err(e) => { + let msg = format!("couldn't read {:?}: {}", path.display(), e); + match spanopt { + Some(sp) => panic!(sess.span_diagnostic.span_fatal(sp, &msg)), + None => sess.span_diagnostic.handler().fatal(&msg) + } } } - sess.codemap().new_filemap(path.to_str().unwrap().to_string(), contents) } /// Given a filemap, produce a sequence of token-trees diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d890708d1234..c9d06423a109 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -79,7 +79,6 @@ use parse::PResult; use diagnostic::FatalError; use std::collections::HashSet; -use std::fs; use std::io::prelude::*; use std::mem; use std::path::{Path, PathBuf}; @@ -4851,8 +4850,8 @@ impl<'a> Parser<'a> { let secondary_path_str = format!("{}/mod.rs", mod_name); let default_path = dir_path.join(&default_path_str[..]); let secondary_path = dir_path.join(&secondary_path_str[..]); - let default_exists = fs::metadata(&default_path).is_ok(); - let secondary_exists = fs::metadata(&secondary_path).is_ok(); + let default_exists = self.sess.codemap().file_exists(&default_path); + let secondary_exists = self.sess.codemap().file_exists(&secondary_path); if !self.owns_directory { self.span_err(id_sp,