1#![allow(clippy::assertions_on_result_states)]
2
3use proc_macro2::{Delimiter, Literal, Spacing, TokenStream, TokenTree};
4
5// #[doc = "..."] -> "..."
6fn lit_of_outer_doc_comment(tokens: &TokenStream) -> Literal {
7 lit_of_doc_comment(tokens, false)
8}
9
10// #![doc = "..."] -> "..."
11fn lit_of_inner_doc_comment(tokens: &TokenStream) -> Literal {
12 lit_of_doc_comment(tokens, true)
13}
14
15fn lit_of_doc_comment(tokens: &TokenStream, inner: bool) -> Literal {
16 let mut iter = tokens.clone().into_iter();
17 match iter.next().unwrap() {
18 TokenTree::Punct(punct) => {
19 assert_eq!(punct.as_char(), '#');
20 assert_eq!(punct.spacing(), Spacing::Alone);
21 }
22 _ => panic!("wrong token {:?}", tokens),
23 }
24 if inner {
25 match iter.next().unwrap() {
26 TokenTree::Punct(punct) => {
27 assert_eq!(punct.as_char(), '!');
28 assert_eq!(punct.spacing(), Spacing::Alone);
29 }
30 _ => panic!("wrong token {:?}", tokens),
31 }
32 }
33 iter = match iter.next().unwrap() {
34 TokenTree::Group(group) => {
35 assert_eq!(group.delimiter(), Delimiter::Bracket);
36 assert!(iter.next().is_none(), "unexpected token {:?}", tokens);
37 group.stream().into_iter()
38 }
39 _ => panic!("wrong token {:?}", tokens),
40 };
41 match iter.next().unwrap() {
42 TokenTree::Ident(ident) => assert_eq!(ident.to_string(), "doc"),
43 _ => panic!("wrong token {:?}", tokens),
44 }
45 match iter.next().unwrap() {
46 TokenTree::Punct(punct) => {
47 assert_eq!(punct.as_char(), '=');
48 assert_eq!(punct.spacing(), Spacing::Alone);
49 }
50 _ => panic!("wrong token {:?}", tokens),
51 }
52 match iter.next().unwrap() {
53 TokenTree::Literal(literal) => {
54 assert!(iter.next().is_none(), "unexpected token {:?}", tokens);
55 literal
56 }
57 _ => panic!("wrong token {:?}", tokens),
58 }
59}
60
61#[test]
62fn closed_immediately() {
63 let stream = "/**/".parse::<TokenStream>().unwrap();
64 let tokens = stream.into_iter().collect::<Vec<_>>();
65 assert!(tokens.is_empty(), "not empty -- {:?}", tokens);
66}
67
68#[test]
69fn incomplete() {
70 assert!("/*/".parse::<TokenStream>().is_err());
71}
72
73#[test]
74fn lit() {
75 let stream = "/// doc".parse::<TokenStream>().unwrap();
76 let lit = lit_of_outer_doc_comment(&stream);
77 assert_eq!(lit.to_string(), "\" doc\"");
78
79 let stream = "//! doc".parse::<TokenStream>().unwrap();
80 let lit = lit_of_inner_doc_comment(&stream);
81 assert_eq!(lit.to_string(), "\" doc\"");
82
83 let stream = "/** doc */".parse::<TokenStream>().unwrap();
84 let lit = lit_of_outer_doc_comment(&stream);
85 assert_eq!(lit.to_string(), "\" doc \"");
86
87 let stream = "/*! doc */".parse::<TokenStream>().unwrap();
88 let lit = lit_of_inner_doc_comment(&stream);
89 assert_eq!(lit.to_string(), "\" doc \"");
90}
91
92#[test]
93fn carriage_return() {
94 let stream = "///\r\n".parse::<TokenStream>().unwrap();
95 let lit = lit_of_outer_doc_comment(&stream);
96 assert_eq!(lit.to_string(), "\"\"");
97
98 let stream = "/**\r\n*/".parse::<TokenStream>().unwrap();
99 let lit = lit_of_outer_doc_comment(&stream);
100 assert_eq!(lit.to_string(), "\"\\r\\n\"");
101
102 "///\r".parse::<TokenStream>().unwrap_err();
103 "///\r \n".parse::<TokenStream>().unwrap_err();
104 "/**\r \n*/".parse::<TokenStream>().unwrap_err();
105}
106