libsyntax: factor out file path resolving
This allows the same logic used by `include_X!` macros to be used by `#[doc(include)]`.
This commit is contained in:
parent
3ebca72a11
commit
ba78db310b
3 changed files with 35 additions and 27 deletions
|
|
@ -6,13 +6,13 @@ use crate::print::pprust;
|
|||
use crate::ptr::P;
|
||||
use crate::symbol::Symbol;
|
||||
use crate::tokenstream;
|
||||
use crate::util::path;
|
||||
|
||||
use smallvec::SmallVec;
|
||||
use syntax_pos::{self, Pos, Span, FileName};
|
||||
use syntax_pos::{self, Pos, Span};
|
||||
|
||||
use std::fs;
|
||||
use std::io::ErrorKind;
|
||||
use std::path::PathBuf;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
||||
// These macros all relate to the file system; they either return
|
||||
|
|
@ -78,9 +78,9 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstrea
|
|||
None => return DummyResult::any(sp),
|
||||
};
|
||||
// The file will be added to the code map by the parser
|
||||
let path = res_rel_file(cx, sp, file);
|
||||
let file = path::resolve(file, sp, cx.source_map());
|
||||
let directory_ownership = DirectoryOwnership::Owned { relative: None };
|
||||
let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);
|
||||
let p = parse::new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp);
|
||||
|
||||
struct ExpandResult<'a> {
|
||||
p: parse::parser::Parser<'a>,
|
||||
|
|
@ -115,7 +115,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::To
|
|||
Some(f) => f,
|
||||
None => return DummyResult::expr(sp)
|
||||
};
|
||||
let file = res_rel_file(cx, sp, file);
|
||||
let file = path::resolve(file, sp, cx.source_map());
|
||||
match fs::read_to_string(&file) {
|
||||
Ok(src) => {
|
||||
let interned_src = Symbol::intern(&src);
|
||||
|
|
@ -143,7 +143,7 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::
|
|||
Some(f) => f,
|
||||
None => return DummyResult::expr(sp)
|
||||
};
|
||||
let file = res_rel_file(cx, sp, file);
|
||||
let file = path::resolve(file, sp, cx.source_map());
|
||||
match fs::read(&file) {
|
||||
Ok(bytes) => {
|
||||
// Add the contents to the source map if it contains UTF-8.
|
||||
|
|
@ -164,24 +164,3 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resolve a file-system path to an absolute file-system path (if it
|
||||
// isn't already)
|
||||
fn res_rel_file(cx: &mut ExtCtxt<'_>, sp: syntax_pos::Span, arg: String) -> PathBuf {
|
||||
let arg = PathBuf::from(arg);
|
||||
// Relative paths are resolved relative to the file in which they are found
|
||||
// after macro expansion (that is, they are unhygienic).
|
||||
if !arg.is_absolute() {
|
||||
let callsite = sp.source_callsite();
|
||||
let mut path = match cx.source_map().span_to_unmapped_path(callsite) {
|
||||
FileName::Real(path) => path,
|
||||
FileName::DocTest(path, _) => path,
|
||||
other => panic!("cannot resolve relative path in non-file source `{}`", other),
|
||||
};
|
||||
path.pop();
|
||||
path.push(arg);
|
||||
path
|
||||
} else {
|
||||
arg
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ pub mod util {
|
|||
#[cfg(test)]
|
||||
pub mod parser_testing;
|
||||
pub mod map_in_place;
|
||||
pub mod path;
|
||||
}
|
||||
|
||||
pub mod json;
|
||||
|
|
|
|||
28
src/libsyntax/util/path.rs
Normal file
28
src/libsyntax/util/path.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
use crate::source_map::SourceMap;
|
||||
use std::path::PathBuf;
|
||||
use syntax_pos::{Span, FileName};
|
||||
|
||||
/// Resolve a path mentioned inside Rust code.
|
||||
///
|
||||
/// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
|
||||
///
|
||||
/// Returns an absolute path to the file that `path` refers to.
|
||||
pub fn resolve(path: impl Into<PathBuf>, span: Span, map: &SourceMap) -> PathBuf {
|
||||
let path = path.into();
|
||||
|
||||
// Relative paths are resolved relative to the file in which they are found
|
||||
// after macro expansion (that is, they are unhygienic).
|
||||
if !path.is_absolute() {
|
||||
let callsite = span.source_callsite();
|
||||
let mut result = match map.span_to_unmapped_path(callsite) {
|
||||
FileName::Real(path) => path,
|
||||
FileName::DocTest(path, _) => path,
|
||||
other => panic!("cannot resolve relative path in non-file source `{}`", other),
|
||||
};
|
||||
result.pop();
|
||||
result.push(path);
|
||||
result
|
||||
} else {
|
||||
path
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue