17ac06127Sopenharmony_ci#[cfg(span_locations)] 27ac06127Sopenharmony_ciuse crate::location::LineColumn; 37ac06127Sopenharmony_ciuse crate::parse::{self, Cursor}; 47ac06127Sopenharmony_ciuse crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut}; 57ac06127Sopenharmony_ciuse crate::{Delimiter, Spacing, TokenTree}; 67ac06127Sopenharmony_ci#[cfg(all(span_locations, not(fuzzing)))] 77ac06127Sopenharmony_ciuse alloc::collections::BTreeMap; 87ac06127Sopenharmony_ci#[cfg(all(span_locations, not(fuzzing)))] 97ac06127Sopenharmony_ciuse core::cell::RefCell; 107ac06127Sopenharmony_ci#[cfg(span_locations)] 117ac06127Sopenharmony_ciuse core::cmp; 127ac06127Sopenharmony_ciuse core::fmt::{self, Debug, Display, Write}; 137ac06127Sopenharmony_ciuse core::mem::ManuallyDrop; 147ac06127Sopenharmony_ciuse core::ops::RangeBounds; 157ac06127Sopenharmony_ciuse core::ptr; 167ac06127Sopenharmony_ciuse core::str::FromStr; 177ac06127Sopenharmony_ciuse std::path::PathBuf; 187ac06127Sopenharmony_ci 197ac06127Sopenharmony_ci/// Force use of proc-macro2's fallback implementation of the API for now, even 207ac06127Sopenharmony_ci/// if the compiler's implementation is available. 217ac06127Sopenharmony_cipub fn force() { 227ac06127Sopenharmony_ci #[cfg(wrap_proc_macro)] 237ac06127Sopenharmony_ci crate::detection::force_fallback(); 247ac06127Sopenharmony_ci} 257ac06127Sopenharmony_ci 267ac06127Sopenharmony_ci/// Resume using the compiler's implementation of the proc macro API if it is 277ac06127Sopenharmony_ci/// available. 287ac06127Sopenharmony_cipub fn unforce() { 297ac06127Sopenharmony_ci #[cfg(wrap_proc_macro)] 307ac06127Sopenharmony_ci crate::detection::unforce_fallback(); 317ac06127Sopenharmony_ci} 327ac06127Sopenharmony_ci 337ac06127Sopenharmony_ci#[derive(Clone)] 347ac06127Sopenharmony_cipub(crate) struct TokenStream { 357ac06127Sopenharmony_ci inner: RcVec<TokenTree>, 367ac06127Sopenharmony_ci} 377ac06127Sopenharmony_ci 387ac06127Sopenharmony_ci#[derive(Debug)] 397ac06127Sopenharmony_cipub(crate) struct LexError { 407ac06127Sopenharmony_ci pub(crate) span: Span, 417ac06127Sopenharmony_ci} 427ac06127Sopenharmony_ci 437ac06127Sopenharmony_ciimpl LexError { 447ac06127Sopenharmony_ci pub(crate) fn span(&self) -> Span { 457ac06127Sopenharmony_ci self.span 467ac06127Sopenharmony_ci } 477ac06127Sopenharmony_ci 487ac06127Sopenharmony_ci pub(crate) fn call_site() -> Self { 497ac06127Sopenharmony_ci LexError { 507ac06127Sopenharmony_ci span: Span::call_site(), 517ac06127Sopenharmony_ci } 527ac06127Sopenharmony_ci } 537ac06127Sopenharmony_ci} 547ac06127Sopenharmony_ci 557ac06127Sopenharmony_ciimpl TokenStream { 567ac06127Sopenharmony_ci pub fn new() -> Self { 577ac06127Sopenharmony_ci TokenStream { 587ac06127Sopenharmony_ci inner: RcVecBuilder::new().build(), 597ac06127Sopenharmony_ci } 607ac06127Sopenharmony_ci } 617ac06127Sopenharmony_ci 627ac06127Sopenharmony_ci pub fn is_empty(&self) -> bool { 637ac06127Sopenharmony_ci self.inner.len() == 0 647ac06127Sopenharmony_ci } 657ac06127Sopenharmony_ci 667ac06127Sopenharmony_ci fn take_inner(self) -> RcVecBuilder<TokenTree> { 677ac06127Sopenharmony_ci let nodrop = ManuallyDrop::new(self); 687ac06127Sopenharmony_ci unsafe { ptr::read(&nodrop.inner) }.make_owned() 697ac06127Sopenharmony_ci } 707ac06127Sopenharmony_ci} 717ac06127Sopenharmony_ci 727ac06127Sopenharmony_cifn push_token_from_proc_macro(mut vec: RcVecMut<TokenTree>, token: TokenTree) { 737ac06127Sopenharmony_ci // https://github.com/dtolnay/proc-macro2/issues/235 747ac06127Sopenharmony_ci match token { 757ac06127Sopenharmony_ci TokenTree::Literal(crate::Literal { 767ac06127Sopenharmony_ci #[cfg(wrap_proc_macro)] 777ac06127Sopenharmony_ci inner: crate::imp::Literal::Fallback(literal), 787ac06127Sopenharmony_ci #[cfg(not(wrap_proc_macro))] 797ac06127Sopenharmony_ci inner: literal, 807ac06127Sopenharmony_ci .. 817ac06127Sopenharmony_ci }) if literal.repr.starts_with('-') => { 827ac06127Sopenharmony_ci push_negative_literal(vec, literal); 837ac06127Sopenharmony_ci } 847ac06127Sopenharmony_ci _ => vec.push(token), 857ac06127Sopenharmony_ci } 867ac06127Sopenharmony_ci 877ac06127Sopenharmony_ci #[cold] 887ac06127Sopenharmony_ci fn push_negative_literal(mut vec: RcVecMut<TokenTree>, mut literal: Literal) { 897ac06127Sopenharmony_ci literal.repr.remove(0); 907ac06127Sopenharmony_ci let mut punct = crate::Punct::new('-', Spacing::Alone); 917ac06127Sopenharmony_ci punct.set_span(crate::Span::_new_fallback(literal.span)); 927ac06127Sopenharmony_ci vec.push(TokenTree::Punct(punct)); 937ac06127Sopenharmony_ci vec.push(TokenTree::Literal(crate::Literal::_new_fallback(literal))); 947ac06127Sopenharmony_ci } 957ac06127Sopenharmony_ci} 967ac06127Sopenharmony_ci 977ac06127Sopenharmony_ci// Nonrecursive to prevent stack overflow. 987ac06127Sopenharmony_ciimpl Drop for TokenStream { 997ac06127Sopenharmony_ci fn drop(&mut self) { 1007ac06127Sopenharmony_ci let mut inner = match self.inner.get_mut() { 1017ac06127Sopenharmony_ci Some(inner) => inner, 1027ac06127Sopenharmony_ci None => return, 1037ac06127Sopenharmony_ci }; 1047ac06127Sopenharmony_ci while let Some(token) = inner.pop() { 1057ac06127Sopenharmony_ci let group = match token { 1067ac06127Sopenharmony_ci TokenTree::Group(group) => group.inner, 1077ac06127Sopenharmony_ci _ => continue, 1087ac06127Sopenharmony_ci }; 1097ac06127Sopenharmony_ci #[cfg(wrap_proc_macro)] 1107ac06127Sopenharmony_ci let group = match group { 1117ac06127Sopenharmony_ci crate::imp::Group::Fallback(group) => group, 1127ac06127Sopenharmony_ci crate::imp::Group::Compiler(_) => continue, 1137ac06127Sopenharmony_ci }; 1147ac06127Sopenharmony_ci inner.extend(group.stream.take_inner()); 1157ac06127Sopenharmony_ci } 1167ac06127Sopenharmony_ci } 1177ac06127Sopenharmony_ci} 1187ac06127Sopenharmony_ci 1197ac06127Sopenharmony_cipub(crate) struct TokenStreamBuilder { 1207ac06127Sopenharmony_ci inner: RcVecBuilder<TokenTree>, 1217ac06127Sopenharmony_ci} 1227ac06127Sopenharmony_ci 1237ac06127Sopenharmony_ciimpl TokenStreamBuilder { 1247ac06127Sopenharmony_ci pub fn new() -> Self { 1257ac06127Sopenharmony_ci TokenStreamBuilder { 1267ac06127Sopenharmony_ci inner: RcVecBuilder::new(), 1277ac06127Sopenharmony_ci } 1287ac06127Sopenharmony_ci } 1297ac06127Sopenharmony_ci 1307ac06127Sopenharmony_ci pub fn with_capacity(cap: usize) -> Self { 1317ac06127Sopenharmony_ci TokenStreamBuilder { 1327ac06127Sopenharmony_ci inner: RcVecBuilder::with_capacity(cap), 1337ac06127Sopenharmony_ci } 1347ac06127Sopenharmony_ci } 1357ac06127Sopenharmony_ci 1367ac06127Sopenharmony_ci pub fn push_token_from_parser(&mut self, tt: TokenTree) { 1377ac06127Sopenharmony_ci self.inner.push(tt); 1387ac06127Sopenharmony_ci } 1397ac06127Sopenharmony_ci 1407ac06127Sopenharmony_ci pub fn build(self) -> TokenStream { 1417ac06127Sopenharmony_ci TokenStream { 1427ac06127Sopenharmony_ci inner: self.inner.build(), 1437ac06127Sopenharmony_ci } 1447ac06127Sopenharmony_ci } 1457ac06127Sopenharmony_ci} 1467ac06127Sopenharmony_ci 1477ac06127Sopenharmony_ci#[cfg(span_locations)] 1487ac06127Sopenharmony_cifn get_cursor(src: &str) -> Cursor { 1497ac06127Sopenharmony_ci #[cfg(fuzzing)] 1507ac06127Sopenharmony_ci return Cursor { rest: src, off: 1 }; 1517ac06127Sopenharmony_ci 1527ac06127Sopenharmony_ci // Create a dummy file & add it to the source map 1537ac06127Sopenharmony_ci #[cfg(not(fuzzing))] 1547ac06127Sopenharmony_ci SOURCE_MAP.with(|cm| { 1557ac06127Sopenharmony_ci let mut cm = cm.borrow_mut(); 1567ac06127Sopenharmony_ci let span = cm.add_file(src); 1577ac06127Sopenharmony_ci Cursor { 1587ac06127Sopenharmony_ci rest: src, 1597ac06127Sopenharmony_ci off: span.lo, 1607ac06127Sopenharmony_ci } 1617ac06127Sopenharmony_ci }) 1627ac06127Sopenharmony_ci} 1637ac06127Sopenharmony_ci 1647ac06127Sopenharmony_ci#[cfg(not(span_locations))] 1657ac06127Sopenharmony_cifn get_cursor(src: &str) -> Cursor { 1667ac06127Sopenharmony_ci Cursor { rest: src } 1677ac06127Sopenharmony_ci} 1687ac06127Sopenharmony_ci 1697ac06127Sopenharmony_ciimpl FromStr for TokenStream { 1707ac06127Sopenharmony_ci type Err = LexError; 1717ac06127Sopenharmony_ci 1727ac06127Sopenharmony_ci fn from_str(src: &str) -> Result<TokenStream, LexError> { 1737ac06127Sopenharmony_ci // Create a dummy file & add it to the source map 1747ac06127Sopenharmony_ci let mut cursor = get_cursor(src); 1757ac06127Sopenharmony_ci 1767ac06127Sopenharmony_ci // Strip a byte order mark if present 1777ac06127Sopenharmony_ci const BYTE_ORDER_MARK: &str = "\u{feff}"; 1787ac06127Sopenharmony_ci if cursor.starts_with(BYTE_ORDER_MARK) { 1797ac06127Sopenharmony_ci cursor = cursor.advance(BYTE_ORDER_MARK.len()); 1807ac06127Sopenharmony_ci } 1817ac06127Sopenharmony_ci 1827ac06127Sopenharmony_ci parse::token_stream(cursor) 1837ac06127Sopenharmony_ci } 1847ac06127Sopenharmony_ci} 1857ac06127Sopenharmony_ci 1867ac06127Sopenharmony_ciimpl Display for LexError { 1877ac06127Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1887ac06127Sopenharmony_ci f.write_str("cannot parse string into token stream") 1897ac06127Sopenharmony_ci } 1907ac06127Sopenharmony_ci} 1917ac06127Sopenharmony_ci 1927ac06127Sopenharmony_ciimpl Display for TokenStream { 1937ac06127Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1947ac06127Sopenharmony_ci let mut joint = false; 1957ac06127Sopenharmony_ci for (i, tt) in self.inner.iter().enumerate() { 1967ac06127Sopenharmony_ci if i != 0 && !joint { 1977ac06127Sopenharmony_ci write!(f, " ")?; 1987ac06127Sopenharmony_ci } 1997ac06127Sopenharmony_ci joint = false; 2007ac06127Sopenharmony_ci match tt { 2017ac06127Sopenharmony_ci TokenTree::Group(tt) => Display::fmt(tt, f), 2027ac06127Sopenharmony_ci TokenTree::Ident(tt) => Display::fmt(tt, f), 2037ac06127Sopenharmony_ci TokenTree::Punct(tt) => { 2047ac06127Sopenharmony_ci joint = tt.spacing() == Spacing::Joint; 2057ac06127Sopenharmony_ci Display::fmt(tt, f) 2067ac06127Sopenharmony_ci } 2077ac06127Sopenharmony_ci TokenTree::Literal(tt) => Display::fmt(tt, f), 2087ac06127Sopenharmony_ci }?; 2097ac06127Sopenharmony_ci } 2107ac06127Sopenharmony_ci 2117ac06127Sopenharmony_ci Ok(()) 2127ac06127Sopenharmony_ci } 2137ac06127Sopenharmony_ci} 2147ac06127Sopenharmony_ci 2157ac06127Sopenharmony_ciimpl Debug for TokenStream { 2167ac06127Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2177ac06127Sopenharmony_ci f.write_str("TokenStream ")?; 2187ac06127Sopenharmony_ci f.debug_list().entries(self.clone()).finish() 2197ac06127Sopenharmony_ci } 2207ac06127Sopenharmony_ci} 2217ac06127Sopenharmony_ci 2227ac06127Sopenharmony_ci#[cfg(feature = "proc-macro")] 2237ac06127Sopenharmony_ciimpl From<proc_macro::TokenStream> for TokenStream { 2247ac06127Sopenharmony_ci fn from(inner: proc_macro::TokenStream) -> Self { 2257ac06127Sopenharmony_ci inner 2267ac06127Sopenharmony_ci .to_string() 2277ac06127Sopenharmony_ci .parse() 2287ac06127Sopenharmony_ci .expect("compiler token stream parse failed") 2297ac06127Sopenharmony_ci } 2307ac06127Sopenharmony_ci} 2317ac06127Sopenharmony_ci 2327ac06127Sopenharmony_ci#[cfg(feature = "proc-macro")] 2337ac06127Sopenharmony_ciimpl From<TokenStream> for proc_macro::TokenStream { 2347ac06127Sopenharmony_ci fn from(inner: TokenStream) -> Self { 2357ac06127Sopenharmony_ci inner 2367ac06127Sopenharmony_ci .to_string() 2377ac06127Sopenharmony_ci .parse() 2387ac06127Sopenharmony_ci .expect("failed to parse to compiler tokens") 2397ac06127Sopenharmony_ci } 2407ac06127Sopenharmony_ci} 2417ac06127Sopenharmony_ci 2427ac06127Sopenharmony_ciimpl From<TokenTree> for TokenStream { 2437ac06127Sopenharmony_ci fn from(tree: TokenTree) -> Self { 2447ac06127Sopenharmony_ci let mut stream = RcVecBuilder::new(); 2457ac06127Sopenharmony_ci push_token_from_proc_macro(stream.as_mut(), tree); 2467ac06127Sopenharmony_ci TokenStream { 2477ac06127Sopenharmony_ci inner: stream.build(), 2487ac06127Sopenharmony_ci } 2497ac06127Sopenharmony_ci } 2507ac06127Sopenharmony_ci} 2517ac06127Sopenharmony_ci 2527ac06127Sopenharmony_ciimpl FromIterator<TokenTree> for TokenStream { 2537ac06127Sopenharmony_ci fn from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self { 2547ac06127Sopenharmony_ci let mut stream = TokenStream::new(); 2557ac06127Sopenharmony_ci stream.extend(tokens); 2567ac06127Sopenharmony_ci stream 2577ac06127Sopenharmony_ci } 2587ac06127Sopenharmony_ci} 2597ac06127Sopenharmony_ci 2607ac06127Sopenharmony_ciimpl FromIterator<TokenStream> for TokenStream { 2617ac06127Sopenharmony_ci fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { 2627ac06127Sopenharmony_ci let mut v = RcVecBuilder::new(); 2637ac06127Sopenharmony_ci 2647ac06127Sopenharmony_ci for stream in streams { 2657ac06127Sopenharmony_ci v.extend(stream.take_inner()); 2667ac06127Sopenharmony_ci } 2677ac06127Sopenharmony_ci 2687ac06127Sopenharmony_ci TokenStream { inner: v.build() } 2697ac06127Sopenharmony_ci } 2707ac06127Sopenharmony_ci} 2717ac06127Sopenharmony_ci 2727ac06127Sopenharmony_ciimpl Extend<TokenTree> for TokenStream { 2737ac06127Sopenharmony_ci fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I) { 2747ac06127Sopenharmony_ci let mut vec = self.inner.make_mut(); 2757ac06127Sopenharmony_ci tokens 2767ac06127Sopenharmony_ci .into_iter() 2777ac06127Sopenharmony_ci .for_each(|token| push_token_from_proc_macro(vec.as_mut(), token)); 2787ac06127Sopenharmony_ci } 2797ac06127Sopenharmony_ci} 2807ac06127Sopenharmony_ci 2817ac06127Sopenharmony_ciimpl Extend<TokenStream> for TokenStream { 2827ac06127Sopenharmony_ci fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { 2837ac06127Sopenharmony_ci self.inner.make_mut().extend(streams.into_iter().flatten()); 2847ac06127Sopenharmony_ci } 2857ac06127Sopenharmony_ci} 2867ac06127Sopenharmony_ci 2877ac06127Sopenharmony_cipub(crate) type TokenTreeIter = RcVecIntoIter<TokenTree>; 2887ac06127Sopenharmony_ci 2897ac06127Sopenharmony_ciimpl IntoIterator for TokenStream { 2907ac06127Sopenharmony_ci type Item = TokenTree; 2917ac06127Sopenharmony_ci type IntoIter = TokenTreeIter; 2927ac06127Sopenharmony_ci 2937ac06127Sopenharmony_ci fn into_iter(self) -> TokenTreeIter { 2947ac06127Sopenharmony_ci self.take_inner().into_iter() 2957ac06127Sopenharmony_ci } 2967ac06127Sopenharmony_ci} 2977ac06127Sopenharmony_ci 2987ac06127Sopenharmony_ci#[derive(Clone, PartialEq, Eq)] 2997ac06127Sopenharmony_cipub(crate) struct SourceFile { 3007ac06127Sopenharmony_ci path: PathBuf, 3017ac06127Sopenharmony_ci} 3027ac06127Sopenharmony_ci 3037ac06127Sopenharmony_ciimpl SourceFile { 3047ac06127Sopenharmony_ci /// Get the path to this source file as a string. 3057ac06127Sopenharmony_ci pub fn path(&self) -> PathBuf { 3067ac06127Sopenharmony_ci self.path.clone() 3077ac06127Sopenharmony_ci } 3087ac06127Sopenharmony_ci 3097ac06127Sopenharmony_ci pub fn is_real(&self) -> bool { 3107ac06127Sopenharmony_ci false 3117ac06127Sopenharmony_ci } 3127ac06127Sopenharmony_ci} 3137ac06127Sopenharmony_ci 3147ac06127Sopenharmony_ciimpl Debug for SourceFile { 3157ac06127Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 3167ac06127Sopenharmony_ci f.debug_struct("SourceFile") 3177ac06127Sopenharmony_ci .field("path", &self.path()) 3187ac06127Sopenharmony_ci .field("is_real", &self.is_real()) 3197ac06127Sopenharmony_ci .finish() 3207ac06127Sopenharmony_ci } 3217ac06127Sopenharmony_ci} 3227ac06127Sopenharmony_ci 3237ac06127Sopenharmony_ci#[cfg(all(span_locations, not(fuzzing)))] 3247ac06127Sopenharmony_cithread_local! { 3257ac06127Sopenharmony_ci static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap { 3267ac06127Sopenharmony_ci // Start with a single dummy file which all call_site() and def_site() 3277ac06127Sopenharmony_ci // spans reference. 3287ac06127Sopenharmony_ci files: vec![FileInfo { 3297ac06127Sopenharmony_ci source_text: String::new(), 3307ac06127Sopenharmony_ci span: Span { lo: 0, hi: 0 }, 3317ac06127Sopenharmony_ci lines: vec![0], 3327ac06127Sopenharmony_ci char_index_to_byte_offset: BTreeMap::new(), 3337ac06127Sopenharmony_ci }], 3347ac06127Sopenharmony_ci }); 3357ac06127Sopenharmony_ci} 3367ac06127Sopenharmony_ci 3377ac06127Sopenharmony_ci#[cfg(all(span_locations, not(fuzzing)))] 3387ac06127Sopenharmony_cistruct FileInfo { 3397ac06127Sopenharmony_ci source_text: String, 3407ac06127Sopenharmony_ci span: Span, 3417ac06127Sopenharmony_ci lines: Vec<usize>, 3427ac06127Sopenharmony_ci char_index_to_byte_offset: BTreeMap<usize, usize>, 3437ac06127Sopenharmony_ci} 3447ac06127Sopenharmony_ci 3457ac06127Sopenharmony_ci#[cfg(all(span_locations, not(fuzzing)))] 3467ac06127Sopenharmony_ciimpl FileInfo { 3477ac06127Sopenharmony_ci fn offset_line_column(&self, offset: usize) -> LineColumn { 3487ac06127Sopenharmony_ci assert!(self.span_within(Span { 3497ac06127Sopenharmony_ci lo: offset as u32, 3507ac06127Sopenharmony_ci hi: offset as u32, 3517ac06127Sopenharmony_ci })); 3527ac06127Sopenharmony_ci let offset = offset - self.span.lo as usize; 3537ac06127Sopenharmony_ci match self.lines.binary_search(&offset) { 3547ac06127Sopenharmony_ci Ok(found) => LineColumn { 3557ac06127Sopenharmony_ci line: found + 1, 3567ac06127Sopenharmony_ci column: 0, 3577ac06127Sopenharmony_ci }, 3587ac06127Sopenharmony_ci Err(idx) => LineColumn { 3597ac06127Sopenharmony_ci line: idx, 3607ac06127Sopenharmony_ci column: offset - self.lines[idx - 1], 3617ac06127Sopenharmony_ci }, 3627ac06127Sopenharmony_ci } 3637ac06127Sopenharmony_ci } 3647ac06127Sopenharmony_ci 3657ac06127Sopenharmony_ci fn span_within(&self, span: Span) -> bool { 3667ac06127Sopenharmony_ci span.lo >= self.span.lo && span.hi <= self.span.hi 3677ac06127Sopenharmony_ci } 3687ac06127Sopenharmony_ci 3697ac06127Sopenharmony_ci fn source_text(&mut self, span: Span) -> String { 3707ac06127Sopenharmony_ci let lo_char = (span.lo - self.span.lo) as usize; 3717ac06127Sopenharmony_ci 3727ac06127Sopenharmony_ci // Look up offset of the largest already-computed char index that is 3737ac06127Sopenharmony_ci // less than or equal to the current requested one. We resume counting 3747ac06127Sopenharmony_ci // chars from that point. 3757ac06127Sopenharmony_ci let (&last_char_index, &last_byte_offset) = self 3767ac06127Sopenharmony_ci .char_index_to_byte_offset 3777ac06127Sopenharmony_ci .range(..=lo_char) 3787ac06127Sopenharmony_ci .next_back() 3797ac06127Sopenharmony_ci .unwrap_or((&0, &0)); 3807ac06127Sopenharmony_ci 3817ac06127Sopenharmony_ci let lo_byte = if last_char_index == lo_char { 3827ac06127Sopenharmony_ci last_byte_offset 3837ac06127Sopenharmony_ci } else { 3847ac06127Sopenharmony_ci let total_byte_offset = match self.source_text[last_byte_offset..] 3857ac06127Sopenharmony_ci .char_indices() 3867ac06127Sopenharmony_ci .nth(lo_char - last_char_index) 3877ac06127Sopenharmony_ci { 3887ac06127Sopenharmony_ci Some((additional_offset, _ch)) => last_byte_offset + additional_offset, 3897ac06127Sopenharmony_ci None => self.source_text.len(), 3907ac06127Sopenharmony_ci }; 3917ac06127Sopenharmony_ci self.char_index_to_byte_offset 3927ac06127Sopenharmony_ci .insert(lo_char, total_byte_offset); 3937ac06127Sopenharmony_ci total_byte_offset 3947ac06127Sopenharmony_ci }; 3957ac06127Sopenharmony_ci 3967ac06127Sopenharmony_ci let trunc_lo = &self.source_text[lo_byte..]; 3977ac06127Sopenharmony_ci let char_len = (span.hi - span.lo) as usize; 3987ac06127Sopenharmony_ci let source_text = match trunc_lo.char_indices().nth(char_len) { 3997ac06127Sopenharmony_ci Some((offset, _ch)) => &trunc_lo[..offset], 4007ac06127Sopenharmony_ci None => trunc_lo, 4017ac06127Sopenharmony_ci }; 4027ac06127Sopenharmony_ci source_text.to_owned() 4037ac06127Sopenharmony_ci } 4047ac06127Sopenharmony_ci} 4057ac06127Sopenharmony_ci 4067ac06127Sopenharmony_ci/// Computes the offsets of each line in the given source string 4077ac06127Sopenharmony_ci/// and the total number of characters 4087ac06127Sopenharmony_ci#[cfg(all(span_locations, not(fuzzing)))] 4097ac06127Sopenharmony_cifn lines_offsets(s: &str) -> (usize, Vec<usize>) { 4107ac06127Sopenharmony_ci let mut lines = vec![0]; 4117ac06127Sopenharmony_ci let mut total = 0; 4127ac06127Sopenharmony_ci 4137ac06127Sopenharmony_ci for ch in s.chars() { 4147ac06127Sopenharmony_ci total += 1; 4157ac06127Sopenharmony_ci if ch == '\n' { 4167ac06127Sopenharmony_ci lines.push(total); 4177ac06127Sopenharmony_ci } 4187ac06127Sopenharmony_ci } 4197ac06127Sopenharmony_ci 4207ac06127Sopenharmony_ci (total, lines) 4217ac06127Sopenharmony_ci} 4227ac06127Sopenharmony_ci 4237ac06127Sopenharmony_ci#[cfg(all(span_locations, not(fuzzing)))] 4247ac06127Sopenharmony_cistruct SourceMap { 4257ac06127Sopenharmony_ci files: Vec<FileInfo>, 4267ac06127Sopenharmony_ci} 4277ac06127Sopenharmony_ci 4287ac06127Sopenharmony_ci#[cfg(all(span_locations, not(fuzzing)))] 4297ac06127Sopenharmony_ciimpl SourceMap { 4307ac06127Sopenharmony_ci fn next_start_pos(&self) -> u32 { 4317ac06127Sopenharmony_ci // Add 1 so there's always space between files. 4327ac06127Sopenharmony_ci // 4337ac06127Sopenharmony_ci // We'll always have at least 1 file, as we initialize our files list 4347ac06127Sopenharmony_ci // with a dummy file. 4357ac06127Sopenharmony_ci self.files.last().unwrap().span.hi + 1 4367ac06127Sopenharmony_ci } 4377ac06127Sopenharmony_ci 4387ac06127Sopenharmony_ci fn add_file(&mut self, src: &str) -> Span { 4397ac06127Sopenharmony_ci let (len, lines) = lines_offsets(src); 4407ac06127Sopenharmony_ci let lo = self.next_start_pos(); 4417ac06127Sopenharmony_ci let span = Span { 4427ac06127Sopenharmony_ci lo, 4437ac06127Sopenharmony_ci hi: lo + (len as u32), 4447ac06127Sopenharmony_ci }; 4457ac06127Sopenharmony_ci 4467ac06127Sopenharmony_ci self.files.push(FileInfo { 4477ac06127Sopenharmony_ci source_text: src.to_owned(), 4487ac06127Sopenharmony_ci span, 4497ac06127Sopenharmony_ci lines, 4507ac06127Sopenharmony_ci // Populated lazily by source_text(). 4517ac06127Sopenharmony_ci char_index_to_byte_offset: BTreeMap::new(), 4527ac06127Sopenharmony_ci }); 4537ac06127Sopenharmony_ci 4547ac06127Sopenharmony_ci span 4557ac06127Sopenharmony_ci } 4567ac06127Sopenharmony_ci 4577ac06127Sopenharmony_ci #[cfg(procmacro2_semver_exempt)] 4587ac06127Sopenharmony_ci fn filepath(&self, span: Span) -> PathBuf { 4597ac06127Sopenharmony_ci for (i, file) in self.files.iter().enumerate() { 4607ac06127Sopenharmony_ci if file.span_within(span) { 4617ac06127Sopenharmony_ci return PathBuf::from(if i == 0 { 4627ac06127Sopenharmony_ci "<unspecified>".to_owned() 4637ac06127Sopenharmony_ci } else { 4647ac06127Sopenharmony_ci format!("<parsed string {}>", i) 4657ac06127Sopenharmony_ci }); 4667ac06127Sopenharmony_ci } 4677ac06127Sopenharmony_ci } 4687ac06127Sopenharmony_ci unreachable!("Invalid span with no related FileInfo!"); 4697ac06127Sopenharmony_ci } 4707ac06127Sopenharmony_ci 4717ac06127Sopenharmony_ci fn fileinfo(&self, span: Span) -> &FileInfo { 4727ac06127Sopenharmony_ci for file in &self.files { 4737ac06127Sopenharmony_ci if file.span_within(span) { 4747ac06127Sopenharmony_ci return file; 4757ac06127Sopenharmony_ci } 4767ac06127Sopenharmony_ci } 4777ac06127Sopenharmony_ci unreachable!("Invalid span with no related FileInfo!"); 4787ac06127Sopenharmony_ci } 4797ac06127Sopenharmony_ci 4807ac06127Sopenharmony_ci fn fileinfo_mut(&mut self, span: Span) -> &mut FileInfo { 4817ac06127Sopenharmony_ci for file in &mut self.files { 4827ac06127Sopenharmony_ci if file.span_within(span) { 4837ac06127Sopenharmony_ci return file; 4847ac06127Sopenharmony_ci } 4857ac06127Sopenharmony_ci } 4867ac06127Sopenharmony_ci unreachable!("Invalid span with no related FileInfo!"); 4877ac06127Sopenharmony_ci } 4887ac06127Sopenharmony_ci} 4897ac06127Sopenharmony_ci 4907ac06127Sopenharmony_ci#[derive(Clone, Copy, PartialEq, Eq)] 4917ac06127Sopenharmony_cipub(crate) struct Span { 4927ac06127Sopenharmony_ci #[cfg(span_locations)] 4937ac06127Sopenharmony_ci pub(crate) lo: u32, 4947ac06127Sopenharmony_ci #[cfg(span_locations)] 4957ac06127Sopenharmony_ci pub(crate) hi: u32, 4967ac06127Sopenharmony_ci} 4977ac06127Sopenharmony_ci 4987ac06127Sopenharmony_ciimpl Span { 4997ac06127Sopenharmony_ci #[cfg(not(span_locations))] 5007ac06127Sopenharmony_ci pub fn call_site() -> Self { 5017ac06127Sopenharmony_ci Span {} 5027ac06127Sopenharmony_ci } 5037ac06127Sopenharmony_ci 5047ac06127Sopenharmony_ci #[cfg(span_locations)] 5057ac06127Sopenharmony_ci pub fn call_site() -> Self { 5067ac06127Sopenharmony_ci Span { lo: 0, hi: 0 } 5077ac06127Sopenharmony_ci } 5087ac06127Sopenharmony_ci 5097ac06127Sopenharmony_ci pub fn mixed_site() -> Self { 5107ac06127Sopenharmony_ci Span::call_site() 5117ac06127Sopenharmony_ci } 5127ac06127Sopenharmony_ci 5137ac06127Sopenharmony_ci #[cfg(procmacro2_semver_exempt)] 5147ac06127Sopenharmony_ci pub fn def_site() -> Self { 5157ac06127Sopenharmony_ci Span::call_site() 5167ac06127Sopenharmony_ci } 5177ac06127Sopenharmony_ci 5187ac06127Sopenharmony_ci pub fn resolved_at(&self, _other: Span) -> Span { 5197ac06127Sopenharmony_ci // Stable spans consist only of line/column information, so 5207ac06127Sopenharmony_ci // `resolved_at` and `located_at` only select which span the 5217ac06127Sopenharmony_ci // caller wants line/column information from. 5227ac06127Sopenharmony_ci *self 5237ac06127Sopenharmony_ci } 5247ac06127Sopenharmony_ci 5257ac06127Sopenharmony_ci pub fn located_at(&self, other: Span) -> Span { 5267ac06127Sopenharmony_ci other 5277ac06127Sopenharmony_ci } 5287ac06127Sopenharmony_ci 5297ac06127Sopenharmony_ci #[cfg(procmacro2_semver_exempt)] 5307ac06127Sopenharmony_ci pub fn source_file(&self) -> SourceFile { 5317ac06127Sopenharmony_ci #[cfg(fuzzing)] 5327ac06127Sopenharmony_ci return SourceFile { 5337ac06127Sopenharmony_ci path: PathBuf::from("<unspecified>"), 5347ac06127Sopenharmony_ci }; 5357ac06127Sopenharmony_ci 5367ac06127Sopenharmony_ci #[cfg(not(fuzzing))] 5377ac06127Sopenharmony_ci SOURCE_MAP.with(|cm| { 5387ac06127Sopenharmony_ci let cm = cm.borrow(); 5397ac06127Sopenharmony_ci let path = cm.filepath(*self); 5407ac06127Sopenharmony_ci SourceFile { path } 5417ac06127Sopenharmony_ci }) 5427ac06127Sopenharmony_ci } 5437ac06127Sopenharmony_ci 5447ac06127Sopenharmony_ci #[cfg(span_locations)] 5457ac06127Sopenharmony_ci pub fn start(&self) -> LineColumn { 5467ac06127Sopenharmony_ci #[cfg(fuzzing)] 5477ac06127Sopenharmony_ci return LineColumn { line: 0, column: 0 }; 5487ac06127Sopenharmony_ci 5497ac06127Sopenharmony_ci #[cfg(not(fuzzing))] 5507ac06127Sopenharmony_ci SOURCE_MAP.with(|cm| { 5517ac06127Sopenharmony_ci let cm = cm.borrow(); 5527ac06127Sopenharmony_ci let fi = cm.fileinfo(*self); 5537ac06127Sopenharmony_ci fi.offset_line_column(self.lo as usize) 5547ac06127Sopenharmony_ci }) 5557ac06127Sopenharmony_ci } 5567ac06127Sopenharmony_ci 5577ac06127Sopenharmony_ci #[cfg(span_locations)] 5587ac06127Sopenharmony_ci pub fn end(&self) -> LineColumn { 5597ac06127Sopenharmony_ci #[cfg(fuzzing)] 5607ac06127Sopenharmony_ci return LineColumn { line: 0, column: 0 }; 5617ac06127Sopenharmony_ci 5627ac06127Sopenharmony_ci #[cfg(not(fuzzing))] 5637ac06127Sopenharmony_ci SOURCE_MAP.with(|cm| { 5647ac06127Sopenharmony_ci let cm = cm.borrow(); 5657ac06127Sopenharmony_ci let fi = cm.fileinfo(*self); 5667ac06127Sopenharmony_ci fi.offset_line_column(self.hi as usize) 5677ac06127Sopenharmony_ci }) 5687ac06127Sopenharmony_ci } 5697ac06127Sopenharmony_ci 5707ac06127Sopenharmony_ci #[cfg(not(span_locations))] 5717ac06127Sopenharmony_ci pub fn join(&self, _other: Span) -> Option<Span> { 5727ac06127Sopenharmony_ci Some(Span {}) 5737ac06127Sopenharmony_ci } 5747ac06127Sopenharmony_ci 5757ac06127Sopenharmony_ci #[cfg(span_locations)] 5767ac06127Sopenharmony_ci pub fn join(&self, other: Span) -> Option<Span> { 5777ac06127Sopenharmony_ci #[cfg(fuzzing)] 5787ac06127Sopenharmony_ci return { 5797ac06127Sopenharmony_ci let _ = other; 5807ac06127Sopenharmony_ci None 5817ac06127Sopenharmony_ci }; 5827ac06127Sopenharmony_ci 5837ac06127Sopenharmony_ci #[cfg(not(fuzzing))] 5847ac06127Sopenharmony_ci SOURCE_MAP.with(|cm| { 5857ac06127Sopenharmony_ci let cm = cm.borrow(); 5867ac06127Sopenharmony_ci // If `other` is not within the same FileInfo as us, return None. 5877ac06127Sopenharmony_ci if !cm.fileinfo(*self).span_within(other) { 5887ac06127Sopenharmony_ci return None; 5897ac06127Sopenharmony_ci } 5907ac06127Sopenharmony_ci Some(Span { 5917ac06127Sopenharmony_ci lo: cmp::min(self.lo, other.lo), 5927ac06127Sopenharmony_ci hi: cmp::max(self.hi, other.hi), 5937ac06127Sopenharmony_ci }) 5947ac06127Sopenharmony_ci }) 5957ac06127Sopenharmony_ci } 5967ac06127Sopenharmony_ci 5977ac06127Sopenharmony_ci #[cfg(not(span_locations))] 5987ac06127Sopenharmony_ci pub fn source_text(&self) -> Option<String> { 5997ac06127Sopenharmony_ci None 6007ac06127Sopenharmony_ci } 6017ac06127Sopenharmony_ci 6027ac06127Sopenharmony_ci #[cfg(span_locations)] 6037ac06127Sopenharmony_ci pub fn source_text(&self) -> Option<String> { 6047ac06127Sopenharmony_ci #[cfg(fuzzing)] 6057ac06127Sopenharmony_ci return None; 6067ac06127Sopenharmony_ci 6077ac06127Sopenharmony_ci #[cfg(not(fuzzing))] 6087ac06127Sopenharmony_ci { 6097ac06127Sopenharmony_ci if self.is_call_site() { 6107ac06127Sopenharmony_ci None 6117ac06127Sopenharmony_ci } else { 6127ac06127Sopenharmony_ci Some(SOURCE_MAP.with(|cm| cm.borrow_mut().fileinfo_mut(*self).source_text(*self))) 6137ac06127Sopenharmony_ci } 6147ac06127Sopenharmony_ci } 6157ac06127Sopenharmony_ci } 6167ac06127Sopenharmony_ci 6177ac06127Sopenharmony_ci #[cfg(not(span_locations))] 6187ac06127Sopenharmony_ci pub(crate) fn first_byte(self) -> Self { 6197ac06127Sopenharmony_ci self 6207ac06127Sopenharmony_ci } 6217ac06127Sopenharmony_ci 6227ac06127Sopenharmony_ci #[cfg(span_locations)] 6237ac06127Sopenharmony_ci pub(crate) fn first_byte(self) -> Self { 6247ac06127Sopenharmony_ci Span { 6257ac06127Sopenharmony_ci lo: self.lo, 6267ac06127Sopenharmony_ci hi: cmp::min(self.lo.saturating_add(1), self.hi), 6277ac06127Sopenharmony_ci } 6287ac06127Sopenharmony_ci } 6297ac06127Sopenharmony_ci 6307ac06127Sopenharmony_ci #[cfg(not(span_locations))] 6317ac06127Sopenharmony_ci pub(crate) fn last_byte(self) -> Self { 6327ac06127Sopenharmony_ci self 6337ac06127Sopenharmony_ci } 6347ac06127Sopenharmony_ci 6357ac06127Sopenharmony_ci #[cfg(span_locations)] 6367ac06127Sopenharmony_ci pub(crate) fn last_byte(self) -> Self { 6377ac06127Sopenharmony_ci Span { 6387ac06127Sopenharmony_ci lo: cmp::max(self.hi.saturating_sub(1), self.lo), 6397ac06127Sopenharmony_ci hi: self.hi, 6407ac06127Sopenharmony_ci } 6417ac06127Sopenharmony_ci } 6427ac06127Sopenharmony_ci 6437ac06127Sopenharmony_ci #[cfg(span_locations)] 6447ac06127Sopenharmony_ci fn is_call_site(&self) -> bool { 6457ac06127Sopenharmony_ci self.lo == 0 && self.hi == 0 6467ac06127Sopenharmony_ci } 6477ac06127Sopenharmony_ci} 6487ac06127Sopenharmony_ci 6497ac06127Sopenharmony_ciimpl Debug for Span { 6507ac06127Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 6517ac06127Sopenharmony_ci #[cfg(span_locations)] 6527ac06127Sopenharmony_ci return write!(f, "bytes({}..{})", self.lo, self.hi); 6537ac06127Sopenharmony_ci 6547ac06127Sopenharmony_ci #[cfg(not(span_locations))] 6557ac06127Sopenharmony_ci write!(f, "Span") 6567ac06127Sopenharmony_ci } 6577ac06127Sopenharmony_ci} 6587ac06127Sopenharmony_ci 6597ac06127Sopenharmony_cipub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { 6607ac06127Sopenharmony_ci #[cfg(span_locations)] 6617ac06127Sopenharmony_ci { 6627ac06127Sopenharmony_ci if span.is_call_site() { 6637ac06127Sopenharmony_ci return; 6647ac06127Sopenharmony_ci } 6657ac06127Sopenharmony_ci } 6667ac06127Sopenharmony_ci 6677ac06127Sopenharmony_ci if cfg!(span_locations) { 6687ac06127Sopenharmony_ci debug.field("span", &span); 6697ac06127Sopenharmony_ci } 6707ac06127Sopenharmony_ci} 6717ac06127Sopenharmony_ci 6727ac06127Sopenharmony_ci#[derive(Clone)] 6737ac06127Sopenharmony_cipub(crate) struct Group { 6747ac06127Sopenharmony_ci delimiter: Delimiter, 6757ac06127Sopenharmony_ci stream: TokenStream, 6767ac06127Sopenharmony_ci span: Span, 6777ac06127Sopenharmony_ci} 6787ac06127Sopenharmony_ci 6797ac06127Sopenharmony_ciimpl Group { 6807ac06127Sopenharmony_ci pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self { 6817ac06127Sopenharmony_ci Group { 6827ac06127Sopenharmony_ci delimiter, 6837ac06127Sopenharmony_ci stream, 6847ac06127Sopenharmony_ci span: Span::call_site(), 6857ac06127Sopenharmony_ci } 6867ac06127Sopenharmony_ci } 6877ac06127Sopenharmony_ci 6887ac06127Sopenharmony_ci pub fn delimiter(&self) -> Delimiter { 6897ac06127Sopenharmony_ci self.delimiter 6907ac06127Sopenharmony_ci } 6917ac06127Sopenharmony_ci 6927ac06127Sopenharmony_ci pub fn stream(&self) -> TokenStream { 6937ac06127Sopenharmony_ci self.stream.clone() 6947ac06127Sopenharmony_ci } 6957ac06127Sopenharmony_ci 6967ac06127Sopenharmony_ci pub fn span(&self) -> Span { 6977ac06127Sopenharmony_ci self.span 6987ac06127Sopenharmony_ci } 6997ac06127Sopenharmony_ci 7007ac06127Sopenharmony_ci pub fn span_open(&self) -> Span { 7017ac06127Sopenharmony_ci self.span.first_byte() 7027ac06127Sopenharmony_ci } 7037ac06127Sopenharmony_ci 7047ac06127Sopenharmony_ci pub fn span_close(&self) -> Span { 7057ac06127Sopenharmony_ci self.span.last_byte() 7067ac06127Sopenharmony_ci } 7077ac06127Sopenharmony_ci 7087ac06127Sopenharmony_ci pub fn set_span(&mut self, span: Span) { 7097ac06127Sopenharmony_ci self.span = span; 7107ac06127Sopenharmony_ci } 7117ac06127Sopenharmony_ci} 7127ac06127Sopenharmony_ci 7137ac06127Sopenharmony_ciimpl Display for Group { 7147ac06127Sopenharmony_ci // We attempt to match libproc_macro's formatting. 7157ac06127Sopenharmony_ci // Empty parens: () 7167ac06127Sopenharmony_ci // Nonempty parens: (...) 7177ac06127Sopenharmony_ci // Empty brackets: [] 7187ac06127Sopenharmony_ci // Nonempty brackets: [...] 7197ac06127Sopenharmony_ci // Empty braces: { } 7207ac06127Sopenharmony_ci // Nonempty braces: { ... } 7217ac06127Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 7227ac06127Sopenharmony_ci let (open, close) = match self.delimiter { 7237ac06127Sopenharmony_ci Delimiter::Parenthesis => ("(", ")"), 7247ac06127Sopenharmony_ci Delimiter::Brace => ("{ ", "}"), 7257ac06127Sopenharmony_ci Delimiter::Bracket => ("[", "]"), 7267ac06127Sopenharmony_ci Delimiter::None => ("", ""), 7277ac06127Sopenharmony_ci }; 7287ac06127Sopenharmony_ci 7297ac06127Sopenharmony_ci f.write_str(open)?; 7307ac06127Sopenharmony_ci Display::fmt(&self.stream, f)?; 7317ac06127Sopenharmony_ci if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() { 7327ac06127Sopenharmony_ci f.write_str(" ")?; 7337ac06127Sopenharmony_ci } 7347ac06127Sopenharmony_ci f.write_str(close)?; 7357ac06127Sopenharmony_ci 7367ac06127Sopenharmony_ci Ok(()) 7377ac06127Sopenharmony_ci } 7387ac06127Sopenharmony_ci} 7397ac06127Sopenharmony_ci 7407ac06127Sopenharmony_ciimpl Debug for Group { 7417ac06127Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 7427ac06127Sopenharmony_ci let mut debug = fmt.debug_struct("Group"); 7437ac06127Sopenharmony_ci debug.field("delimiter", &self.delimiter); 7447ac06127Sopenharmony_ci debug.field("stream", &self.stream); 7457ac06127Sopenharmony_ci debug_span_field_if_nontrivial(&mut debug, self.span); 7467ac06127Sopenharmony_ci debug.finish() 7477ac06127Sopenharmony_ci } 7487ac06127Sopenharmony_ci} 7497ac06127Sopenharmony_ci 7507ac06127Sopenharmony_ci#[derive(Clone)] 7517ac06127Sopenharmony_cipub(crate) struct Ident { 7527ac06127Sopenharmony_ci sym: String, 7537ac06127Sopenharmony_ci span: Span, 7547ac06127Sopenharmony_ci raw: bool, 7557ac06127Sopenharmony_ci} 7567ac06127Sopenharmony_ci 7577ac06127Sopenharmony_ciimpl Ident { 7587ac06127Sopenharmony_ci #[track_caller] 7597ac06127Sopenharmony_ci pub fn new_checked(string: &str, span: Span) -> Self { 7607ac06127Sopenharmony_ci validate_ident(string); 7617ac06127Sopenharmony_ci Ident::new_unchecked(string, span) 7627ac06127Sopenharmony_ci } 7637ac06127Sopenharmony_ci 7647ac06127Sopenharmony_ci pub fn new_unchecked(string: &str, span: Span) -> Self { 7657ac06127Sopenharmony_ci Ident { 7667ac06127Sopenharmony_ci sym: string.to_owned(), 7677ac06127Sopenharmony_ci span, 7687ac06127Sopenharmony_ci raw: false, 7697ac06127Sopenharmony_ci } 7707ac06127Sopenharmony_ci } 7717ac06127Sopenharmony_ci 7727ac06127Sopenharmony_ci #[track_caller] 7737ac06127Sopenharmony_ci pub fn new_raw_checked(string: &str, span: Span) -> Self { 7747ac06127Sopenharmony_ci validate_ident_raw(string); 7757ac06127Sopenharmony_ci Ident::new_raw_unchecked(string, span) 7767ac06127Sopenharmony_ci } 7777ac06127Sopenharmony_ci 7787ac06127Sopenharmony_ci pub fn new_raw_unchecked(string: &str, span: Span) -> Self { 7797ac06127Sopenharmony_ci Ident { 7807ac06127Sopenharmony_ci sym: string.to_owned(), 7817ac06127Sopenharmony_ci span, 7827ac06127Sopenharmony_ci raw: true, 7837ac06127Sopenharmony_ci } 7847ac06127Sopenharmony_ci } 7857ac06127Sopenharmony_ci 7867ac06127Sopenharmony_ci pub fn span(&self) -> Span { 7877ac06127Sopenharmony_ci self.span 7887ac06127Sopenharmony_ci } 7897ac06127Sopenharmony_ci 7907ac06127Sopenharmony_ci pub fn set_span(&mut self, span: Span) { 7917ac06127Sopenharmony_ci self.span = span; 7927ac06127Sopenharmony_ci } 7937ac06127Sopenharmony_ci} 7947ac06127Sopenharmony_ci 7957ac06127Sopenharmony_cipub(crate) fn is_ident_start(c: char) -> bool { 7967ac06127Sopenharmony_ci c == '_' || unicode_ident::is_xid_start(c) 7977ac06127Sopenharmony_ci} 7987ac06127Sopenharmony_ci 7997ac06127Sopenharmony_cipub(crate) fn is_ident_continue(c: char) -> bool { 8007ac06127Sopenharmony_ci unicode_ident::is_xid_continue(c) 8017ac06127Sopenharmony_ci} 8027ac06127Sopenharmony_ci 8037ac06127Sopenharmony_ci#[track_caller] 8047ac06127Sopenharmony_cifn validate_ident(string: &str) { 8057ac06127Sopenharmony_ci if string.is_empty() { 8067ac06127Sopenharmony_ci panic!("Ident is not allowed to be empty; use Option<Ident>"); 8077ac06127Sopenharmony_ci } 8087ac06127Sopenharmony_ci 8097ac06127Sopenharmony_ci if string.bytes().all(|digit| b'0' <= digit && digit <= b'9') { 8107ac06127Sopenharmony_ci panic!("Ident cannot be a number; use Literal instead"); 8117ac06127Sopenharmony_ci } 8127ac06127Sopenharmony_ci 8137ac06127Sopenharmony_ci fn ident_ok(string: &str) -> bool { 8147ac06127Sopenharmony_ci let mut chars = string.chars(); 8157ac06127Sopenharmony_ci let first = chars.next().unwrap(); 8167ac06127Sopenharmony_ci if !is_ident_start(first) { 8177ac06127Sopenharmony_ci return false; 8187ac06127Sopenharmony_ci } 8197ac06127Sopenharmony_ci for ch in chars { 8207ac06127Sopenharmony_ci if !is_ident_continue(ch) { 8217ac06127Sopenharmony_ci return false; 8227ac06127Sopenharmony_ci } 8237ac06127Sopenharmony_ci } 8247ac06127Sopenharmony_ci true 8257ac06127Sopenharmony_ci } 8267ac06127Sopenharmony_ci 8277ac06127Sopenharmony_ci if !ident_ok(string) { 8287ac06127Sopenharmony_ci panic!("{:?} is not a valid Ident", string); 8297ac06127Sopenharmony_ci } 8307ac06127Sopenharmony_ci} 8317ac06127Sopenharmony_ci 8327ac06127Sopenharmony_ci#[track_caller] 8337ac06127Sopenharmony_cifn validate_ident_raw(string: &str) { 8347ac06127Sopenharmony_ci validate_ident(string); 8357ac06127Sopenharmony_ci 8367ac06127Sopenharmony_ci match string { 8377ac06127Sopenharmony_ci "_" | "super" | "self" | "Self" | "crate" => { 8387ac06127Sopenharmony_ci panic!("`r#{}` cannot be a raw identifier", string); 8397ac06127Sopenharmony_ci } 8407ac06127Sopenharmony_ci _ => {} 8417ac06127Sopenharmony_ci } 8427ac06127Sopenharmony_ci} 8437ac06127Sopenharmony_ci 8447ac06127Sopenharmony_ciimpl PartialEq for Ident { 8457ac06127Sopenharmony_ci fn eq(&self, other: &Ident) -> bool { 8467ac06127Sopenharmony_ci self.sym == other.sym && self.raw == other.raw 8477ac06127Sopenharmony_ci } 8487ac06127Sopenharmony_ci} 8497ac06127Sopenharmony_ci 8507ac06127Sopenharmony_ciimpl<T> PartialEq<T> for Ident 8517ac06127Sopenharmony_ciwhere 8527ac06127Sopenharmony_ci T: ?Sized + AsRef<str>, 8537ac06127Sopenharmony_ci{ 8547ac06127Sopenharmony_ci fn eq(&self, other: &T) -> bool { 8557ac06127Sopenharmony_ci let other = other.as_ref(); 8567ac06127Sopenharmony_ci if self.raw { 8577ac06127Sopenharmony_ci other.starts_with("r#") && self.sym == other[2..] 8587ac06127Sopenharmony_ci } else { 8597ac06127Sopenharmony_ci self.sym == other 8607ac06127Sopenharmony_ci } 8617ac06127Sopenharmony_ci } 8627ac06127Sopenharmony_ci} 8637ac06127Sopenharmony_ci 8647ac06127Sopenharmony_ciimpl Display for Ident { 8657ac06127Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 8667ac06127Sopenharmony_ci if self.raw { 8677ac06127Sopenharmony_ci f.write_str("r#")?; 8687ac06127Sopenharmony_ci } 8697ac06127Sopenharmony_ci Display::fmt(&self.sym, f) 8707ac06127Sopenharmony_ci } 8717ac06127Sopenharmony_ci} 8727ac06127Sopenharmony_ci 8737ac06127Sopenharmony_ci#[allow(clippy::missing_fields_in_debug)] 8747ac06127Sopenharmony_ciimpl Debug for Ident { 8757ac06127Sopenharmony_ci // Ident(proc_macro), Ident(r#union) 8767ac06127Sopenharmony_ci #[cfg(not(span_locations))] 8777ac06127Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 8787ac06127Sopenharmony_ci let mut debug = f.debug_tuple("Ident"); 8797ac06127Sopenharmony_ci debug.field(&format_args!("{}", self)); 8807ac06127Sopenharmony_ci debug.finish() 8817ac06127Sopenharmony_ci } 8827ac06127Sopenharmony_ci 8837ac06127Sopenharmony_ci // Ident { 8847ac06127Sopenharmony_ci // sym: proc_macro, 8857ac06127Sopenharmony_ci // span: bytes(128..138) 8867ac06127Sopenharmony_ci // } 8877ac06127Sopenharmony_ci #[cfg(span_locations)] 8887ac06127Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 8897ac06127Sopenharmony_ci let mut debug = f.debug_struct("Ident"); 8907ac06127Sopenharmony_ci debug.field("sym", &format_args!("{}", self)); 8917ac06127Sopenharmony_ci debug_span_field_if_nontrivial(&mut debug, self.span); 8927ac06127Sopenharmony_ci debug.finish() 8937ac06127Sopenharmony_ci } 8947ac06127Sopenharmony_ci} 8957ac06127Sopenharmony_ci 8967ac06127Sopenharmony_ci#[derive(Clone)] 8977ac06127Sopenharmony_cipub(crate) struct Literal { 8987ac06127Sopenharmony_ci repr: String, 8997ac06127Sopenharmony_ci span: Span, 9007ac06127Sopenharmony_ci} 9017ac06127Sopenharmony_ci 9027ac06127Sopenharmony_cimacro_rules! suffixed_numbers { 9037ac06127Sopenharmony_ci ($($name:ident => $kind:ident,)*) => ($( 9047ac06127Sopenharmony_ci pub fn $name(n: $kind) -> Literal { 9057ac06127Sopenharmony_ci Literal::_new(format!(concat!("{}", stringify!($kind)), n)) 9067ac06127Sopenharmony_ci } 9077ac06127Sopenharmony_ci )*) 9087ac06127Sopenharmony_ci} 9097ac06127Sopenharmony_ci 9107ac06127Sopenharmony_cimacro_rules! unsuffixed_numbers { 9117ac06127Sopenharmony_ci ($($name:ident => $kind:ident,)*) => ($( 9127ac06127Sopenharmony_ci pub fn $name(n: $kind) -> Literal { 9137ac06127Sopenharmony_ci Literal::_new(n.to_string()) 9147ac06127Sopenharmony_ci } 9157ac06127Sopenharmony_ci )*) 9167ac06127Sopenharmony_ci} 9177ac06127Sopenharmony_ci 9187ac06127Sopenharmony_ciimpl Literal { 9197ac06127Sopenharmony_ci pub(crate) fn _new(repr: String) -> Self { 9207ac06127Sopenharmony_ci Literal { 9217ac06127Sopenharmony_ci repr, 9227ac06127Sopenharmony_ci span: Span::call_site(), 9237ac06127Sopenharmony_ci } 9247ac06127Sopenharmony_ci } 9257ac06127Sopenharmony_ci 9267ac06127Sopenharmony_ci pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self { 9277ac06127Sopenharmony_ci Literal::_new(repr.to_owned()) 9287ac06127Sopenharmony_ci } 9297ac06127Sopenharmony_ci 9307ac06127Sopenharmony_ci suffixed_numbers! { 9317ac06127Sopenharmony_ci u8_suffixed => u8, 9327ac06127Sopenharmony_ci u16_suffixed => u16, 9337ac06127Sopenharmony_ci u32_suffixed => u32, 9347ac06127Sopenharmony_ci u64_suffixed => u64, 9357ac06127Sopenharmony_ci u128_suffixed => u128, 9367ac06127Sopenharmony_ci usize_suffixed => usize, 9377ac06127Sopenharmony_ci i8_suffixed => i8, 9387ac06127Sopenharmony_ci i16_suffixed => i16, 9397ac06127Sopenharmony_ci i32_suffixed => i32, 9407ac06127Sopenharmony_ci i64_suffixed => i64, 9417ac06127Sopenharmony_ci i128_suffixed => i128, 9427ac06127Sopenharmony_ci isize_suffixed => isize, 9437ac06127Sopenharmony_ci 9447ac06127Sopenharmony_ci f32_suffixed => f32, 9457ac06127Sopenharmony_ci f64_suffixed => f64, 9467ac06127Sopenharmony_ci } 9477ac06127Sopenharmony_ci 9487ac06127Sopenharmony_ci unsuffixed_numbers! { 9497ac06127Sopenharmony_ci u8_unsuffixed => u8, 9507ac06127Sopenharmony_ci u16_unsuffixed => u16, 9517ac06127Sopenharmony_ci u32_unsuffixed => u32, 9527ac06127Sopenharmony_ci u64_unsuffixed => u64, 9537ac06127Sopenharmony_ci u128_unsuffixed => u128, 9547ac06127Sopenharmony_ci usize_unsuffixed => usize, 9557ac06127Sopenharmony_ci i8_unsuffixed => i8, 9567ac06127Sopenharmony_ci i16_unsuffixed => i16, 9577ac06127Sopenharmony_ci i32_unsuffixed => i32, 9587ac06127Sopenharmony_ci i64_unsuffixed => i64, 9597ac06127Sopenharmony_ci i128_unsuffixed => i128, 9607ac06127Sopenharmony_ci isize_unsuffixed => isize, 9617ac06127Sopenharmony_ci } 9627ac06127Sopenharmony_ci 9637ac06127Sopenharmony_ci pub fn f32_unsuffixed(f: f32) -> Literal { 9647ac06127Sopenharmony_ci let mut s = f.to_string(); 9657ac06127Sopenharmony_ci if !s.contains('.') { 9667ac06127Sopenharmony_ci s.push_str(".0"); 9677ac06127Sopenharmony_ci } 9687ac06127Sopenharmony_ci Literal::_new(s) 9697ac06127Sopenharmony_ci } 9707ac06127Sopenharmony_ci 9717ac06127Sopenharmony_ci pub fn f64_unsuffixed(f: f64) -> Literal { 9727ac06127Sopenharmony_ci let mut s = f.to_string(); 9737ac06127Sopenharmony_ci if !s.contains('.') { 9747ac06127Sopenharmony_ci s.push_str(".0"); 9757ac06127Sopenharmony_ci } 9767ac06127Sopenharmony_ci Literal::_new(s) 9777ac06127Sopenharmony_ci } 9787ac06127Sopenharmony_ci 9797ac06127Sopenharmony_ci pub fn string(t: &str) -> Literal { 9807ac06127Sopenharmony_ci let mut repr = String::with_capacity(t.len() + 2); 9817ac06127Sopenharmony_ci repr.push('"'); 9827ac06127Sopenharmony_ci let mut chars = t.chars(); 9837ac06127Sopenharmony_ci while let Some(ch) = chars.next() { 9847ac06127Sopenharmony_ci if ch == '\0' { 9857ac06127Sopenharmony_ci repr.push_str( 9867ac06127Sopenharmony_ci if chars 9877ac06127Sopenharmony_ci .as_str() 9887ac06127Sopenharmony_ci .starts_with(|next| '0' <= next && next <= '7') 9897ac06127Sopenharmony_ci { 9907ac06127Sopenharmony_ci // circumvent clippy::octal_escapes lint 9917ac06127Sopenharmony_ci "\\x00" 9927ac06127Sopenharmony_ci } else { 9937ac06127Sopenharmony_ci "\\0" 9947ac06127Sopenharmony_ci }, 9957ac06127Sopenharmony_ci ); 9967ac06127Sopenharmony_ci } else if ch == '\'' { 9977ac06127Sopenharmony_ci // escape_debug turns this into "\'" which is unnecessary. 9987ac06127Sopenharmony_ci repr.push(ch); 9997ac06127Sopenharmony_ci } else { 10007ac06127Sopenharmony_ci repr.extend(ch.escape_debug()); 10017ac06127Sopenharmony_ci } 10027ac06127Sopenharmony_ci } 10037ac06127Sopenharmony_ci repr.push('"'); 10047ac06127Sopenharmony_ci Literal::_new(repr) 10057ac06127Sopenharmony_ci } 10067ac06127Sopenharmony_ci 10077ac06127Sopenharmony_ci pub fn character(t: char) -> Literal { 10087ac06127Sopenharmony_ci let mut repr = String::new(); 10097ac06127Sopenharmony_ci repr.push('\''); 10107ac06127Sopenharmony_ci if t == '"' { 10117ac06127Sopenharmony_ci // escape_debug turns this into '\"' which is unnecessary. 10127ac06127Sopenharmony_ci repr.push(t); 10137ac06127Sopenharmony_ci } else { 10147ac06127Sopenharmony_ci repr.extend(t.escape_debug()); 10157ac06127Sopenharmony_ci } 10167ac06127Sopenharmony_ci repr.push('\''); 10177ac06127Sopenharmony_ci Literal::_new(repr) 10187ac06127Sopenharmony_ci } 10197ac06127Sopenharmony_ci 10207ac06127Sopenharmony_ci pub fn byte_string(bytes: &[u8]) -> Literal { 10217ac06127Sopenharmony_ci let mut escaped = "b\"".to_string(); 10227ac06127Sopenharmony_ci let mut bytes = bytes.iter(); 10237ac06127Sopenharmony_ci while let Some(&b) = bytes.next() { 10247ac06127Sopenharmony_ci #[allow(clippy::match_overlapping_arm)] 10257ac06127Sopenharmony_ci match b { 10267ac06127Sopenharmony_ci b'\0' => escaped.push_str(match bytes.as_slice().first() { 10277ac06127Sopenharmony_ci // circumvent clippy::octal_escapes lint 10287ac06127Sopenharmony_ci Some(b'0'..=b'7') => r"\x00", 10297ac06127Sopenharmony_ci _ => r"\0", 10307ac06127Sopenharmony_ci }), 10317ac06127Sopenharmony_ci b'\t' => escaped.push_str(r"\t"), 10327ac06127Sopenharmony_ci b'\n' => escaped.push_str(r"\n"), 10337ac06127Sopenharmony_ci b'\r' => escaped.push_str(r"\r"), 10347ac06127Sopenharmony_ci b'"' => escaped.push_str("\\\""), 10357ac06127Sopenharmony_ci b'\\' => escaped.push_str("\\\\"), 10367ac06127Sopenharmony_ci b'\x20'..=b'\x7E' => escaped.push(b as char), 10377ac06127Sopenharmony_ci _ => { 10387ac06127Sopenharmony_ci let _ = write!(escaped, "\\x{:02X}", b); 10397ac06127Sopenharmony_ci } 10407ac06127Sopenharmony_ci } 10417ac06127Sopenharmony_ci } 10427ac06127Sopenharmony_ci escaped.push('"'); 10437ac06127Sopenharmony_ci Literal::_new(escaped) 10447ac06127Sopenharmony_ci } 10457ac06127Sopenharmony_ci 10467ac06127Sopenharmony_ci pub fn span(&self) -> Span { 10477ac06127Sopenharmony_ci self.span 10487ac06127Sopenharmony_ci } 10497ac06127Sopenharmony_ci 10507ac06127Sopenharmony_ci pub fn set_span(&mut self, span: Span) { 10517ac06127Sopenharmony_ci self.span = span; 10527ac06127Sopenharmony_ci } 10537ac06127Sopenharmony_ci 10547ac06127Sopenharmony_ci pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> { 10557ac06127Sopenharmony_ci #[cfg(not(span_locations))] 10567ac06127Sopenharmony_ci { 10577ac06127Sopenharmony_ci let _ = range; 10587ac06127Sopenharmony_ci None 10597ac06127Sopenharmony_ci } 10607ac06127Sopenharmony_ci 10617ac06127Sopenharmony_ci #[cfg(span_locations)] 10627ac06127Sopenharmony_ci { 10637ac06127Sopenharmony_ci use core::ops::Bound; 10647ac06127Sopenharmony_ci 10657ac06127Sopenharmony_ci let lo = match range.start_bound() { 10667ac06127Sopenharmony_ci Bound::Included(start) => { 10677ac06127Sopenharmony_ci let start = u32::try_from(*start).ok()?; 10687ac06127Sopenharmony_ci self.span.lo.checked_add(start)? 10697ac06127Sopenharmony_ci } 10707ac06127Sopenharmony_ci Bound::Excluded(start) => { 10717ac06127Sopenharmony_ci let start = u32::try_from(*start).ok()?; 10727ac06127Sopenharmony_ci self.span.lo.checked_add(start)?.checked_add(1)? 10737ac06127Sopenharmony_ci } 10747ac06127Sopenharmony_ci Bound::Unbounded => self.span.lo, 10757ac06127Sopenharmony_ci }; 10767ac06127Sopenharmony_ci let hi = match range.end_bound() { 10777ac06127Sopenharmony_ci Bound::Included(end) => { 10787ac06127Sopenharmony_ci let end = u32::try_from(*end).ok()?; 10797ac06127Sopenharmony_ci self.span.lo.checked_add(end)?.checked_add(1)? 10807ac06127Sopenharmony_ci } 10817ac06127Sopenharmony_ci Bound::Excluded(end) => { 10827ac06127Sopenharmony_ci let end = u32::try_from(*end).ok()?; 10837ac06127Sopenharmony_ci self.span.lo.checked_add(end)? 10847ac06127Sopenharmony_ci } 10857ac06127Sopenharmony_ci Bound::Unbounded => self.span.hi, 10867ac06127Sopenharmony_ci }; 10877ac06127Sopenharmony_ci if lo <= hi && hi <= self.span.hi { 10887ac06127Sopenharmony_ci Some(Span { lo, hi }) 10897ac06127Sopenharmony_ci } else { 10907ac06127Sopenharmony_ci None 10917ac06127Sopenharmony_ci } 10927ac06127Sopenharmony_ci } 10937ac06127Sopenharmony_ci } 10947ac06127Sopenharmony_ci} 10957ac06127Sopenharmony_ci 10967ac06127Sopenharmony_ciimpl FromStr for Literal { 10977ac06127Sopenharmony_ci type Err = LexError; 10987ac06127Sopenharmony_ci 10997ac06127Sopenharmony_ci fn from_str(repr: &str) -> Result<Self, Self::Err> { 11007ac06127Sopenharmony_ci let mut cursor = get_cursor(repr); 11017ac06127Sopenharmony_ci #[cfg(span_locations)] 11027ac06127Sopenharmony_ci let lo = cursor.off; 11037ac06127Sopenharmony_ci 11047ac06127Sopenharmony_ci let negative = cursor.starts_with_char('-'); 11057ac06127Sopenharmony_ci if negative { 11067ac06127Sopenharmony_ci cursor = cursor.advance(1); 11077ac06127Sopenharmony_ci if !cursor.starts_with_fn(|ch| ch.is_ascii_digit()) { 11087ac06127Sopenharmony_ci return Err(LexError::call_site()); 11097ac06127Sopenharmony_ci } 11107ac06127Sopenharmony_ci } 11117ac06127Sopenharmony_ci 11127ac06127Sopenharmony_ci if let Ok((rest, mut literal)) = parse::literal(cursor) { 11137ac06127Sopenharmony_ci if rest.is_empty() { 11147ac06127Sopenharmony_ci if negative { 11157ac06127Sopenharmony_ci literal.repr.insert(0, '-'); 11167ac06127Sopenharmony_ci } 11177ac06127Sopenharmony_ci literal.span = Span { 11187ac06127Sopenharmony_ci #[cfg(span_locations)] 11197ac06127Sopenharmony_ci lo, 11207ac06127Sopenharmony_ci #[cfg(span_locations)] 11217ac06127Sopenharmony_ci hi: rest.off, 11227ac06127Sopenharmony_ci }; 11237ac06127Sopenharmony_ci return Ok(literal); 11247ac06127Sopenharmony_ci } 11257ac06127Sopenharmony_ci } 11267ac06127Sopenharmony_ci Err(LexError::call_site()) 11277ac06127Sopenharmony_ci } 11287ac06127Sopenharmony_ci} 11297ac06127Sopenharmony_ci 11307ac06127Sopenharmony_ciimpl Display for Literal { 11317ac06127Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 11327ac06127Sopenharmony_ci Display::fmt(&self.repr, f) 11337ac06127Sopenharmony_ci } 11347ac06127Sopenharmony_ci} 11357ac06127Sopenharmony_ci 11367ac06127Sopenharmony_ciimpl Debug for Literal { 11377ac06127Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 11387ac06127Sopenharmony_ci let mut debug = fmt.debug_struct("Literal"); 11397ac06127Sopenharmony_ci debug.field("lit", &format_args!("{}", self.repr)); 11407ac06127Sopenharmony_ci debug_span_field_if_nontrivial(&mut debug, self.span); 11417ac06127Sopenharmony_ci debug.finish() 11427ac06127Sopenharmony_ci } 11437ac06127Sopenharmony_ci} 1144