diff options
Diffstat (limited to 'src/tools/rustfmt/src/source_map.rs')
-rw-r--r-- | src/tools/rustfmt/src/source_map.rs | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/tools/rustfmt/src/source_map.rs b/src/tools/rustfmt/src/source_map.rs new file mode 100644 index 000000000..76e0d24cf --- /dev/null +++ b/src/tools/rustfmt/src/source_map.rs @@ -0,0 +1,82 @@ +//! This module contains utilities that work with the `SourceMap` from `libsyntax`/`syntex_syntax`. +//! This includes extension traits and methods for looking up spans and line ranges for AST nodes. + +use rustc_span::{BytePos, Span}; + +use crate::comment::FindUncommented; +use crate::config::file_lines::LineRange; +use crate::visitor::SnippetProvider; + +pub(crate) trait SpanUtils { + fn span_after(&self, original: Span, needle: &str) -> BytePos; + fn span_after_last(&self, original: Span, needle: &str) -> BytePos; + fn span_before(&self, original: Span, needle: &str) -> BytePos; + fn span_before_last(&self, original: Span, needle: &str) -> BytePos; + fn opt_span_after(&self, original: Span, needle: &str) -> Option<BytePos>; + fn opt_span_before(&self, original: Span, needle: &str) -> Option<BytePos>; +} + +pub(crate) trait LineRangeUtils { + /// Returns the `LineRange` that corresponds to `span` in `self`. + /// + /// # Panics + /// + /// Panics if `span` crosses a file boundary, which shouldn't happen. + fn lookup_line_range(&self, span: Span) -> LineRange; +} + +impl SpanUtils for SnippetProvider { + fn span_after(&self, original: Span, needle: &str) -> BytePos { + self.opt_span_after(original, needle).unwrap_or_else(|| { + panic!( + "bad span: `{}`: `{}`", + needle, + self.span_to_snippet(original).unwrap() + ) + }) + } + + fn span_after_last(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let mut offset = 0; + + while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { + offset += additional_offset + needle.len(); + } + + original.lo() + BytePos(offset as u32) + } + + fn span_before(&self, original: Span, needle: &str) -> BytePos { + self.opt_span_before(original, needle).unwrap_or_else(|| { + panic!( + "bad span: `{}`: `{}`", + needle, + self.span_to_snippet(original).unwrap() + ) + }) + } + + fn span_before_last(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let mut offset = 0; + + while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { + offset += additional_offset + needle.len(); + } + + original.lo() + BytePos(offset as u32 - 1) + } + + fn opt_span_after(&self, original: Span, needle: &str) -> Option<BytePos> { + self.opt_span_before(original, needle) + .map(|bytepos| bytepos + BytePos(needle.len() as u32)) + } + + fn opt_span_before(&self, original: Span, needle: &str) -> Option<BytePos> { + let snippet = self.span_to_snippet(original)?; + let offset = snippet.find_uncommented(needle)?; + + Some(original.lo() + BytePos(offset as u32)) + } +} |