diff options
| author | Robin Krahl <robin.krahl@ireas.org> | 2020-01-07 11:18:04 +0000 | 
|---|---|---|
| committer | Daniel Mueller <deso@posteo.net> | 2020-01-08 09:20:25 -0800 | 
| commit | 5e20a29b4fdc8a2d442d1093681b396dcb4b816b (patch) | |
| tree | 55ab083fa8999d2ccbb5e921c1ffe52560dca152 /proc-macro2/src | |
| parent | 203e691f46d591a2cc8acdfd850fa9f5b0fb8a98 (diff) | |
| download | nitrocli-5e20a29b4fdc8a2d442d1093681b396dcb4b816b.tar.gz nitrocli-5e20a29b4fdc8a2d442d1093681b396dcb4b816b.tar.bz2 | |
Add structopt dependency in version 0.3.7
This patch series replaces argparse with structopt in the argument
handling code. As a first step, we need structopt as a dependency.
Import subrepo structopt/:structopt at efbdda4753592e27bc430fb01f7b9650b2f3174d
Import subrepo bitflags/:bitflags at 30668016aca6bd3b02c766e8347e0b4080d4c296
Import subrepo clap/:clap at 784524f7eb193e35f81082cc69454c8c21b948f7
Import subrepo heck/:heck at 093d56fbf001e1506e56dbfa38631d99b1066df1
Import subrepo proc-macro-error/:proc-macro-error at 6c4cfe79a622c5de8ae68557993542be46eacae2
Import subrepo proc-macro2/:proc-macro2 at d5d48eddca4566e5438e8a2cbed4a74e049544de
Import subrepo quote/:quote at 727436c6c137b20f0f34dde5d8fda2679b9747ad
Import subrepo rustversion/:rustversion at 0c5663313516263059ce9059ef81fc7a1cf655ca
Import subrepo syn-mid/:syn-mid at 5d3d85414a9e6674e1857ec22a87b96e04a6851a
Import subrepo syn/:syn at e87c27e87f6f4ef8919d0372bdb056d53ef0d8f3
Import subrepo textwrap/:textwrap at abcd618beae3f74841032aa5b53c1086b0a57ca2
Import subrepo unicode-segmentation/:unicode-segmentation at 637c9874c4fe0c205ff27787faf150a40295c6c3
Import subrepo unicode-width/:unicode-width at 3033826f8bf05e82724140a981d5941e48fce393
Import subrepo unicode-xid/:unicode-xid at 4baae9fffb156ba229665b972a9cd5991787ceb7
Diffstat (limited to 'proc-macro2/src')
| -rw-r--r-- | proc-macro2/src/fallback.rs | 1458 | ||||
| -rw-r--r-- | proc-macro2/src/lib.rs | 1199 | ||||
| -rw-r--r-- | proc-macro2/src/strnom.rs | 391 | ||||
| -rw-r--r-- | proc-macro2/src/wrapper.rs | 927 | 
4 files changed, 3975 insertions, 0 deletions
| diff --git a/proc-macro2/src/fallback.rs b/proc-macro2/src/fallback.rs new file mode 100644 index 0000000..9762d3b --- /dev/null +++ b/proc-macro2/src/fallback.rs @@ -0,0 +1,1458 @@ +#[cfg(span_locations)] +use std::cell::RefCell; +#[cfg(span_locations)] +use std::cmp; +use std::fmt; +use std::iter; +use std::ops::RangeBounds; +#[cfg(procmacro2_semver_exempt)] +use std::path::Path; +use std::path::PathBuf; +use std::str::FromStr; +use std::vec; + +use crate::strnom::{block_comment, skip_whitespace, whitespace, word_break, Cursor, PResult}; +use crate::{Delimiter, Punct, Spacing, TokenTree}; +use unicode_xid::UnicodeXID; + +#[derive(Clone)] +pub struct TokenStream { +    inner: Vec<TokenTree>, +} + +#[derive(Debug)] +pub struct LexError; + +impl TokenStream { +    pub fn new() -> TokenStream { +        TokenStream { inner: Vec::new() } +    } + +    pub fn is_empty(&self) -> bool { +        self.inner.len() == 0 +    } +} + +#[cfg(span_locations)] +fn get_cursor(src: &str) -> Cursor { +    // Create a dummy file & add it to the source map +    SOURCE_MAP.with(|cm| { +        let mut cm = cm.borrow_mut(); +        let name = format!("<parsed string {}>", cm.files.len()); +        let span = cm.add_file(&name, src); +        Cursor { +            rest: src, +            off: span.lo, +        } +    }) +} + +#[cfg(not(span_locations))] +fn get_cursor(src: &str) -> Cursor { +    Cursor { rest: src } +} + +impl FromStr for TokenStream { +    type Err = LexError; + +    fn from_str(src: &str) -> Result<TokenStream, LexError> { +        // Create a dummy file & add it to the source map +        let cursor = get_cursor(src); + +        match token_stream(cursor) { +            Ok((input, output)) => { +                if skip_whitespace(input).len() != 0 { +                    Err(LexError) +                } else { +                    Ok(output) +                } +            } +            Err(LexError) => Err(LexError), +        } +    } +} + +impl fmt::Display for TokenStream { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        let mut joint = false; +        for (i, tt) in self.inner.iter().enumerate() { +            if i != 0 && !joint { +                write!(f, " ")?; +            } +            joint = false; +            match *tt { +                TokenTree::Group(ref tt) => { +                    let (start, end) = match tt.delimiter() { +                        Delimiter::Parenthesis => ("(", ")"), +                        Delimiter::Brace => ("{", "}"), +                        Delimiter::Bracket => ("[", "]"), +                        Delimiter::None => ("", ""), +                    }; +                    if tt.stream().into_iter().next().is_none() { +                        write!(f, "{} {}", start, end)? +                    } else { +                        write!(f, "{} {} {}", start, tt.stream(), end)? +                    } +                } +                TokenTree::Ident(ref tt) => write!(f, "{}", tt)?, +                TokenTree::Punct(ref tt) => { +                    write!(f, "{}", tt.as_char())?; +                    match tt.spacing() { +                        Spacing::Alone => {} +                        Spacing::Joint => joint = true, +                    } +                } +                TokenTree::Literal(ref tt) => write!(f, "{}", tt)?, +            } +        } + +        Ok(()) +    } +} + +impl fmt::Debug for TokenStream { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        f.write_str("TokenStream ")?; +        f.debug_list().entries(self.clone()).finish() +    } +} + +#[cfg(use_proc_macro)] +impl From<proc_macro::TokenStream> for TokenStream { +    fn from(inner: proc_macro::TokenStream) -> TokenStream { +        inner +            .to_string() +            .parse() +            .expect("compiler token stream parse failed") +    } +} + +#[cfg(use_proc_macro)] +impl From<TokenStream> for proc_macro::TokenStream { +    fn from(inner: TokenStream) -> proc_macro::TokenStream { +        inner +            .to_string() +            .parse() +            .expect("failed to parse to compiler tokens") +    } +} + +impl From<TokenTree> for TokenStream { +    fn from(tree: TokenTree) -> TokenStream { +        TokenStream { inner: vec![tree] } +    } +} + +impl iter::FromIterator<TokenTree> for TokenStream { +    fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self { +        let mut v = Vec::new(); + +        for token in streams.into_iter() { +            v.push(token); +        } + +        TokenStream { inner: v } +    } +} + +impl iter::FromIterator<TokenStream> for TokenStream { +    fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { +        let mut v = Vec::new(); + +        for stream in streams.into_iter() { +            v.extend(stream.inner); +        } + +        TokenStream { inner: v } +    } +} + +impl Extend<TokenTree> for TokenStream { +    fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) { +        self.inner.extend(streams); +    } +} + +impl Extend<TokenStream> for TokenStream { +    fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { +        self.inner +            .extend(streams.into_iter().flat_map(|stream| stream)); +    } +} + +pub type TokenTreeIter = vec::IntoIter<TokenTree>; + +impl IntoIterator for TokenStream { +    type Item = TokenTree; +    type IntoIter = TokenTreeIter; + +    fn into_iter(self) -> TokenTreeIter { +        self.inner.into_iter() +    } +} + +#[derive(Clone, PartialEq, Eq)] +pub struct SourceFile { +    path: PathBuf, +} + +impl SourceFile { +    /// Get the path to this source file as a string. +    pub fn path(&self) -> PathBuf { +        self.path.clone() +    } + +    pub fn is_real(&self) -> bool { +        // XXX(nika): Support real files in the future? +        false +    } +} + +impl fmt::Debug for SourceFile { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        f.debug_struct("SourceFile") +            .field("path", &self.path()) +            .field("is_real", &self.is_real()) +            .finish() +    } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct LineColumn { +    pub line: usize, +    pub column: usize, +} + +#[cfg(span_locations)] +thread_local! { +    static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap { +        // NOTE: We start with a single dummy file which all call_site() and +        // def_site() spans reference. +        files: vec![{ +            #[cfg(procmacro2_semver_exempt)] +            { +                FileInfo { +                    name: "<unspecified>".to_owned(), +                    span: Span { lo: 0, hi: 0 }, +                    lines: vec![0], +                } +            } + +            #[cfg(not(procmacro2_semver_exempt))] +            { +                FileInfo { +                    span: Span { lo: 0, hi: 0 }, +                    lines: vec![0], +                } +            } +        }], +    }); +} + +#[cfg(span_locations)] +struct FileInfo { +    #[cfg(procmacro2_semver_exempt)] +    name: String, +    span: Span, +    lines: Vec<usize>, +} + +#[cfg(span_locations)] +impl FileInfo { +    fn offset_line_column(&self, offset: usize) -> LineColumn { +        assert!(self.span_within(Span { +            lo: offset as u32, +            hi: offset as u32 +        })); +        let offset = offset - self.span.lo as usize; +        match self.lines.binary_search(&offset) { +            Ok(found) => LineColumn { +                line: found + 1, +                column: 0, +            }, +            Err(idx) => LineColumn { +                line: idx, +                column: offset - self.lines[idx - 1], +            }, +        } +    } + +    fn span_within(&self, span: Span) -> bool { +        span.lo >= self.span.lo && span.hi <= self.span.hi +    } +} + +/// Computesthe offsets of each line in the given source string. +#[cfg(span_locations)] +fn lines_offsets(s: &str) -> Vec<usize> { +    let mut lines = vec![0]; +    let mut prev = 0; +    while let Some(len) = s[prev..].find('\n') { +        prev += len + 1; +        lines.push(prev); +    } +    lines +} + +#[cfg(span_locations)] +struct SourceMap { +    files: Vec<FileInfo>, +} + +#[cfg(span_locations)] +impl SourceMap { +    fn next_start_pos(&self) -> u32 { +        // Add 1 so there's always space between files. +        // +        // We'll always have at least 1 file, as we initialize our files list +        // with a dummy file. +        self.files.last().unwrap().span.hi + 1 +    } + +    fn add_file(&mut self, name: &str, src: &str) -> Span { +        let lines = lines_offsets(src); +        let lo = self.next_start_pos(); +        // XXX(nika): Shouild we bother doing a checked cast or checked add here? +        let span = Span { +            lo, +            hi: lo + (src.len() as u32), +        }; + +        #[cfg(procmacro2_semver_exempt)] +        self.files.push(FileInfo { +            name: name.to_owned(), +            span, +            lines, +        }); + +        #[cfg(not(procmacro2_semver_exempt))] +        self.files.push(FileInfo { span, lines }); +        let _ = name; + +        span +    } + +    fn fileinfo(&self, span: Span) -> &FileInfo { +        for file in &self.files { +            if file.span_within(span) { +                return file; +            } +        } +        panic!("Invalid span with no related FileInfo!"); +    } +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct Span { +    #[cfg(span_locations)] +    lo: u32, +    #[cfg(span_locations)] +    hi: u32, +} + +impl Span { +    #[cfg(not(span_locations))] +    pub fn call_site() -> Span { +        Span {} +    } + +    #[cfg(span_locations)] +    pub fn call_site() -> Span { +        Span { lo: 0, hi: 0 } +    } + +    #[cfg(procmacro2_semver_exempt)] +    pub fn def_site() -> Span { +        Span::call_site() +    } + +    #[cfg(procmacro2_semver_exempt)] +    pub fn resolved_at(&self, _other: Span) -> Span { +        // Stable spans consist only of line/column information, so +        // `resolved_at` and `located_at` only select which span the +        // caller wants line/column information from. +        *self +    } + +    #[cfg(procmacro2_semver_exempt)] +    pub fn located_at(&self, other: Span) -> Span { +        other +    } + +    #[cfg(procmacro2_semver_exempt)] +    pub fn source_file(&self) -> SourceFile { +        SOURCE_MAP.with(|cm| { +            let cm = cm.borrow(); +            let fi = cm.fileinfo(*self); +            SourceFile { +                path: Path::new(&fi.name).to_owned(), +            } +        }) +    } + +    #[cfg(span_locations)] +    pub fn start(&self) -> LineColumn { +        SOURCE_MAP.with(|cm| { +            let cm = cm.borrow(); +            let fi = cm.fileinfo(*self); +            fi.offset_line_column(self.lo as usize) +        }) +    } + +    #[cfg(span_locations)] +    pub fn end(&self) -> LineColumn { +        SOURCE_MAP.with(|cm| { +            let cm = cm.borrow(); +            let fi = cm.fileinfo(*self); +            fi.offset_line_column(self.hi as usize) +        }) +    } + +    #[cfg(not(span_locations))] +    pub fn join(&self, _other: Span) -> Option<Span> { +        Some(Span {}) +    } + +    #[cfg(span_locations)] +    pub fn join(&self, other: Span) -> Option<Span> { +        SOURCE_MAP.with(|cm| { +            let cm = cm.borrow(); +            // If `other` is not within the same FileInfo as us, return None. +            if !cm.fileinfo(*self).span_within(other) { +                return None; +            } +            Some(Span { +                lo: cmp::min(self.lo, other.lo), +                hi: cmp::max(self.hi, other.hi), +            }) +        }) +    } + +    #[cfg(not(span_locations))] +    fn first_byte(self) -> Self { +        self +    } + +    #[cfg(span_locations)] +    fn first_byte(self) -> Self { +        Span { +            lo: self.lo, +            hi: cmp::min(self.lo.saturating_add(1), self.hi), +        } +    } + +    #[cfg(not(span_locations))] +    fn last_byte(self) -> Self { +        self +    } + +    #[cfg(span_locations)] +    fn last_byte(self) -> Self { +        Span { +            lo: cmp::max(self.hi.saturating_sub(1), self.lo), +            hi: self.hi, +        } +    } +} + +impl fmt::Debug for Span { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        #[cfg(procmacro2_semver_exempt)] +        return write!(f, "bytes({}..{})", self.lo, self.hi); + +        #[cfg(not(procmacro2_semver_exempt))] +        write!(f, "Span") +    } +} + +pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { +    if cfg!(procmacro2_semver_exempt) { +        debug.field("span", &span); +    } +} + +#[derive(Clone)] +pub struct Group { +    delimiter: Delimiter, +    stream: TokenStream, +    span: Span, +} + +impl Group { +    pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { +        Group { +            delimiter, +            stream, +            span: Span::call_site(), +        } +    } + +    pub fn delimiter(&self) -> Delimiter { +        self.delimiter +    } + +    pub fn stream(&self) -> TokenStream { +        self.stream.clone() +    } + +    pub fn span(&self) -> Span { +        self.span +    } + +    pub fn span_open(&self) -> Span { +        self.span.first_byte() +    } + +    pub fn span_close(&self) -> Span { +        self.span.last_byte() +    } + +    pub fn set_span(&mut self, span: Span) { +        self.span = span; +    } +} + +impl fmt::Display for Group { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        let (left, right) = match self.delimiter { +            Delimiter::Parenthesis => ("(", ")"), +            Delimiter::Brace => ("{", "}"), +            Delimiter::Bracket => ("[", "]"), +            Delimiter::None => ("", ""), +        }; + +        f.write_str(left)?; +        self.stream.fmt(f)?; +        f.write_str(right)?; + +        Ok(()) +    } +} + +impl fmt::Debug for Group { +    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +        let mut debug = fmt.debug_struct("Group"); +        debug.field("delimiter", &self.delimiter); +        debug.field("stream", &self.stream); +        #[cfg(procmacro2_semver_exempt)] +        debug.field("span", &self.span); +        debug.finish() +    } +} + +#[derive(Clone)] +pub struct Ident { +    sym: String, +    span: Span, +    raw: bool, +} + +impl Ident { +    fn _new(string: &str, raw: bool, span: Span) -> Ident { +        validate_ident(string); + +        Ident { +            sym: string.to_owned(), +            span, +            raw, +        } +    } + +    pub fn new(string: &str, span: Span) -> Ident { +        Ident::_new(string, false, span) +    } + +    pub fn new_raw(string: &str, span: Span) -> Ident { +        Ident::_new(string, true, span) +    } + +    pub fn span(&self) -> Span { +        self.span +    } + +    pub fn set_span(&mut self, span: Span) { +        self.span = span; +    } +} + +fn is_ident_start(c: char) -> bool { +    ('a' <= c && c <= 'z') +        || ('A' <= c && c <= 'Z') +        || c == '_' +        || (c > '\x7f' && UnicodeXID::is_xid_start(c)) +} + +fn is_ident_continue(c: char) -> bool { +    ('a' <= c && c <= 'z') +        || ('A' <= c && c <= 'Z') +        || c == '_' +        || ('0' <= c && c <= '9') +        || (c > '\x7f' && UnicodeXID::is_xid_continue(c)) +} + +fn validate_ident(string: &str) { +    let validate = string; +    if validate.is_empty() { +        panic!("Ident is not allowed to be empty; use Option<Ident>"); +    } + +    if validate.bytes().all(|digit| digit >= b'0' && digit <= b'9') { +        panic!("Ident cannot be a number; use Literal instead"); +    } + +    fn ident_ok(string: &str) -> bool { +        let mut chars = string.chars(); +        let first = chars.next().unwrap(); +        if !is_ident_start(first) { +            return false; +        } +        for ch in chars { +            if !is_ident_continue(ch) { +                return false; +            } +        } +        true +    } + +    if !ident_ok(validate) { +        panic!("{:?} is not a valid Ident", string); +    } +} + +impl PartialEq for Ident { +    fn eq(&self, other: &Ident) -> bool { +        self.sym == other.sym && self.raw == other.raw +    } +} + +impl<T> PartialEq<T> for Ident +where +    T: ?Sized + AsRef<str>, +{ +    fn eq(&self, other: &T) -> bool { +        let other = other.as_ref(); +        if self.raw { +            other.starts_with("r#") && self.sym == other[2..] +        } else { +            self.sym == other +        } +    } +} + +impl fmt::Display for Ident { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        if self.raw { +            "r#".fmt(f)?; +        } +        self.sym.fmt(f) +    } +} + +impl fmt::Debug for Ident { +    // Ident(proc_macro), Ident(r#union) +    #[cfg(not(procmacro2_semver_exempt))] +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        let mut debug = f.debug_tuple("Ident"); +        debug.field(&format_args!("{}", self)); +        debug.finish() +    } + +    // Ident { +    //     sym: proc_macro, +    //     span: bytes(128..138) +    // } +    #[cfg(procmacro2_semver_exempt)] +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        let mut debug = f.debug_struct("Ident"); +        debug.field("sym", &format_args!("{}", self)); +        debug.field("span", &self.span); +        debug.finish() +    } +} + +#[derive(Clone)] +pub struct Literal { +    text: String, +    span: Span, +} + +macro_rules! suffixed_numbers { +    ($($name:ident => $kind:ident,)*) => ($( +        pub fn $name(n: $kind) -> Literal { +            Literal::_new(format!(concat!("{}", stringify!($kind)), n)) +        } +    )*) +} + +macro_rules! unsuffixed_numbers { +    ($($name:ident => $kind:ident,)*) => ($( +        pub fn $name(n: $kind) -> Literal { +            Literal::_new(n.to_string()) +        } +    )*) +} + +impl Literal { +    fn _new(text: String) -> Literal { +        Literal { +            text, +            span: Span::call_site(), +        } +    } + +    suffixed_numbers! { +        u8_suffixed => u8, +        u16_suffixed => u16, +        u32_suffixed => u32, +        u64_suffixed => u64, +        u128_suffixed => u128, +        usize_suffixed => usize, +        i8_suffixed => i8, +        i16_suffixed => i16, +        i32_suffixed => i32, +        i64_suffixed => i64, +        i128_suffixed => i128, +        isize_suffixed => isize, + +        f32_suffixed => f32, +        f64_suffixed => f64, +    } + +    unsuffixed_numbers! { +        u8_unsuffixed => u8, +        u16_unsuffixed => u16, +        u32_unsuffixed => u32, +        u64_unsuffixed => u64, +        u128_unsuffixed => u128, +        usize_unsuffixed => usize, +        i8_unsuffixed => i8, +        i16_unsuffixed => i16, +        i32_unsuffixed => i32, +        i64_unsuffixed => i64, +        i128_unsuffixed => i128, +        isize_unsuffixed => isize, +    } + +    pub fn f32_unsuffixed(f: f32) -> Literal { +        let mut s = f.to_string(); +        if !s.contains(".") { +            s.push_str(".0"); +        } +        Literal::_new(s) +    } + +    pub fn f64_unsuffixed(f: f64) -> Literal { +        let mut s = f.to_string(); +        if !s.contains(".") { +            s.push_str(".0"); +        } +        Literal::_new(s) +    } + +    pub fn string(t: &str) -> Literal { +        let mut text = String::with_capacity(t.len() + 2); +        text.push('"'); +        for c in t.chars() { +            if c == '\'' { +                // escape_default turns this into "\'" which is unnecessary. +                text.push(c); +            } else { +                text.extend(c.escape_default()); +            } +        } +        text.push('"'); +        Literal::_new(text) +    } + +    pub fn character(t: char) -> Literal { +        let mut text = String::new(); +        text.push('\''); +        if t == '"' { +            // escape_default turns this into '\"' which is unnecessary. +            text.push(t); +        } else { +            text.extend(t.escape_default()); +        } +        text.push('\''); +        Literal::_new(text) +    } + +    pub fn byte_string(bytes: &[u8]) -> Literal { +        let mut escaped = "b\"".to_string(); +        for b in bytes { +            match *b { +                b'\0' => escaped.push_str(r"\0"), +                b'\t' => escaped.push_str(r"\t"), +                b'\n' => escaped.push_str(r"\n"), +                b'\r' => escaped.push_str(r"\r"), +                b'"' => escaped.push_str("\\\""), +                b'\\' => escaped.push_str("\\\\"), +                b'\x20'..=b'\x7E' => escaped.push(*b as char), +                _ => escaped.push_str(&format!("\\x{:02X}", b)), +            } +        } +        escaped.push('"'); +        Literal::_new(escaped) +    } + +    pub fn span(&self) -> Span { +        self.span +    } + +    pub fn set_span(&mut self, span: Span) { +        self.span = span; +    } + +    pub fn subspan<R: RangeBounds<usize>>(&self, _range: R) -> Option<Span> { +        None +    } +} + +impl fmt::Display for Literal { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        self.text.fmt(f) +    } +} + +impl fmt::Debug for Literal { +    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +        let mut debug = fmt.debug_struct("Literal"); +        debug.field("lit", &format_args!("{}", self.text)); +        #[cfg(procmacro2_semver_exempt)] +        debug.field("span", &self.span); +        debug.finish() +    } +} + +fn token_stream(mut input: Cursor) -> PResult<TokenStream> { +    let mut trees = Vec::new(); +    loop { +        let input_no_ws = skip_whitespace(input); +        if input_no_ws.rest.len() == 0 { +            break; +        } +        if let Ok((a, tokens)) = doc_comment(input_no_ws) { +            input = a; +            trees.extend(tokens); +            continue; +        } + +        let (a, tt) = match token_tree(input_no_ws) { +            Ok(p) => p, +            Err(_) => break, +        }; +        trees.push(tt); +        input = a; +    } +    Ok((input, TokenStream { inner: trees })) +} + +#[cfg(not(span_locations))] +fn spanned<'a, T>( +    input: Cursor<'a>, +    f: fn(Cursor<'a>) -> PResult<'a, T>, +) -> PResult<'a, (T, crate::Span)> { +    let (a, b) = f(skip_whitespace(input))?; +    Ok((a, ((b, crate::Span::_new_stable(Span::call_site()))))) +} + +#[cfg(span_locations)] +fn spanned<'a, T>( +    input: Cursor<'a>, +    f: fn(Cursor<'a>) -> PResult<'a, T>, +) -> PResult<'a, (T, crate::Span)> { +    let input = skip_whitespace(input); +    let lo = input.off; +    let (a, b) = f(input)?; +    let hi = a.off; +    let span = crate::Span::_new_stable(Span { lo, hi }); +    Ok((a, (b, span))) +} + +fn token_tree(input: Cursor) -> PResult<TokenTree> { +    let (rest, (mut tt, span)) = spanned(input, token_kind)?; +    tt.set_span(span); +    Ok((rest, tt)) +} + +named!(token_kind -> TokenTree, alt!( +    map!(group, |g| TokenTree::Group(crate::Group::_new_stable(g))) +    | +    map!(literal, |l| TokenTree::Literal(crate::Literal::_new_stable(l))) // must be before symbol +    | +    map!(op, TokenTree::Punct) +    | +    symbol_leading_ws +)); + +named!(group -> Group, alt!( +    delimited!( +        punct!("("), +        token_stream, +        punct!(")") +    ) => { |ts| Group::new(Delimiter::Parenthesis, ts) } +    | +    delimited!( +        punct!("["), +        token_stream, +        punct!("]") +    ) => { |ts| Group::new(Delimiter::Bracket, ts) } +    | +    delimited!( +        punct!("{"), +        token_stream, +        punct!("}") +    ) => { |ts| Group::new(Delimiter::Brace, ts) } +)); + +fn symbol_leading_ws(input: Cursor) -> PResult<TokenTree> { +    symbol(skip_whitespace(input)) +} + +fn symbol(input: Cursor) -> PResult<TokenTree> { +    let raw = input.starts_with("r#"); +    let rest = input.advance((raw as usize) << 1); + +    let (rest, sym) = symbol_not_raw(rest)?; + +    if !raw { +        let ident = crate::Ident::new(sym, crate::Span::call_site()); +        return Ok((rest, ident.into())); +    } + +    if sym == "_" { +        return Err(LexError); +    } + +    let ident = crate::Ident::_new_raw(sym, crate::Span::call_site()); +    Ok((rest, ident.into())) +} + +fn symbol_not_raw(input: Cursor) -> PResult<&str> { +    let mut chars = input.char_indices(); + +    match chars.next() { +        Some((_, ch)) if is_ident_start(ch) => {} +        _ => return Err(LexError), +    } + +    let mut end = input.len(); +    for (i, ch) in chars { +        if !is_ident_continue(ch) { +            end = i; +            break; +        } +    } + +    Ok((input.advance(end), &input.rest[..end])) +} + +fn literal(input: Cursor) -> PResult<Literal> { +    let input_no_ws = skip_whitespace(input); + +    match literal_nocapture(input_no_ws) { +        Ok((a, ())) => { +            let start = input.len() - input_no_ws.len(); +            let len = input_no_ws.len() - a.len(); +            let end = start + len; +            Ok((a, Literal::_new(input.rest[start..end].to_string()))) +        } +        Err(LexError) => Err(LexError), +    } +} + +named!(literal_nocapture -> (), alt!( +    string +    | +    byte_string +    | +    byte +    | +    character +    | +    float +    | +    int +)); + +named!(string -> (), alt!( +    quoted_string +    | +    preceded!( +        punct!("r"), +        raw_string +    ) => { |_| () } +)); + +named!(quoted_string -> (), do_parse!( +    punct!("\"") >> +    cooked_string >> +    tag!("\"") >> +    option!(symbol_not_raw) >> +    (()) +)); + +fn cooked_string(input: Cursor) -> PResult<()> { +    let mut chars = input.char_indices().peekable(); +    while let Some((byte_offset, ch)) = chars.next() { +        match ch { +            '"' => { +                return Ok((input.advance(byte_offset), ())); +            } +            '\r' => { +                if let Some((_, '\n')) = chars.next() { +                    // ... +                } else { +                    break; +                } +            } +            '\\' => match chars.next() { +                Some((_, 'x')) => { +                    if !backslash_x_char(&mut chars) { +                        break; +                    } +                } +                Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\')) +                | Some((_, '\'')) | Some((_, '"')) | Some((_, '0')) => {} +                Some((_, 'u')) => { +                    if !backslash_u(&mut chars) { +                        break; +                    } +                } +                Some((_, '\n')) | Some((_, '\r')) => { +                    while let Some(&(_, ch)) = chars.peek() { +                        if ch.is_whitespace() { +                            chars.next(); +                        } else { +                            break; +                        } +                    } +                } +                _ => break, +            }, +            _ch => {} +        } +    } +    Err(LexError) +} + +named!(byte_string -> (), alt!( +    delimited!( +        punct!("b\""), +        cooked_byte_string, +        tag!("\"") +    ) => { |_| () } +    | +    preceded!( +        punct!("br"), +        raw_string +    ) => { |_| () } +)); + +fn cooked_byte_string(mut input: Cursor) -> PResult<()> { +    let mut bytes = input.bytes().enumerate(); +    'outer: while let Some((offset, b)) = bytes.next() { +        match b { +            b'"' => { +                return Ok((input.advance(offset), ())); +            } +            b'\r' => { +                if let Some((_, b'\n')) = bytes.next() { +                    // ... +                } else { +                    break; +                } +            } +            b'\\' => match bytes.next() { +                Some((_, b'x')) => { +                    if !backslash_x_byte(&mut bytes) { +                        break; +                    } +                } +                Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\')) +                | Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {} +                Some((newline, b'\n')) | Some((newline, b'\r')) => { +                    let rest = input.advance(newline + 1); +                    for (offset, ch) in rest.char_indices() { +                        if !ch.is_whitespace() { +                            input = rest.advance(offset); +                            bytes = input.bytes().enumerate(); +                            continue 'outer; +                        } +                    } +                    break; +                } +                _ => break, +            }, +            b if b < 0x80 => {} +            _ => break, +        } +    } +    Err(LexError) +} + +fn raw_string(input: Cursor) -> PResult<()> { +    let mut chars = input.char_indices(); +    let mut n = 0; +    while let Some((byte_offset, ch)) = chars.next() { +        match ch { +            '"' => { +                n = byte_offset; +                break; +            } +            '#' => {} +            _ => return Err(LexError), +        } +    } +    for (byte_offset, ch) in chars { +        match ch { +            '"' if input.advance(byte_offset + 1).starts_with(&input.rest[..n]) => { +                let rest = input.advance(byte_offset + 1 + n); +                return Ok((rest, ())); +            } +            '\r' => {} +            _ => {} +        } +    } +    Err(LexError) +} + +named!(byte -> (), do_parse!( +    punct!("b") >> +    tag!("'") >> +    cooked_byte >> +    tag!("'") >> +    (()) +)); + +fn cooked_byte(input: Cursor) -> PResult<()> { +    let mut bytes = input.bytes().enumerate(); +    let ok = match bytes.next().map(|(_, b)| b) { +        Some(b'\\') => match bytes.next().map(|(_, b)| b) { +            Some(b'x') => backslash_x_byte(&mut bytes), +            Some(b'n') | Some(b'r') | Some(b't') | Some(b'\\') | Some(b'0') | Some(b'\'') +            | Some(b'"') => true, +            _ => false, +        }, +        b => b.is_some(), +    }; +    if ok { +        match bytes.next() { +            Some((offset, _)) => { +                if input.chars().as_str().is_char_boundary(offset) { +                    Ok((input.advance(offset), ())) +                } else { +                    Err(LexError) +                } +            } +            None => Ok((input.advance(input.len()), ())), +        } +    } else { +        Err(LexError) +    } +} + +named!(character -> (), do_parse!( +    punct!("'") >> +    cooked_char >> +    tag!("'") >> +    (()) +)); + +fn cooked_char(input: Cursor) -> PResult<()> { +    let mut chars = input.char_indices(); +    let ok = match chars.next().map(|(_, ch)| ch) { +        Some('\\') => match chars.next().map(|(_, ch)| ch) { +            Some('x') => backslash_x_char(&mut chars), +            Some('u') => backslash_u(&mut chars), +            Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"') => { +                true +            } +            _ => false, +        }, +        ch => ch.is_some(), +    }; +    if ok { +        match chars.next() { +            Some((idx, _)) => Ok((input.advance(idx), ())), +            None => Ok((input.advance(input.len()), ())), +        } +    } else { +        Err(LexError) +    } +} + +macro_rules! next_ch { +    ($chars:ident @ $pat:pat $(| $rest:pat)*) => { +        match $chars.next() { +            Some((_, ch)) => match ch { +                $pat $(| $rest)*  => ch, +                _ => return false, +            }, +            None => return false +        } +    }; +} + +fn backslash_x_char<I>(chars: &mut I) -> bool +where +    I: Iterator<Item = (usize, char)>, +{ +    next_ch!(chars @ '0'..='7'); +    next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); +    true +} + +fn backslash_x_byte<I>(chars: &mut I) -> bool +where +    I: Iterator<Item = (usize, u8)>, +{ +    next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); +    next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); +    true +} + +fn backslash_u<I>(chars: &mut I) -> bool +where +    I: Iterator<Item = (usize, char)>, +{ +    next_ch!(chars @ '{'); +    next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); +    loop { +        let c = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F' | '_' | '}'); +        if c == '}' { +            return true; +        } +    } +} + +fn float(input: Cursor) -> PResult<()> { +    let (mut rest, ()) = float_digits(input)?; +    if let Some(ch) = rest.chars().next() { +        if is_ident_start(ch) { +            rest = symbol_not_raw(rest)?.0; +        } +    } +    word_break(rest) +} + +fn float_digits(input: Cursor) -> PResult<()> { +    let mut chars = input.chars().peekable(); +    match chars.next() { +        Some(ch) if ch >= '0' && ch <= '9' => {} +        _ => return Err(LexError), +    } + +    let mut len = 1; +    let mut has_dot = false; +    let mut has_exp = false; +    while let Some(&ch) = chars.peek() { +        match ch { +            '0'..='9' | '_' => { +                chars.next(); +                len += 1; +            } +            '.' => { +                if has_dot { +                    break; +                } +                chars.next(); +                if chars +                    .peek() +                    .map(|&ch| ch == '.' || is_ident_start(ch)) +                    .unwrap_or(false) +                { +                    return Err(LexError); +                } +                len += 1; +                has_dot = true; +            } +            'e' | 'E' => { +                chars.next(); +                len += 1; +                has_exp = true; +                break; +            } +            _ => break, +        } +    } + +    let rest = input.advance(len); +    if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) { +        return Err(LexError); +    } + +    if has_exp { +        let mut has_exp_value = false; +        while let Some(&ch) = chars.peek() { +            match ch { +                '+' | '-' => { +                    if has_exp_value { +                        break; +                    } +                    chars.next(); +                    len += 1; +                } +                '0'..='9' => { +                    chars.next(); +                    len += 1; +                    has_exp_value = true; +                } +                '_' => { +                    chars.next(); +                    len += 1; +                } +                _ => break, +            } +        } +        if !has_exp_value { +            return Err(LexError); +        } +    } + +    Ok((input.advance(len), ())) +} + +fn int(input: Cursor) -> PResult<()> { +    let (mut rest, ()) = digits(input)?; +    if let Some(ch) = rest.chars().next() { +        if is_ident_start(ch) { +            rest = symbol_not_raw(rest)?.0; +        } +    } +    word_break(rest) +} + +fn digits(mut input: Cursor) -> PResult<()> { +    let base = if input.starts_with("0x") { +        input = input.advance(2); +        16 +    } else if input.starts_with("0o") { +        input = input.advance(2); +        8 +    } else if input.starts_with("0b") { +        input = input.advance(2); +        2 +    } else { +        10 +    }; + +    let mut len = 0; +    let mut empty = true; +    for b in input.bytes() { +        let digit = match b { +            b'0'..=b'9' => (b - b'0') as u64, +            b'a'..=b'f' => 10 + (b - b'a') as u64, +            b'A'..=b'F' => 10 + (b - b'A') as u64, +            b'_' => { +                if empty && base == 10 { +                    return Err(LexError); +                } +                len += 1; +                continue; +            } +            _ => break, +        }; +        if digit >= base { +            return Err(LexError); +        } +        len += 1; +        empty = false; +    } +    if empty { +        Err(LexError) +    } else { +        Ok((input.advance(len), ())) +    } +} + +fn op(input: Cursor) -> PResult<Punct> { +    let input = skip_whitespace(input); +    match op_char(input) { +        Ok((rest, '\'')) => { +            symbol(rest)?; +            Ok((rest, Punct::new('\'', Spacing::Joint))) +        } +        Ok((rest, ch)) => { +            let kind = match op_char(rest) { +                Ok(_) => Spacing::Joint, +                Err(LexError) => Spacing::Alone, +            }; +            Ok((rest, Punct::new(ch, kind))) +        } +        Err(LexError) => Err(LexError), +    } +} + +fn op_char(input: Cursor) -> PResult<char> { +    if input.starts_with("//") || input.starts_with("/*") { +        // Do not accept `/` of a comment as an op. +        return Err(LexError); +    } + +    let mut chars = input.chars(); +    let first = match chars.next() { +        Some(ch) => ch, +        None => { +            return Err(LexError); +        } +    }; +    let recognized = "~!@#$%^&*-=+|;:,<.>/?'"; +    if recognized.contains(first) { +        Ok((input.advance(first.len_utf8()), first)) +    } else { +        Err(LexError) +    } +} + +fn doc_comment(input: Cursor) -> PResult<Vec<TokenTree>> { +    let mut trees = Vec::new(); +    let (rest, ((comment, inner), span)) = spanned(input, doc_comment_contents)?; +    trees.push(TokenTree::Punct(Punct::new('#', Spacing::Alone))); +    if inner { +        trees.push(Punct::new('!', Spacing::Alone).into()); +    } +    let mut stream = vec![ +        TokenTree::Ident(crate::Ident::new("doc", span)), +        TokenTree::Punct(Punct::new('=', Spacing::Alone)), +        TokenTree::Literal(crate::Literal::string(comment)), +    ]; +    for tt in stream.iter_mut() { +        tt.set_span(span); +    } +    let group = Group::new(Delimiter::Bracket, stream.into_iter().collect()); +    trees.push(crate::Group::_new_stable(group).into()); +    for tt in trees.iter_mut() { +        tt.set_span(span); +    } +    Ok((rest, trees)) +} + +named!(doc_comment_contents -> (&str, bool), alt!( +    do_parse!( +        punct!("//!") >> +        s: take_until_newline_or_eof!() >> +        ((s, true)) +    ) +    | +    do_parse!( +        option!(whitespace) >> +        peek!(tag!("/*!")) >> +        s: block_comment >> +        ((s, true)) +    ) +    | +    do_parse!( +        punct!("///") >> +        not!(tag!("/")) >> +        s: take_until_newline_or_eof!() >> +        ((s, false)) +    ) +    | +    do_parse!( +        option!(whitespace) >> +        peek!(tuple!(tag!("/**"), not!(tag!("*")))) >> +        s: block_comment >> +        ((s, false)) +    ) +)); diff --git a/proc-macro2/src/lib.rs b/proc-macro2/src/lib.rs new file mode 100644 index 0000000..bbfb375 --- /dev/null +++ b/proc-macro2/src/lib.rs @@ -0,0 +1,1199 @@ +//! A wrapper around the procedural macro API of the compiler's [`proc_macro`] +//! crate. This library serves two purposes: +//! +//! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/ +//! +//! - **Bring proc-macro-like functionality to other contexts like build.rs and +//!   main.rs.** Types from `proc_macro` are entirely specific to procedural +//!   macros and cannot ever exist in code outside of a procedural macro. +//!   Meanwhile `proc_macro2` types may exist anywhere including non-macro code. +//!   By developing foundational libraries like [syn] and [quote] against +//!   `proc_macro2` rather than `proc_macro`, the procedural macro ecosystem +//!   becomes easily applicable to many other use cases and we avoid +//!   reimplementing non-macro equivalents of those libraries. +//! +//! - **Make procedural macros unit testable.** As a consequence of being +//!   specific to procedural macros, nothing that uses `proc_macro` can be +//!   executed from a unit test. In order for helper libraries or components of +//!   a macro to be testable in isolation, they must be implemented using +//!   `proc_macro2`. +//! +//! [syn]: https://github.com/dtolnay/syn +//! [quote]: https://github.com/dtolnay/quote +//! +//! # Usage +//! +//! The skeleton of a typical procedural macro typically looks like this: +//! +//! ``` +//! extern crate proc_macro; +//! +//! # const IGNORE: &str = stringify! { +//! #[proc_macro_derive(MyDerive)] +//! # }; +//! # #[cfg(wrap_proc_macro)] +//! pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { +//!     let input = proc_macro2::TokenStream::from(input); +//! +//!     let output: proc_macro2::TokenStream = { +//!         /* transform input */ +//!         # input +//!     }; +//! +//!     proc_macro::TokenStream::from(output) +//! } +//! ``` +//! +//! If parsing with [Syn], you'll use [`parse_macro_input!`] instead to +//! propagate parse errors correctly back to the compiler when parsing fails. +//! +//! [`parse_macro_input!`]: https://docs.rs/syn/1.0/syn/macro.parse_macro_input.html +//! +//! # Unstable features +//! +//! The default feature set of proc-macro2 tracks the most recent stable +//! compiler API. Functionality in `proc_macro` that is not yet stable is not +//! exposed by proc-macro2 by default. +//! +//! To opt into the additional APIs available in the most recent nightly +//! compiler, the `procmacro2_semver_exempt` config flag must be passed to +//! rustc. We will polyfill those nightly-only APIs back to Rust 1.31.0. As +//! these are unstable APIs that track the nightly compiler, minor versions of +//! proc-macro2 may make breaking changes to them at any time. +//! +//! ```sh +//! RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build +//! ``` +//! +//! Note that this must not only be done for your crate, but for any crate that +//! depends on your crate. This infectious nature is intentional, as it serves +//! as a reminder that you are outside of the normal semver guarantees. +//! +//! Semver exempt methods are marked as such in the proc-macro2 documentation. +//! +//! # Thread-Safety +//! +//! Most types in this crate are `!Sync` because the underlying compiler +//! types make use of thread-local memory, meaning they cannot be accessed from +//! a different thread. + +// Proc-macro2 types in rustdoc of other crates get linked to here. +#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.7")] +#![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))] +#![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))] + +#[cfg(use_proc_macro)] +extern crate proc_macro; + +use std::cmp::Ordering; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::iter::FromIterator; +use std::marker; +use std::ops::RangeBounds; +#[cfg(procmacro2_semver_exempt)] +use std::path::PathBuf; +use std::rc::Rc; +use std::str::FromStr; + +#[macro_use] +mod strnom; +mod fallback; + +#[cfg(not(wrap_proc_macro))] +use crate::fallback as imp; +#[path = "wrapper.rs"] +#[cfg(wrap_proc_macro)] +mod imp; + +/// An abstract stream of tokens, or more concretely a sequence of token trees. +/// +/// This type provides interfaces for iterating over token trees and for +/// collecting token trees into one stream. +/// +/// Token stream is both the input and output of `#[proc_macro]`, +/// `#[proc_macro_attribute]` and `#[proc_macro_derive]` definitions. +#[derive(Clone)] +pub struct TokenStream { +    inner: imp::TokenStream, +    _marker: marker::PhantomData<Rc<()>>, +} + +/// Error returned from `TokenStream::from_str`. +pub struct LexError { +    inner: imp::LexError, +    _marker: marker::PhantomData<Rc<()>>, +} + +impl TokenStream { +    fn _new(inner: imp::TokenStream) -> TokenStream { +        TokenStream { +            inner, +            _marker: marker::PhantomData, +        } +    } + +    fn _new_stable(inner: fallback::TokenStream) -> TokenStream { +        TokenStream { +            inner: inner.into(), +            _marker: marker::PhantomData, +        } +    } + +    /// Returns an empty `TokenStream` containing no token trees. +    pub fn new() -> TokenStream { +        TokenStream::_new(imp::TokenStream::new()) +    } + +    /// Checks if this `TokenStream` is empty. +    pub fn is_empty(&self) -> bool { +        self.inner.is_empty() +    } +} + +/// `TokenStream::default()` returns an empty stream, +/// i.e. this is equivalent with `TokenStream::new()`. +impl Default for TokenStream { +    fn default() -> Self { +        TokenStream::new() +    } +} + +/// Attempts to break the string into tokens and parse those tokens into a token +/// stream. +/// +/// May fail for a number of reasons, for example, if the string contains +/// unbalanced delimiters or characters not existing in the language. +/// +/// NOTE: Some errors may cause panics instead of returning `LexError`. We +/// reserve the right to change these errors into `LexError`s later. +impl FromStr for TokenStream { +    type Err = LexError; + +    fn from_str(src: &str) -> Result<TokenStream, LexError> { +        let e = src.parse().map_err(|e| LexError { +            inner: e, +            _marker: marker::PhantomData, +        })?; +        Ok(TokenStream::_new(e)) +    } +} + +#[cfg(use_proc_macro)] +impl From<proc_macro::TokenStream> for TokenStream { +    fn from(inner: proc_macro::TokenStream) -> TokenStream { +        TokenStream::_new(inner.into()) +    } +} + +#[cfg(use_proc_macro)] +impl From<TokenStream> for proc_macro::TokenStream { +    fn from(inner: TokenStream) -> proc_macro::TokenStream { +        inner.inner.into() +    } +} + +impl From<TokenTree> for TokenStream { +    fn from(token: TokenTree) -> Self { +        TokenStream::_new(imp::TokenStream::from(token)) +    } +} + +impl Extend<TokenTree> for TokenStream { +    fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) { +        self.inner.extend(streams) +    } +} + +impl Extend<TokenStream> for TokenStream { +    fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { +        self.inner +            .extend(streams.into_iter().map(|stream| stream.inner)) +    } +} + +/// Collects a number of token trees into a single stream. +impl FromIterator<TokenTree> for TokenStream { +    fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self { +        TokenStream::_new(streams.into_iter().collect()) +    } +} +impl FromIterator<TokenStream> for TokenStream { +    fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { +        TokenStream::_new(streams.into_iter().map(|i| i.inner).collect()) +    } +} + +/// Prints the token stream as a string that is supposed to be losslessly +/// convertible back into the same token stream (modulo spans), except for +/// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative +/// numeric literals. +impl fmt::Display for TokenStream { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        self.inner.fmt(f) +    } +} + +/// Prints token in a form convenient for debugging. +impl fmt::Debug for TokenStream { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        self.inner.fmt(f) +    } +} + +impl fmt::Debug for LexError { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        self.inner.fmt(f) +    } +} + +/// The source file of a given `Span`. +/// +/// This type is semver exempt and not exposed by default. +#[cfg(procmacro2_semver_exempt)] +#[derive(Clone, PartialEq, Eq)] +pub struct SourceFile { +    inner: imp::SourceFile, +    _marker: marker::PhantomData<Rc<()>>, +} + +#[cfg(procmacro2_semver_exempt)] +impl SourceFile { +    fn _new(inner: imp::SourceFile) -> Self { +        SourceFile { +            inner, +            _marker: marker::PhantomData, +        } +    } + +    /// Get the path to this source file. +    /// +    /// ### Note +    /// +    /// If the code span associated with this `SourceFile` was generated by an +    /// external macro, this may not be an actual path on the filesystem. Use +    /// [`is_real`] to check. +    /// +    /// Also note that even if `is_real` returns `true`, if +    /// `--remap-path-prefix` was passed on the command line, the path as given +    /// may not actually be valid. +    /// +    /// [`is_real`]: #method.is_real +    pub fn path(&self) -> PathBuf { +        self.inner.path() +    } + +    /// Returns `true` if this source file is a real source file, and not +    /// generated by an external macro's expansion. +    pub fn is_real(&self) -> bool { +        self.inner.is_real() +    } +} + +#[cfg(procmacro2_semver_exempt)] +impl fmt::Debug for SourceFile { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        self.inner.fmt(f) +    } +} + +/// A line-column pair representing the start or end of a `Span`. +/// +/// This type is semver exempt and not exposed by default. +#[cfg(span_locations)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct LineColumn { +    /// The 1-indexed line in the source file on which the span starts or ends +    /// (inclusive). +    pub line: usize, +    /// The 0-indexed column (in UTF-8 characters) in the source file on which +    /// the span starts or ends (inclusive). +    pub column: usize, +} + +/// A region of source code, along with macro expansion information. +#[derive(Copy, Clone)] +pub struct Span { +    inner: imp::Span, +    _marker: marker::PhantomData<Rc<()>>, +} + +impl Span { +    fn _new(inner: imp::Span) -> Span { +        Span { +            inner, +            _marker: marker::PhantomData, +        } +    } + +    fn _new_stable(inner: fallback::Span) -> Span { +        Span { +            inner: inner.into(), +            _marker: marker::PhantomData, +        } +    } + +    /// The span of the invocation of the current procedural macro. +    /// +    /// Identifiers created with this span will be resolved as if they were +    /// written directly at the macro call location (call-site hygiene) and +    /// other code at the macro call site will be able to refer to them as well. +    pub fn call_site() -> Span { +        Span::_new(imp::Span::call_site()) +    } + +    /// A span that resolves at the macro definition site. +    /// +    /// This method is semver exempt and not exposed by default. +    #[cfg(procmacro2_semver_exempt)] +    pub fn def_site() -> Span { +        Span::_new(imp::Span::def_site()) +    } + +    /// Creates a new span with the same line/column information as `self` but +    /// that resolves symbols as though it were at `other`. +    /// +    /// This method is semver exempt and not exposed by default. +    #[cfg(procmacro2_semver_exempt)] +    pub fn resolved_at(&self, other: Span) -> Span { +        Span::_new(self.inner.resolved_at(other.inner)) +    } + +    /// Creates a new span with the same name resolution behavior as `self` but +    /// with the line/column information of `other`. +    /// +    /// This method is semver exempt and not exposed by default. +    #[cfg(procmacro2_semver_exempt)] +    pub fn located_at(&self, other: Span) -> Span { +        Span::_new(self.inner.located_at(other.inner)) +    } + +    /// Convert `proc_macro2::Span` to `proc_macro::Span`. +    /// +    /// This method is available when building with a nightly compiler, or when +    /// building with rustc 1.29+ *without* semver exempt features. +    /// +    /// # Panics +    /// +    /// Panics if called from outside of a procedural macro. Unlike +    /// `proc_macro2::Span`, the `proc_macro::Span` type can only exist within +    /// the context of a procedural macro invocation. +    #[cfg(wrap_proc_macro)] +    pub fn unwrap(self) -> proc_macro::Span { +        self.inner.unwrap() +    } + +    // Soft deprecated. Please use Span::unwrap. +    #[cfg(wrap_proc_macro)] +    #[doc(hidden)] +    pub fn unstable(self) -> proc_macro::Span { +        self.unwrap() +    } + +    /// The original source file into which this span points. +    /// +    /// This method is semver exempt and not exposed by default. +    #[cfg(procmacro2_semver_exempt)] +    pub fn source_file(&self) -> SourceFile { +        SourceFile::_new(self.inner.source_file()) +    } + +    /// Get the starting line/column in the source file for this span. +    /// +    /// This method requires the `"span-locations"` feature to be enabled. +    #[cfg(span_locations)] +    pub fn start(&self) -> LineColumn { +        let imp::LineColumn { line, column } = self.inner.start(); +        LineColumn { line, column } +    } + +    /// Get the ending line/column in the source file for this span. +    /// +    /// This method requires the `"span-locations"` feature to be enabled. +    #[cfg(span_locations)] +    pub fn end(&self) -> LineColumn { +        let imp::LineColumn { line, column } = self.inner.end(); +        LineColumn { line, column } +    } + +    /// Create a new span encompassing `self` and `other`. +    /// +    /// Returns `None` if `self` and `other` are from different files. +    /// +    /// Warning: the underlying [`proc_macro::Span::join`] method is +    /// nightly-only. When called from within a procedural macro not using a +    /// nightly compiler, this method will always return `None`. +    /// +    /// [`proc_macro::Span::join`]: https://doc.rust-lang.org/proc_macro/struct.Span.html#method.join +    pub fn join(&self, other: Span) -> Option<Span> { +        self.inner.join(other.inner).map(Span::_new) +    } + +    /// Compares two spans to see if they're equal. +    /// +    /// This method is semver exempt and not exposed by default. +    #[cfg(procmacro2_semver_exempt)] +    pub fn eq(&self, other: &Span) -> bool { +        self.inner.eq(&other.inner) +    } +} + +/// Prints a span in a form convenient for debugging. +impl fmt::Debug for Span { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        self.inner.fmt(f) +    } +} + +/// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`). +#[derive(Clone)] +pub enum TokenTree { +    /// A token stream surrounded by bracket delimiters. +    Group(Group), +    /// An identifier. +    Ident(Ident), +    /// A single punctuation character (`+`, `,`, `$`, etc.). +    Punct(Punct), +    /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc. +    Literal(Literal), +} + +impl TokenTree { +    /// Returns the span of this tree, delegating to the `span` method of +    /// the contained token or a delimited stream. +    pub fn span(&self) -> Span { +        match *self { +            TokenTree::Group(ref t) => t.span(), +            TokenTree::Ident(ref t) => t.span(), +            TokenTree::Punct(ref t) => t.span(), +            TokenTree::Literal(ref t) => t.span(), +        } +    } + +    /// Configures the span for *only this token*. +    /// +    /// Note that if this token is a `Group` then this method will not configure +    /// the span of each of the internal tokens, this will simply delegate to +    /// the `set_span` method of each variant. +    pub fn set_span(&mut self, span: Span) { +        match *self { +            TokenTree::Group(ref mut t) => t.set_span(span), +            TokenTree::Ident(ref mut t) => t.set_span(span), +            TokenTree::Punct(ref mut t) => t.set_span(span), +            TokenTree::Literal(ref mut t) => t.set_span(span), +        } +    } +} + +impl From<Group> for TokenTree { +    fn from(g: Group) -> TokenTree { +        TokenTree::Group(g) +    } +} + +impl From<Ident> for TokenTree { +    fn from(g: Ident) -> TokenTree { +        TokenTree::Ident(g) +    } +} + +impl From<Punct> for TokenTree { +    fn from(g: Punct) -> TokenTree { +        TokenTree::Punct(g) +    } +} + +impl From<Literal> for TokenTree { +    fn from(g: Literal) -> TokenTree { +        TokenTree::Literal(g) +    } +} + +/// Prints the token tree as a string that is supposed to be losslessly +/// convertible back into the same token tree (modulo spans), except for +/// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative +/// numeric literals. +impl fmt::Display for TokenTree { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match *self { +            TokenTree::Group(ref t) => t.fmt(f), +            TokenTree::Ident(ref t) => t.fmt(f), +            TokenTree::Punct(ref t) => t.fmt(f), +            TokenTree::Literal(ref t) => t.fmt(f), +        } +    } +} + +/// Prints token tree in a form convenient for debugging. +impl fmt::Debug for TokenTree { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        // Each of these has the name in the struct type in the derived debug, +        // so don't bother with an extra layer of indirection +        match *self { +            TokenTree::Group(ref t) => t.fmt(f), +            TokenTree::Ident(ref t) => { +                let mut debug = f.debug_struct("Ident"); +                debug.field("sym", &format_args!("{}", t)); +                imp::debug_span_field_if_nontrivial(&mut debug, t.span().inner); +                debug.finish() +            } +            TokenTree::Punct(ref t) => t.fmt(f), +            TokenTree::Literal(ref t) => t.fmt(f), +        } +    } +} + +/// A delimited token stream. +/// +/// A `Group` internally contains a `TokenStream` which is surrounded by +/// `Delimiter`s. +#[derive(Clone)] +pub struct Group { +    inner: imp::Group, +} + +/// Describes how a sequence of token trees is delimited. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum Delimiter { +    /// `( ... )` +    Parenthesis, +    /// `{ ... }` +    Brace, +    /// `[ ... ]` +    Bracket, +    /// `Ø ... Ø` +    /// +    /// An implicit delimiter, that may, for example, appear around tokens +    /// coming from a "macro variable" `$var`. It is important to preserve +    /// operator priorities in cases like `$var * 3` where `$var` is `1 + 2`. +    /// Implicit delimiters may not survive roundtrip of a token stream through +    /// a string. +    None, +} + +impl Group { +    fn _new(inner: imp::Group) -> Self { +        Group { inner } +    } + +    fn _new_stable(inner: fallback::Group) -> Self { +        Group { +            inner: inner.into(), +        } +    } + +    /// Creates a new `Group` with the given delimiter and token stream. +    /// +    /// This constructor will set the span for this group to +    /// `Span::call_site()`. To change the span you can use the `set_span` +    /// method below. +    pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { +        Group { +            inner: imp::Group::new(delimiter, stream.inner), +        } +    } + +    /// Returns the delimiter of this `Group` +    pub fn delimiter(&self) -> Delimiter { +        self.inner.delimiter() +    } + +    /// Returns the `TokenStream` of tokens that are delimited in this `Group`. +    /// +    /// Note that the returned token stream does not include the delimiter +    /// returned above. +    pub fn stream(&self) -> TokenStream { +        TokenStream::_new(self.inner.stream()) +    } + +    /// Returns the span for the delimiters of this token stream, spanning the +    /// entire `Group`. +    /// +    /// ```text +    /// pub fn span(&self) -> Span { +    ///            ^^^^^^^ +    /// ``` +    pub fn span(&self) -> Span { +        Span::_new(self.inner.span()) +    } + +    /// Returns the span pointing to the opening delimiter of this group. +    /// +    /// ```text +    /// pub fn span_open(&self) -> Span { +    ///                 ^ +    /// ``` +    pub fn span_open(&self) -> Span { +        Span::_new(self.inner.span_open()) +    } + +    /// Returns the span pointing to the closing delimiter of this group. +    /// +    /// ```text +    /// pub fn span_close(&self) -> Span { +    ///                        ^ +    /// ``` +    pub fn span_close(&self) -> Span { +        Span::_new(self.inner.span_close()) +    } + +    /// Configures the span for this `Group`'s delimiters, but not its internal +    /// tokens. +    /// +    /// This method will **not** set the span of all the internal tokens spanned +    /// by this group, but rather it will only set the span of the delimiter +    /// tokens at the level of the `Group`. +    pub fn set_span(&mut self, span: Span) { +        self.inner.set_span(span.inner) +    } +} + +/// Prints the group as a string that should be losslessly convertible back +/// into the same group (modulo spans), except for possibly `TokenTree::Group`s +/// with `Delimiter::None` delimiters. +impl fmt::Display for Group { +    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +        fmt::Display::fmt(&self.inner, formatter) +    } +} + +impl fmt::Debug for Group { +    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +        fmt::Debug::fmt(&self.inner, formatter) +    } +} + +/// An `Punct` is an single punctuation character like `+`, `-` or `#`. +/// +/// Multicharacter operators like `+=` are represented as two instances of +/// `Punct` with different forms of `Spacing` returned. +#[derive(Clone)] +pub struct Punct { +    op: char, +    spacing: Spacing, +    span: Span, +} + +/// Whether an `Punct` is followed immediately by another `Punct` or followed by +/// another token or whitespace. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum Spacing { +    /// E.g. `+` is `Alone` in `+ =`, `+ident` or `+()`. +    Alone, +    /// E.g. `+` is `Joint` in `+=` or `'` is `Joint` in `'#`. +    /// +    /// Additionally, single quote `'` can join with identifiers to form +    /// lifetimes `'ident`. +    Joint, +} + +impl Punct { +    /// Creates a new `Punct` from the given character and spacing. +    /// +    /// The `ch` argument must be a valid punctuation character permitted by the +    /// language, otherwise the function will panic. +    /// +    /// The returned `Punct` will have the default span of `Span::call_site()` +    /// which can be further configured with the `set_span` method below. +    pub fn new(op: char, spacing: Spacing) -> Punct { +        Punct { +            op, +            spacing, +            span: Span::call_site(), +        } +    } + +    /// Returns the value of this punctuation character as `char`. +    pub fn as_char(&self) -> char { +        self.op +    } + +    /// Returns the spacing of this punctuation character, indicating whether +    /// it's immediately followed by another `Punct` in the token stream, so +    /// they can potentially be combined into a multicharacter operator +    /// (`Joint`), or it's followed by some other token or whitespace (`Alone`) +    /// so the operator has certainly ended. +    pub fn spacing(&self) -> Spacing { +        self.spacing +    } + +    /// Returns the span for this punctuation character. +    pub fn span(&self) -> Span { +        self.span +    } + +    /// Configure the span for this punctuation character. +    pub fn set_span(&mut self, span: Span) { +        self.span = span; +    } +} + +/// Prints the punctuation character as a string that should be losslessly +/// convertible back into the same character. +impl fmt::Display for Punct { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        self.op.fmt(f) +    } +} + +impl fmt::Debug for Punct { +    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +        let mut debug = fmt.debug_struct("Punct"); +        debug.field("op", &self.op); +        debug.field("spacing", &self.spacing); +        imp::debug_span_field_if_nontrivial(&mut debug, self.span.inner); +        debug.finish() +    } +} + +/// A word of Rust code, which may be a keyword or legal variable name. +/// +/// An identifier consists of at least one Unicode code point, the first of +/// which has the XID_Start property and the rest of which have the XID_Continue +/// property. +/// +/// - The empty string is not an identifier. Use `Option<Ident>`. +/// - A lifetime is not an identifier. Use `syn::Lifetime` instead. +/// +/// An identifier constructed with `Ident::new` is permitted to be a Rust +/// keyword, though parsing one through its [`Parse`] implementation rejects +/// Rust keywords. Use `input.call(Ident::parse_any)` when parsing to match the +/// behaviour of `Ident::new`. +/// +/// [`Parse`]: https://docs.rs/syn/1.0/syn/parse/trait.Parse.html +/// +/// # Examples +/// +/// A new ident can be created from a string using the `Ident::new` function. +/// A span must be provided explicitly which governs the name resolution +/// behavior of the resulting identifier. +/// +/// ``` +/// use proc_macro2::{Ident, Span}; +/// +/// fn main() { +///     let call_ident = Ident::new("calligraphy", Span::call_site()); +/// +///     println!("{}", call_ident); +/// } +/// ``` +/// +/// An ident can be interpolated into a token stream using the `quote!` macro. +/// +/// ``` +/// use proc_macro2::{Ident, Span}; +/// use quote::quote; +/// +/// fn main() { +///     let ident = Ident::new("demo", Span::call_site()); +/// +///     // Create a variable binding whose name is this ident. +///     let expanded = quote! { let #ident = 10; }; +/// +///     // Create a variable binding with a slightly different name. +///     let temp_ident = Ident::new(&format!("new_{}", ident), Span::call_site()); +///     let expanded = quote! { let #temp_ident = 10; }; +/// } +/// ``` +/// +/// A string representation of the ident is available through the `to_string()` +/// method. +/// +/// ``` +/// # use proc_macro2::{Ident, Span}; +/// # +/// # let ident = Ident::new("another_identifier", Span::call_site()); +/// # +/// // Examine the ident as a string. +/// let ident_string = ident.to_string(); +/// if ident_string.len() > 60 { +///     println!("Very long identifier: {}", ident_string) +/// } +/// ``` +#[derive(Clone)] +pub struct Ident { +    inner: imp::Ident, +    _marker: marker::PhantomData<Rc<()>>, +} + +impl Ident { +    fn _new(inner: imp::Ident) -> Ident { +        Ident { +            inner, +            _marker: marker::PhantomData, +        } +    } + +    /// Creates a new `Ident` with the given `string` as well as the specified +    /// `span`. +    /// +    /// The `string` argument must be a valid identifier permitted by the +    /// language, otherwise the function will panic. +    /// +    /// Note that `span`, currently in rustc, configures the hygiene information +    /// for this identifier. +    /// +    /// As of this time `Span::call_site()` explicitly opts-in to "call-site" +    /// hygiene meaning that identifiers created with this span will be resolved +    /// as if they were written directly at the location of the macro call, and +    /// other code at the macro call site will be able to refer to them as well. +    /// +    /// Later spans like `Span::def_site()` will allow to opt-in to +    /// "definition-site" hygiene meaning that identifiers created with this +    /// span will be resolved at the location of the macro definition and other +    /// code at the macro call site will not be able to refer to them. +    /// +    /// Due to the current importance of hygiene this constructor, unlike other +    /// tokens, requires a `Span` to be specified at construction. +    /// +    /// # Panics +    /// +    /// Panics if the input string is neither a keyword nor a legal variable +    /// name. If you are not sure whether the string contains an identifier and +    /// need to handle an error case, use +    /// <a href="https://docs.rs/syn/1.0/syn/fn.parse_str.html"><code +    ///   style="padding-right:0;">syn::parse_str</code></a><code +    ///   style="padding-left:0;">::<Ident></code> +    /// rather than `Ident::new`. +    pub fn new(string: &str, span: Span) -> Ident { +        Ident::_new(imp::Ident::new(string, span.inner)) +    } + +    /// Same as `Ident::new`, but creates a raw identifier (`r#ident`). +    /// +    /// This method is semver exempt and not exposed by default. +    #[cfg(procmacro2_semver_exempt)] +    pub fn new_raw(string: &str, span: Span) -> Ident { +        Ident::_new_raw(string, span) +    } + +    fn _new_raw(string: &str, span: Span) -> Ident { +        Ident::_new(imp::Ident::new_raw(string, span.inner)) +    } + +    /// Returns the span of this `Ident`. +    pub fn span(&self) -> Span { +        Span::_new(self.inner.span()) +    } + +    /// Configures the span of this `Ident`, possibly changing its hygiene +    /// context. +    pub fn set_span(&mut self, span: Span) { +        self.inner.set_span(span.inner); +    } +} + +impl PartialEq for Ident { +    fn eq(&self, other: &Ident) -> bool { +        self.inner == other.inner +    } +} + +impl<T> PartialEq<T> for Ident +where +    T: ?Sized + AsRef<str>, +{ +    fn eq(&self, other: &T) -> bool { +        self.inner == other +    } +} + +impl Eq for Ident {} + +impl PartialOrd for Ident { +    fn partial_cmp(&self, other: &Ident) -> Option<Ordering> { +        Some(self.cmp(other)) +    } +} + +impl Ord for Ident { +    fn cmp(&self, other: &Ident) -> Ordering { +        self.to_string().cmp(&other.to_string()) +    } +} + +impl Hash for Ident { +    fn hash<H: Hasher>(&self, hasher: &mut H) { +        self.to_string().hash(hasher) +    } +} + +/// Prints the identifier as a string that should be losslessly convertible back +/// into the same identifier. +impl fmt::Display for Ident { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        self.inner.fmt(f) +    } +} + +impl fmt::Debug for Ident { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        self.inner.fmt(f) +    } +} + +/// A literal string (`"hello"`), byte string (`b"hello"`), character (`'a'`), +/// byte character (`b'a'`), an integer or floating point number with or without +/// a suffix (`1`, `1u8`, `2.3`, `2.3f32`). +/// +/// Boolean literals like `true` and `false` do not belong here, they are +/// `Ident`s. +#[derive(Clone)] +pub struct Literal { +    inner: imp::Literal, +    _marker: marker::PhantomData<Rc<()>>, +} + +macro_rules! suffixed_int_literals { +    ($($name:ident => $kind:ident,)*) => ($( +        /// Creates a new suffixed integer literal with the specified value. +        /// +        /// This function will create an integer like `1u32` where the integer +        /// value specified is the first part of the token and the integral is +        /// also suffixed at the end. Literals created from negative numbers may +        /// not survive rountrips through `TokenStream` or strings and may be +        /// broken into two tokens (`-` and positive literal). +        /// +        /// Literals created through this method have the `Span::call_site()` +        /// span by default, which can be configured with the `set_span` method +        /// below. +        pub fn $name(n: $kind) -> Literal { +            Literal::_new(imp::Literal::$name(n)) +        } +    )*) +} + +macro_rules! unsuffixed_int_literals { +    ($($name:ident => $kind:ident,)*) => ($( +        /// Creates a new unsuffixed integer literal with the specified value. +        /// +        /// This function will create an integer like `1` where the integer +        /// value specified is the first part of the token. No suffix is +        /// specified on this token, meaning that invocations like +        /// `Literal::i8_unsuffixed(1)` are equivalent to +        /// `Literal::u32_unsuffixed(1)`. Literals created from negative numbers +        /// may not survive rountrips through `TokenStream` or strings and may +        /// be broken into two tokens (`-` and positive literal). +        /// +        /// Literals created through this method have the `Span::call_site()` +        /// span by default, which can be configured with the `set_span` method +        /// below. +        pub fn $name(n: $kind) -> Literal { +            Literal::_new(imp::Literal::$name(n)) +        } +    )*) +} + +impl Literal { +    fn _new(inner: imp::Literal) -> Literal { +        Literal { +            inner, +            _marker: marker::PhantomData, +        } +    } + +    fn _new_stable(inner: fallback::Literal) -> Literal { +        Literal { +            inner: inner.into(), +            _marker: marker::PhantomData, +        } +    } + +    suffixed_int_literals! { +        u8_suffixed => u8, +        u16_suffixed => u16, +        u32_suffixed => u32, +        u64_suffixed => u64, +        u128_suffixed => u128, +        usize_suffixed => usize, +        i8_suffixed => i8, +        i16_suffixed => i16, +        i32_suffixed => i32, +        i64_suffixed => i64, +        i128_suffixed => i128, +        isize_suffixed => isize, +    } + +    unsuffixed_int_literals! { +        u8_unsuffixed => u8, +        u16_unsuffixed => u16, +        u32_unsuffixed => u32, +        u64_unsuffixed => u64, +        u128_unsuffixed => u128, +        usize_unsuffixed => usize, +        i8_unsuffixed => i8, +        i16_unsuffixed => i16, +        i32_unsuffixed => i32, +        i64_unsuffixed => i64, +        i128_unsuffixed => i128, +        isize_unsuffixed => isize, +    } + +    /// Creates a new unsuffixed floating-point literal. +    /// +    /// This constructor is similar to those like `Literal::i8_unsuffixed` where +    /// the float's value is emitted directly into the token but no suffix is +    /// used, so it may be inferred to be a `f64` later in the compiler. +    /// Literals created from negative numbers may not survive rountrips through +    /// `TokenStream` or strings and may be broken into two tokens (`-` and +    /// positive literal). +    /// +    /// # Panics +    /// +    /// This function requires that the specified float is finite, for example +    /// if it is infinity or NaN this function will panic. +    pub fn f64_unsuffixed(f: f64) -> Literal { +        assert!(f.is_finite()); +        Literal::_new(imp::Literal::f64_unsuffixed(f)) +    } + +    /// Creates a new suffixed floating-point literal. +    /// +    /// This constructor will create a literal like `1.0f64` where the value +    /// specified is the preceding part of the token and `f64` is the suffix of +    /// the token. This token will always be inferred to be an `f64` in the +    /// compiler. Literals created from negative numbers may not survive +    /// rountrips through `TokenStream` or strings and may be broken into two +    /// tokens (`-` and positive literal). +    /// +    /// # Panics +    /// +    /// This function requires that the specified float is finite, for example +    /// if it is infinity or NaN this function will panic. +    pub fn f64_suffixed(f: f64) -> Literal { +        assert!(f.is_finite()); +        Literal::_new(imp::Literal::f64_suffixed(f)) +    } + +    /// Creates a new unsuffixed floating-point literal. +    /// +    /// This constructor is similar to those like `Literal::i8_unsuffixed` where +    /// the float's value is emitted directly into the token but no suffix is +    /// used, so it may be inferred to be a `f64` later in the compiler. +    /// Literals created from negative numbers may not survive rountrips through +    /// `TokenStream` or strings and may be broken into two tokens (`-` and +    /// positive literal). +    /// +    /// # Panics +    /// +    /// This function requires that the specified float is finite, for example +    /// if it is infinity or NaN this function will panic. +    pub fn f32_unsuffixed(f: f32) -> Literal { +        assert!(f.is_finite()); +        Literal::_new(imp::Literal::f32_unsuffixed(f)) +    } + +    /// Creates a new suffixed floating-point literal. +    /// +    /// This constructor will create a literal like `1.0f32` where the value +    /// specified is the preceding part of the token and `f32` is the suffix of +    /// the token. This token will always be inferred to be an `f32` in the +    /// compiler. Literals created from negative numbers may not survive +    /// rountrips through `TokenStream` or strings and may be broken into two +    /// tokens (`-` and positive literal). +    /// +    /// # Panics +    /// +    /// This function requires that the specified float is finite, for example +    /// if it is infinity or NaN this function will panic. +    pub fn f32_suffixed(f: f32) -> Literal { +        assert!(f.is_finite()); +        Literal::_new(imp::Literal::f32_suffixed(f)) +    } + +    /// String literal. +    pub fn string(string: &str) -> Literal { +        Literal::_new(imp::Literal::string(string)) +    } + +    /// Character literal. +    pub fn character(ch: char) -> Literal { +        Literal::_new(imp::Literal::character(ch)) +    } + +    /// Byte string literal. +    pub fn byte_string(s: &[u8]) -> Literal { +        Literal::_new(imp::Literal::byte_string(s)) +    } + +    /// Returns the span encompassing this literal. +    pub fn span(&self) -> Span { +        Span::_new(self.inner.span()) +    } + +    /// Configures the span associated for this literal. +    pub fn set_span(&mut self, span: Span) { +        self.inner.set_span(span.inner); +    } + +    /// Returns a `Span` that is a subset of `self.span()` containing only +    /// the source bytes in range `range`. Returns `None` if the would-be +    /// trimmed span is outside the bounds of `self`. +    /// +    /// Warning: the underlying [`proc_macro::Literal::subspan`] method is +    /// nightly-only. When called from within a procedural macro not using a +    /// nightly compiler, this method will always return `None`. +    /// +    /// [`proc_macro::Literal::subspan`]: https://doc.rust-lang.org/proc_macro/struct.Literal.html#method.subspan +    pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> { +        self.inner.subspan(range).map(Span::_new) +    } +} + +impl fmt::Debug for Literal { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        self.inner.fmt(f) +    } +} + +impl fmt::Display for Literal { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        self.inner.fmt(f) +    } +} + +/// Public implementation details for the `TokenStream` type, such as iterators. +pub mod token_stream { +    use std::fmt; +    use std::marker; +    use std::rc::Rc; + +    pub use crate::TokenStream; +    use crate::{imp, TokenTree}; + +    /// An iterator over `TokenStream`'s `TokenTree`s. +    /// +    /// The iteration is "shallow", e.g. the iterator doesn't recurse into +    /// delimited groups, and returns whole groups as token trees. +    #[derive(Clone)] +    pub struct IntoIter { +        inner: imp::TokenTreeIter, +        _marker: marker::PhantomData<Rc<()>>, +    } + +    impl Iterator for IntoIter { +        type Item = TokenTree; + +        fn next(&mut self) -> Option<TokenTree> { +            self.inner.next() +        } +    } + +    impl fmt::Debug for IntoIter { +        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +            self.inner.fmt(f) +        } +    } + +    impl IntoIterator for TokenStream { +        type Item = TokenTree; +        type IntoIter = IntoIter; + +        fn into_iter(self) -> IntoIter { +            IntoIter { +                inner: self.inner.into_iter(), +                _marker: marker::PhantomData, +            } +        } +    } +} diff --git a/proc-macro2/src/strnom.rs b/proc-macro2/src/strnom.rs new file mode 100644 index 0000000..eb7d0b8 --- /dev/null +++ b/proc-macro2/src/strnom.rs @@ -0,0 +1,391 @@ +//! Adapted from [`nom`](https://github.com/Geal/nom). + +use crate::fallback::LexError; +use std::str::{Bytes, CharIndices, Chars}; +use unicode_xid::UnicodeXID; + +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct Cursor<'a> { +    pub rest: &'a str, +    #[cfg(span_locations)] +    pub off: u32, +} + +impl<'a> Cursor<'a> { +    #[cfg(not(span_locations))] +    pub fn advance(&self, amt: usize) -> Cursor<'a> { +        Cursor { +            rest: &self.rest[amt..], +        } +    } +    #[cfg(span_locations)] +    pub fn advance(&self, amt: usize) -> Cursor<'a> { +        Cursor { +            rest: &self.rest[amt..], +            off: self.off + (amt as u32), +        } +    } + +    pub fn find(&self, p: char) -> Option<usize> { +        self.rest.find(p) +    } + +    pub fn starts_with(&self, s: &str) -> bool { +        self.rest.starts_with(s) +    } + +    pub fn is_empty(&self) -> bool { +        self.rest.is_empty() +    } + +    pub fn len(&self) -> usize { +        self.rest.len() +    } + +    pub fn as_bytes(&self) -> &'a [u8] { +        self.rest.as_bytes() +    } + +    pub fn bytes(&self) -> Bytes<'a> { +        self.rest.bytes() +    } + +    pub fn chars(&self) -> Chars<'a> { +        self.rest.chars() +    } + +    pub fn char_indices(&self) -> CharIndices<'a> { +        self.rest.char_indices() +    } +} + +pub type PResult<'a, O> = Result<(Cursor<'a>, O), LexError>; + +pub fn whitespace(input: Cursor) -> PResult<()> { +    if input.is_empty() { +        return Err(LexError); +    } + +    let bytes = input.as_bytes(); +    let mut i = 0; +    while i < bytes.len() { +        let s = input.advance(i); +        if bytes[i] == b'/' { +            if s.starts_with("//") +                && (!s.starts_with("///") || s.starts_with("////")) +                && !s.starts_with("//!") +            { +                if let Some(len) = s.find('\n') { +                    i += len + 1; +                    continue; +                } +                break; +            } else if s.starts_with("/**/") { +                i += 4; +                continue; +            } else if s.starts_with("/*") +                && (!s.starts_with("/**") || s.starts_with("/***")) +                && !s.starts_with("/*!") +            { +                let (_, com) = block_comment(s)?; +                i += com.len(); +                continue; +            } +        } +        match bytes[i] { +            b' ' | 0x09..=0x0d => { +                i += 1; +                continue; +            } +            b if b <= 0x7f => {} +            _ => { +                let ch = s.chars().next().unwrap(); +                if is_whitespace(ch) { +                    i += ch.len_utf8(); +                    continue; +                } +            } +        } +        return if i > 0 { Ok((s, ())) } else { Err(LexError) }; +    } +    Ok((input.advance(input.len()), ())) +} + +pub fn block_comment(input: Cursor) -> PResult<&str> { +    if !input.starts_with("/*") { +        return Err(LexError); +    } + +    let mut depth = 0; +    let bytes = input.as_bytes(); +    let mut i = 0; +    let upper = bytes.len() - 1; +    while i < upper { +        if bytes[i] == b'/' && bytes[i + 1] == b'*' { +            depth += 1; +            i += 1; // eat '*' +        } else if bytes[i] == b'*' && bytes[i + 1] == b'/' { +            depth -= 1; +            if depth == 0 { +                return Ok((input.advance(i + 2), &input.rest[..i + 2])); +            } +            i += 1; // eat '/' +        } +        i += 1; +    } +    Err(LexError) +} + +pub fn skip_whitespace(input: Cursor) -> Cursor { +    match whitespace(input) { +        Ok((rest, _)) => rest, +        Err(LexError) => input, +    } +} + +fn is_whitespace(ch: char) -> bool { +    // Rust treats left-to-right mark and right-to-left mark as whitespace +    ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' +} + +pub fn word_break(input: Cursor) -> PResult<()> { +    match input.chars().next() { +        Some(ch) if UnicodeXID::is_xid_continue(ch) => Err(LexError), +        Some(_) | None => Ok((input, ())), +    } +} + +macro_rules! named { +    ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => { +        fn $name<'a>(i: Cursor<'a>) -> $crate::strnom::PResult<'a, $o> { +            $submac!(i, $($args)*) +        } +    }; +} + +macro_rules! alt { +    ($i:expr, $e:ident | $($rest:tt)*) => { +        alt!($i, call!($e) | $($rest)*) +    }; + +    ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => { +        match $subrule!($i, $($args)*) { +            res @ Ok(_) => res, +            _ => alt!($i, $($rest)*) +        } +    }; + +    ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => { +        match $subrule!($i, $($args)*) { +            Ok((i, o)) => Ok((i, $gen(o))), +            Err(LexError) => alt!($i, $($rest)*) +        } +    }; + +    ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => { +        alt!($i, call!($e) => { $gen } | $($rest)*) +    }; + +    ($i:expr, $e:ident => { $gen:expr }) => { +        alt!($i, call!($e) => { $gen }) +    }; + +    ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => { +        match $subrule!($i, $($args)*) { +            Ok((i, o)) => Ok((i, $gen(o))), +            Err(LexError) => Err(LexError), +        } +    }; + +    ($i:expr, $e:ident) => { +        alt!($i, call!($e)) +    }; + +    ($i:expr, $subrule:ident!( $($args:tt)*)) => { +        $subrule!($i, $($args)*) +    }; +} + +macro_rules! do_parse { +    ($i:expr, ( $($rest:expr),* )) => { +        Ok(($i, ( $($rest),* ))) +    }; + +    ($i:expr, $e:ident >> $($rest:tt)*) => { +        do_parse!($i, call!($e) >> $($rest)*) +    }; + +    ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => { +        match $submac!($i, $($args)*) { +            Err(LexError) => Err(LexError), +            Ok((i, _)) => do_parse!(i, $($rest)*), +        } +    }; + +    ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => { +        do_parse!($i, $field: call!($e) >> $($rest)*) +    }; + +    ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => { +        match $submac!($i, $($args)*) { +            Err(LexError) => Err(LexError), +            Ok((i, o)) => { +                let $field = o; +                do_parse!(i, $($rest)*) +            }, +        } +    }; +} + +macro_rules! peek { +    ($i:expr, $submac:ident!( $($args:tt)* )) => { +        match $submac!($i, $($args)*) { +            Ok((_, o)) => Ok(($i, o)), +            Err(LexError) => Err(LexError), +        } +    }; +} + +macro_rules! call { +    ($i:expr, $fun:expr $(, $args:expr)*) => { +        $fun($i $(, $args)*) +    }; +} + +macro_rules! option { +    ($i:expr, $f:expr) => { +        match $f($i) { +            Ok((i, o)) => Ok((i, Some(o))), +            Err(LexError) => Ok(($i, None)), +        } +    }; +} + +macro_rules! take_until_newline_or_eof { +    ($i:expr,) => {{ +        if $i.len() == 0 { +            Ok(($i, "")) +        } else { +            match $i.find('\n') { +                Some(i) => Ok(($i.advance(i), &$i.rest[..i])), +                None => Ok(($i.advance($i.len()), &$i.rest[..$i.len()])), +            } +        } +    }}; +} + +macro_rules! tuple { +    ($i:expr, $($rest:tt)*) => { +        tuple_parser!($i, (), $($rest)*) +    }; +} + +/// Do not use directly. Use `tuple!`. +macro_rules! tuple_parser { +    ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => { +        tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*) +    }; + +    ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => { +        match $submac!($i, $($args)*) { +            Err(LexError) => Err(LexError), +            Ok((i, o)) => tuple_parser!(i, (o), $($rest)*), +        } +    }; + +    ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => { +        match $submac!($i, $($args)*) { +            Err(LexError) => Err(LexError), +            Ok((i, o)) => tuple_parser!(i, ($($parsed)* , o), $($rest)*), +        } +    }; + +    ($i:expr, ($($parsed:tt),*), $e:ident) => { +        tuple_parser!($i, ($($parsed),*), call!($e)) +    }; + +    ($i:expr, (), $submac:ident!( $($args:tt)* )) => { +        $submac!($i, $($args)*) +    }; + +    ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => { +        match $submac!($i, $($args)*) { +            Err(LexError) => Err(LexError), +            Ok((i, o)) => Ok((i, ($($parsed),*, o))) +        } +    }; + +    ($i:expr, ($($parsed:expr),*)) => { +        Ok(($i, ($($parsed),*))) +    }; +} + +macro_rules! not { +    ($i:expr, $submac:ident!( $($args:tt)* )) => { +        match $submac!($i, $($args)*) { +            Ok((_, _)) => Err(LexError), +            Err(LexError) => Ok(($i, ())), +        } +    }; +} + +macro_rules! tag { +    ($i:expr, $tag:expr) => { +        if $i.starts_with($tag) { +            Ok(($i.advance($tag.len()), &$i.rest[..$tag.len()])) +        } else { +            Err(LexError) +        } +    }; +} + +macro_rules! punct { +    ($i:expr, $punct:expr) => { +        $crate::strnom::punct($i, $punct) +    }; +} + +/// Do not use directly. Use `punct!`. +pub fn punct<'a>(input: Cursor<'a>, token: &'static str) -> PResult<'a, &'a str> { +    let input = skip_whitespace(input); +    if input.starts_with(token) { +        Ok((input.advance(token.len()), token)) +    } else { +        Err(LexError) +    } +} + +macro_rules! preceded { +    ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => { +        match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) { +            Ok((remaining, (_, o))) => Ok((remaining, o)), +            Err(LexError) => Err(LexError), +        } +    }; + +    ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => { +        preceded!($i, $submac!($($args)*), call!($g)) +    }; +} + +macro_rules! delimited { +    ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => { +        match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) { +            Err(LexError) => Err(LexError), +            Ok((i1, (_, o, _))) => Ok((i1, o)) +        } +    }; +} + +macro_rules! map { +    ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => { +        match $submac!($i, $($args)*) { +            Err(LexError) => Err(LexError), +            Ok((i, o)) => Ok((i, call!(o, $g))) +        } +    }; + +    ($i:expr, $f:expr, $g:expr) => { +        map!($i, call!($f), $g) +    }; +} diff --git a/proc-macro2/src/wrapper.rs b/proc-macro2/src/wrapper.rs new file mode 100644 index 0000000..552b938 --- /dev/null +++ b/proc-macro2/src/wrapper.rs @@ -0,0 +1,927 @@ +use std::fmt; +use std::iter; +use std::ops::RangeBounds; +use std::panic::{self, PanicInfo}; +#[cfg(super_unstable)] +use std::path::PathBuf; +use std::str::FromStr; + +use crate::{fallback, Delimiter, Punct, Spacing, TokenTree}; + +#[derive(Clone)] +pub enum TokenStream { +    Compiler(DeferredTokenStream), +    Fallback(fallback::TokenStream), +} + +// Work around https://github.com/rust-lang/rust/issues/65080. +// In `impl Extend<TokenTree> for TokenStream` which is used heavily by quote, +// we hold on to the appended tokens and do proc_macro::TokenStream::extend as +// late as possible to batch together consecutive uses of the Extend impl. +#[derive(Clone)] +pub struct DeferredTokenStream { +    stream: proc_macro::TokenStream, +    extra: Vec<proc_macro::TokenTree>, +} + +pub enum LexError { +    Compiler(proc_macro::LexError), +    Fallback(fallback::LexError), +} + +fn nightly_works() -> bool { +    use std::sync::atomic::*; +    use std::sync::Once; + +    static WORKS: AtomicUsize = AtomicUsize::new(0); +    static INIT: Once = Once::new(); + +    match WORKS.load(Ordering::SeqCst) { +        1 => return false, +        2 => return true, +        _ => {} +    } + +    // Swap in a null panic hook to avoid printing "thread panicked" to stderr, +    // then use catch_unwind to determine whether the compiler's proc_macro is +    // working. When proc-macro2 is used from outside of a procedural macro all +    // of the proc_macro crate's APIs currently panic. +    // +    // The Once is to prevent the possibility of this ordering: +    // +    //     thread 1 calls take_hook, gets the user's original hook +    //     thread 1 calls set_hook with the null hook +    //     thread 2 calls take_hook, thinks null hook is the original hook +    //     thread 2 calls set_hook with the null hook +    //     thread 1 calls set_hook with the actual original hook +    //     thread 2 calls set_hook with what it thinks is the original hook +    // +    // in which the user's hook has been lost. +    // +    // There is still a race condition where a panic in a different thread can +    // happen during the interval that the user's original panic hook is +    // unregistered such that their hook is incorrectly not called. This is +    // sufficiently unlikely and less bad than printing panic messages to stderr +    // on correct use of this crate. Maybe there is a libstd feature request +    // here. For now, if a user needs to guarantee that this failure mode does +    // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from +    // the main thread before launching any other threads. +    INIT.call_once(|| { +        type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static; + +        let null_hook: Box<PanicHook> = Box::new(|_panic_info| { /* ignore */ }); +        let sanity_check = &*null_hook as *const PanicHook; +        let original_hook = panic::take_hook(); +        panic::set_hook(null_hook); + +        let works = panic::catch_unwind(|| proc_macro::Span::call_site()).is_ok(); +        WORKS.store(works as usize + 1, Ordering::SeqCst); + +        let hopefully_null_hook = panic::take_hook(); +        panic::set_hook(original_hook); +        if sanity_check != &*hopefully_null_hook { +            panic!("observed race condition in proc_macro2::nightly_works"); +        } +    }); +    nightly_works() +} + +fn mismatch() -> ! { +    panic!("stable/nightly mismatch") +} + +impl DeferredTokenStream { +    fn new(stream: proc_macro::TokenStream) -> Self { +        DeferredTokenStream { +            stream, +            extra: Vec::new(), +        } +    } + +    fn is_empty(&self) -> bool { +        self.stream.is_empty() && self.extra.is_empty() +    } + +    fn evaluate_now(&mut self) { +        self.stream.extend(self.extra.drain(..)); +    } + +    fn into_token_stream(mut self) -> proc_macro::TokenStream { +        self.evaluate_now(); +        self.stream +    } +} + +impl TokenStream { +    pub fn new() -> TokenStream { +        if nightly_works() { +            TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::new())) +        } else { +            TokenStream::Fallback(fallback::TokenStream::new()) +        } +    } + +    pub fn is_empty(&self) -> bool { +        match self { +            TokenStream::Compiler(tts) => tts.is_empty(), +            TokenStream::Fallback(tts) => tts.is_empty(), +        } +    } + +    fn unwrap_nightly(self) -> proc_macro::TokenStream { +        match self { +            TokenStream::Compiler(s) => s.into_token_stream(), +            TokenStream::Fallback(_) => mismatch(), +        } +    } + +    fn unwrap_stable(self) -> fallback::TokenStream { +        match self { +            TokenStream::Compiler(_) => mismatch(), +            TokenStream::Fallback(s) => s, +        } +    } +} + +impl FromStr for TokenStream { +    type Err = LexError; + +    fn from_str(src: &str) -> Result<TokenStream, LexError> { +        if nightly_works() { +            Ok(TokenStream::Compiler(DeferredTokenStream::new( +                src.parse()?, +            ))) +        } else { +            Ok(TokenStream::Fallback(src.parse()?)) +        } +    } +} + +impl fmt::Display for TokenStream { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match self { +            TokenStream::Compiler(tts) => tts.clone().into_token_stream().fmt(f), +            TokenStream::Fallback(tts) => tts.fmt(f), +        } +    } +} + +impl From<proc_macro::TokenStream> for TokenStream { +    fn from(inner: proc_macro::TokenStream) -> TokenStream { +        TokenStream::Compiler(DeferredTokenStream::new(inner)) +    } +} + +impl From<TokenStream> for proc_macro::TokenStream { +    fn from(inner: TokenStream) -> proc_macro::TokenStream { +        match inner { +            TokenStream::Compiler(inner) => inner.into_token_stream(), +            TokenStream::Fallback(inner) => inner.to_string().parse().unwrap(), +        } +    } +} + +impl From<fallback::TokenStream> for TokenStream { +    fn from(inner: fallback::TokenStream) -> TokenStream { +        TokenStream::Fallback(inner) +    } +} + +// Assumes nightly_works(). +fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree { +    match token { +        TokenTree::Group(tt) => tt.inner.unwrap_nightly().into(), +        TokenTree::Punct(tt) => { +            let spacing = match tt.spacing() { +                Spacing::Joint => proc_macro::Spacing::Joint, +                Spacing::Alone => proc_macro::Spacing::Alone, +            }; +            let mut op = proc_macro::Punct::new(tt.as_char(), spacing); +            op.set_span(tt.span().inner.unwrap_nightly()); +            op.into() +        } +        TokenTree::Ident(tt) => tt.inner.unwrap_nightly().into(), +        TokenTree::Literal(tt) => tt.inner.unwrap_nightly().into(), +    } +} + +impl From<TokenTree> for TokenStream { +    fn from(token: TokenTree) -> TokenStream { +        if nightly_works() { +            TokenStream::Compiler(DeferredTokenStream::new(into_compiler_token(token).into())) +        } else { +            TokenStream::Fallback(token.into()) +        } +    } +} + +impl iter::FromIterator<TokenTree> for TokenStream { +    fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self { +        if nightly_works() { +            TokenStream::Compiler(DeferredTokenStream::new( +                trees.into_iter().map(into_compiler_token).collect(), +            )) +        } else { +            TokenStream::Fallback(trees.into_iter().collect()) +        } +    } +} + +impl iter::FromIterator<TokenStream> for TokenStream { +    fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { +        let mut streams = streams.into_iter(); +        match streams.next() { +            Some(TokenStream::Compiler(mut first)) => { +                first.evaluate_now(); +                first.stream.extend(streams.map(|s| match s { +                    TokenStream::Compiler(s) => s.into_token_stream(), +                    TokenStream::Fallback(_) => mismatch(), +                })); +                TokenStream::Compiler(first) +            } +            Some(TokenStream::Fallback(mut first)) => { +                first.extend(streams.map(|s| match s { +                    TokenStream::Fallback(s) => s, +                    TokenStream::Compiler(_) => mismatch(), +                })); +                TokenStream::Fallback(first) +            } +            None => TokenStream::new(), +        } +    } +} + +impl Extend<TokenTree> for TokenStream { +    fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) { +        match self { +            TokenStream::Compiler(tts) => { +                // Here is the reason for DeferredTokenStream. +                tts.extra +                    .extend(streams.into_iter().map(into_compiler_token)); +            } +            TokenStream::Fallback(tts) => tts.extend(streams), +        } +    } +} + +impl Extend<TokenStream> for TokenStream { +    fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { +        match self { +            TokenStream::Compiler(tts) => { +                tts.evaluate_now(); +                tts.stream +                    .extend(streams.into_iter().map(|stream| stream.unwrap_nightly())); +            } +            TokenStream::Fallback(tts) => { +                tts.extend(streams.into_iter().map(|stream| stream.unwrap_stable())); +            } +        } +    } +} + +impl fmt::Debug for TokenStream { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match self { +            TokenStream::Compiler(tts) => tts.clone().into_token_stream().fmt(f), +            TokenStream::Fallback(tts) => tts.fmt(f), +        } +    } +} + +impl From<proc_macro::LexError> for LexError { +    fn from(e: proc_macro::LexError) -> LexError { +        LexError::Compiler(e) +    } +} + +impl From<fallback::LexError> for LexError { +    fn from(e: fallback::LexError) -> LexError { +        LexError::Fallback(e) +    } +} + +impl fmt::Debug for LexError { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match self { +            LexError::Compiler(e) => e.fmt(f), +            LexError::Fallback(e) => e.fmt(f), +        } +    } +} + +#[derive(Clone)] +pub enum TokenTreeIter { +    Compiler(proc_macro::token_stream::IntoIter), +    Fallback(fallback::TokenTreeIter), +} + +impl IntoIterator for TokenStream { +    type Item = TokenTree; +    type IntoIter = TokenTreeIter; + +    fn into_iter(self) -> TokenTreeIter { +        match self { +            TokenStream::Compiler(tts) => { +                TokenTreeIter::Compiler(tts.into_token_stream().into_iter()) +            } +            TokenStream::Fallback(tts) => TokenTreeIter::Fallback(tts.into_iter()), +        } +    } +} + +impl Iterator for TokenTreeIter { +    type Item = TokenTree; + +    fn next(&mut self) -> Option<TokenTree> { +        let token = match self { +            TokenTreeIter::Compiler(iter) => iter.next()?, +            TokenTreeIter::Fallback(iter) => return iter.next(), +        }; +        Some(match token { +            proc_macro::TokenTree::Group(tt) => crate::Group::_new(Group::Compiler(tt)).into(), +            proc_macro::TokenTree::Punct(tt) => { +                let spacing = match tt.spacing() { +                    proc_macro::Spacing::Joint => Spacing::Joint, +                    proc_macro::Spacing::Alone => Spacing::Alone, +                }; +                let mut o = Punct::new(tt.as_char(), spacing); +                o.set_span(crate::Span::_new(Span::Compiler(tt.span()))); +                o.into() +            } +            proc_macro::TokenTree::Ident(s) => crate::Ident::_new(Ident::Compiler(s)).into(), +            proc_macro::TokenTree::Literal(l) => crate::Literal::_new(Literal::Compiler(l)).into(), +        }) +    } + +    fn size_hint(&self) -> (usize, Option<usize>) { +        match self { +            TokenTreeIter::Compiler(tts) => tts.size_hint(), +            TokenTreeIter::Fallback(tts) => tts.size_hint(), +        } +    } +} + +impl fmt::Debug for TokenTreeIter { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        f.debug_struct("TokenTreeIter").finish() +    } +} + +#[derive(Clone, PartialEq, Eq)] +#[cfg(super_unstable)] +pub enum SourceFile { +    Compiler(proc_macro::SourceFile), +    Fallback(fallback::SourceFile), +} + +#[cfg(super_unstable)] +impl SourceFile { +    fn nightly(sf: proc_macro::SourceFile) -> Self { +        SourceFile::Compiler(sf) +    } + +    /// Get the path to this source file as a string. +    pub fn path(&self) -> PathBuf { +        match self { +            SourceFile::Compiler(a) => a.path(), +            SourceFile::Fallback(a) => a.path(), +        } +    } + +    pub fn is_real(&self) -> bool { +        match self { +            SourceFile::Compiler(a) => a.is_real(), +            SourceFile::Fallback(a) => a.is_real(), +        } +    } +} + +#[cfg(super_unstable)] +impl fmt::Debug for SourceFile { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match self { +            SourceFile::Compiler(a) => a.fmt(f), +            SourceFile::Fallback(a) => a.fmt(f), +        } +    } +} + +#[cfg(any(super_unstable, feature = "span-locations"))] +pub struct LineColumn { +    pub line: usize, +    pub column: usize, +} + +#[derive(Copy, Clone)] +pub enum Span { +    Compiler(proc_macro::Span), +    Fallback(fallback::Span), +} + +impl Span { +    pub fn call_site() -> Span { +        if nightly_works() { +            Span::Compiler(proc_macro::Span::call_site()) +        } else { +            Span::Fallback(fallback::Span::call_site()) +        } +    } + +    #[cfg(super_unstable)] +    pub fn def_site() -> Span { +        if nightly_works() { +            Span::Compiler(proc_macro::Span::def_site()) +        } else { +            Span::Fallback(fallback::Span::def_site()) +        } +    } + +    #[cfg(super_unstable)] +    pub fn resolved_at(&self, other: Span) -> Span { +        match (self, other) { +            (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)), +            (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)), +            _ => mismatch(), +        } +    } + +    #[cfg(super_unstable)] +    pub fn located_at(&self, other: Span) -> Span { +        match (self, other) { +            (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)), +            (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)), +            _ => mismatch(), +        } +    } + +    pub fn unwrap(self) -> proc_macro::Span { +        match self { +            Span::Compiler(s) => s, +            Span::Fallback(_) => panic!("proc_macro::Span is only available in procedural macros"), +        } +    } + +    #[cfg(super_unstable)] +    pub fn source_file(&self) -> SourceFile { +        match self { +            Span::Compiler(s) => SourceFile::nightly(s.source_file()), +            Span::Fallback(s) => SourceFile::Fallback(s.source_file()), +        } +    } + +    #[cfg(any(super_unstable, feature = "span-locations"))] +    pub fn start(&self) -> LineColumn { +        match self { +            #[cfg(proc_macro_span)] +            Span::Compiler(s) => { +                let proc_macro::LineColumn { line, column } = s.start(); +                LineColumn { line, column } +            } +            #[cfg(not(proc_macro_span))] +            Span::Compiler(_) => LineColumn { line: 0, column: 0 }, +            Span::Fallback(s) => { +                let fallback::LineColumn { line, column } = s.start(); +                LineColumn { line, column } +            } +        } +    } + +    #[cfg(any(super_unstable, feature = "span-locations"))] +    pub fn end(&self) -> LineColumn { +        match self { +            #[cfg(proc_macro_span)] +            Span::Compiler(s) => { +                let proc_macro::LineColumn { line, column } = s.end(); +                LineColumn { line, column } +            } +            #[cfg(not(proc_macro_span))] +            Span::Compiler(_) => LineColumn { line: 0, column: 0 }, +            Span::Fallback(s) => { +                let fallback::LineColumn { line, column } = s.end(); +                LineColumn { line, column } +            } +        } +    } + +    pub fn join(&self, other: Span) -> Option<Span> { +        let ret = match (self, other) { +            #[cfg(proc_macro_span)] +            (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.join(b)?), +            (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?), +            _ => return None, +        }; +        Some(ret) +    } + +    #[cfg(super_unstable)] +    pub fn eq(&self, other: &Span) -> bool { +        match (self, other) { +            (Span::Compiler(a), Span::Compiler(b)) => a.eq(b), +            (Span::Fallback(a), Span::Fallback(b)) => a.eq(b), +            _ => false, +        } +    } + +    fn unwrap_nightly(self) -> proc_macro::Span { +        match self { +            Span::Compiler(s) => s, +            Span::Fallback(_) => mismatch(), +        } +    } +} + +impl From<proc_macro::Span> for crate::Span { +    fn from(proc_span: proc_macro::Span) -> crate::Span { +        crate::Span::_new(Span::Compiler(proc_span)) +    } +} + +impl From<fallback::Span> for Span { +    fn from(inner: fallback::Span) -> Span { +        Span::Fallback(inner) +    } +} + +impl fmt::Debug for Span { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match self { +            Span::Compiler(s) => s.fmt(f), +            Span::Fallback(s) => s.fmt(f), +        } +    } +} + +pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { +    match span { +        Span::Compiler(s) => { +            debug.field("span", &s); +        } +        Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s), +    } +} + +#[derive(Clone)] +pub enum Group { +    Compiler(proc_macro::Group), +    Fallback(fallback::Group), +} + +impl Group { +    pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { +        match stream { +            TokenStream::Compiler(tts) => { +                let delimiter = match delimiter { +                    Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis, +                    Delimiter::Bracket => proc_macro::Delimiter::Bracket, +                    Delimiter::Brace => proc_macro::Delimiter::Brace, +                    Delimiter::None => proc_macro::Delimiter::None, +                }; +                Group::Compiler(proc_macro::Group::new(delimiter, tts.into_token_stream())) +            } +            TokenStream::Fallback(stream) => { +                Group::Fallback(fallback::Group::new(delimiter, stream)) +            } +        } +    } + +    pub fn delimiter(&self) -> Delimiter { +        match self { +            Group::Compiler(g) => match g.delimiter() { +                proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis, +                proc_macro::Delimiter::Bracket => Delimiter::Bracket, +                proc_macro::Delimiter::Brace => Delimiter::Brace, +                proc_macro::Delimiter::None => Delimiter::None, +            }, +            Group::Fallback(g) => g.delimiter(), +        } +    } + +    pub fn stream(&self) -> TokenStream { +        match self { +            Group::Compiler(g) => TokenStream::Compiler(DeferredTokenStream::new(g.stream())), +            Group::Fallback(g) => TokenStream::Fallback(g.stream()), +        } +    } + +    pub fn span(&self) -> Span { +        match self { +            Group::Compiler(g) => Span::Compiler(g.span()), +            Group::Fallback(g) => Span::Fallback(g.span()), +        } +    } + +    pub fn span_open(&self) -> Span { +        match self { +            #[cfg(proc_macro_span)] +            Group::Compiler(g) => Span::Compiler(g.span_open()), +            #[cfg(not(proc_macro_span))] +            Group::Compiler(g) => Span::Compiler(g.span()), +            Group::Fallback(g) => Span::Fallback(g.span_open()), +        } +    } + +    pub fn span_close(&self) -> Span { +        match self { +            #[cfg(proc_macro_span)] +            Group::Compiler(g) => Span::Compiler(g.span_close()), +            #[cfg(not(proc_macro_span))] +            Group::Compiler(g) => Span::Compiler(g.span()), +            Group::Fallback(g) => Span::Fallback(g.span_close()), +        } +    } + +    pub fn set_span(&mut self, span: Span) { +        match (self, span) { +            (Group::Compiler(g), Span::Compiler(s)) => g.set_span(s), +            (Group::Fallback(g), Span::Fallback(s)) => g.set_span(s), +            _ => mismatch(), +        } +    } + +    fn unwrap_nightly(self) -> proc_macro::Group { +        match self { +            Group::Compiler(g) => g, +            Group::Fallback(_) => mismatch(), +        } +    } +} + +impl From<fallback::Group> for Group { +    fn from(g: fallback::Group) -> Self { +        Group::Fallback(g) +    } +} + +impl fmt::Display for Group { +    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +        match self { +            Group::Compiler(group) => group.fmt(formatter), +            Group::Fallback(group) => group.fmt(formatter), +        } +    } +} + +impl fmt::Debug for Group { +    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +        match self { +            Group::Compiler(group) => group.fmt(formatter), +            Group::Fallback(group) => group.fmt(formatter), +        } +    } +} + +#[derive(Clone)] +pub enum Ident { +    Compiler(proc_macro::Ident), +    Fallback(fallback::Ident), +} + +impl Ident { +    pub fn new(string: &str, span: Span) -> Ident { +        match span { +            Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)), +            Span::Fallback(s) => Ident::Fallback(fallback::Ident::new(string, s)), +        } +    } + +    pub fn new_raw(string: &str, span: Span) -> Ident { +        match span { +            Span::Compiler(s) => { +                let p: proc_macro::TokenStream = string.parse().unwrap(); +                let ident = match p.into_iter().next() { +                    Some(proc_macro::TokenTree::Ident(mut i)) => { +                        i.set_span(s); +                        i +                    } +                    _ => panic!(), +                }; +                Ident::Compiler(ident) +            } +            Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw(string, s)), +        } +    } + +    pub fn span(&self) -> Span { +        match self { +            Ident::Compiler(t) => Span::Compiler(t.span()), +            Ident::Fallback(t) => Span::Fallback(t.span()), +        } +    } + +    pub fn set_span(&mut self, span: Span) { +        match (self, span) { +            (Ident::Compiler(t), Span::Compiler(s)) => t.set_span(s), +            (Ident::Fallback(t), Span::Fallback(s)) => t.set_span(s), +            _ => mismatch(), +        } +    } + +    fn unwrap_nightly(self) -> proc_macro::Ident { +        match self { +            Ident::Compiler(s) => s, +            Ident::Fallback(_) => mismatch(), +        } +    } +} + +impl PartialEq for Ident { +    fn eq(&self, other: &Ident) -> bool { +        match (self, other) { +            (Ident::Compiler(t), Ident::Compiler(o)) => t.to_string() == o.to_string(), +            (Ident::Fallback(t), Ident::Fallback(o)) => t == o, +            _ => mismatch(), +        } +    } +} + +impl<T> PartialEq<T> for Ident +where +    T: ?Sized + AsRef<str>, +{ +    fn eq(&self, other: &T) -> bool { +        let other = other.as_ref(); +        match self { +            Ident::Compiler(t) => t.to_string() == other, +            Ident::Fallback(t) => t == other, +        } +    } +} + +impl fmt::Display for Ident { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match self { +            Ident::Compiler(t) => t.fmt(f), +            Ident::Fallback(t) => t.fmt(f), +        } +    } +} + +impl fmt::Debug for Ident { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match self { +            Ident::Compiler(t) => t.fmt(f), +            Ident::Fallback(t) => t.fmt(f), +        } +    } +} + +#[derive(Clone)] +pub enum Literal { +    Compiler(proc_macro::Literal), +    Fallback(fallback::Literal), +} + +macro_rules! suffixed_numbers { +    ($($name:ident => $kind:ident,)*) => ($( +        pub fn $name(n: $kind) -> Literal { +            if nightly_works() { +                Literal::Compiler(proc_macro::Literal::$name(n)) +            } else { +                Literal::Fallback(fallback::Literal::$name(n)) +            } +        } +    )*) +} + +macro_rules! unsuffixed_integers { +    ($($name:ident => $kind:ident,)*) => ($( +        pub fn $name(n: $kind) -> Literal { +            if nightly_works() { +                Literal::Compiler(proc_macro::Literal::$name(n)) +            } else { +                Literal::Fallback(fallback::Literal::$name(n)) +            } +        } +    )*) +} + +impl Literal { +    suffixed_numbers! { +        u8_suffixed => u8, +        u16_suffixed => u16, +        u32_suffixed => u32, +        u64_suffixed => u64, +        u128_suffixed => u128, +        usize_suffixed => usize, +        i8_suffixed => i8, +        i16_suffixed => i16, +        i32_suffixed => i32, +        i64_suffixed => i64, +        i128_suffixed => i128, +        isize_suffixed => isize, + +        f32_suffixed => f32, +        f64_suffixed => f64, +    } + +    unsuffixed_integers! { +        u8_unsuffixed => u8, +        u16_unsuffixed => u16, +        u32_unsuffixed => u32, +        u64_unsuffixed => u64, +        u128_unsuffixed => u128, +        usize_unsuffixed => usize, +        i8_unsuffixed => i8, +        i16_unsuffixed => i16, +        i32_unsuffixed => i32, +        i64_unsuffixed => i64, +        i128_unsuffixed => i128, +        isize_unsuffixed => isize, +    } + +    pub fn f32_unsuffixed(f: f32) -> Literal { +        if nightly_works() { +            Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f)) +        } else { +            Literal::Fallback(fallback::Literal::f32_unsuffixed(f)) +        } +    } + +    pub fn f64_unsuffixed(f: f64) -> Literal { +        if nightly_works() { +            Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f)) +        } else { +            Literal::Fallback(fallback::Literal::f64_unsuffixed(f)) +        } +    } + +    pub fn string(t: &str) -> Literal { +        if nightly_works() { +            Literal::Compiler(proc_macro::Literal::string(t)) +        } else { +            Literal::Fallback(fallback::Literal::string(t)) +        } +    } + +    pub fn character(t: char) -> Literal { +        if nightly_works() { +            Literal::Compiler(proc_macro::Literal::character(t)) +        } else { +            Literal::Fallback(fallback::Literal::character(t)) +        } +    } + +    pub fn byte_string(bytes: &[u8]) -> Literal { +        if nightly_works() { +            Literal::Compiler(proc_macro::Literal::byte_string(bytes)) +        } else { +            Literal::Fallback(fallback::Literal::byte_string(bytes)) +        } +    } + +    pub fn span(&self) -> Span { +        match self { +            Literal::Compiler(lit) => Span::Compiler(lit.span()), +            Literal::Fallback(lit) => Span::Fallback(lit.span()), +        } +    } + +    pub fn set_span(&mut self, span: Span) { +        match (self, span) { +            (Literal::Compiler(lit), Span::Compiler(s)) => lit.set_span(s), +            (Literal::Fallback(lit), Span::Fallback(s)) => lit.set_span(s), +            _ => mismatch(), +        } +    } + +    pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> { +        match self { +            #[cfg(proc_macro_span)] +            Literal::Compiler(lit) => lit.subspan(range).map(Span::Compiler), +            #[cfg(not(proc_macro_span))] +            Literal::Compiler(_lit) => None, +            Literal::Fallback(lit) => lit.subspan(range).map(Span::Fallback), +        } +    } + +    fn unwrap_nightly(self) -> proc_macro::Literal { +        match self { +            Literal::Compiler(s) => s, +            Literal::Fallback(_) => mismatch(), +        } +    } +} + +impl From<fallback::Literal> for Literal { +    fn from(s: fallback::Literal) -> Literal { +        Literal::Fallback(s) +    } +} + +impl fmt::Display for Literal { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match self { +            Literal::Compiler(t) => t.fmt(f), +            Literal::Fallback(t) => t.fmt(f), +        } +    } +} + +impl fmt::Debug for Literal { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match self { +            Literal::Compiler(t) => t.fmt(f), +            Literal::Fallback(t) => t.fmt(f), +        } +    } +} | 
