test_visibility.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #[macro_use]
  2. mod macros;
  3. use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
  4. use std::iter::FromIterator;
  5. use syn::parse::{Parse, ParseStream};
  6. use syn::{DeriveInput, Result, Visibility};
  7. #[derive(Debug)]
  8. struct VisRest {
  9. vis: Visibility,
  10. rest: TokenStream,
  11. }
  12. impl Parse for VisRest {
  13. fn parse(input: ParseStream) -> Result<Self> {
  14. Ok(VisRest {
  15. vis: input.parse()?,
  16. rest: input.parse()?,
  17. })
  18. }
  19. }
  20. macro_rules! assert_vis_parse {
  21. ($input:expr, Ok($p:pat)) => {
  22. assert_vis_parse!($input, Ok($p) + "");
  23. };
  24. ($input:expr, Ok($p:pat) + $rest:expr) => {
  25. let expected = $rest.parse::<TokenStream>().unwrap();
  26. let parse: VisRest = syn::parse_str($input).unwrap();
  27. match parse.vis {
  28. $p => {}
  29. _ => panic!("Expected {}, got {:?}", stringify!($p), parse.vis),
  30. }
  31. // NOTE: Round-trips through `to_string` to avoid potential whitespace
  32. // diffs.
  33. assert_eq!(parse.rest.to_string(), expected.to_string());
  34. };
  35. ($input:expr, Err) => {
  36. syn::parse2::<VisRest>($input.parse().unwrap()).unwrap_err();
  37. };
  38. }
  39. #[test]
  40. fn test_pub() {
  41. assert_vis_parse!("pub", Ok(Visibility::Public(_)));
  42. }
  43. #[test]
  44. fn test_crate() {
  45. assert_vis_parse!("crate", Ok(Visibility::Crate(_)));
  46. }
  47. #[test]
  48. fn test_inherited() {
  49. assert_vis_parse!("", Ok(Visibility::Inherited));
  50. }
  51. #[test]
  52. fn test_in() {
  53. assert_vis_parse!("pub(in foo::bar)", Ok(Visibility::Restricted(_)));
  54. }
  55. #[test]
  56. fn test_pub_crate() {
  57. assert_vis_parse!("pub(crate)", Ok(Visibility::Restricted(_)));
  58. }
  59. #[test]
  60. fn test_pub_self() {
  61. assert_vis_parse!("pub(self)", Ok(Visibility::Restricted(_)));
  62. }
  63. #[test]
  64. fn test_pub_super() {
  65. assert_vis_parse!("pub(super)", Ok(Visibility::Restricted(_)));
  66. }
  67. #[test]
  68. fn test_missing_in() {
  69. assert_vis_parse!("pub(foo::bar)", Ok(Visibility::Public(_)) + "(foo::bar)");
  70. }
  71. #[test]
  72. fn test_missing_in_path() {
  73. assert_vis_parse!("pub(in)", Err);
  74. }
  75. #[test]
  76. fn test_crate_path() {
  77. assert_vis_parse!(
  78. "pub(crate::A, crate::B)",
  79. Ok(Visibility::Public(_)) + "(crate::A, crate::B)"
  80. );
  81. }
  82. #[test]
  83. fn test_junk_after_in() {
  84. assert_vis_parse!("pub(in some::path @@garbage)", Err);
  85. }
  86. #[test]
  87. fn test_empty_group_vis() {
  88. // mimics `struct S { $vis $field: () }` where $vis is empty
  89. let tokens = TokenStream::from_iter(vec![
  90. TokenTree::Ident(Ident::new("struct", Span::call_site())),
  91. TokenTree::Ident(Ident::new("S", Span::call_site())),
  92. TokenTree::Group(Group::new(
  93. Delimiter::Brace,
  94. TokenStream::from_iter(vec![
  95. TokenTree::Group(Group::new(Delimiter::None, TokenStream::new())),
  96. TokenTree::Group(Group::new(
  97. Delimiter::None,
  98. TokenStream::from_iter(vec![TokenTree::Ident(Ident::new(
  99. "f",
  100. Span::call_site(),
  101. ))]),
  102. )),
  103. TokenTree::Punct(Punct::new(':', Spacing::Alone)),
  104. TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
  105. ]),
  106. )),
  107. ]);
  108. snapshot!(tokens as DeriveInput, @r###"
  109. DeriveInput {
  110. vis: Inherited,
  111. ident: "S",
  112. generics: Generics,
  113. data: Data::Struct {
  114. fields: Fields::Named {
  115. named: [
  116. Field {
  117. vis: Inherited,
  118. ident: Some("f"),
  119. colon_token: Some,
  120. ty: Type::Tuple,
  121. },
  122. ],
  123. },
  124. },
  125. }
  126. "###);
  127. }