Skip to content

Commit

Permalink
syntax: abstract over the file loading mechanism.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed May 13, 2015
1 parent 0d50b04 commit 07d4f77
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 15 deletions.
48 changes: 46 additions & 2 deletions src/libsyntax/codemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -527,24 +529,66 @@ 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<String>;
}

/// 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<String> {
let mut src = String::new();
try!(try!(fs::File::open(path)).read_to_string(&mut src));
Ok(src)
}
}

// _____________________________________________________________________________
// CodeMap
//

pub struct CodeMap {
pub files: RefCell<Vec<Rc<FileMap>>>,
expansions: RefCell<Vec<ExpnInfo>>
expansions: RefCell<Vec<ExpnInfo>>,
file_loader: Box<FileLoader>
}

impl CodeMap {
pub fn new() -> 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<FileLoader>) -> 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<Rc<FileMap>> {
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<FileMap> {
let mut files = self.files.borrow_mut();
let start_pos = match files.last() {
Expand Down
20 changes: 10 additions & 10 deletions src/libsyntax/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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<Span>)
-> Rc<FileMap> {
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<Span>)
-> Rc<FileMap> {
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
Expand Down
5 changes: 2 additions & 3 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 07d4f77

Please sign in to comment.