1use core::mem::take;
2
3use crate::ast::prelude::*;
4
5#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
7#[non_exhaustive]
8pub enum Item {
9 Use(ast::ItemUse),
11 Fn(ast::ItemFn),
14 Enum(ast::ItemEnum),
16 Struct(ast::ItemStruct),
18 Impl(ast::ItemImpl),
20 Mod(ast::ItemMod),
22 Const(ast::ItemConst),
24 Static(ast::ItemStatic),
26 MacroCall(ast::MacroCall),
28}
29
30impl Item {
31 pub(crate) fn needs_semi_colon(&self) -> bool {
33 match self {
34 Self::Use(..) => true,
35 Self::Struct(st) => st.needs_semi_colon(),
36 Self::Const(..) => true,
37 Self::Static(..) => true,
38 _ => false,
39 }
40 }
41
42 pub(crate) fn peek_as_item(p: &mut Peeker<'_>) -> bool {
44 match p.nth(0) {
45 K![use] => true,
46 K![enum] => true,
47 K![struct] => true,
48 K![impl] => true,
49 K![async] => matches!(p.nth(1), K![fn]),
50 K![fn] => true,
51 K![mod] => true,
52 K![const] => true,
53 K![static] => true,
54 _ => false,
55 }
56 }
57
58 pub(crate) fn parse_with_meta_path(
65 p: &mut Parser<'_>,
66 attributes: Vec<ast::Attribute>,
67 visibility: ast::Visibility,
68 path: Option<ast::Path>,
69 ) -> Result<Self> {
70 p.nested(|p| Self::parse_with_meta_path_inner(p, attributes, visibility, path))
71 }
72
73 fn parse_with_meta_path_inner(
74 p: &mut Parser<'_>,
75 mut attributes: Vec<ast::Attribute>,
76 mut visibility: ast::Visibility,
77 path: Option<ast::Path>,
78 ) -> Result<Self> {
79 let item = if let Some(path) = path {
80 Self::MacroCall(ast::MacroCall::parse_with_meta_path(
81 p,
82 take(&mut attributes),
83 path,
84 )?)
85 } else {
86 let mut const_token = p.parse::<Option<T![const]>>()?;
87 let mut static_token = p.parse::<Option<T![static]>>()?;
88 let mut async_token = p.parse::<Option<T![async]>>()?;
89
90 let item = match p.nth(0)? {
91 K![use] => Self::Use(ast::ItemUse::parse_with_meta(
92 p,
93 take(&mut attributes),
94 take(&mut visibility),
95 )?),
96 K![enum] => Self::Enum(ast::ItemEnum::parse_with_meta(
97 p,
98 take(&mut attributes),
99 take(&mut visibility),
100 )?),
101 K![struct] => Self::Struct(ast::ItemStruct::parse_with_meta(
102 p,
103 take(&mut attributes),
104 take(&mut visibility),
105 )?),
106 K![impl] => Self::Impl(ast::ItemImpl::parse_with_attributes(
107 p,
108 take(&mut attributes),
109 )?),
110 K![fn] => Self::Fn(ast::ItemFn::parse_with_meta(
111 p,
112 take(&mut attributes),
113 take(&mut visibility),
114 take(&mut const_token),
115 take(&mut async_token),
116 )?),
117 K![mod] => Self::Mod(ast::ItemMod::parse_with_meta(
118 p,
119 take(&mut attributes),
120 take(&mut visibility),
121 )?),
122 K![ident] => {
123 if let Some(const_token) = const_token.take() {
124 Self::Const(ast::ItemConst::parse_with_meta(
125 p,
126 take(&mut attributes),
127 take(&mut visibility),
128 const_token,
129 )?)
130 } else if let Some(static_token) = static_token.take() {
131 Self::Static(ast::ItemStatic::parse_with_meta(
132 p,
133 take(&mut attributes),
134 take(&mut visibility),
135 static_token,
136 )?)
137 } else {
138 Self::MacroCall(p.parse()?)
139 }
140 }
141 _ => {
142 return Err(compile::Error::expected(
143 p.tok_at(0)?,
144 "`fn`, `mod`, `struct`, `enum`, `use`, or macro call",
145 ))
146 }
147 };
148
149 if let Some(span) = const_token.option_span() {
150 return Err(compile::Error::unsupported(span, "const modifier"));
151 }
152
153 if let Some(span) = static_token.option_span() {
154 return Err(compile::Error::unsupported(span, "static modifier"));
155 }
156
157 if let Some(span) = async_token.option_span() {
158 return Err(compile::Error::unsupported(span, "async modifier"));
159 }
160
161 item
162 };
163
164 if let Some(span) = attributes.option_span() {
165 return Err(compile::Error::unsupported(span, "attribute"));
166 }
167
168 if let Some(span) = visibility.option_span() {
169 return Err(compile::Error::unsupported(span, "visibility modifier"));
170 }
171
172 Ok(item)
173 }
174}
175
176impl Parse for Item {
177 fn parse(p: &mut Parser<'_>) -> Result<Self> {
178 let attributes = p.parse()?;
179 let visibility = p.parse()?;
180 let path = p.parse()?;
181 Self::parse_with_meta_path(p, attributes, visibility, path)
182 }
183}