syntax: abstract over the file loading mechanism.
This commit is contained in:
parent
0d50b043f7
commit
07d4f77790
3 changed files with 58 additions and 15 deletions
|
@ -21,9 +21,11 @@ pub use self::MacroFormat::*;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ops::{Add, Sub};
|
use std::ops::{Add, Sub};
|
||||||
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use std::fmt;
|
use std::{fmt, fs};
|
||||||
|
use std::io::{self, Read};
|
||||||
|
|
||||||
use serialize::{Encodable, Decodable, Encoder, Decoder};
|
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<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
|
// CodeMap
|
||||||
|
@ -534,7 +559,8 @@ impl FileMap {
|
||||||
|
|
||||||
pub struct CodeMap {
|
pub struct CodeMap {
|
||||||
pub files: RefCell<Vec<Rc<FileMap>>>,
|
pub files: RefCell<Vec<Rc<FileMap>>>,
|
||||||
expansions: RefCell<Vec<ExpnInfo>>
|
expansions: RefCell<Vec<ExpnInfo>>,
|
||||||
|
file_loader: Box<FileLoader>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CodeMap {
|
impl CodeMap {
|
||||||
|
@ -542,9 +568,27 @@ impl CodeMap {
|
||||||
CodeMap {
|
CodeMap {
|
||||||
files: RefCell::new(Vec::new()),
|
files: RefCell::new(Vec::new()),
|
||||||
expansions: 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> {
|
pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc<FileMap> {
|
||||||
let mut files = self.files.borrow_mut();
|
let mut files = self.files.borrow_mut();
|
||||||
let start_pos = match files.last() {
|
let start_pos = match files.last() {
|
||||||
|
|
|
@ -19,7 +19,6 @@ use ptr::P;
|
||||||
use str::char_at;
|
use str::char_at;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::{Path, PathBuf};
|
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),
|
/// 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.
|
/// 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>)
|
fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
|
||||||
-> Rc<FileMap> {
|
-> Rc<FileMap> {
|
||||||
let mut contents = String::new();
|
match sess.codemap().load_file(path) {
|
||||||
if let Err(e) = File::open(path).and_then(|mut f| f.read_to_string(&mut contents)) {
|
Ok(filemap) => filemap,
|
||||||
|
Err(e) => {
|
||||||
let msg = format!("couldn't read {:?}: {}", path.display(), e);
|
let msg = format!("couldn't read {:?}: {}", path.display(), e);
|
||||||
match spanopt {
|
match spanopt {
|
||||||
Some(sp) => panic!(sess.span_diagnostic.span_fatal(sp, &msg)),
|
Some(sp) => panic!(sess.span_diagnostic.span_fatal(sp, &msg)),
|
||||||
None => sess.span_diagnostic.handler().fatal(&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
|
/// Given a filemap, produce a sequence of token-trees
|
||||||
|
|
|
@ -79,7 +79,6 @@ use parse::PResult;
|
||||||
use diagnostic::FatalError;
|
use diagnostic::FatalError;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fs;
|
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
@ -4851,8 +4850,8 @@ impl<'a> Parser<'a> {
|
||||||
let secondary_path_str = format!("{}/mod.rs", mod_name);
|
let secondary_path_str = format!("{}/mod.rs", mod_name);
|
||||||
let default_path = dir_path.join(&default_path_str[..]);
|
let default_path = dir_path.join(&default_path_str[..]);
|
||||||
let secondary_path = dir_path.join(&secondary_path_str[..]);
|
let secondary_path = dir_path.join(&secondary_path_str[..]);
|
||||||
let default_exists = fs::metadata(&default_path).is_ok();
|
let default_exists = self.sess.codemap().file_exists(&default_path);
|
||||||
let secondary_exists = fs::metadata(&secondary_path).is_ok();
|
let secondary_exists = self.sess.codemap().file_exists(&secondary_path);
|
||||||
|
|
||||||
if !self.owns_directory {
|
if !self.owns_directory {
|
||||||
self.span_err(id_sp,
|
self.span_err(id_sp,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue