test_lit.rs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #![allow(clippy::float_cmp, clippy::non_ascii_literal)]
  2. #[macro_use]
  3. mod macros;
  4. use proc_macro2::{Delimiter, Group, Literal, Span, TokenStream, TokenTree};
  5. use quote::ToTokens;
  6. use std::iter::FromIterator;
  7. use std::str::FromStr;
  8. use syn::{Lit, LitFloat, LitInt, LitStr};
  9. fn lit(s: &str) -> Lit {
  10. match TokenStream::from_str(s)
  11. .unwrap()
  12. .into_iter()
  13. .next()
  14. .unwrap()
  15. {
  16. TokenTree::Literal(lit) => Lit::new(lit),
  17. _ => panic!(),
  18. }
  19. }
  20. #[test]
  21. fn strings() {
  22. fn test_string(s: &str, value: &str) {
  23. match lit(s) {
  24. Lit::Str(lit) => {
  25. assert_eq!(lit.value(), value);
  26. let again = lit.into_token_stream().to_string();
  27. if again != s {
  28. test_string(&again, value);
  29. }
  30. }
  31. wrong => panic!("{:?}", wrong),
  32. }
  33. }
  34. test_string("\"a\"", "a");
  35. test_string("\"\\n\"", "\n");
  36. test_string("\"\\r\"", "\r");
  37. test_string("\"\\t\"", "\t");
  38. test_string("\"🐕\"", "🐕"); // NOTE: This is an emoji
  39. test_string("\"\\\"\"", "\"");
  40. test_string("\"'\"", "'");
  41. test_string("\"\"", "");
  42. test_string("\"\\u{1F415}\"", "\u{1F415}");
  43. test_string("\"\\u{1_2__3_}\"", "\u{123}");
  44. test_string(
  45. "\"contains\nnewlines\\\nescaped newlines\"",
  46. "contains\nnewlinesescaped newlines",
  47. );
  48. test_string("r\"raw\nstring\\\nhere\"", "raw\nstring\\\nhere");
  49. test_string("\"...\"q", "...");
  50. test_string("r\"...\"q", "...");
  51. test_string("r##\"...\"##q", "...");
  52. }
  53. #[test]
  54. fn byte_strings() {
  55. fn test_byte_string(s: &str, value: &[u8]) {
  56. match lit(s) {
  57. Lit::ByteStr(lit) => {
  58. assert_eq!(lit.value(), value);
  59. let again = lit.into_token_stream().to_string();
  60. if again != s {
  61. test_byte_string(&again, value);
  62. }
  63. }
  64. wrong => panic!("{:?}", wrong),
  65. }
  66. }
  67. test_byte_string("b\"a\"", b"a");
  68. test_byte_string("b\"\\n\"", b"\n");
  69. test_byte_string("b\"\\r\"", b"\r");
  70. test_byte_string("b\"\\t\"", b"\t");
  71. test_byte_string("b\"\\\"\"", b"\"");
  72. test_byte_string("b\"'\"", b"'");
  73. test_byte_string("b\"\"", b"");
  74. test_byte_string(
  75. "b\"contains\nnewlines\\\nescaped newlines\"",
  76. b"contains\nnewlinesescaped newlines",
  77. );
  78. test_byte_string("br\"raw\nstring\\\nhere\"", b"raw\nstring\\\nhere");
  79. test_byte_string("b\"...\"q", b"...");
  80. test_byte_string("br\"...\"q", b"...");
  81. test_byte_string("br##\"...\"##q", b"...");
  82. }
  83. #[test]
  84. fn bytes() {
  85. fn test_byte(s: &str, value: u8) {
  86. match lit(s) {
  87. Lit::Byte(lit) => {
  88. assert_eq!(lit.value(), value);
  89. let again = lit.into_token_stream().to_string();
  90. assert_eq!(again, s);
  91. }
  92. wrong => panic!("{:?}", wrong),
  93. }
  94. }
  95. test_byte("b'a'", b'a');
  96. test_byte("b'\\n'", b'\n');
  97. test_byte("b'\\r'", b'\r');
  98. test_byte("b'\\t'", b'\t');
  99. test_byte("b'\\''", b'\'');
  100. test_byte("b'\"'", b'"');
  101. test_byte("b'a'q", b'a');
  102. }
  103. #[test]
  104. fn chars() {
  105. fn test_char(s: &str, value: char) {
  106. match lit(s) {
  107. Lit::Char(lit) => {
  108. assert_eq!(lit.value(), value);
  109. let again = lit.into_token_stream().to_string();
  110. if again != s {
  111. test_char(&again, value);
  112. }
  113. }
  114. wrong => panic!("{:?}", wrong),
  115. }
  116. }
  117. test_char("'a'", 'a');
  118. test_char("'\\n'", '\n');
  119. test_char("'\\r'", '\r');
  120. test_char("'\\t'", '\t');
  121. test_char("'🐕'", '🐕'); // NOTE: This is an emoji
  122. test_char("'\\''", '\'');
  123. test_char("'\"'", '"');
  124. test_char("'\\u{1F415}'", '\u{1F415}');
  125. test_char("'a'q", 'a');
  126. }
  127. #[test]
  128. fn ints() {
  129. fn test_int(s: &str, value: u64, suffix: &str) {
  130. match lit(s) {
  131. Lit::Int(lit) => {
  132. assert_eq!(lit.base10_digits().parse::<u64>().unwrap(), value);
  133. assert_eq!(lit.suffix(), suffix);
  134. let again = lit.into_token_stream().to_string();
  135. if again != s {
  136. test_int(&again, value, suffix);
  137. }
  138. }
  139. wrong => panic!("{:?}", wrong),
  140. }
  141. }
  142. test_int("5", 5, "");
  143. test_int("5u32", 5, "u32");
  144. test_int("0E", 0, "E");
  145. test_int("0ECMA", 0, "ECMA");
  146. test_int("0o0A", 0, "A");
  147. test_int("5_0", 50, "");
  148. test_int("5_____0_____", 50, "");
  149. test_int("0x7f", 127, "");
  150. test_int("0x7F", 127, "");
  151. test_int("0b1001", 9, "");
  152. test_int("0o73", 59, "");
  153. test_int("0x7Fu8", 127, "u8");
  154. test_int("0b1001i8", 9, "i8");
  155. test_int("0o73u32", 59, "u32");
  156. test_int("0x__7___f_", 127, "");
  157. test_int("0x__7___F_", 127, "");
  158. test_int("0b_1_0__01", 9, "");
  159. test_int("0o_7__3", 59, "");
  160. test_int("0x_7F__u8", 127, "u8");
  161. test_int("0b__10__0_1i8", 9, "i8");
  162. test_int("0o__7__________________3u32", 59, "u32");
  163. test_int("0e1\u{5c5}", 0, "e1\u{5c5}");
  164. }
  165. #[test]
  166. fn floats() {
  167. fn test_float(s: &str, value: f64, suffix: &str) {
  168. match lit(s) {
  169. Lit::Float(lit) => {
  170. assert_eq!(lit.base10_digits().parse::<f64>().unwrap(), value);
  171. assert_eq!(lit.suffix(), suffix);
  172. let again = lit.into_token_stream().to_string();
  173. if again != s {
  174. test_float(&again, value, suffix);
  175. }
  176. }
  177. wrong => panic!("{:?}", wrong),
  178. }
  179. }
  180. test_float("5.5", 5.5, "");
  181. test_float("5.5E12", 5.5e12, "");
  182. test_float("5.5e12", 5.5e12, "");
  183. test_float("1.0__3e-12", 1.03e-12, "");
  184. test_float("1.03e+12", 1.03e12, "");
  185. test_float("9e99e99", 9e99, "e99");
  186. test_float("1e_0", 1.0, "");
  187. test_float("0.0ECMA", 0.0, "ECMA");
  188. }
  189. #[test]
  190. fn negative() {
  191. let span = Span::call_site();
  192. assert_eq!("-1", LitInt::new("-1", span).to_string());
  193. assert_eq!("-1i8", LitInt::new("-1i8", span).to_string());
  194. assert_eq!("-1i16", LitInt::new("-1i16", span).to_string());
  195. assert_eq!("-1i32", LitInt::new("-1i32", span).to_string());
  196. assert_eq!("-1i64", LitInt::new("-1i64", span).to_string());
  197. assert_eq!("-1.5", LitFloat::new("-1.5", span).to_string());
  198. assert_eq!("-1.5f32", LitFloat::new("-1.5f32", span).to_string());
  199. assert_eq!("-1.5f64", LitFloat::new("-1.5f64", span).to_string());
  200. }
  201. #[test]
  202. fn suffix() {
  203. fn get_suffix(token: &str) -> String {
  204. let lit = syn::parse_str::<Lit>(token).unwrap();
  205. match lit {
  206. Lit::Str(lit) => lit.suffix().to_owned(),
  207. Lit::ByteStr(lit) => lit.suffix().to_owned(),
  208. Lit::Byte(lit) => lit.suffix().to_owned(),
  209. Lit::Char(lit) => lit.suffix().to_owned(),
  210. Lit::Int(lit) => lit.suffix().to_owned(),
  211. Lit::Float(lit) => lit.suffix().to_owned(),
  212. _ => unimplemented!(),
  213. }
  214. }
  215. assert_eq!(get_suffix("\"\"s"), "s");
  216. assert_eq!(get_suffix("r\"\"r"), "r");
  217. assert_eq!(get_suffix("b\"\"b"), "b");
  218. assert_eq!(get_suffix("br\"\"br"), "br");
  219. assert_eq!(get_suffix("r#\"\"#r"), "r");
  220. assert_eq!(get_suffix("'c'c"), "c");
  221. assert_eq!(get_suffix("b'b'b"), "b");
  222. assert_eq!(get_suffix("1i32"), "i32");
  223. assert_eq!(get_suffix("1_i32"), "i32");
  224. assert_eq!(get_suffix("1.0f32"), "f32");
  225. assert_eq!(get_suffix("1.0_f32"), "f32");
  226. }
  227. #[test]
  228. fn test_deep_group_empty() {
  229. let tokens = TokenStream::from_iter(vec![TokenTree::Group(Group::new(
  230. Delimiter::None,
  231. TokenStream::from_iter(vec![TokenTree::Group(Group::new(
  232. Delimiter::None,
  233. TokenStream::from_iter(vec![TokenTree::Literal(Literal::string("hi"))]),
  234. ))]),
  235. ))]);
  236. snapshot!(tokens as Lit, @r#""hi""# );
  237. }
  238. #[test]
  239. fn test_error() {
  240. let err = syn::parse_str::<LitStr>("...").unwrap_err();
  241. assert_eq!("expected string literal", err.to_string());
  242. let err = syn::parse_str::<LitStr>("5").unwrap_err();
  243. assert_eq!("expected string literal", err.to_string());
  244. }