rustfmt_nightly/
source_map.rs

1//! This module contains utilities that work with the `SourceMap` from `libsyntax`/`syntex_syntax`.
2//! This includes extension traits and methods for looking up spans and line ranges for AST nodes.
3
4use rustc_span::{BytePos, Span};
5
6use crate::comment::FindUncommented;
7use crate::config::file_lines::LineRange;
8use crate::visitor::SnippetProvider;
9
10pub(crate) trait SpanUtils {
11    fn span_after(&self, original: Span, needle: &str) -> BytePos;
12    fn span_after_last(&self, original: Span, needle: &str) -> BytePos;
13    fn span_before(&self, original: Span, needle: &str) -> BytePos;
14    fn span_before_last(&self, original: Span, needle: &str) -> BytePos;
15    fn opt_span_after(&self, original: Span, needle: &str) -> Option<BytePos>;
16    fn opt_span_before(&self, original: Span, needle: &str) -> Option<BytePos>;
17}
18
19pub(crate) trait LineRangeUtils {
20    /// Returns the `LineRange` that corresponds to `span` in `self`.
21    ///
22    /// # Panics
23    ///
24    /// Panics if `span` crosses a file boundary, which shouldn't happen.
25    fn lookup_line_range(&self, span: Span) -> LineRange;
26}
27
28impl SpanUtils for SnippetProvider {
29    fn span_after(&self, original: Span, needle: &str) -> BytePos {
30        self.opt_span_after(original, needle).unwrap_or_else(|| {
31            panic!(
32                "bad span: `{}`: `{}`",
33                needle,
34                self.span_to_snippet(original).unwrap()
35            )
36        })
37    }
38
39    fn span_after_last(&self, original: Span, needle: &str) -> BytePos {
40        let snippet = self.span_to_snippet(original).unwrap();
41        let mut offset = 0;
42
43        while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) {
44            offset += additional_offset + needle.len();
45        }
46
47        original.lo() + BytePos(offset as u32)
48    }
49
50    fn span_before(&self, original: Span, needle: &str) -> BytePos {
51        self.opt_span_before(original, needle).unwrap_or_else(|| {
52            panic!(
53                "bad span: `{}`: `{}`",
54                needle,
55                self.span_to_snippet(original).unwrap()
56            )
57        })
58    }
59
60    fn span_before_last(&self, original: Span, needle: &str) -> BytePos {
61        let snippet = self.span_to_snippet(original).unwrap();
62        let mut offset = 0;
63
64        while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) {
65            offset += additional_offset + needle.len();
66        }
67
68        original.lo() + BytePos(offset as u32 - 1)
69    }
70
71    fn opt_span_after(&self, original: Span, needle: &str) -> Option<BytePos> {
72        self.opt_span_before(original, needle)
73            .map(|bytepos| bytepos + BytePos(needle.len() as u32))
74    }
75
76    fn opt_span_before(&self, original: Span, needle: &str) -> Option<BytePos> {
77        let snippet = self.span_to_snippet(original)?;
78        let offset = snippet.find_uncommented(needle)?;
79
80        Some(original.lo() + BytePos(offset as u32))
81    }
82}