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 4 use rustc_span::{BytePos, Span}; 5 6 use crate::comment::FindUncommented; 7 use crate::config::file_lines::LineRange; 8 use crate::visitor::SnippetProvider; 9 10 pub(crate) trait SpanUtils { span_after(&self, original: Span, needle: &str) -> BytePos11 fn span_after(&self, original: Span, needle: &str) -> BytePos; span_after_last(&self, original: Span, needle: &str) -> BytePos12 fn span_after_last(&self, original: Span, needle: &str) -> BytePos; span_before(&self, original: Span, needle: &str) -> BytePos13 fn span_before(&self, original: Span, needle: &str) -> BytePos; span_before_last(&self, original: Span, needle: &str) -> BytePos14 fn span_before_last(&self, original: Span, needle: &str) -> BytePos; opt_span_after(&self, original: Span, needle: &str) -> Option<BytePos>15 fn opt_span_after(&self, original: Span, needle: &str) -> Option<BytePos>; opt_span_before(&self, original: Span, needle: &str) -> Option<BytePos>16 fn opt_span_before(&self, original: Span, needle: &str) -> Option<BytePos>; 17 } 18 19 pub(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. lookup_line_range(&self, span: Span) -> LineRange25 fn lookup_line_range(&self, span: Span) -> LineRange; 26 } 27 28 impl SpanUtils for SnippetProvider { span_after(&self, original: Span, needle: &str) -> BytePos29 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 span_after_last(&self, original: Span, needle: &str) -> BytePos39 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 span_before(&self, original: Span, needle: &str) -> BytePos50 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 span_before_last(&self, original: Span, needle: &str) -> BytePos60 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 opt_span_after(&self, original: Span, needle: &str) -> Option<BytePos>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 opt_span_before(&self, original: Span, needle: &str) -> Option<BytePos>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 } 83