Skip to content

Commit 07d4f77

Browse files
committed
syntax: abstract over the file loading mechanism.
1 parent 0d50b04 commit 07d4f77

File tree

3 files changed

+58
-15
lines changed

3 files changed

+58
-15
lines changed

src/libsyntax/codemap.rs

+46-2
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ pub use self::MacroFormat::*;
2121

2222
use std::cell::RefCell;
2323
use std::ops::{Add, Sub};
24+
use std::path::Path;
2425
use std::rc::Rc;
2526

26-
use std::fmt;
27+
use std::{fmt, fs};
28+
use std::io::{self, Read};
2729

2830
use serialize::{Encodable, Decodable, Encoder, Decoder};
2931

@@ -527,24 +529,66 @@ impl FileMap {
527529
}
528530
}
529531

532+
/// An abstraction over the fs operations used by the Parser.
533+
pub trait FileLoader {
534+
/// Query the existence of a file.
535+
fn file_exists(&self, path: &Path) -> bool;
536+
537+
/// Read the contents of an UTF-8 file into memory.
538+
fn read_file(&self, path: &Path) -> io::Result<String>;
539+
}
540+
541+
/// A FileLoader that uses std::fs to load real files.
542+
pub struct RealFileLoader;
543+
544+
impl FileLoader for RealFileLoader {
545+
fn file_exists(&self, path: &Path) -> bool {
546+
fs::metadata(path).is_ok()
547+
}
548+
549+
fn read_file(&self, path: &Path) -> io::Result<String> {
550+
let mut src = String::new();
551+
try!(try!(fs::File::open(path)).read_to_string(&mut src));
552+
Ok(src)
553+
}
554+
}
530555

531556
// _____________________________________________________________________________
532557
// CodeMap
533558
//
534559

535560
pub struct CodeMap {
536561
pub files: RefCell<Vec<Rc<FileMap>>>,
537-
expansions: RefCell<Vec<ExpnInfo>>
562+
expansions: RefCell<Vec<ExpnInfo>>,
563+
file_loader: Box<FileLoader>
538564
}
539565

540566
impl CodeMap {
541567
pub fn new() -> CodeMap {
542568
CodeMap {
543569
files: RefCell::new(Vec::new()),
544570
expansions: RefCell::new(Vec::new()),
571+
file_loader: Box::new(RealFileLoader)
572+
}
573+
}
574+
575+
pub fn with_file_loader(file_loader: Box<FileLoader>) -> CodeMap {
576+
CodeMap {
577+
files: RefCell::new(Vec::new()),
578+
expansions: RefCell::new(Vec::new()),
579+
file_loader: file_loader
545580
}
546581
}
547582

583+
pub fn file_exists(&self, path: &Path) -> bool {
584+
self.file_loader.file_exists(path)
585+
}
586+
587+
pub fn load_file(&self, path: &Path) -> io::Result<Rc<FileMap>> {
588+
let src = try!(self.file_loader.read_file(path));
589+
Ok(self.new_filemap(path.to_str().unwrap().to_string(), src))
590+
}
591+
548592
pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc<FileMap> {
549593
let mut files = self.files.borrow_mut();
550594
let start_pos = match files.last() {

src/libsyntax/parse/mod.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use ptr::P;
1919
use str::char_at;
2020

2121
use std::cell::RefCell;
22-
use std::fs::File;
2322
use std::io::Read;
2423
use std::iter;
2524
use std::path::{Path, PathBuf};
@@ -220,17 +219,18 @@ pub fn new_parser_from_tts<'a>(sess: &'a ParseSess,
220219

221220
/// Given a session and a path and an optional span (for error reporting),
222221
/// add the path to the session's codemap and return the new filemap.
223-
pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
224-
-> Rc<FileMap> {
225-
let mut contents = String::new();
226-
if let Err(e) = File::open(path).and_then(|mut f| f.read_to_string(&mut contents)) {
227-
let msg = format!("couldn't read {:?}: {}", path.display(), e);
228-
match spanopt {
229-
Some(sp) => panic!(sess.span_diagnostic.span_fatal(sp, &msg)),
230-
None => sess.span_diagnostic.handler().fatal(&msg)
222+
fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
223+
-> Rc<FileMap> {
224+
match sess.codemap().load_file(path) {
225+
Ok(filemap) => filemap,
226+
Err(e) => {
227+
let msg = format!("couldn't read {:?}: {}", path.display(), e);
228+
match spanopt {
229+
Some(sp) => panic!(sess.span_diagnostic.span_fatal(sp, &msg)),
230+
None => sess.span_diagnostic.handler().fatal(&msg)
231+
}
231232
}
232233
}
233-
sess.codemap().new_filemap(path.to_str().unwrap().to_string(), contents)
234234
}
235235

236236
/// Given a filemap, produce a sequence of token-trees

src/libsyntax/parse/parser.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ use parse::PResult;
7979
use diagnostic::FatalError;
8080

8181
use std::collections::HashSet;
82-
use std::fs;
8382
use std::io::prelude::*;
8483
use std::mem;
8584
use std::path::{Path, PathBuf};
@@ -4851,8 +4850,8 @@ impl<'a> Parser<'a> {
48514850
let secondary_path_str = format!("{}/mod.rs", mod_name);
48524851
let default_path = dir_path.join(&default_path_str[..]);
48534852
let secondary_path = dir_path.join(&secondary_path_str[..]);
4854-
let default_exists = fs::metadata(&default_path).is_ok();
4855-
let secondary_exists = fs::metadata(&secondary_path).is_ok();
4853+
let default_exists = self.sess.codemap().file_exists(&default_path);
4854+
let secondary_exists = self.sess.codemap().file_exists(&secondary_path);
48564855

48574856
if !self.owns_directory {
48584857
self.span_err(id_sp,

0 commit comments

Comments
 (0)