17ac06127Sopenharmony_ci#![allow(
27ac06127Sopenharmony_ci    clippy::assertions_on_result_states,
37ac06127Sopenharmony_ci    clippy::items_after_statements,
47ac06127Sopenharmony_ci    clippy::non_ascii_literal,
57ac06127Sopenharmony_ci    clippy::octal_escapes
67ac06127Sopenharmony_ci)]
77ac06127Sopenharmony_ci
87ac06127Sopenharmony_ciuse proc_macro2::{Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
97ac06127Sopenharmony_ciuse std::iter;
107ac06127Sopenharmony_ciuse std::str::{self, FromStr};
117ac06127Sopenharmony_ci
127ac06127Sopenharmony_ci#[test]
137ac06127Sopenharmony_cifn idents() {
147ac06127Sopenharmony_ci    assert_eq!(
157ac06127Sopenharmony_ci        Ident::new("String", Span::call_site()).to_string(),
167ac06127Sopenharmony_ci        "String"
177ac06127Sopenharmony_ci    );
187ac06127Sopenharmony_ci    assert_eq!(Ident::new("fn", Span::call_site()).to_string(), "fn");
197ac06127Sopenharmony_ci    assert_eq!(Ident::new("_", Span::call_site()).to_string(), "_");
207ac06127Sopenharmony_ci}
217ac06127Sopenharmony_ci
227ac06127Sopenharmony_ci#[test]
237ac06127Sopenharmony_cifn raw_idents() {
247ac06127Sopenharmony_ci    assert_eq!(
257ac06127Sopenharmony_ci        Ident::new_raw("String", Span::call_site()).to_string(),
267ac06127Sopenharmony_ci        "r#String"
277ac06127Sopenharmony_ci    );
287ac06127Sopenharmony_ci    assert_eq!(Ident::new_raw("fn", Span::call_site()).to_string(), "r#fn");
297ac06127Sopenharmony_ci}
307ac06127Sopenharmony_ci
317ac06127Sopenharmony_ci#[test]
327ac06127Sopenharmony_ci#[should_panic(expected = "`r#_` cannot be a raw identifier")]
337ac06127Sopenharmony_cifn ident_raw_underscore() {
347ac06127Sopenharmony_ci    Ident::new_raw("_", Span::call_site());
357ac06127Sopenharmony_ci}
367ac06127Sopenharmony_ci
377ac06127Sopenharmony_ci#[test]
387ac06127Sopenharmony_ci#[should_panic(expected = "`r#super` cannot be a raw identifier")]
397ac06127Sopenharmony_cifn ident_raw_reserved() {
407ac06127Sopenharmony_ci    Ident::new_raw("super", Span::call_site());
417ac06127Sopenharmony_ci}
427ac06127Sopenharmony_ci
437ac06127Sopenharmony_ci#[test]
447ac06127Sopenharmony_ci#[should_panic(expected = "Ident is not allowed to be empty; use Option<Ident>")]
457ac06127Sopenharmony_cifn ident_empty() {
467ac06127Sopenharmony_ci    Ident::new("", Span::call_site());
477ac06127Sopenharmony_ci}
487ac06127Sopenharmony_ci
497ac06127Sopenharmony_ci#[test]
507ac06127Sopenharmony_ci#[should_panic(expected = "Ident cannot be a number; use Literal instead")]
517ac06127Sopenharmony_cifn ident_number() {
527ac06127Sopenharmony_ci    Ident::new("255", Span::call_site());
537ac06127Sopenharmony_ci}
547ac06127Sopenharmony_ci
557ac06127Sopenharmony_ci#[test]
567ac06127Sopenharmony_ci#[should_panic(expected = "\"a#\" is not a valid Ident")]
577ac06127Sopenharmony_cifn ident_invalid() {
587ac06127Sopenharmony_ci    Ident::new("a#", Span::call_site());
597ac06127Sopenharmony_ci}
607ac06127Sopenharmony_ci
617ac06127Sopenharmony_ci#[test]
627ac06127Sopenharmony_ci#[should_panic(expected = "not a valid Ident")]
637ac06127Sopenharmony_cifn raw_ident_empty() {
647ac06127Sopenharmony_ci    Ident::new("r#", Span::call_site());
657ac06127Sopenharmony_ci}
667ac06127Sopenharmony_ci
677ac06127Sopenharmony_ci#[test]
687ac06127Sopenharmony_ci#[should_panic(expected = "not a valid Ident")]
697ac06127Sopenharmony_cifn raw_ident_number() {
707ac06127Sopenharmony_ci    Ident::new("r#255", Span::call_site());
717ac06127Sopenharmony_ci}
727ac06127Sopenharmony_ci
737ac06127Sopenharmony_ci#[test]
747ac06127Sopenharmony_ci#[should_panic(expected = "\"r#a#\" is not a valid Ident")]
757ac06127Sopenharmony_cifn raw_ident_invalid() {
767ac06127Sopenharmony_ci    Ident::new("r#a#", Span::call_site());
777ac06127Sopenharmony_ci}
787ac06127Sopenharmony_ci
797ac06127Sopenharmony_ci#[test]
807ac06127Sopenharmony_ci#[should_panic(expected = "not a valid Ident")]
817ac06127Sopenharmony_cifn lifetime_empty() {
827ac06127Sopenharmony_ci    Ident::new("'", Span::call_site());
837ac06127Sopenharmony_ci}
847ac06127Sopenharmony_ci
857ac06127Sopenharmony_ci#[test]
867ac06127Sopenharmony_ci#[should_panic(expected = "not a valid Ident")]
877ac06127Sopenharmony_cifn lifetime_number() {
887ac06127Sopenharmony_ci    Ident::new("'255", Span::call_site());
897ac06127Sopenharmony_ci}
907ac06127Sopenharmony_ci
917ac06127Sopenharmony_ci#[test]
927ac06127Sopenharmony_ci#[should_panic(expected = r#""'a#" is not a valid Ident"#)]
937ac06127Sopenharmony_cifn lifetime_invalid() {
947ac06127Sopenharmony_ci    Ident::new("'a#", Span::call_site());
957ac06127Sopenharmony_ci}
967ac06127Sopenharmony_ci
977ac06127Sopenharmony_ci#[test]
987ac06127Sopenharmony_cifn literal_string() {
997ac06127Sopenharmony_ci    assert_eq!(Literal::string("foo").to_string(), "\"foo\"");
1007ac06127Sopenharmony_ci    assert_eq!(Literal::string("\"").to_string(), "\"\\\"\"");
1017ac06127Sopenharmony_ci    assert_eq!(Literal::string("didn't").to_string(), "\"didn't\"");
1027ac06127Sopenharmony_ci    assert_eq!(
1037ac06127Sopenharmony_ci        Literal::string("a\00b\07c\08d\0e\0").to_string(),
1047ac06127Sopenharmony_ci        "\"a\\x000b\\x007c\\08d\\0e\\0\"",
1057ac06127Sopenharmony_ci    );
1067ac06127Sopenharmony_ci
1077ac06127Sopenharmony_ci    "\"\\\r\n    x\"".parse::<TokenStream>().unwrap();
1087ac06127Sopenharmony_ci    "\"\\\r\n  \rx\"".parse::<TokenStream>().unwrap_err();
1097ac06127Sopenharmony_ci}
1107ac06127Sopenharmony_ci
1117ac06127Sopenharmony_ci#[test]
1127ac06127Sopenharmony_cifn literal_raw_string() {
1137ac06127Sopenharmony_ci    "r\"\r\n\"".parse::<TokenStream>().unwrap();
1147ac06127Sopenharmony_ci
1157ac06127Sopenharmony_ci    fn raw_string_literal_with_hashes(n: usize) -> String {
1167ac06127Sopenharmony_ci        let mut literal = String::new();
1177ac06127Sopenharmony_ci        literal.push('r');
1187ac06127Sopenharmony_ci        literal.extend(iter::repeat('#').take(n));
1197ac06127Sopenharmony_ci        literal.push('"');
1207ac06127Sopenharmony_ci        literal.push('"');
1217ac06127Sopenharmony_ci        literal.extend(iter::repeat('#').take(n));
1227ac06127Sopenharmony_ci        literal
1237ac06127Sopenharmony_ci    }
1247ac06127Sopenharmony_ci
1257ac06127Sopenharmony_ci    raw_string_literal_with_hashes(255)
1267ac06127Sopenharmony_ci        .parse::<TokenStream>()
1277ac06127Sopenharmony_ci        .unwrap();
1287ac06127Sopenharmony_ci
1297ac06127Sopenharmony_ci    // https://github.com/rust-lang/rust/pull/95251
1307ac06127Sopenharmony_ci    raw_string_literal_with_hashes(256)
1317ac06127Sopenharmony_ci        .parse::<TokenStream>()
1327ac06127Sopenharmony_ci        .unwrap_err();
1337ac06127Sopenharmony_ci}
1347ac06127Sopenharmony_ci
1357ac06127Sopenharmony_ci#[test]
1367ac06127Sopenharmony_cifn literal_byte_string() {
1377ac06127Sopenharmony_ci    assert_eq!(Literal::byte_string(b"").to_string(), "b\"\"");
1387ac06127Sopenharmony_ci    assert_eq!(
1397ac06127Sopenharmony_ci        Literal::byte_string(b"\0\t\n\r\"\\2\x10").to_string(),
1407ac06127Sopenharmony_ci        "b\"\\0\\t\\n\\r\\\"\\\\2\\x10\"",
1417ac06127Sopenharmony_ci    );
1427ac06127Sopenharmony_ci    assert_eq!(
1437ac06127Sopenharmony_ci        Literal::byte_string(b"a\00b\07c\08d\0e\0").to_string(),
1447ac06127Sopenharmony_ci        "b\"a\\x000b\\x007c\\08d\\0e\\0\"",
1457ac06127Sopenharmony_ci    );
1467ac06127Sopenharmony_ci
1477ac06127Sopenharmony_ci    "b\"\\\r\n    x\"".parse::<TokenStream>().unwrap();
1487ac06127Sopenharmony_ci    "b\"\\\r\n  \rx\"".parse::<TokenStream>().unwrap_err();
1497ac06127Sopenharmony_ci    "b\"\\\r\n  \u{a0}x\"".parse::<TokenStream>().unwrap_err();
1507ac06127Sopenharmony_ci    "br\"\u{a0}\"".parse::<TokenStream>().unwrap_err();
1517ac06127Sopenharmony_ci}
1527ac06127Sopenharmony_ci
1537ac06127Sopenharmony_ci#[test]
1547ac06127Sopenharmony_cifn literal_c_string() {
1557ac06127Sopenharmony_ci    let strings = r###"
1567ac06127Sopenharmony_ci        c"hello\x80我叫\u{1F980}"  // from the RFC
1577ac06127Sopenharmony_ci        cr"\"
1587ac06127Sopenharmony_ci        cr##"Hello "world"!"##
1597ac06127Sopenharmony_ci        c"\t\n\r\"\\"
1607ac06127Sopenharmony_ci    "###;
1617ac06127Sopenharmony_ci
1627ac06127Sopenharmony_ci    let mut tokens = strings.parse::<TokenStream>().unwrap().into_iter();
1637ac06127Sopenharmony_ci
1647ac06127Sopenharmony_ci    for expected in &[
1657ac06127Sopenharmony_ci        r#"c"hello\x80我叫\u{1F980}""#,
1667ac06127Sopenharmony_ci        r#"cr"\""#,
1677ac06127Sopenharmony_ci        r###"cr##"Hello "world"!"##"###,
1687ac06127Sopenharmony_ci        r#"c"\t\n\r\"\\""#,
1697ac06127Sopenharmony_ci    ] {
1707ac06127Sopenharmony_ci        match tokens.next().unwrap() {
1717ac06127Sopenharmony_ci            TokenTree::Literal(literal) => {
1727ac06127Sopenharmony_ci                assert_eq!(literal.to_string(), *expected);
1737ac06127Sopenharmony_ci            }
1747ac06127Sopenharmony_ci            unexpected => panic!("unexpected token: {:?}", unexpected),
1757ac06127Sopenharmony_ci        }
1767ac06127Sopenharmony_ci    }
1777ac06127Sopenharmony_ci
1787ac06127Sopenharmony_ci    if let Some(unexpected) = tokens.next() {
1797ac06127Sopenharmony_ci        panic!("unexpected token: {:?}", unexpected);
1807ac06127Sopenharmony_ci    }
1817ac06127Sopenharmony_ci
1827ac06127Sopenharmony_ci    for invalid in &[r#"c"\0""#, r#"c"\x00""#, r#"c"\u{0}""#, "c\"\0\""] {
1837ac06127Sopenharmony_ci        if let Ok(unexpected) = invalid.parse::<TokenStream>() {
1847ac06127Sopenharmony_ci            panic!("unexpected token: {:?}", unexpected);
1857ac06127Sopenharmony_ci        }
1867ac06127Sopenharmony_ci    }
1877ac06127Sopenharmony_ci}
1887ac06127Sopenharmony_ci
1897ac06127Sopenharmony_ci#[test]
1907ac06127Sopenharmony_cifn literal_character() {
1917ac06127Sopenharmony_ci    assert_eq!(Literal::character('x').to_string(), "'x'");
1927ac06127Sopenharmony_ci    assert_eq!(Literal::character('\'').to_string(), "'\\''");
1937ac06127Sopenharmony_ci    assert_eq!(Literal::character('"').to_string(), "'\"'");
1947ac06127Sopenharmony_ci}
1957ac06127Sopenharmony_ci
1967ac06127Sopenharmony_ci#[test]
1977ac06127Sopenharmony_cifn literal_integer() {
1987ac06127Sopenharmony_ci    assert_eq!(Literal::u8_suffixed(10).to_string(), "10u8");
1997ac06127Sopenharmony_ci    assert_eq!(Literal::u16_suffixed(10).to_string(), "10u16");
2007ac06127Sopenharmony_ci    assert_eq!(Literal::u32_suffixed(10).to_string(), "10u32");
2017ac06127Sopenharmony_ci    assert_eq!(Literal::u64_suffixed(10).to_string(), "10u64");
2027ac06127Sopenharmony_ci    assert_eq!(Literal::u128_suffixed(10).to_string(), "10u128");
2037ac06127Sopenharmony_ci    assert_eq!(Literal::usize_suffixed(10).to_string(), "10usize");
2047ac06127Sopenharmony_ci
2057ac06127Sopenharmony_ci    assert_eq!(Literal::i8_suffixed(10).to_string(), "10i8");
2067ac06127Sopenharmony_ci    assert_eq!(Literal::i16_suffixed(10).to_string(), "10i16");
2077ac06127Sopenharmony_ci    assert_eq!(Literal::i32_suffixed(10).to_string(), "10i32");
2087ac06127Sopenharmony_ci    assert_eq!(Literal::i64_suffixed(10).to_string(), "10i64");
2097ac06127Sopenharmony_ci    assert_eq!(Literal::i128_suffixed(10).to_string(), "10i128");
2107ac06127Sopenharmony_ci    assert_eq!(Literal::isize_suffixed(10).to_string(), "10isize");
2117ac06127Sopenharmony_ci
2127ac06127Sopenharmony_ci    assert_eq!(Literal::u8_unsuffixed(10).to_string(), "10");
2137ac06127Sopenharmony_ci    assert_eq!(Literal::u16_unsuffixed(10).to_string(), "10");
2147ac06127Sopenharmony_ci    assert_eq!(Literal::u32_unsuffixed(10).to_string(), "10");
2157ac06127Sopenharmony_ci    assert_eq!(Literal::u64_unsuffixed(10).to_string(), "10");
2167ac06127Sopenharmony_ci    assert_eq!(Literal::u128_unsuffixed(10).to_string(), "10");
2177ac06127Sopenharmony_ci    assert_eq!(Literal::usize_unsuffixed(10).to_string(), "10");
2187ac06127Sopenharmony_ci
2197ac06127Sopenharmony_ci    assert_eq!(Literal::i8_unsuffixed(10).to_string(), "10");
2207ac06127Sopenharmony_ci    assert_eq!(Literal::i16_unsuffixed(10).to_string(), "10");
2217ac06127Sopenharmony_ci    assert_eq!(Literal::i32_unsuffixed(10).to_string(), "10");
2227ac06127Sopenharmony_ci    assert_eq!(Literal::i64_unsuffixed(10).to_string(), "10");
2237ac06127Sopenharmony_ci    assert_eq!(Literal::i128_unsuffixed(10).to_string(), "10");
2247ac06127Sopenharmony_ci    assert_eq!(Literal::isize_unsuffixed(10).to_string(), "10");
2257ac06127Sopenharmony_ci}
2267ac06127Sopenharmony_ci
2277ac06127Sopenharmony_ci#[test]
2287ac06127Sopenharmony_cifn literal_float() {
2297ac06127Sopenharmony_ci    assert_eq!(Literal::f32_suffixed(10.0).to_string(), "10f32");
2307ac06127Sopenharmony_ci    assert_eq!(Literal::f64_suffixed(10.0).to_string(), "10f64");
2317ac06127Sopenharmony_ci
2327ac06127Sopenharmony_ci    assert_eq!(Literal::f32_unsuffixed(10.0).to_string(), "10.0");
2337ac06127Sopenharmony_ci    assert_eq!(Literal::f64_unsuffixed(10.0).to_string(), "10.0");
2347ac06127Sopenharmony_ci}
2357ac06127Sopenharmony_ci
2367ac06127Sopenharmony_ci#[test]
2377ac06127Sopenharmony_cifn literal_suffix() {
2387ac06127Sopenharmony_ci    fn token_count(p: &str) -> usize {
2397ac06127Sopenharmony_ci        p.parse::<TokenStream>().unwrap().into_iter().count()
2407ac06127Sopenharmony_ci    }
2417ac06127Sopenharmony_ci
2427ac06127Sopenharmony_ci    assert_eq!(token_count("999u256"), 1);
2437ac06127Sopenharmony_ci    assert_eq!(token_count("999r#u256"), 3);
2447ac06127Sopenharmony_ci    assert_eq!(token_count("1."), 1);
2457ac06127Sopenharmony_ci    assert_eq!(token_count("1.f32"), 3);
2467ac06127Sopenharmony_ci    assert_eq!(token_count("1.0_0"), 1);
2477ac06127Sopenharmony_ci    assert_eq!(token_count("1._0"), 3);
2487ac06127Sopenharmony_ci    assert_eq!(token_count("1._m"), 3);
2497ac06127Sopenharmony_ci    assert_eq!(token_count("\"\"s"), 1);
2507ac06127Sopenharmony_ci    assert_eq!(token_count("r\"\"r"), 1);
2517ac06127Sopenharmony_ci    assert_eq!(token_count("b\"\"b"), 1);
2527ac06127Sopenharmony_ci    assert_eq!(token_count("br\"\"br"), 1);
2537ac06127Sopenharmony_ci    assert_eq!(token_count("r#\"\"#r"), 1);
2547ac06127Sopenharmony_ci    assert_eq!(token_count("'c'c"), 1);
2557ac06127Sopenharmony_ci    assert_eq!(token_count("b'b'b"), 1);
2567ac06127Sopenharmony_ci    assert_eq!(token_count("0E"), 1);
2577ac06127Sopenharmony_ci    assert_eq!(token_count("0o0A"), 1);
2587ac06127Sopenharmony_ci    assert_eq!(token_count("0E--0"), 4);
2597ac06127Sopenharmony_ci    assert_eq!(token_count("0.0ECMA"), 1);
2607ac06127Sopenharmony_ci}
2617ac06127Sopenharmony_ci
2627ac06127Sopenharmony_ci#[test]
2637ac06127Sopenharmony_cifn literal_iter_negative() {
2647ac06127Sopenharmony_ci    let negative_literal = Literal::i32_suffixed(-3);
2657ac06127Sopenharmony_ci    let tokens = TokenStream::from(TokenTree::Literal(negative_literal));
2667ac06127Sopenharmony_ci    let mut iter = tokens.into_iter();
2677ac06127Sopenharmony_ci    match iter.next().unwrap() {
2687ac06127Sopenharmony_ci        TokenTree::Punct(punct) => {
2697ac06127Sopenharmony_ci            assert_eq!(punct.as_char(), '-');
2707ac06127Sopenharmony_ci            assert_eq!(punct.spacing(), Spacing::Alone);
2717ac06127Sopenharmony_ci        }
2727ac06127Sopenharmony_ci        unexpected => panic!("unexpected token {:?}", unexpected),
2737ac06127Sopenharmony_ci    }
2747ac06127Sopenharmony_ci    match iter.next().unwrap() {
2757ac06127Sopenharmony_ci        TokenTree::Literal(literal) => {
2767ac06127Sopenharmony_ci            assert_eq!(literal.to_string(), "3i32");
2777ac06127Sopenharmony_ci        }
2787ac06127Sopenharmony_ci        unexpected => panic!("unexpected token {:?}", unexpected),
2797ac06127Sopenharmony_ci    }
2807ac06127Sopenharmony_ci    assert!(iter.next().is_none());
2817ac06127Sopenharmony_ci}
2827ac06127Sopenharmony_ci
2837ac06127Sopenharmony_ci#[test]
2847ac06127Sopenharmony_cifn literal_parse() {
2857ac06127Sopenharmony_ci    assert!("1".parse::<Literal>().is_ok());
2867ac06127Sopenharmony_ci    assert!("-1".parse::<Literal>().is_ok());
2877ac06127Sopenharmony_ci    assert!("-1u12".parse::<Literal>().is_ok());
2887ac06127Sopenharmony_ci    assert!("1.0".parse::<Literal>().is_ok());
2897ac06127Sopenharmony_ci    assert!("-1.0".parse::<Literal>().is_ok());
2907ac06127Sopenharmony_ci    assert!("-1.0f12".parse::<Literal>().is_ok());
2917ac06127Sopenharmony_ci    assert!("'a'".parse::<Literal>().is_ok());
2927ac06127Sopenharmony_ci    assert!("\"\n\"".parse::<Literal>().is_ok());
2937ac06127Sopenharmony_ci    assert!("0 1".parse::<Literal>().is_err());
2947ac06127Sopenharmony_ci    assert!(" 0".parse::<Literal>().is_err());
2957ac06127Sopenharmony_ci    assert!("0 ".parse::<Literal>().is_err());
2967ac06127Sopenharmony_ci    assert!("/* comment */0".parse::<Literal>().is_err());
2977ac06127Sopenharmony_ci    assert!("0/* comment */".parse::<Literal>().is_err());
2987ac06127Sopenharmony_ci    assert!("0// comment".parse::<Literal>().is_err());
2997ac06127Sopenharmony_ci    assert!("- 1".parse::<Literal>().is_err());
3007ac06127Sopenharmony_ci    assert!("- 1.0".parse::<Literal>().is_err());
3017ac06127Sopenharmony_ci    assert!("-\"\"".parse::<Literal>().is_err());
3027ac06127Sopenharmony_ci}
3037ac06127Sopenharmony_ci
3047ac06127Sopenharmony_ci#[test]
3057ac06127Sopenharmony_cifn literal_span() {
3067ac06127Sopenharmony_ci    let positive = "0.1".parse::<Literal>().unwrap();
3077ac06127Sopenharmony_ci    let negative = "-0.1".parse::<Literal>().unwrap();
3087ac06127Sopenharmony_ci    let subspan = positive.subspan(1..2);
3097ac06127Sopenharmony_ci
3107ac06127Sopenharmony_ci    #[cfg(not(span_locations))]
3117ac06127Sopenharmony_ci    {
3127ac06127Sopenharmony_ci        let _ = negative;
3137ac06127Sopenharmony_ci        assert!(subspan.is_none());
3147ac06127Sopenharmony_ci    }
3157ac06127Sopenharmony_ci
3167ac06127Sopenharmony_ci    #[cfg(span_locations)]
3177ac06127Sopenharmony_ci    {
3187ac06127Sopenharmony_ci        assert_eq!(positive.span().start().column, 0);
3197ac06127Sopenharmony_ci        assert_eq!(positive.span().end().column, 3);
3207ac06127Sopenharmony_ci        assert_eq!(negative.span().start().column, 0);
3217ac06127Sopenharmony_ci        assert_eq!(negative.span().end().column, 4);
3227ac06127Sopenharmony_ci        assert_eq!(subspan.unwrap().source_text().unwrap(), ".");
3237ac06127Sopenharmony_ci    }
3247ac06127Sopenharmony_ci
3257ac06127Sopenharmony_ci    assert!(positive.subspan(1..4).is_none());
3267ac06127Sopenharmony_ci}
3277ac06127Sopenharmony_ci
3287ac06127Sopenharmony_ci#[cfg(span_locations)]
3297ac06127Sopenharmony_ci#[test]
3307ac06127Sopenharmony_cifn source_text() {
3317ac06127Sopenharmony_ci    let input = "    � a z    ";
3327ac06127Sopenharmony_ci    let mut tokens = input
3337ac06127Sopenharmony_ci        .parse::<proc_macro2::TokenStream>()
3347ac06127Sopenharmony_ci        .unwrap()
3357ac06127Sopenharmony_ci        .into_iter();
3367ac06127Sopenharmony_ci
3377ac06127Sopenharmony_ci    let first = tokens.next().unwrap();
3387ac06127Sopenharmony_ci    assert_eq!("�", first.span().source_text().unwrap());
3397ac06127Sopenharmony_ci
3407ac06127Sopenharmony_ci    let second = tokens.next().unwrap();
3417ac06127Sopenharmony_ci    let third = tokens.next().unwrap();
3427ac06127Sopenharmony_ci    assert_eq!("z", third.span().source_text().unwrap());
3437ac06127Sopenharmony_ci    assert_eq!("a", second.span().source_text().unwrap());
3447ac06127Sopenharmony_ci}
3457ac06127Sopenharmony_ci
3467ac06127Sopenharmony_ci#[test]
3477ac06127Sopenharmony_cifn roundtrip() {
3487ac06127Sopenharmony_ci    fn roundtrip(p: &str) {
3497ac06127Sopenharmony_ci        println!("parse: {}", p);
3507ac06127Sopenharmony_ci        let s = p.parse::<TokenStream>().unwrap().to_string();
3517ac06127Sopenharmony_ci        println!("first: {}", s);
3527ac06127Sopenharmony_ci        let s2 = s.parse::<TokenStream>().unwrap().to_string();
3537ac06127Sopenharmony_ci        assert_eq!(s, s2);
3547ac06127Sopenharmony_ci    }
3557ac06127Sopenharmony_ci    roundtrip("a");
3567ac06127Sopenharmony_ci    roundtrip("<<");
3577ac06127Sopenharmony_ci    roundtrip("<<=");
3587ac06127Sopenharmony_ci    roundtrip(
3597ac06127Sopenharmony_ci        "
3607ac06127Sopenharmony_ci        1
3617ac06127Sopenharmony_ci        1.0
3627ac06127Sopenharmony_ci        1f32
3637ac06127Sopenharmony_ci        2f64
3647ac06127Sopenharmony_ci        1usize
3657ac06127Sopenharmony_ci        4isize
3667ac06127Sopenharmony_ci        4e10
3677ac06127Sopenharmony_ci        1_000
3687ac06127Sopenharmony_ci        1_0i32
3697ac06127Sopenharmony_ci        8u8
3707ac06127Sopenharmony_ci        9
3717ac06127Sopenharmony_ci        0
3727ac06127Sopenharmony_ci        0xffffffffffffffffffffffffffffffff
3737ac06127Sopenharmony_ci        1x
3747ac06127Sopenharmony_ci        1u80
3757ac06127Sopenharmony_ci        1f320
3767ac06127Sopenharmony_ci    ",
3777ac06127Sopenharmony_ci    );
3787ac06127Sopenharmony_ci    roundtrip("'a");
3797ac06127Sopenharmony_ci    roundtrip("'_");
3807ac06127Sopenharmony_ci    roundtrip("'static");
3817ac06127Sopenharmony_ci    roundtrip("'\\u{10__FFFF}'");
3827ac06127Sopenharmony_ci    roundtrip("\"\\u{10_F0FF__}foo\\u{1_0_0_0__}\"");
3837ac06127Sopenharmony_ci}
3847ac06127Sopenharmony_ci
3857ac06127Sopenharmony_ci#[test]
3867ac06127Sopenharmony_cifn fail() {
3877ac06127Sopenharmony_ci    fn fail(p: &str) {
3887ac06127Sopenharmony_ci        if let Ok(s) = p.parse::<TokenStream>() {
3897ac06127Sopenharmony_ci            panic!("should have failed to parse: {}\n{:#?}", p, s);
3907ac06127Sopenharmony_ci        }
3917ac06127Sopenharmony_ci    }
3927ac06127Sopenharmony_ci    fail("' static");
3937ac06127Sopenharmony_ci    fail("r#1");
3947ac06127Sopenharmony_ci    fail("r#_");
3957ac06127Sopenharmony_ci    fail("\"\\u{0000000}\""); // overlong unicode escape (rust allows at most 6 hex digits)
3967ac06127Sopenharmony_ci    fail("\"\\u{999999}\""); // outside of valid range of char
3977ac06127Sopenharmony_ci    fail("\"\\u{_0}\""); // leading underscore
3987ac06127Sopenharmony_ci    fail("\"\\u{}\""); // empty
3997ac06127Sopenharmony_ci    fail("b\"\r\""); // bare carriage return in byte string
4007ac06127Sopenharmony_ci    fail("r\"\r\""); // bare carriage return in raw string
4017ac06127Sopenharmony_ci    fail("\"\\\r  \""); // backslash carriage return
4027ac06127Sopenharmony_ci    fail("'aa'aa");
4037ac06127Sopenharmony_ci    fail("br##\"\"#");
4047ac06127Sopenharmony_ci    fail("\"\\\n\u{85}\r\"");
4057ac06127Sopenharmony_ci}
4067ac06127Sopenharmony_ci
4077ac06127Sopenharmony_ci#[cfg(span_locations)]
4087ac06127Sopenharmony_ci#[test]
4097ac06127Sopenharmony_cifn span_test() {
4107ac06127Sopenharmony_ci    check_spans(
4117ac06127Sopenharmony_ci        "\
4127ac06127Sopenharmony_ci/// This is a document comment
4137ac06127Sopenharmony_citesting 123
4147ac06127Sopenharmony_ci{
4157ac06127Sopenharmony_ci  testing 234
4167ac06127Sopenharmony_ci}",
4177ac06127Sopenharmony_ci        &[
4187ac06127Sopenharmony_ci            (1, 0, 1, 30),  // #
4197ac06127Sopenharmony_ci            (1, 0, 1, 30),  // [ ... ]
4207ac06127Sopenharmony_ci            (1, 0, 1, 30),  // doc
4217ac06127Sopenharmony_ci            (1, 0, 1, 30),  // =
4227ac06127Sopenharmony_ci            (1, 0, 1, 30),  // "This is..."
4237ac06127Sopenharmony_ci            (2, 0, 2, 7),   // testing
4247ac06127Sopenharmony_ci            (2, 8, 2, 11),  // 123
4257ac06127Sopenharmony_ci            (3, 0, 5, 1),   // { ... }
4267ac06127Sopenharmony_ci            (4, 2, 4, 9),   // testing
4277ac06127Sopenharmony_ci            (4, 10, 4, 13), // 234
4287ac06127Sopenharmony_ci        ],
4297ac06127Sopenharmony_ci    );
4307ac06127Sopenharmony_ci}
4317ac06127Sopenharmony_ci
4327ac06127Sopenharmony_ci#[cfg(procmacro2_semver_exempt)]
4337ac06127Sopenharmony_ci#[cfg(not(nightly))]
4347ac06127Sopenharmony_ci#[test]
4357ac06127Sopenharmony_cifn default_span() {
4367ac06127Sopenharmony_ci    let start = Span::call_site().start();
4377ac06127Sopenharmony_ci    assert_eq!(start.line, 1);
4387ac06127Sopenharmony_ci    assert_eq!(start.column, 0);
4397ac06127Sopenharmony_ci    let end = Span::call_site().end();
4407ac06127Sopenharmony_ci    assert_eq!(end.line, 1);
4417ac06127Sopenharmony_ci    assert_eq!(end.column, 0);
4427ac06127Sopenharmony_ci    let source_file = Span::call_site().source_file();
4437ac06127Sopenharmony_ci    assert_eq!(source_file.path().to_string_lossy(), "<unspecified>");
4447ac06127Sopenharmony_ci    assert!(!source_file.is_real());
4457ac06127Sopenharmony_ci}
4467ac06127Sopenharmony_ci
4477ac06127Sopenharmony_ci#[cfg(procmacro2_semver_exempt)]
4487ac06127Sopenharmony_ci#[test]
4497ac06127Sopenharmony_cifn span_join() {
4507ac06127Sopenharmony_ci    let source1 = "aaa\nbbb"
4517ac06127Sopenharmony_ci        .parse::<TokenStream>()
4527ac06127Sopenharmony_ci        .unwrap()
4537ac06127Sopenharmony_ci        .into_iter()
4547ac06127Sopenharmony_ci        .collect::<Vec<_>>();
4557ac06127Sopenharmony_ci    let source2 = "ccc\nddd"
4567ac06127Sopenharmony_ci        .parse::<TokenStream>()
4577ac06127Sopenharmony_ci        .unwrap()
4587ac06127Sopenharmony_ci        .into_iter()
4597ac06127Sopenharmony_ci        .collect::<Vec<_>>();
4607ac06127Sopenharmony_ci
4617ac06127Sopenharmony_ci    assert!(source1[0].span().source_file() != source2[0].span().source_file());
4627ac06127Sopenharmony_ci    assert_eq!(
4637ac06127Sopenharmony_ci        source1[0].span().source_file(),
4647ac06127Sopenharmony_ci        source1[1].span().source_file()
4657ac06127Sopenharmony_ci    );
4667ac06127Sopenharmony_ci
4677ac06127Sopenharmony_ci    let joined1 = source1[0].span().join(source1[1].span());
4687ac06127Sopenharmony_ci    let joined2 = source1[0].span().join(source2[0].span());
4697ac06127Sopenharmony_ci    assert!(joined1.is_some());
4707ac06127Sopenharmony_ci    assert!(joined2.is_none());
4717ac06127Sopenharmony_ci
4727ac06127Sopenharmony_ci    let start = joined1.unwrap().start();
4737ac06127Sopenharmony_ci    let end = joined1.unwrap().end();
4747ac06127Sopenharmony_ci    assert_eq!(start.line, 1);
4757ac06127Sopenharmony_ci    assert_eq!(start.column, 0);
4767ac06127Sopenharmony_ci    assert_eq!(end.line, 2);
4777ac06127Sopenharmony_ci    assert_eq!(end.column, 3);
4787ac06127Sopenharmony_ci
4797ac06127Sopenharmony_ci    assert_eq!(
4807ac06127Sopenharmony_ci        joined1.unwrap().source_file(),
4817ac06127Sopenharmony_ci        source1[0].span().source_file()
4827ac06127Sopenharmony_ci    );
4837ac06127Sopenharmony_ci}
4847ac06127Sopenharmony_ci
4857ac06127Sopenharmony_ci#[test]
4867ac06127Sopenharmony_cifn no_panic() {
4877ac06127Sopenharmony_ci    let s = str::from_utf8(b"b\'\xc2\x86  \x00\x00\x00^\"").unwrap();
4887ac06127Sopenharmony_ci    assert!(s.parse::<TokenStream>().is_err());
4897ac06127Sopenharmony_ci}
4907ac06127Sopenharmony_ci
4917ac06127Sopenharmony_ci#[test]
4927ac06127Sopenharmony_cifn punct_before_comment() {
4937ac06127Sopenharmony_ci    let mut tts = TokenStream::from_str("~// comment").unwrap().into_iter();
4947ac06127Sopenharmony_ci    match tts.next().unwrap() {
4957ac06127Sopenharmony_ci        TokenTree::Punct(tt) => {
4967ac06127Sopenharmony_ci            assert_eq!(tt.as_char(), '~');
4977ac06127Sopenharmony_ci            assert_eq!(tt.spacing(), Spacing::Alone);
4987ac06127Sopenharmony_ci        }
4997ac06127Sopenharmony_ci        wrong => panic!("wrong token {:?}", wrong),
5007ac06127Sopenharmony_ci    }
5017ac06127Sopenharmony_ci}
5027ac06127Sopenharmony_ci
5037ac06127Sopenharmony_ci#[test]
5047ac06127Sopenharmony_cifn joint_last_token() {
5057ac06127Sopenharmony_ci    // This test verifies that we match the behavior of libproc_macro *not* in
5067ac06127Sopenharmony_ci    // the range nightly-2020-09-06 through nightly-2020-09-10, in which this
5077ac06127Sopenharmony_ci    // behavior was temporarily broken.
5087ac06127Sopenharmony_ci    // See https://github.com/rust-lang/rust/issues/76399
5097ac06127Sopenharmony_ci
5107ac06127Sopenharmony_ci    let joint_punct = Punct::new(':', Spacing::Joint);
5117ac06127Sopenharmony_ci    let stream = TokenStream::from(TokenTree::Punct(joint_punct));
5127ac06127Sopenharmony_ci    let punct = match stream.into_iter().next().unwrap() {
5137ac06127Sopenharmony_ci        TokenTree::Punct(punct) => punct,
5147ac06127Sopenharmony_ci        _ => unreachable!(),
5157ac06127Sopenharmony_ci    };
5167ac06127Sopenharmony_ci    assert_eq!(punct.spacing(), Spacing::Joint);
5177ac06127Sopenharmony_ci}
5187ac06127Sopenharmony_ci
5197ac06127Sopenharmony_ci#[test]
5207ac06127Sopenharmony_cifn raw_identifier() {
5217ac06127Sopenharmony_ci    let mut tts = TokenStream::from_str("r#dyn").unwrap().into_iter();
5227ac06127Sopenharmony_ci    match tts.next().unwrap() {
5237ac06127Sopenharmony_ci        TokenTree::Ident(raw) => assert_eq!("r#dyn", raw.to_string()),
5247ac06127Sopenharmony_ci        wrong => panic!("wrong token {:?}", wrong),
5257ac06127Sopenharmony_ci    }
5267ac06127Sopenharmony_ci    assert!(tts.next().is_none());
5277ac06127Sopenharmony_ci}
5287ac06127Sopenharmony_ci
5297ac06127Sopenharmony_ci#[test]
5307ac06127Sopenharmony_cifn test_debug_ident() {
5317ac06127Sopenharmony_ci    let ident = Ident::new("proc_macro", Span::call_site());
5327ac06127Sopenharmony_ci
5337ac06127Sopenharmony_ci    #[cfg(not(span_locations))]
5347ac06127Sopenharmony_ci    let expected = "Ident(proc_macro)";
5357ac06127Sopenharmony_ci
5367ac06127Sopenharmony_ci    #[cfg(span_locations)]
5377ac06127Sopenharmony_ci    let expected = "Ident { sym: proc_macro }";
5387ac06127Sopenharmony_ci
5397ac06127Sopenharmony_ci    assert_eq!(expected, format!("{:?}", ident));
5407ac06127Sopenharmony_ci}
5417ac06127Sopenharmony_ci
5427ac06127Sopenharmony_ci#[test]
5437ac06127Sopenharmony_cifn test_debug_tokenstream() {
5447ac06127Sopenharmony_ci    let tts = TokenStream::from_str("[a + 1]").unwrap();
5457ac06127Sopenharmony_ci
5467ac06127Sopenharmony_ci    #[cfg(not(span_locations))]
5477ac06127Sopenharmony_ci    let expected = "\
5487ac06127Sopenharmony_ciTokenStream [
5497ac06127Sopenharmony_ci    Group {
5507ac06127Sopenharmony_ci        delimiter: Bracket,
5517ac06127Sopenharmony_ci        stream: TokenStream [
5527ac06127Sopenharmony_ci            Ident {
5537ac06127Sopenharmony_ci                sym: a,
5547ac06127Sopenharmony_ci            },
5557ac06127Sopenharmony_ci            Punct {
5567ac06127Sopenharmony_ci                char: '+',
5577ac06127Sopenharmony_ci                spacing: Alone,
5587ac06127Sopenharmony_ci            },
5597ac06127Sopenharmony_ci            Literal {
5607ac06127Sopenharmony_ci                lit: 1,
5617ac06127Sopenharmony_ci            },
5627ac06127Sopenharmony_ci        ],
5637ac06127Sopenharmony_ci    },
5647ac06127Sopenharmony_ci]\
5657ac06127Sopenharmony_ci    ";
5667ac06127Sopenharmony_ci
5677ac06127Sopenharmony_ci    #[cfg(not(span_locations))]
5687ac06127Sopenharmony_ci    let expected_before_trailing_commas = "\
5697ac06127Sopenharmony_ciTokenStream [
5707ac06127Sopenharmony_ci    Group {
5717ac06127Sopenharmony_ci        delimiter: Bracket,
5727ac06127Sopenharmony_ci        stream: TokenStream [
5737ac06127Sopenharmony_ci            Ident {
5747ac06127Sopenharmony_ci                sym: a
5757ac06127Sopenharmony_ci            },
5767ac06127Sopenharmony_ci            Punct {
5777ac06127Sopenharmony_ci                char: '+',
5787ac06127Sopenharmony_ci                spacing: Alone
5797ac06127Sopenharmony_ci            },
5807ac06127Sopenharmony_ci            Literal {
5817ac06127Sopenharmony_ci                lit: 1
5827ac06127Sopenharmony_ci            }
5837ac06127Sopenharmony_ci        ]
5847ac06127Sopenharmony_ci    }
5857ac06127Sopenharmony_ci]\
5867ac06127Sopenharmony_ci    ";
5877ac06127Sopenharmony_ci
5887ac06127Sopenharmony_ci    #[cfg(span_locations)]
5897ac06127Sopenharmony_ci    let expected = "\
5907ac06127Sopenharmony_ciTokenStream [
5917ac06127Sopenharmony_ci    Group {
5927ac06127Sopenharmony_ci        delimiter: Bracket,
5937ac06127Sopenharmony_ci        stream: TokenStream [
5947ac06127Sopenharmony_ci            Ident {
5957ac06127Sopenharmony_ci                sym: a,
5967ac06127Sopenharmony_ci                span: bytes(2..3),
5977ac06127Sopenharmony_ci            },
5987ac06127Sopenharmony_ci            Punct {
5997ac06127Sopenharmony_ci                char: '+',
6007ac06127Sopenharmony_ci                spacing: Alone,
6017ac06127Sopenharmony_ci                span: bytes(4..5),
6027ac06127Sopenharmony_ci            },
6037ac06127Sopenharmony_ci            Literal {
6047ac06127Sopenharmony_ci                lit: 1,
6057ac06127Sopenharmony_ci                span: bytes(6..7),
6067ac06127Sopenharmony_ci            },
6077ac06127Sopenharmony_ci        ],
6087ac06127Sopenharmony_ci        span: bytes(1..8),
6097ac06127Sopenharmony_ci    },
6107ac06127Sopenharmony_ci]\
6117ac06127Sopenharmony_ci    ";
6127ac06127Sopenharmony_ci
6137ac06127Sopenharmony_ci    #[cfg(span_locations)]
6147ac06127Sopenharmony_ci    let expected_before_trailing_commas = "\
6157ac06127Sopenharmony_ciTokenStream [
6167ac06127Sopenharmony_ci    Group {
6177ac06127Sopenharmony_ci        delimiter: Bracket,
6187ac06127Sopenharmony_ci        stream: TokenStream [
6197ac06127Sopenharmony_ci            Ident {
6207ac06127Sopenharmony_ci                sym: a,
6217ac06127Sopenharmony_ci                span: bytes(2..3)
6227ac06127Sopenharmony_ci            },
6237ac06127Sopenharmony_ci            Punct {
6247ac06127Sopenharmony_ci                char: '+',
6257ac06127Sopenharmony_ci                spacing: Alone,
6267ac06127Sopenharmony_ci                span: bytes(4..5)
6277ac06127Sopenharmony_ci            },
6287ac06127Sopenharmony_ci            Literal {
6297ac06127Sopenharmony_ci                lit: 1,
6307ac06127Sopenharmony_ci                span: bytes(6..7)
6317ac06127Sopenharmony_ci            }
6327ac06127Sopenharmony_ci        ],
6337ac06127Sopenharmony_ci        span: bytes(1..8)
6347ac06127Sopenharmony_ci    }
6357ac06127Sopenharmony_ci]\
6367ac06127Sopenharmony_ci    ";
6377ac06127Sopenharmony_ci
6387ac06127Sopenharmony_ci    let actual = format!("{:#?}", tts);
6397ac06127Sopenharmony_ci    if actual.ends_with(",\n]") {
6407ac06127Sopenharmony_ci        assert_eq!(expected, actual);
6417ac06127Sopenharmony_ci    } else {
6427ac06127Sopenharmony_ci        assert_eq!(expected_before_trailing_commas, actual);
6437ac06127Sopenharmony_ci    }
6447ac06127Sopenharmony_ci}
6457ac06127Sopenharmony_ci
6467ac06127Sopenharmony_ci#[test]
6477ac06127Sopenharmony_cifn default_tokenstream_is_empty() {
6487ac06127Sopenharmony_ci    let default_token_stream = <TokenStream as Default>::default();
6497ac06127Sopenharmony_ci
6507ac06127Sopenharmony_ci    assert!(default_token_stream.is_empty());
6517ac06127Sopenharmony_ci}
6527ac06127Sopenharmony_ci
6537ac06127Sopenharmony_ci#[test]
6547ac06127Sopenharmony_cifn tokenstream_size_hint() {
6557ac06127Sopenharmony_ci    let tokens = "a b (c d) e".parse::<TokenStream>().unwrap();
6567ac06127Sopenharmony_ci
6577ac06127Sopenharmony_ci    assert_eq!(tokens.into_iter().size_hint(), (4, Some(4)));
6587ac06127Sopenharmony_ci}
6597ac06127Sopenharmony_ci
6607ac06127Sopenharmony_ci#[test]
6617ac06127Sopenharmony_cifn tuple_indexing() {
6627ac06127Sopenharmony_ci    // This behavior may change depending on https://github.com/rust-lang/rust/pull/71322
6637ac06127Sopenharmony_ci    let mut tokens = "tuple.0.0".parse::<TokenStream>().unwrap().into_iter();
6647ac06127Sopenharmony_ci    assert_eq!("tuple", tokens.next().unwrap().to_string());
6657ac06127Sopenharmony_ci    assert_eq!(".", tokens.next().unwrap().to_string());
6667ac06127Sopenharmony_ci    assert_eq!("0.0", tokens.next().unwrap().to_string());
6677ac06127Sopenharmony_ci    assert!(tokens.next().is_none());
6687ac06127Sopenharmony_ci}
6697ac06127Sopenharmony_ci
6707ac06127Sopenharmony_ci#[cfg(span_locations)]
6717ac06127Sopenharmony_ci#[test]
6727ac06127Sopenharmony_cifn non_ascii_tokens() {
6737ac06127Sopenharmony_ci    check_spans("// abc", &[]);
6747ac06127Sopenharmony_ci    check_spans("// ábc", &[]);
6757ac06127Sopenharmony_ci    check_spans("// abc x", &[]);
6767ac06127Sopenharmony_ci    check_spans("// ábc x", &[]);
6777ac06127Sopenharmony_ci    check_spans("/* abc */ x", &[(1, 10, 1, 11)]);
6787ac06127Sopenharmony_ci    check_spans("/* ábc */ x", &[(1, 10, 1, 11)]);
6797ac06127Sopenharmony_ci    check_spans("/* ab\nc */ x", &[(2, 5, 2, 6)]);
6807ac06127Sopenharmony_ci    check_spans("/* áb\nc */ x", &[(2, 5, 2, 6)]);
6817ac06127Sopenharmony_ci    check_spans("/*** abc */ x", &[(1, 12, 1, 13)]);
6827ac06127Sopenharmony_ci    check_spans("/*** ábc */ x", &[(1, 12, 1, 13)]);
6837ac06127Sopenharmony_ci    check_spans(r#""abc""#, &[(1, 0, 1, 5)]);
6847ac06127Sopenharmony_ci    check_spans(r#""ábc""#, &[(1, 0, 1, 5)]);
6857ac06127Sopenharmony_ci    check_spans(r##"r#"abc"#"##, &[(1, 0, 1, 8)]);
6867ac06127Sopenharmony_ci    check_spans(r##"r#"ábc"#"##, &[(1, 0, 1, 8)]);
6877ac06127Sopenharmony_ci    check_spans("r#\"a\nc\"#", &[(1, 0, 2, 3)]);
6887ac06127Sopenharmony_ci    check_spans("r#\"á\nc\"#", &[(1, 0, 2, 3)]);
6897ac06127Sopenharmony_ci    check_spans("'a'", &[(1, 0, 1, 3)]);
6907ac06127Sopenharmony_ci    check_spans("'á'", &[(1, 0, 1, 3)]);
6917ac06127Sopenharmony_ci    check_spans("//! abc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]);
6927ac06127Sopenharmony_ci    check_spans("//! ábc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]);
6937ac06127Sopenharmony_ci    check_spans("//! abc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]);
6947ac06127Sopenharmony_ci    check_spans("//! ábc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]);
6957ac06127Sopenharmony_ci    check_spans("/*! abc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]);
6967ac06127Sopenharmony_ci    check_spans("/*! ábc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]);
6977ac06127Sopenharmony_ci    check_spans("/*! a\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]);
6987ac06127Sopenharmony_ci    check_spans("/*! á\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]);
6997ac06127Sopenharmony_ci    check_spans("abc", &[(1, 0, 1, 3)]);
7007ac06127Sopenharmony_ci    check_spans("ábc", &[(1, 0, 1, 3)]);
7017ac06127Sopenharmony_ci    check_spans("ábć", &[(1, 0, 1, 3)]);
7027ac06127Sopenharmony_ci    check_spans("abc// foo", &[(1, 0, 1, 3)]);
7037ac06127Sopenharmony_ci    check_spans("ábc// foo", &[(1, 0, 1, 3)]);
7047ac06127Sopenharmony_ci    check_spans("ábć// foo", &[(1, 0, 1, 3)]);
7057ac06127Sopenharmony_ci    check_spans("b\"a\\\n c\"", &[(1, 0, 2, 3)]);
7067ac06127Sopenharmony_ci}
7077ac06127Sopenharmony_ci
7087ac06127Sopenharmony_ci#[cfg(span_locations)]
7097ac06127Sopenharmony_cifn check_spans(p: &str, mut lines: &[(usize, usize, usize, usize)]) {
7107ac06127Sopenharmony_ci    let ts = p.parse::<TokenStream>().unwrap();
7117ac06127Sopenharmony_ci    check_spans_internal(ts, &mut lines);
7127ac06127Sopenharmony_ci    assert!(lines.is_empty(), "leftover ranges: {:?}", lines);
7137ac06127Sopenharmony_ci}
7147ac06127Sopenharmony_ci
7157ac06127Sopenharmony_ci#[cfg(span_locations)]
7167ac06127Sopenharmony_cifn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usize)]) {
7177ac06127Sopenharmony_ci    for i in ts {
7187ac06127Sopenharmony_ci        if let Some((&(sline, scol, eline, ecol), rest)) = lines.split_first() {
7197ac06127Sopenharmony_ci            *lines = rest;
7207ac06127Sopenharmony_ci
7217ac06127Sopenharmony_ci            let start = i.span().start();
7227ac06127Sopenharmony_ci            assert_eq!(start.line, sline, "sline did not match for {}", i);
7237ac06127Sopenharmony_ci            assert_eq!(start.column, scol, "scol did not match for {}", i);
7247ac06127Sopenharmony_ci
7257ac06127Sopenharmony_ci            let end = i.span().end();
7267ac06127Sopenharmony_ci            assert_eq!(end.line, eline, "eline did not match for {}", i);
7277ac06127Sopenharmony_ci            assert_eq!(end.column, ecol, "ecol did not match for {}", i);
7287ac06127Sopenharmony_ci
7297ac06127Sopenharmony_ci            if let TokenTree::Group(g) = i {
7307ac06127Sopenharmony_ci                check_spans_internal(g.stream().clone(), lines);
7317ac06127Sopenharmony_ci            }
7327ac06127Sopenharmony_ci        }
7337ac06127Sopenharmony_ci    }
7347ac06127Sopenharmony_ci}
7357ac06127Sopenharmony_ci
7367ac06127Sopenharmony_ci#[test]
7377ac06127Sopenharmony_cifn whitespace() {
7387ac06127Sopenharmony_ci    // space, horizontal tab, vertical tab, form feed, carriage return, line
7397ac06127Sopenharmony_ci    // feed, non-breaking space, left-to-right mark, right-to-left mark
7407ac06127Sopenharmony_ci    let various_spaces = " \t\u{b}\u{c}\r\n\u{a0}\u{200e}\u{200f}";
7417ac06127Sopenharmony_ci    let tokens = various_spaces.parse::<TokenStream>().unwrap();
7427ac06127Sopenharmony_ci    assert_eq!(tokens.into_iter().count(), 0);
7437ac06127Sopenharmony_ci
7447ac06127Sopenharmony_ci    let lone_carriage_returns = " \r \r\r\n ";
7457ac06127Sopenharmony_ci    lone_carriage_returns.parse::<TokenStream>().unwrap();
7467ac06127Sopenharmony_ci}
7477ac06127Sopenharmony_ci
7487ac06127Sopenharmony_ci#[test]
7497ac06127Sopenharmony_cifn byte_order_mark() {
7507ac06127Sopenharmony_ci    let string = "\u{feff}foo";
7517ac06127Sopenharmony_ci    let tokens = string.parse::<TokenStream>().unwrap();
7527ac06127Sopenharmony_ci    match tokens.into_iter().next().unwrap() {
7537ac06127Sopenharmony_ci        TokenTree::Ident(ident) => assert_eq!(ident, "foo"),
7547ac06127Sopenharmony_ci        _ => unreachable!(),
7557ac06127Sopenharmony_ci    }
7567ac06127Sopenharmony_ci
7577ac06127Sopenharmony_ci    let string = "foo\u{feff}";
7587ac06127Sopenharmony_ci    string.parse::<TokenStream>().unwrap_err();
7597ac06127Sopenharmony_ci}
760