diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /compiler/rustc_save_analysis/src/span_utils.rs | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_save_analysis/src/span_utils.rs')
-rw-r--r-- | compiler/rustc_save_analysis/src/span_utils.rs | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/compiler/rustc_save_analysis/src/span_utils.rs b/compiler/rustc_save_analysis/src/span_utils.rs new file mode 100644 index 000000000..8d6758f40 --- /dev/null +++ b/compiler/rustc_save_analysis/src/span_utils.rs @@ -0,0 +1,102 @@ +use crate::generated_code; +use rustc_data_structures::sync::Lrc; +use rustc_lexer::{tokenize, TokenKind}; +use rustc_session::Session; +use rustc_span::*; + +#[derive(Clone)] +pub struct SpanUtils<'a> { + pub sess: &'a Session, +} + +impl<'a> SpanUtils<'a> { + pub fn new(sess: &'a Session) -> SpanUtils<'a> { + SpanUtils { sess } + } + + pub fn make_filename_string(&self, file: &SourceFile) -> String { + match &file.name { + FileName::Real(RealFileName::LocalPath(path)) => { + if path.is_absolute() { + self.sess + .source_map() + .path_mapping() + .map_prefix(path.into()) + .0 + .display() + .to_string() + } else { + self.sess + .opts + .working_dir + .remapped_path_if_available() + .join(&path) + .display() + .to_string() + } + } + filename => filename.prefer_remapped().to_string(), + } + } + + pub fn snippet(&self, span: Span) -> String { + match self.sess.source_map().span_to_snippet(span) { + Ok(s) => s, + Err(_) => String::new(), + } + } + + /// Finds the span of `*` token withing the larger `span`. + pub fn sub_span_of_star(&self, mut span: Span) -> Option<Span> { + let begin = self.sess.source_map().lookup_byte_offset(span.lo()); + let end = self.sess.source_map().lookup_byte_offset(span.hi()); + // Make the range zero-length if the span is invalid. + if begin.sf.start_pos != end.sf.start_pos { + span = span.shrink_to_lo(); + } + + let sf = Lrc::clone(&begin.sf); + + self.sess.source_map().ensure_source_file_source_present(Lrc::clone(&sf)); + let src = + sf.src.clone().or_else(|| sf.external_src.borrow().get_source().map(Lrc::clone))?; + let to_index = |pos: BytePos| -> usize { (pos - sf.start_pos).0 as usize }; + let text = &src[to_index(span.lo())..to_index(span.hi())]; + let start_pos = { + let mut pos = 0; + tokenize(text) + .map(|token| { + let start = pos; + pos += token.len; + (start, token) + }) + .find(|(_pos, token)| token.kind == TokenKind::Star)? + .0 + }; + let lo = span.lo() + BytePos(start_pos as u32); + let hi = lo + BytePos(1); + Some(span.with_lo(lo).with_hi(hi)) + } + + /// Return true if the span is generated code, and + /// it is not a subspan of the root callsite. + /// + /// Used to filter out spans of minimal value, + /// such as references to macro internal variables. + pub fn filter_generated(&self, span: Span) -> bool { + if generated_code(span) { + return true; + } + + //If the span comes from a fake source_file, filter it. + !self.sess.source_map().lookup_char_pos(span.lo()).file.is_real_file() + } +} + +macro_rules! filter { + ($util: expr, $parent: expr) => { + if $util.filter_generated($parent) { + return None; + } + }; +} |