| use proc_macro2::{Delimiter, Literal, Spacing, TokenStream, TokenTree}; |
| |
| // #[doc = "..."] -> "..." |
| fn lit_of_outer_doc_comment(tokens: &TokenStream) -> Literal { |
| lit_of_doc_comment(tokens, false) |
| } |
| |
| // #![doc = "..."] -> "..." |
| fn lit_of_inner_doc_comment(tokens: &TokenStream) -> Literal { |
| lit_of_doc_comment(tokens, true) |
| } |
| |
| fn lit_of_doc_comment(tokens: &TokenStream, inner: bool) -> Literal { |
| let mut iter = tokens.clone().into_iter(); |
| match iter.next().unwrap() { |
| TokenTree::Punct(punct) => { |
| assert_eq!(punct.as_char(), '#'); |
| assert_eq!(punct.spacing(), Spacing::Alone); |
| } |
| _ => panic!("wrong token {:?}", tokens), |
| } |
| if inner { |
| match iter.next().unwrap() { |
| TokenTree::Punct(punct) => { |
| assert_eq!(punct.as_char(), '!'); |
| assert_eq!(punct.spacing(), Spacing::Alone); |
| } |
| _ => panic!("wrong token {:?}", tokens), |
| } |
| } |
| iter = match iter.next().unwrap() { |
| TokenTree::Group(group) => { |
| assert_eq!(group.delimiter(), Delimiter::Bracket); |
| assert!(iter.next().is_none(), "unexpected token {:?}", tokens); |
| group.stream().into_iter() |
| } |
| _ => panic!("wrong token {:?}", tokens), |
| }; |
| match iter.next().unwrap() { |
| TokenTree::Ident(ident) => assert_eq!(ident.to_string(), "doc"), |
| _ => panic!("wrong token {:?}", tokens), |
| } |
| match iter.next().unwrap() { |
| TokenTree::Punct(punct) => { |
| assert_eq!(punct.as_char(), '='); |
| assert_eq!(punct.spacing(), Spacing::Alone); |
| } |
| _ => panic!("wrong token {:?}", tokens), |
| } |
| match iter.next().unwrap() { |
| TokenTree::Literal(literal) => { |
| assert!(iter.next().is_none(), "unexpected token {:?}", tokens); |
| literal |
| } |
| _ => panic!("wrong token {:?}", tokens), |
| } |
| } |
| |
| #[test] |
| fn closed_immediately() { |
| let stream = "/**/".parse::<TokenStream>().unwrap(); |
| let tokens = stream.into_iter().collect::<Vec<_>>(); |
| assert!(tokens.is_empty(), "not empty -- {:?}", tokens); |
| } |
| |
| #[test] |
| fn incomplete() { |
| assert!("/*/".parse::<TokenStream>().is_err()); |
| } |
| |
| #[test] |
| fn lit() { |
| let stream = "/// doc".parse::<TokenStream>().unwrap(); |
| let lit = lit_of_outer_doc_comment(&stream); |
| assert_eq!(lit.to_string(), "\" doc\""); |
| |
| let stream = "//! doc".parse::<TokenStream>().unwrap(); |
| let lit = lit_of_inner_doc_comment(&stream); |
| assert_eq!(lit.to_string(), "\" doc\""); |
| |
| let stream = "/** doc */".parse::<TokenStream>().unwrap(); |
| let lit = lit_of_outer_doc_comment(&stream); |
| assert_eq!(lit.to_string(), "\" doc \""); |
| |
| let stream = "/*! doc */".parse::<TokenStream>().unwrap(); |
| let lit = lit_of_inner_doc_comment(&stream); |
| assert_eq!(lit.to_string(), "\" doc \""); |
| } |
| |
| #[test] |
| fn carriage_return() { |
| let stream = "///\r\n".parse::<TokenStream>().unwrap(); |
| let lit = lit_of_outer_doc_comment(&stream); |
| assert_eq!(lit.to_string(), "\"\""); |
| |
| let stream = "/**\r\n*/".parse::<TokenStream>().unwrap(); |
| let lit = lit_of_outer_doc_comment(&stream); |
| assert_eq!(lit.to_string(), "\"\\r\\n\""); |
| |
| "///\r".parse::<TokenStream>().unwrap_err(); |
| "///\r \n".parse::<TokenStream>().unwrap_err(); |
| "/**\r \n*/".parse::<TokenStream>().unwrap_err(); |
| } |