summaryrefslogtreecommitdiffstats
path: root/src/tools/rustfmt/src/source_map.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rustfmt/src/source_map.rs')
-rw-r--r--src/tools/rustfmt/src/source_map.rs82
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))
+ }
+}