// containing the information we need.
let codemap::FileMap {
name,
+ abs_path,
start_pos,
end_pos,
lines,
}
let local_version = local_codemap.new_imported_filemap(name,
+ abs_path,
source_length,
lines,
multibyte_chars);
// are incompatible with spans over other filemaps.
let filemap = self.sess
.codemap()
- .new_filemap(String::from("<anon-dxr>"), self.snippet(span));
+ .new_filemap(String::from("<anon-dxr>"), None, self.snippet(span));
let s = self.sess;
lexer::StringReader::new(s.diagnostic(), filemap)
}
}
let loc = span_start(ccx, scope_data.span);
- let file_metadata = file_metadata(ccx, &loc.file.name);
scopes[scope] = unsafe {
+ let file_metadata = file_metadata(ccx, &loc.file.name, &loc.file.abs_path);
llvm::LLVMDIBuilderCreateLexicalBlock(
DIB(ccx),
parent_scope,
{
// Create a new lexical scope and push it onto the stack
let loc = span_start(cx, scope_span);
- let file_metadata = file_metadata(cx, &loc.file.name);
+ let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path);
let parent_scope = scope_stack.last().unwrap().scope_metadata;
let scope_metadata = unsafe {
if need_new_scope {
// Create a new lexical scope and push it onto the stack
let loc = span_start(cx, pat.span);
- let file_metadata = file_metadata(cx, &loc.file.name);
+ let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path);
let parent_scope = scope_stack.last().unwrap().scope_metadata;
let scope_metadata = unsafe {
assert!(member_descriptions.len() == member_llvm_types.len());
let loc = span_start(cx, span);
- let file_metadata = file_metadata(cx, &loc.file.name);
+ let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path);
let metadata = composite_type_metadata(cx,
slice_llvm_type,
metadata
}
-pub fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
+pub fn file_metadata(cx: &CrateContext, path: &str, full_path: &Option<String>) -> DIFile {
// FIXME (#9639): This needs to handle non-utf8 paths
let work_dir = cx.sess().working_dir.to_str().unwrap();
let file_name =
- if full_path.starts_with(work_dir) {
- &full_path[work_dir.len() + 1..full_path.len()]
- } else {
- full_path
- };
+ full_path.as_ref().map(|p| p.as_str()).unwrap_or_else(|| {
+ if path.starts_with(work_dir) {
+ &path[work_dir.len() + 1..path.len()]
+ } else {
+ path
+ }
+ });
- file_metadata_(cx, full_path, file_name, &work_dir)
+ file_metadata_(cx, path, file_name, &work_dir)
}
pub fn unknown_file_metadata(cx: &CrateContext) -> DIFile {
let (file_metadata, line_number) = if span != codemap::DUMMY_SP {
let loc = span_start(cx, span);
- (file_metadata(cx, &loc.file.name), loc.line as c_uint)
+ (file_metadata(cx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
} else {
(NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
};
}
let loc = span_start(cx, span);
- let file_metadata = file_metadata(cx, &loc.file.name);
+ let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path);
let function_type_metadata = unsafe {
let fn_signature = get_function_signature(cx, sig, abi);
span: Span) {
let cx: &CrateContext = bcx.ccx();
- let filename = span_start(cx, span).file.name.clone();
- let file_metadata = file_metadata(cx, &filename[..]);
+ let file = span_start(cx, span).file;
+ let filename = file.name.clone();
+ let file_metadata = file_metadata(cx, &filename[..], &file.abs_path);
let loc = span_start(cx, span);
let type_metadata = type_metadata(cx, variable_type, span);
let span = ccx.tcx().map.def_id_span(def_id, DUMMY_SP);
let (file, line) = if span != DUMMY_SP {
let loc = span_start(ccx, span);
- (file_metadata(ccx, &loc.file.name), loc.line as c_uint)
+ (file_metadata(ccx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
} else {
(NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
};
pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>) -> String {
debug!("highlighting: ================\n{}\n==============", src);
let sess = parse::ParseSess::new();
- let fm = sess.codemap().new_filemap("<stdin>".to_string(), src.to_string());
+ let fm = sess.codemap().new_filemap("<stdin>".to_string(), None, src.to_string());
let mut out = Vec::new();
write_header(class, id, &mut out).unwrap();
/// an enclosing `<pre>` block.
pub fn render_inner_with_highlighting(src: &str) -> io::Result<String> {
let sess = parse::ParseSess::new();
- let fm = sess.codemap().new_filemap("<stdin>".to_string(), src.to_string());
+ let fm = sess.codemap().new_filemap("<stdin>".to_string(), None, src.to_string());
let mut out = Vec::new();
let mut classifier = Classifier::new(lexer::StringReader::new(&sess.span_diagnostic, fm),
use std::cell::{Cell, RefCell};
use std::ops::{Add, Sub};
-use std::path::Path;
+use std::path::{Path,PathBuf};
use std::rc::Rc;
use std::cmp;
+use std::env;
use std::{fmt, fs};
use std::io::{self, Read};
/// originate from files has names between angle brackets by convention,
/// e.g. `<anon>`
pub name: FileName,
+ /// The absolute path of the file that the source came from.
+ pub abs_path: Option<FileName>,
/// The complete source code
pub src: Option<Rc<String>>,
/// The start position of this source in the CodeMap
impl Encodable for FileMap {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_struct("FileMap", 5, |s| {
+ s.emit_struct("FileMap", 6, |s| {
s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
- s.emit_struct_field("start_pos", 1, |s| self.start_pos.encode(s))?;
- s.emit_struct_field("end_pos", 2, |s| self.end_pos.encode(s))?;
- s.emit_struct_field("lines", 3, |s| {
+ s.emit_struct_field("abs_path", 1, |s| self.abs_path.encode(s))?;
+ s.emit_struct_field("start_pos", 2, |s| self.start_pos.encode(s))?;
+ s.emit_struct_field("end_pos", 3, |s| self.end_pos.encode(s))?;
+ s.emit_struct_field("lines", 4, |s| {
let lines = self.lines.borrow();
// store the length
s.emit_u32(lines.len() as u32)?;
Ok(())
})?;
- s.emit_struct_field("multibyte_chars", 4, |s| {
+ s.emit_struct_field("multibyte_chars", 5, |s| {
(*self.multibyte_chars.borrow()).encode(s)
})
})
impl Decodable for FileMap {
fn decode<D: Decoder>(d: &mut D) -> Result<FileMap, D::Error> {
- d.read_struct("FileMap", 5, |d| {
+ d.read_struct("FileMap", 6, |d| {
let name: String = d.read_struct_field("name", 0, |d| Decodable::decode(d))?;
- let start_pos: BytePos = d.read_struct_field("start_pos", 1, |d| Decodable::decode(d))?;
- let end_pos: BytePos = d.read_struct_field("end_pos", 2, |d| Decodable::decode(d))?;
- let lines: Vec<BytePos> = d.read_struct_field("lines", 3, |d| {
+ let abs_path: Option<String> =
+ d.read_struct_field("abs_path", 1, |d| Decodable::decode(d))?;
+ let start_pos: BytePos = d.read_struct_field("start_pos", 2, |d| Decodable::decode(d))?;
+ let end_pos: BytePos = d.read_struct_field("end_pos", 3, |d| Decodable::decode(d))?;
+ let lines: Vec<BytePos> = d.read_struct_field("lines", 4, |d| {
let num_lines: u32 = Decodable::decode(d)?;
let mut lines = Vec::with_capacity(num_lines as usize);
Ok(lines)
})?;
let multibyte_chars: Vec<MultiByteChar> =
- d.read_struct_field("multibyte_chars", 4, |d| Decodable::decode(d))?;
+ d.read_struct_field("multibyte_chars", 5, |d| Decodable::decode(d))?;
Ok(FileMap {
name: name,
+ abs_path: abs_path,
start_pos: start_pos,
end_pos: end_pos,
src: None,
/// Query the existence of a file.
fn file_exists(&self, path: &Path) -> bool;
+ /// Return an absolute path to a file, if possible.
+ fn abs_path(&self, path: &Path) -> Option<PathBuf>;
+
/// Read the contents of an UTF-8 file into memory.
fn read_file(&self, path: &Path) -> io::Result<String>;
}
fs::metadata(path).is_ok()
}
+ fn abs_path(&self, path: &Path) -> Option<PathBuf> {
+ if path.is_absolute() {
+ Some(path.to_path_buf())
+ } else {
+ env::current_dir()
+ .ok()
+ .map(|cwd| cwd.join(path))
+ }
+ }
+
fn read_file(&self, path: &Path) -> io::Result<String> {
let mut src = String::new();
fs::File::open(path)?.read_to_string(&mut src)?;
pub fn load_file(&self, path: &Path) -> io::Result<Rc<FileMap>> {
let src = self.file_loader.read_file(path)?;
- Ok(self.new_filemap(path.to_str().unwrap().to_string(), src))
+ let abs_path = self.file_loader.abs_path(path).map(|p| p.to_str().unwrap().to_string());
+ Ok(self.new_filemap(path.to_str().unwrap().to_string(), abs_path, src))
}
fn next_start_pos(&self) -> usize {
/// Creates a new filemap without setting its line information. If you don't
/// intend to set the line information yourself, you should use new_filemap_and_lines.
- pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc<FileMap> {
+ pub fn new_filemap(&self, filename: FileName, abs_path: Option<FileName>,
+ mut src: String) -> Rc<FileMap> {
let start_pos = self.next_start_pos();
let mut files = self.files.borrow_mut();
let filemap = Rc::new(FileMap {
name: filename,
+ abs_path: abs_path,
src: Some(Rc::new(src)),
start_pos: Pos::from_usize(start_pos),
end_pos: Pos::from_usize(end_pos),
}
/// Creates a new filemap and sets its line information.
- pub fn new_filemap_and_lines(&self, filename: &str, src: &str) -> Rc<FileMap> {
- let fm = self.new_filemap(filename.to_string(), src.to_owned());
+ pub fn new_filemap_and_lines(&self, filename: &str, abs_path: Option<&str>,
+ src: &str) -> Rc<FileMap> {
+ let fm = self.new_filemap(filename.to_string(),
+ abs_path.map(|s| s.to_owned()),
+ src.to_owned());
let mut byte_pos: u32 = fm.start_pos.0;
for line in src.lines() {
// register the start of this line
/// information for things inlined from other crates.
pub fn new_imported_filemap(&self,
filename: FileName,
+ abs_path: Option<FileName>,
source_len: usize,
mut file_local_lines: Vec<BytePos>,
mut file_local_multibyte_chars: Vec<MultiByteChar>)
let filemap = Rc::new(FileMap {
name: filename,
+ abs_path: abs_path,
src: None,
start_pos: start_pos,
end_pos: end_pos,
fn t1 () {
let cm = CodeMap::new();
let fm = cm.new_filemap("blork.rs".to_string(),
+ None,
"first line.\nsecond line".to_string());
fm.next_line(BytePos(0));
// Test we can get lines with partial line info.
fn t2 () {
let cm = CodeMap::new();
let fm = cm.new_filemap("blork.rs".to_string(),
+ None,
"first line.\nsecond line".to_string());
// TESTING *REALLY* BROKEN BEHAVIOR:
fm.next_line(BytePos(0));
fn init_code_map() -> CodeMap {
let cm = CodeMap::new();
let fm1 = cm.new_filemap("blork.rs".to_string(),
+ None,
"first line.\nsecond line".to_string());
let fm2 = cm.new_filemap("empty.rs".to_string(),
+ None,
"".to_string());
let fm3 = cm.new_filemap("blork2.rs".to_string(),
+ None,
"first line.\nsecond line".to_string());
fm1.next_line(BytePos(0));
// € is a three byte utf8 char.
let fm1 =
cm.new_filemap("blork.rs".to_string(),
+ None,
"fir€st €€€€ line.\nsecond line".to_string());
let fm2 = cm.new_filemap("blork2.rs".to_string(),
+ None,
"first line€€.\n€ second line".to_string());
fm1.next_line(BytePos(0));
let cm = CodeMap::new();
let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
let selection = " \n ~~\n~~~\n~~~~~ \n \n";
- cm.new_filemap_and_lines("blork.rs", inputtext);
+ cm.new_filemap_and_lines("blork.rs", None, inputtext);
let span = span_from_selection(inputtext, selection);
// check that we are extracting the text we thought we were extracting
tolv
dreizehn
";
- let file = cm.new_filemap_and_lines("dummy.txt", content);
+ let file = cm.new_filemap_and_lines("dummy.txt", None, content);
let start = file.lines.borrow()[10];
let end = file.lines.borrow()[11];
let sp = mk_sp(start, end);
let cm = CodeMap::new();
let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
let selection = " \n ~~\n~~~\n~~~~~ \n \n";
- cm.new_filemap_and_lines("blork.rs", inputtext);
+ cm.new_filemap_and_lines("blork.rs", None, inputtext);
let sp = span_from_selection(inputtext, selection);
let msp: MultiSpan = sp.into();
let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
let selection1 = " \n \n \n \n ~ \n"; // intentionally out of order
let selection2 = " \n ~~\n~~~\n~~~~~ \n \n";
- cm.new_filemap_and_lines("blork.rs", inputtext);
+ cm.new_filemap_and_lines("blork.rs", None, inputtext);
let sp1 = span_from_selection(inputtext, selection1);
let sp2 = span_from_selection(inputtext, selection2);
let msp: MultiSpan = MultiSpan::from_spans(vec![sp1, sp2]);
assert_eq!(&cm.span_to_snippet(sp).unwrap(), expected);
sp
};
- cm.new_filemap_and_lines("dummy.txt", inp);
+ cm.new_filemap_and_lines("dummy.txt", None, inp);
let sp1 = span(sp1, "aaaaaa");
let sp2 = span(sp2, "bbbbbb");
let sp3 = span(sp3, "ccccc");
ddd__eee_\n\
elided\n\
__f_gg";
- let file = cm.new_filemap_and_lines("dummy.txt", inp);
+ let file = cm.new_filemap_and_lines("dummy.txt", None, inp);
let span = |lo, hi, (off_lo, off_hi)| {
let lines = file.lines.borrow();
";
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span_bar = cm.span_substr(&foo, file_text, "bar", 0);
let mut snippet = SnippetData::new(cm, Some(span_bar));
"#;
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span_vec0 = cm.span_substr(&foo, file_text, "vec", 0);
let span_vec1 = cm.span_substr(&foo, file_text, "vec", 1);
let span_semi = cm.span_substr(&foo, file_text, ";", 0);
"#;
let cm = Rc::new(CodeMap::new());
- let foo_map = cm.new_filemap_and_lines("foo.rs", file_text_foo);
+ let foo_map = cm.new_filemap_and_lines("foo.rs", None, file_text_foo);
let span_foo_vec0 = cm.span_substr(&foo_map, file_text_foo, "vec", 0);
let span_foo_vec1 = cm.span_substr(&foo_map, file_text_foo, "vec", 1);
let span_foo_semi = cm.span_substr(&foo_map, file_text_foo, ";", 0);
- let bar_map = cm.new_filemap_and_lines("bar.rs", file_text_bar);
+ let bar_map = cm.new_filemap_and_lines("bar.rs", None, file_text_bar);
let span_bar_vec0 = cm.span_substr(&bar_map, file_text_bar, "vec", 0);
let span_bar_vec1 = cm.span_substr(&bar_map, file_text_bar, "vec", 1);
let span_bar_semi = cm.span_substr(&bar_map, file_text_bar, ";", 0);
"#;
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span_data0 = cm.span_substr(&foo, file_text, "data", 0);
let span_data1 = cm.span_substr(&foo, file_text, "data", 1);
let span_rbrace = cm.span_substr(&foo, file_text, "}", 3);
"#;
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span0 = cm.span_substr(&foo, file_text, "vec.push", 0);
let span1 = cm.span_substr(&foo, file_text, "vec", 0);
let span2 = cm.span_substr(&foo, file_text, "ec.push", 0);
"#;
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span_vec0 = cm.span_substr(&foo, file_text, "vec", 0);
let span_vec1 = cm.span_substr(&foo, file_text, "vec", 1);
let span_semi = cm.span_substr(&foo, file_text, ";", 0);
"#;
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let span_vec0 = cm.span_substr(&foo, file_text, "vec", 3);
let span_vec1 = cm.span_substr(&foo, file_text, "vec", 8);
"#;
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut snippet = SnippetData::new(cm.clone(), None);
for i in 0..4 {
"#;
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut snippet = SnippetData::new(cm.clone(), None);
let fn_span = cm.span_substr(&foo, file_text, "fn", 0);
"#;
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut snippet = SnippetData::new(cm.clone(), None);
let fn_span = cm.span_substr(&foo, file_text, "fn foo(x: u32)", 0);
"#;
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut snippet = SnippetData::new(cm.clone(), None);
let fn_span = cm.span_substr(&foo, file_text, "fn foo(x", 0);
"#;
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut snippet = SnippetData::new(cm.clone(), None);
let cm = Rc::new(CodeMap::new());
- let foo = cm.new_filemap_and_lines("foo.rs", file_text);
+ let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
let mut rbrace_span = cm.span_substr(&foo, file_text, "}", 1);
rbrace_span.lo = rbrace_span.hi;
// dependency information
let filename = format!("{}", file.display());
let interned = token::intern_and_get_ident(&src[..]);
- cx.codemap().new_filemap_and_lines(&filename, &src);
+ cx.codemap().new_filemap_and_lines(&filename, None, &src);
base::MacEager::expr(cx.expr_str(sp, interned))
}
// Add this input file to the code map to make it available as
// dependency information, but don't enter it's contents
let filename = format!("{}", file.display());
- cx.codemap().new_filemap_and_lines(&filename, "");
+ cx.codemap().new_filemap_and_lines(&filename, None, "");
base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Rc::new(bytes))))
}
srdr.read_to_end(&mut src).unwrap();
let src = String::from_utf8(src).unwrap();
let cm = CodeMap::new();
- let filemap = cm.new_filemap(path, src);
+ let filemap = cm.new_filemap(path, None, src);
let mut rdr = lexer::StringReader::new_raw(span_diagnostic, filemap);
let mut comments: Vec<Comment> = Vec::new();
span_handler: &'a errors::Handler,
teststr: String)
-> StringReader<'a> {
- let fm = cm.new_filemap("zebra.rs".to_string(), teststr);
+ let fm = cm.new_filemap("zebra.rs".to_string(), None, teststr);
StringReader::new(span_handler, fm)
}
name: String,
source: String)
-> Parser<'a> {
- filemap_to_parser(sess, sess.codemap().new_filemap(name, source), cfg)
+ filemap_to_parser(sess, sess.codemap().new_filemap(name, None, source), cfg)
}
/// Create a new parser, handling errors as appropriate
/// Map a string to tts, using a made-up filename:
pub fn string_to_tts(source_str: String) -> Vec<ast::TokenTree> {
let ps = ParseSess::new();
- filemap_to_tts(&ps, ps.codemap().new_filemap("bogofile".to_string(), source_str))
+ filemap_to_tts(&ps, ps.codemap().new_filemap("bogofile".to_string(), None, source_str))
}
/// Map string to parser (via tts)