summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_span/src/source_map.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_span/src/source_map.rs')
-rw-r--r--compiler/rustc_span/src/source_map.rs81
1 files changed, 40 insertions, 41 deletions
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 2e339a9d2..56573814e 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -100,6 +100,9 @@ pub trait FileLoader {
/// Read the contents of a UTF-8 file into memory.
fn read_file(&self, path: &Path) -> io::Result<String>;
+
+ /// Read the contents of a potentially non-UTF-8 file into memory.
+ fn read_binary_file(&self, path: &Path) -> io::Result<Vec<u8>>;
}
/// A FileLoader that uses std::fs to load real files.
@@ -113,6 +116,10 @@ impl FileLoader for RealFileLoader {
fn read_file(&self, path: &Path) -> io::Result<String> {
fs::read_to_string(path)
}
+
+ fn read_binary_file(&self, path: &Path) -> io::Result<Vec<u8>> {
+ fs::read(path)
+ }
}
/// This is a [SourceFile] identifier that is used to correlate source files between
@@ -220,9 +227,7 @@ impl SourceMap {
/// Unlike `load_file`, guarantees that no normalization like BOM-removal
/// takes place.
pub fn load_binary_file(&self, path: &Path) -> io::Result<Vec<u8>> {
- // Ideally, this should use `self.file_loader`, but it can't
- // deal with binary files yet.
- let bytes = fs::read(path)?;
+ let bytes = self.file_loader.read_binary_file(path)?;
// We need to add file to the `SourceMap`, so that it is present
// in dep-info. There's also an edge case that file might be both
@@ -443,25 +448,36 @@ impl SourceMap {
sp: Span,
filename_display_pref: FileNameDisplayPreference,
) -> String {
- if self.files.borrow().source_files.is_empty() || sp.is_dummy() {
- return "no-location".to_string();
- }
+ let (source_file, lo_line, lo_col, hi_line, hi_col) = self.span_to_location_info(sp);
+
+ let file_name = match source_file {
+ Some(sf) => sf.name.display(filename_display_pref).to_string(),
+ None => return "no-location".to_string(),
+ };
- let lo = self.lookup_char_pos(sp.lo());
- let hi = self.lookup_char_pos(sp.hi());
format!(
- "{}:{}:{}{}",
- lo.file.name.display(filename_display_pref),
- lo.line,
- lo.col.to_usize() + 1,
+ "{file_name}:{lo_line}:{lo_col}{}",
if let FileNameDisplayPreference::Short = filename_display_pref {
String::new()
} else {
- format!(": {}:{}", hi.line, hi.col.to_usize() + 1)
+ format!(": {hi_line}:{hi_col}")
}
)
}
+ pub fn span_to_location_info(
+ &self,
+ sp: Span,
+ ) -> (Option<Lrc<SourceFile>>, usize, usize, usize, usize) {
+ if self.files.borrow().source_files.is_empty() || sp.is_dummy() {
+ return (None, 0, 0, 0, 0);
+ }
+
+ let lo = self.lookup_char_pos(sp.lo());
+ let hi = self.lookup_char_pos(sp.hi());
+ (Some(lo.file), lo.line, lo.col.to_usize() + 1, hi.line, hi.col.to_usize() + 1)
+ }
+
/// Format the span location suitable for embedding in build artifacts
pub fn span_to_embeddable_string(&self, sp: Span) -> String {
self.span_to_string(sp, FileNameDisplayPreference::Remapped)
@@ -526,10 +542,10 @@ impl SourceMap {
let hi = self.lookup_char_pos(sp.hi());
trace!(?hi);
if lo.file.start_pos != hi.file.start_pos {
- return Err(SpanLinesError::DistinctSources(DistinctSources {
+ return Err(SpanLinesError::DistinctSources(Box::new(DistinctSources {
begin: (lo.file.name.clone(), lo.file.start_pos),
end: (hi.file.name.clone(), hi.file.start_pos),
- }));
+ })));
}
Ok((lo, hi))
}
@@ -587,10 +603,10 @@ impl SourceMap {
let local_end = self.lookup_byte_offset(sp.hi());
if local_begin.sf.start_pos != local_end.sf.start_pos {
- Err(SpanSnippetError::DistinctSources(DistinctSources {
+ Err(SpanSnippetError::DistinctSources(Box::new(DistinctSources {
begin: (local_begin.sf.name.clone(), local_begin.sf.start_pos),
end: (local_end.sf.name.clone(), local_end.sf.start_pos),
- }))
+ })))
} else {
self.ensure_source_file_source_present(local_begin.sf.clone());
@@ -1003,36 +1019,19 @@ impl SourceMap {
let src = local_begin.sf.external_src.borrow();
- // We need to extend the snippet to the end of the src rather than to end_index so when
- // searching forwards for boundaries we've got somewhere to search.
- let snippet = if let Some(ref src) = local_begin.sf.src {
- &src[start_index..]
+ let snippet = if let Some(src) = &local_begin.sf.src {
+ src
} else if let Some(src) = src.get_source() {
- &src[start_index..]
+ src
} else {
return 1;
};
- debug!("snippet=`{:?}`", snippet);
-
- let mut target = if forwards { end_index + 1 } else { end_index - 1 };
- debug!("initial target=`{:?}`", target);
- while !snippet.is_char_boundary(target - start_index) && target < source_len {
- target = if forwards {
- target + 1
- } else {
- match target.checked_sub(1) {
- Some(target) => target,
- None => {
- break;
- }
- }
- };
- debug!("target=`{:?}`", target);
+ if forwards {
+ (snippet.ceil_char_boundary(end_index + 1) - end_index) as u32
+ } else {
+ (end_index - snippet.floor_char_boundary(end_index - 1)) as u32
}
- debug!("final target=`{:?}`", target);
-
- if forwards { (target - end_index) as u32 } else { (end_index - target) as u32 }
}
pub fn get_source_file(&self, filename: &FileName) -> Option<Lrc<SourceFile>> {