about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2019-05-14 21:50:39 +0200
committerJonas Schievink <jonasschievink@gmail.com>2019-07-23 17:17:31 +0200
commitba78db310b2ddf9b5f8e6c87a58e8ea8df374e16 (patch)
treea78833c1d85282943777c9f00fff82bfe709d594 /src/libsyntax
parent3ebca72a11869f946b31f900faffb75c2bb2473a (diff)
downloadrust-ba78db310b2ddf9b5f8e6c87a58e8ea8df374e16.tar.gz
rust-ba78db310b2ddf9b5f8e6c87a58e8ea8df374e16.zip
libsyntax: factor out file path resolving
This allows the same logic used by `include_X!` macros to be used by
`#[doc(include)]`.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/source_util.rs33
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax/util/path.rs28
3 files changed, 35 insertions, 27 deletions
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index c2ba8b983f5..aad390f3bf6 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -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
-    }
-}
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 3dea1977c4d..1b2873b1de7 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -135,6 +135,7 @@ pub mod util {
     #[cfg(test)]
     pub mod parser_testing;
     pub mod map_in_place;
+    pub mod path;
 }
 
 pub mod json;
diff --git a/src/libsyntax/util/path.rs b/src/libsyntax/util/path.rs
new file mode 100644
index 00000000000..a3511bac8e7
--- /dev/null
+++ b/src/libsyntax/util/path.rs
@@ -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
+    }
+}