solar_parse/parser/
item.rs

1use super::{ExpectedToken, SeqSep};
2use crate::{PResult, Parser};
3use itertools::Itertools;
4use smallvec::SmallVec;
5use solar_ast::{token::*, *};
6use solar_interface::{Ident, Span, Spanned, diagnostics::DiagMsg, error_code, kw, sym};
7
8impl<'sess, 'ast> Parser<'sess, 'ast> {
9    /// Parses a source unit.
10    #[instrument(level = "debug", skip_all)]
11    pub fn parse_file(&mut self) -> PResult<'sess, SourceUnit<'ast>> {
12        self.parse_items(TokenKind::Eof).map(SourceUnit::new)
13    }
14
15    /// Parses a list of items until the given token is encountered.
16    fn parse_items(&mut self, end: TokenKind) -> PResult<'sess, Box<'ast, [Item<'ast>]>> {
17        let get_msg_note = |this: &mut Self| {
18            let (prefix, list, link);
19            if this.in_contract {
20                prefix = "contract";
21                list = "function, variable, struct, or modifier definition";
22                link = "contractBodyElement";
23            } else {
24                prefix = "global";
25                list = "pragma, import directive, contract, interface, library, struct, enum, constant, function, modifier, or error definition";
26                link = "sourceUnit";
27            }
28            let msg =
29                format!("expected {prefix} item ({list}), found {}", this.token.full_description());
30            let note = format!(
31                "for a full list of valid {prefix} items, see <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.{link}>"
32            );
33            (msg, note)
34        };
35
36        let mut items = Vec::new();
37        while let Some(item) = self.parse_item()? {
38            if self.in_contract && !item.is_allowed_in_contract() {
39                let msg = format!("{}s are not allowed in contracts", item.description());
40                let (_, note) = get_msg_note(self);
41                self.dcx().err(msg).span(item.span).note(note).emit();
42            } else {
43                items.push(item);
44            }
45        }
46        if !self.eat(end) {
47            let (msg, note) = get_msg_note(self);
48            return Err(self.dcx().err(msg).span(self.token.span).note(note));
49        }
50        Ok(self.alloc_vec(items))
51    }
52
53    /// Parses an item.
54    #[instrument(level = "debug", skip_all)]
55    pub fn parse_item(&mut self) -> PResult<'sess, Option<Item<'ast>>> {
56        let docs = self.parse_doc_comments();
57        self.parse_spanned(Self::parse_item_kind)
58            .map(|(span, kind)| kind.map(|kind| Item { docs, span, kind }))
59    }
60
61    fn parse_item_kind(&mut self) -> PResult<'sess, Option<ItemKind<'ast>>> {
62        let kind = if self.is_function_like() {
63            self.parse_function().map(ItemKind::Function)
64        } else if self.eat_keyword(kw::Struct) {
65            self.parse_struct().map(ItemKind::Struct)
66        } else if self.eat_keyword(kw::Event) {
67            self.parse_event().map(ItemKind::Event)
68        } else if self.is_contract_like() {
69            self.parse_contract().map(ItemKind::Contract)
70        } else if self.eat_keyword(kw::Enum) {
71            self.parse_enum().map(ItemKind::Enum)
72        } else if self.eat_keyword(kw::Type) {
73            self.parse_udvt().map(ItemKind::Udvt)
74        } else if self.eat_keyword(kw::Pragma) {
75            self.parse_pragma().map(ItemKind::Pragma)
76        } else if self.eat_keyword(kw::Import) {
77            self.parse_import().map(ItemKind::Import)
78        } else if self.eat_keyword(kw::Using) {
79            self.parse_using().map(ItemKind::Using)
80        } else if self.check_keyword(sym::error)
81            && self.look_ahead(1).is_ident()
82            && self.look_ahead(2).is_open_delim(Delimiter::Parenthesis)
83        {
84            self.bump(); // `error`
85            self.parse_error().map(ItemKind::Error)
86        } else if self.is_variable_declaration() {
87            let flags = if self.in_contract { VarFlags::STATE_VAR } else { VarFlags::CONSTANT_VAR };
88            self.parse_variable_definition(flags).map(ItemKind::Variable)
89        } else {
90            return Ok(None);
91        };
92        kind.map(Some)
93    }
94
95    /// Returns `true` if the current token is the start of a function definition.
96    fn is_function_like(&self) -> bool {
97        (self.token.is_keyword(kw::Function)
98            && !self.look_ahead(1).is_open_delim(Delimiter::Parenthesis))
99            || self.token.is_keyword_any(&[
100                kw::Constructor,
101                kw::Fallback,
102                kw::Receive,
103                kw::Modifier,
104            ])
105    }
106
107    /// Returns `true` if the current token is the start of a contract definition.
108    fn is_contract_like(&self) -> bool {
109        self.token.is_keyword_any(&[kw::Abstract, kw::Contract, kw::Interface, kw::Library])
110    }
111
112    /// Returns `true` if the current token is the start of a variable declaration.
113    pub(super) fn is_variable_declaration(&self) -> bool {
114        // https://github.com/ethereum/solidity/blob/194b114664c7daebc2ff68af3c573272f5d28913/libsolidity/parsing/Parser.cpp#L2451
115        self.token.is_non_reserved_ident(false) || self.is_non_custom_variable_declaration()
116    }
117
118    pub(super) fn is_non_custom_variable_declaration(&self) -> bool {
119        self.token.is_keyword(kw::Mapping)
120            || (self.token.is_keyword(kw::Function)
121                && self.look_ahead(1).is_open_delim(Delimiter::Parenthesis))
122            || self.token.is_elementary_type()
123    }
124
125    /* ----------------------------------------- Items ----------------------------------------- */
126    // These functions expect that the keyword has already been eaten unless otherwise noted.
127
128    /// Parses a function definition.
129    ///
130    /// Expects the current token to be a function-like keyword.
131    fn parse_function(&mut self) -> PResult<'sess, ItemFunction<'ast>> {
132        let Token { span: lo, kind: TokenKind::Ident(kw) } = self.token else {
133            unreachable!("parse_function called without function-like keyword");
134        };
135        self.bump(); // kw
136
137        let kind = match kw {
138            kw::Constructor => FunctionKind::Constructor,
139            kw::Function => FunctionKind::Function,
140            kw::Fallback => FunctionKind::Fallback,
141            kw::Receive => FunctionKind::Receive,
142            kw::Modifier => FunctionKind::Modifier,
143            _ => unreachable!("parse_function called without function-like keyword"),
144        };
145        let flags = FunctionFlags::from_kind(kind);
146        let header = self.parse_function_header(flags)?;
147        let (body_span, body) = self.parse_spanned(|this| {
148            Ok(if !flags.contains(FunctionFlags::ONLY_BLOCK) && this.eat(TokenKind::Semi) {
149                None
150            } else {
151                Some(this.parse_block()?)
152            })
153        })?;
154
155        if !self.in_contract && !kind.allowed_in_global() {
156            let msg = format!("{kind}s are not allowed in the global scope");
157            self.dcx().err(msg).span(lo.to(self.prev_token.span)).emit();
158        }
159        // All function kinds are allowed in contracts.
160
161        Ok(ItemFunction { kind, header, body, body_span })
162    }
163
164    /// Parses a function a header.
165    pub(super) fn parse_function_header(
166        &mut self,
167        flags: FunctionFlags,
168    ) -> PResult<'sess, FunctionHeader<'ast>> {
169        let lo = self.prev_token.span; // the header span includes the "function" kw
170
171        let mut header = FunctionHeader::default();
172        let var_flags = if flags.contains(FunctionFlags::PARAM_NAME) {
173            VarFlags::FUNCTION_TY
174        } else {
175            VarFlags::FUNCTION
176        };
177
178        if flags.contains(FunctionFlags::NAME) {
179            // Allow and warn on `function fallback` or `function receive`.
180            let ident;
181            if flags == FunctionFlags::FUNCTION
182                && self.token.is_keyword_any(&[kw::Fallback, kw::Receive])
183            {
184                let kw_span = self.prev_token.span;
185                ident = self.parse_ident_any()?;
186                let msg = format!("function named `{ident}`");
187                let mut warn = self.dcx().warn(msg).span(ident.span).code(error_code!(3445));
188                if self.in_contract {
189                    let help = format!(
190                        "remove the `function` keyword if you intend this to be a contract's {ident} function"
191                    );
192                    warn = warn.span_help(kw_span, help);
193                }
194                warn.emit();
195            } else {
196                ident = self.parse_ident()?;
197            }
198            header.name = Some(ident);
199        } else if self.token.is_non_reserved_ident(false) {
200            let msg = "function names are not allowed here";
201            self.dcx().err(msg).span(self.token.span).emit();
202            self.bump();
203        }
204
205        if flags.contains(FunctionFlags::NO_PARENS)
206            && !self.token.is_open_delim(Delimiter::Parenthesis)
207        {
208            // Omitted parens.
209        } else {
210            header.parameters = self.parse_parameter_list(true, var_flags)?;
211        }
212
213        let mut modifiers = Vec::new();
214        loop {
215            // This is needed to skip parsing surrounding variable's visibility in function types.
216            // E.g. in `function(uint) external internal e;` the `internal` is the surrounding
217            // variable's visibility, not the function's.
218            if !(flags == FunctionFlags::FUNCTION_TY && header.visibility.is_some())
219                && let Some(visibility) = self.parse_visibility()
220            {
221                let span = self.prev_token.span;
222                if let Some(prev) = header.visibility {
223                    let msg = "visibility already specified";
224                    self.dcx()
225                        .err(msg)
226                        .span(span)
227                        .span_note(prev.span, "previous definition")
228                        .emit();
229                } else {
230                    let mut v = Some(visibility);
231                    if !flags.contains(FunctionFlags::from_visibility(visibility)) {
232                        let msg = visibility_error(visibility, flags.visibilities());
233                        self.dcx().err(msg).span(span).emit();
234                        // Set to the first valid visibility, if any.
235                        v = flags.visibilities().into_iter().flatten().next();
236                    }
237                    header.visibility = v.map(|v| Spanned { span, data: v });
238                }
239            } else if let Some(state_mutability) = self.parse_state_mutability() {
240                let span = self.prev_token.span;
241                if let Some(prev) = header.state_mutability {
242                    let msg = "state mutability already specified";
243                    self.dcx()
244                        .err(msg)
245                        .span(span)
246                        .span_note(prev.span, "previous definition")
247                        .emit();
248                } else {
249                    let mut sm = Some(state_mutability);
250                    if !flags.contains(FunctionFlags::from_state_mutability(state_mutability)) {
251                        let msg =
252                            state_mutability_error(state_mutability, flags.state_mutabilities());
253                        self.dcx().err(msg).span(span).emit();
254                        // Set to the first valid state mutability, if any.
255                        sm = flags.state_mutabilities().into_iter().flatten().next();
256                    }
257                    header.state_mutability = sm.map(|sm| Spanned { span, data: sm });
258                }
259            } else if self.eat_keyword(kw::Virtual) {
260                let span = self.prev_token.span;
261                if !flags.contains(FunctionFlags::VIRTUAL) {
262                    let msg = "`virtual` is not allowed here";
263                    self.dcx().err(msg).span(span).emit();
264                } else if let Some(prev) = header.virtual_ {
265                    let msg = "virtual already specified";
266                    self.dcx().err(msg).span(span).span_note(prev, "previous definition").emit();
267                } else {
268                    header.virtual_ = Some(span);
269                }
270            } else if self.eat_keyword(kw::Override) {
271                let o = self.parse_override()?;
272                let span = o.span;
273                if !flags.contains(FunctionFlags::OVERRIDE) {
274                    let msg = "`override` is not allowed here";
275                    self.dcx().err(msg).span(span).emit();
276                } else if let Some(prev) = &header.override_ {
277                    let msg = "override already specified";
278                    self.dcx()
279                        .err(msg)
280                        .span(span)
281                        .span_note(prev.span, "previous definition")
282                        .emit();
283                } else {
284                    header.override_ = Some(o);
285                }
286            } else if flags.contains(FunctionFlags::MODIFIERS)
287                && self.token.is_non_reserved_ident(false)
288            {
289                modifiers.push(self.parse_modifier()?);
290            } else {
291                break;
292            }
293        }
294
295        header.modifiers = self.alloc_vec(modifiers);
296
297        if flags.contains(FunctionFlags::RETURNS) && self.eat_keyword(kw::Returns) {
298            header.returns = Some(self.parse_parameter_list(false, var_flags)?);
299        }
300
301        header.span = lo.to(self.prev_token.span);
302
303        Ok(header)
304    }
305
306    /// Parses a struct definition.
307    fn parse_struct(&mut self) -> PResult<'sess, ItemStruct<'ast>> {
308        let name = self.parse_ident()?;
309        let fields = self.parse_delim_seq(
310            Delimiter::Brace,
311            SeqSep::trailing_enforced(TokenKind::Semi),
312            true,
313            |this| this.parse_variable_definition(VarFlags::STRUCT),
314        )?;
315        Ok(ItemStruct { name, fields })
316    }
317
318    /// Parses an event definition.
319    fn parse_event(&mut self) -> PResult<'sess, ItemEvent<'ast>> {
320        let name = self.parse_ident()?;
321        let parameters = self.parse_parameter_list(true, VarFlags::EVENT)?;
322        let anonymous = self.eat_keyword(kw::Anonymous);
323        self.expect_semi()?;
324        Ok(ItemEvent { name, parameters, anonymous })
325    }
326
327    /// Parses an error definition.
328    fn parse_error(&mut self) -> PResult<'sess, ItemError<'ast>> {
329        let name = self.parse_ident()?;
330        let parameters = self.parse_parameter_list(true, VarFlags::ERROR)?;
331        self.expect_semi()?;
332        Ok(ItemError { name, parameters })
333    }
334
335    /// Parses a contract definition.
336    ///
337    /// Expects the current token to be a contract-like keyword.
338    fn parse_contract(&mut self) -> PResult<'sess, ItemContract<'ast>> {
339        let TokenKind::Ident(kw) = self.token.kind else {
340            unreachable!("parse_contract called without contract-like keyword");
341        };
342        self.bump(); // kw
343
344        let kind = match kw {
345            kw::Abstract => {
346                self.expect_keyword(kw::Contract)?;
347                ContractKind::AbstractContract
348            }
349            kw::Contract => ContractKind::Contract,
350            kw::Interface => ContractKind::Interface,
351            kw::Library => ContractKind::Library,
352            _ => unreachable!("parse_contract called without contract-like keyword"),
353        };
354        let name = self.parse_ident()?;
355
356        let mut bases = None::<Box<'_, [Modifier<'_>]>>;
357        let mut layout = None::<StorageLayoutSpecifier<'_>>;
358        loop {
359            if self.eat_keyword(kw::Is) {
360                let new_bases = self.parse_inheritance()?;
361                if let Some(prev) = &bases {
362                    let msg = "base contracts already specified";
363                    let span = |bases: &[Modifier<'_>]| {
364                        Span::join_first_last(bases.iter().map(|m| m.span()))
365                    };
366                    self.dcx()
367                        .err(msg)
368                        .span(span(new_bases))
369                        .span_note(span(prev), "previous definition")
370                        .emit();
371                } else if !new_bases.is_empty() {
372                    bases = Some(new_bases);
373                }
374            } else if self.check_keyword(sym::layout) {
375                let new_layout = self.parse_storage_layout_specifier()?;
376                if let Some(prev) = &layout {
377                    let msg = "storage layout already specified";
378                    self.dcx()
379                        .err(msg)
380                        .span(new_layout.span)
381                        .span_note(prev.span, "previous definition")
382                        .emit();
383                } else {
384                    layout = Some(new_layout);
385                }
386            } else {
387                break;
388            }
389        }
390
391        if let Some(layout) = &layout
392            && !kind.is_contract()
393        {
394            let msg = "storage layout is only allowed for contracts";
395            self.dcx().err(msg).span(layout.span).emit();
396        }
397
398        self.expect(TokenKind::OpenDelim(Delimiter::Brace))?;
399        let body =
400            self.in_contract(|this| this.parse_items(TokenKind::CloseDelim(Delimiter::Brace)))?;
401
402        Ok(ItemContract { kind, name, layout, bases: bases.unwrap_or_default(), body })
403    }
404
405    /// Parses an enum definition.
406    fn parse_enum(&mut self) -> PResult<'sess, ItemEnum<'ast>> {
407        let name = self.parse_ident()?;
408        let variants = self.parse_delim_comma_seq(Delimiter::Brace, true, Self::parse_ident)?;
409        Ok(ItemEnum { name, variants })
410    }
411
412    /// Parses a user-defined value type.
413    fn parse_udvt(&mut self) -> PResult<'sess, ItemUdvt<'ast>> {
414        let name = self.parse_ident()?;
415        self.expect_keyword(kw::Is)?;
416        let ty = self.parse_type()?;
417        self.expect_semi()?;
418        Ok(ItemUdvt { name, ty })
419    }
420
421    /// Parses a pragma directive.
422    fn parse_pragma(&mut self) -> PResult<'sess, PragmaDirective<'ast>> {
423        let is_ident_or_strlit = |t: Token| t.is_ident() || t.is_str_lit();
424
425        let tokens = if self.check_keyword(sym::solidity)
426            || (self.token.is_ident()
427                && self.look_ahead_with(1, |t| t.is_op() || t.is_rational_lit()))
428        {
429            // `pragma <ident> <req>;`
430            let ident = self.parse_ident_any()?;
431            let req = self.parse_semver_req()?;
432            PragmaTokens::Version(ident, req)
433        } else if (is_ident_or_strlit(self.token) && self.look_ahead(1).kind == TokenKind::Semi)
434            || (is_ident_or_strlit(self.token)
435                && self.look_ahead_with(1, is_ident_or_strlit)
436                && self.look_ahead(2).kind == TokenKind::Semi)
437        {
438            // `pragma <k>;`
439            // `pragma <k> <v>;`
440            let k = self.parse_ident_or_strlit()?;
441            let v = if self.token.is_ident() || self.token.is_str_lit() {
442                Some(self.parse_ident_or_strlit()?)
443            } else {
444                None
445            };
446            PragmaTokens::Custom(k, v)
447        } else {
448            let mut tokens = Vec::new();
449            while !matches!(self.token.kind, TokenKind::Semi | TokenKind::Eof) {
450                tokens.push(self.token);
451                self.bump();
452            }
453            if !self.token.is_eof() && tokens.is_empty() {
454                let msg = "expected at least one token in pragma directive";
455                self.dcx().err(msg).span(self.prev_token.span).emit();
456            }
457            PragmaTokens::Verbatim(self.alloc_vec(tokens))
458        };
459        self.expect_semi()?;
460        Ok(PragmaDirective { tokens })
461    }
462
463    fn parse_ident_or_strlit(&mut self) -> PResult<'sess, IdentOrStrLit> {
464        if self.check_ident() {
465            self.parse_ident().map(IdentOrStrLit::Ident)
466        } else if self.check_str_lit() {
467            self.parse_str_lit().map(IdentOrStrLit::StrLit)
468        } else {
469            self.unexpected()
470        }
471    }
472
473    /// Parses a SemVer version requirement.
474    ///
475    /// See `crates/ast/src/ast/semver.rs` for more details on the implementation.
476    pub fn parse_semver_req(&mut self) -> PResult<'sess, SemverReq<'ast>> {
477        if self.check_noexpect(TokenKind::Semi) || self.check_noexpect(TokenKind::Eof) {
478            let msg = "empty version requirement";
479            let span = self.prev_token.span.to(self.token.span);
480            return Err(self.dcx().err(msg).span(span));
481        }
482        self.parse_semver_req_components_dis().map(|dis| SemverReq { dis })
483    }
484
485    /// `any(c)`
486    fn parse_semver_req_components_dis(
487        &mut self,
488    ) -> PResult<'sess, Box<'ast, [SemverReqCon<'ast>]>> {
489        // https://github.com/ethereum/solidity/blob/e81f2bdbd66e9c8780f74b8a8d67b4dc2c87945e/liblangutil/SemVerHandler.cpp#L170
490        let mut dis = Vec::new();
491        loop {
492            dis.push(self.parse_semver_req_components_con()?);
493            if self.eat(TokenKind::OrOr) {
494                continue;
495            }
496            if self.check(TokenKind::Semi) || self.check(TokenKind::Eof) {
497                break;
498            }
499            // `parse_semver_req_components_con` parses a single range,
500            // or all the values until `||`.
501            debug_assert!(
502                matches!(
503                    dis.last().map(|x| &x.components),
504                    Some([
505                        ..,
506                        SemverReqComponent { span: _, kind: SemverReqComponentKind::Range(..) }
507                    ])
508                ),
509                "not a range: last={:?}",
510                dis.last()
511            );
512            return Err(self.dcx().err("ranges can only be combined using the || operator"));
513        }
514        Ok(self.alloc_vec(dis))
515    }
516
517    /// `all(c)`
518    fn parse_semver_req_components_con(&mut self) -> PResult<'sess, SemverReqCon<'ast>> {
519        // component - component (range)
520        // or component component* (conjunction)
521
522        let mut components = Vec::new();
523        let lo = self.token.span;
524        let (op, v) = self.parse_semver_component()?;
525        if self.eat(TokenKind::BinOp(BinOpToken::Minus)) {
526            // range
527            // Ops are parsed and overwritten: https://github.com/ethereum/solidity/blob/e81f2bdbd66e9c8780f74b8a8d67b4dc2c87945e/liblangutil/SemVerHandler.cpp#L210
528            let _ = op;
529            let (_second_op, right) = self.parse_semver_component()?;
530            let kind = SemverReqComponentKind::Range(v, right);
531            let span = lo.to(self.prev_token.span);
532            components.push(SemverReqComponent { span, kind });
533        } else {
534            // conjunction; first is already parsed
535            let span = lo.to(self.prev_token.span);
536            let kind = SemverReqComponentKind::Op(op, v);
537            components.push(SemverReqComponent { span, kind });
538            // others
539            while !matches!(self.token.kind, TokenKind::OrOr | TokenKind::Eof | TokenKind::Semi) {
540                let (span, (op, v)) = self.parse_spanned(Self::parse_semver_component)?;
541                let kind = SemverReqComponentKind::Op(op, v);
542                components.push(SemverReqComponent { span, kind });
543            }
544        }
545        let span = lo.to(self.prev_token.span);
546        let components = self.alloc_vec(components);
547        Ok(SemverReqCon { span, components })
548    }
549
550    fn parse_semver_component(&mut self) -> PResult<'sess, (Option<SemverOp>, SemverVersion)> {
551        let op = self.parse_semver_op();
552        let v = self.parse_semver_version()?;
553        Ok((op, v))
554    }
555
556    fn parse_semver_op(&mut self) -> Option<SemverOp> {
557        // https://github.com/ethereum/solidity/blob/e81f2bdbd66e9c8780f74b8a8d67b4dc2c87945e/liblangutil/SemVerHandler.cpp#L227
558        let op = match self.token.kind {
559            TokenKind::Eq => SemverOp::Exact,
560            TokenKind::Gt => SemverOp::Greater,
561            TokenKind::Ge => SemverOp::GreaterEq,
562            TokenKind::Lt => SemverOp::Less,
563            TokenKind::Le => SemverOp::LessEq,
564            TokenKind::Tilde => SemverOp::Tilde,
565            TokenKind::BinOp(BinOpToken::Caret) => SemverOp::Caret,
566            _ => return None,
567        };
568        self.bump();
569        Some(op)
570    }
571
572    fn parse_semver_version(&mut self) -> PResult<'sess, SemverVersion> {
573        Ok(SemverVersionParser::new(self).parse())
574    }
575
576    /// Parses an import directive.
577    fn parse_import(&mut self) -> PResult<'sess, ImportDirective<'ast>> {
578        let path;
579        let items = if self.eat(TokenKind::BinOp(BinOpToken::Star)) {
580            // * as alias from ""
581            let alias = self.parse_as_alias()?;
582            self.expect_keyword(sym::from)?;
583            path = self.parse_str_lit()?;
584            ImportItems::Glob(alias)
585        } else if self.check(TokenKind::OpenDelim(Delimiter::Brace)) {
586            // { x as y, ... } from ""
587            let list = self.parse_delim_comma_seq(Delimiter::Brace, false, |this| {
588                let name = this.parse_ident()?;
589                let alias = this.parse_as_alias_opt()?;
590                Ok((name, alias))
591            })?;
592            self.expect_keyword(sym::from)?;
593            path = self.parse_str_lit()?;
594            ImportItems::Aliases(list)
595        } else {
596            // "" as alias
597            path = self.parse_str_lit()?;
598            let alias = self.parse_as_alias_opt()?;
599            ImportItems::Plain(alias)
600        };
601        if path.value.as_str().is_empty() {
602            let msg = "import path cannot be empty";
603            self.dcx().err(msg).span(path.span).emit();
604        }
605        self.expect_semi()?;
606        Ok(ImportDirective { path, items })
607    }
608
609    /// Parses an optional `as` alias identifier.
610    fn parse_as_alias_opt(&mut self) -> PResult<'sess, Option<Ident>> {
611        if self.eat_keyword(kw::As) { self.parse_ident().map(Some) } else { Ok(None) }
612    }
613
614    /// Parses an `as` alias identifier.
615    fn parse_as_alias(&mut self) -> PResult<'sess, Ident> {
616        self.expect_keyword(kw::As)?;
617        self.parse_ident()
618    }
619
620    /// Parses a using directive.
621    fn parse_using(&mut self) -> PResult<'sess, UsingDirective<'ast>> {
622        let list = self.parse_using_list()?;
623        self.expect_keyword(kw::For)?;
624        let ty = if self.eat(TokenKind::BinOp(BinOpToken::Star)) {
625            None
626        } else {
627            Some(self.parse_type()?)
628        };
629        let global = self.eat_keyword(sym::global);
630        self.expect_semi()?;
631        Ok(UsingDirective { list, ty, global })
632    }
633
634    fn parse_using_list(&mut self) -> PResult<'sess, UsingList<'ast>> {
635        if self.check(TokenKind::OpenDelim(Delimiter::Brace)) {
636            self.parse_delim_comma_seq(Delimiter::Brace, false, |this| {
637                let path = this.parse_path()?;
638                let op = if this.eat_keyword(kw::As) {
639                    Some(this.parse_user_definable_operator()?)
640                } else {
641                    None
642                };
643                Ok((path, op))
644            })
645            .map(UsingList::Multiple)
646        } else {
647            self.parse_path().map(UsingList::Single)
648        }
649    }
650
651    fn parse_user_definable_operator(&mut self) -> PResult<'sess, UserDefinableOperator> {
652        use BinOpToken::*;
653        use TokenKind::*;
654        use UserDefinableOperator as Op;
655        macro_rules! user_op {
656            ($($tok1:tt $(($tok2:tt))? => $op:expr),* $(,)?) => {
657                match self.token.kind {
658                    $($tok1 $(($tok2))? => $op,)*
659                    _ => {
660                        self.expected_tokens.extend_from_slice(&[$(ExpectedToken::Token($tok1 $(($tok2))?)),*]);
661                        return self.unexpected();
662                    }
663                }
664            };
665        }
666        let op = user_op! {
667            BinOp(And) => Op::BitAnd,
668            Tilde => Op::BitNot,
669            BinOp(Or) => Op::BitOr,
670            BinOp(Caret) => Op::BitXor,
671            BinOp(Plus) => Op::Add,
672            BinOp(Slash) => Op::Div,
673            BinOp(Percent) => Op::Rem,
674            BinOp(Star) => Op::Mul,
675            BinOp(Minus) => Op::Sub,
676            EqEq => Op::Eq,
677            Ge => Op::Ge,
678            Gt => Op::Gt,
679            Le => Op::Le,
680            Lt => Op::Lt,
681            Ne => Op::Ne,
682        };
683        self.bump();
684        Ok(op)
685    }
686
687    /* ----------------------------------------- Common ----------------------------------------- */
688
689    /// Parses a variable declaration/definition.
690    ///
691    /// `state-variable-declaration`, `constant-variable-declaration`, `variable-declaration`,
692    /// `variable-declaration-statement`, and more.
693    pub(super) fn parse_variable_definition(
694        &mut self,
695        flags: VarFlags,
696    ) -> PResult<'sess, VariableDefinition<'ast>> {
697        self.parse_variable_definition_with(flags, None)
698    }
699
700    pub(super) fn parse_variable_definition_with(
701        &mut self,
702        flags: VarFlags,
703        ty: Option<Type<'ast>>,
704    ) -> PResult<'sess, VariableDefinition<'ast>> {
705        let mut lo = self.token.span;
706        let ty = match ty {
707            Some(ty) => {
708                lo = lo.with_lo(ty.span.lo());
709                ty
710            }
711            None => self.parse_type()?,
712        };
713
714        if ty.is_function()
715            && flags == VarFlags::STATE_VAR
716            && self.check_noexpect(TokenKind::OpenDelim(Delimiter::Brace))
717        {
718            let msg = "expected a state variable declaration";
719            let note = "this style of fallback function has been removed; use the `fallback` or `receive` keywords instead";
720            self.dcx().err(msg).span(self.token.span).note(note).emit();
721            let _ = self.parse_block()?;
722            return Ok(VariableDefinition {
723                span: lo.to(self.prev_token.span),
724                ty,
725                visibility: None,
726                mutability: None,
727                data_location: None,
728                override_: None,
729                indexed: false,
730                name: None,
731                initializer: None,
732            });
733        }
734
735        let mut data_location = None;
736        let mut visibility = None;
737        let mut mutability = None;
738        let mut override_ = None;
739        let mut indexed = false;
740        loop {
741            if let Some(s) = self.parse_data_location() {
742                if !flags.contains(VarFlags::DATALOC) {
743                    let msg = "data locations are not allowed here";
744                    self.dcx().err(msg).span(self.prev_token.span).emit();
745                } else if data_location.is_some() {
746                    let msg = "data location already specified";
747                    self.dcx().err(msg).span(self.prev_token.span).emit();
748                } else {
749                    data_location = Some(s);
750                }
751            } else if let Some(v) = self.parse_visibility() {
752                if !flags.contains(VarFlags::from_visibility(v)) {
753                    let msg = visibility_error(v, flags.visibilities());
754                    self.dcx().err(msg).span(self.prev_token.span).emit();
755                } else if visibility.is_some() {
756                    let msg = "visibility already specified";
757                    self.dcx().err(msg).span(self.prev_token.span).emit();
758                } else {
759                    visibility = Some(v);
760                }
761            } else if let Some(m) = self.parse_variable_mutability() {
762                // `CONSTANT_VAR` is special cased later.
763                if flags != VarFlags::CONSTANT_VAR && !flags.contains(VarFlags::from_varmut(m)) {
764                    let msg = varmut_error(m, flags.varmuts());
765                    self.dcx().err(msg).span(self.prev_token.span).emit();
766                } else if mutability.is_some() {
767                    let msg = "mutability already specified";
768                    self.dcx().err(msg).span(self.prev_token.span).emit();
769                } else {
770                    mutability = Some(m);
771                }
772            } else if self.eat_keyword(kw::Indexed) {
773                if !flags.contains(VarFlags::INDEXED) {
774                    let msg = "`indexed` is not allowed here";
775                    self.dcx().err(msg).span(self.prev_token.span).emit();
776                } else if indexed {
777                    let msg = "`indexed` already specified";
778                    self.dcx().err(msg).span(self.prev_token.span).emit();
779                } else {
780                    indexed = true;
781                }
782            } else if self.eat_keyword(kw::Virtual) {
783                let msg = "`virtual` is not allowed here";
784                self.dcx().err(msg).span(self.prev_token.span).emit();
785            } else if self.eat_keyword(kw::Override) {
786                let o = self.parse_override()?;
787                if !flags.contains(VarFlags::OVERRIDE) {
788                    let msg = "`override` is not allowed here";
789                    self.dcx().err(msg).span(self.prev_token.span).emit();
790                } else if override_.is_some() {
791                    let msg = "override already specified";
792                    self.dcx().err(msg).span(self.prev_token.span).emit();
793                } else {
794                    override_ = Some(o);
795                }
796            } else {
797                break;
798            }
799        }
800
801        let name = if flags.contains(VarFlags::NAME) {
802            self.parse_ident().map(Some)
803        } else {
804            self.parse_ident_opt()
805        }?;
806        if let Some(name) = &name
807            && flags.contains(VarFlags::NAME_WARN)
808        {
809            debug_assert!(!flags.contains(VarFlags::NAME));
810            let msg = "named function type parameters are deprecated";
811            self.dcx().warn(msg).code(error_code!(6162)).span(name.span).emit();
812        }
813
814        let initializer = if flags.contains(VarFlags::INITIALIZER) && self.eat(TokenKind::Eq) {
815            Some(self.parse_expr()?)
816        } else {
817            None
818        };
819
820        if flags.contains(VarFlags::SEMI) {
821            self.expect_semi()?;
822        }
823
824        let span = lo.to(self.prev_token.span);
825
826        if mutability == Some(VarMut::Constant) && initializer.is_none() {
827            let msg = "constant variable must be initialized";
828            self.dcx().err(msg).span(span).emit();
829        }
830        if flags == VarFlags::CONSTANT_VAR && mutability != Some(VarMut::Constant) {
831            let msg = "only constant variables are allowed at file level";
832            self.dcx().err(msg).span(span).emit();
833        }
834
835        Ok(VariableDefinition {
836            span,
837            ty,
838            data_location,
839            visibility,
840            mutability,
841            override_,
842            indexed,
843            name,
844            initializer,
845        })
846    }
847
848    /// Parses mutability of a variable: `constant | immutable`.
849    fn parse_variable_mutability(&mut self) -> Option<VarMut> {
850        if self.eat_keyword(kw::Constant) {
851            Some(VarMut::Constant)
852        } else if self.eat_keyword(kw::Immutable) {
853            Some(VarMut::Immutable)
854        } else {
855            None
856        }
857    }
858
859    /// Parses a parameter list: `($(vardecl),*)`.
860    pub(super) fn parse_parameter_list(
861        &mut self,
862        allow_empty: bool,
863        flags: VarFlags,
864    ) -> PResult<'sess, ParameterList<'ast>> {
865        let lo = self.token.span;
866        let vars =
867            self.parse_paren_comma_seq(allow_empty, |this| this.parse_variable_definition(flags))?;
868        Ok(ParameterList { vars, span: lo.to(self.prev_token.span) })
869    }
870
871    /// Parses a list of inheritance specifiers.
872    fn parse_inheritance(&mut self) -> PResult<'sess, Box<'ast, [Modifier<'ast>]>> {
873        let mut list = SmallVec::<[_; 8]>::new();
874        loop {
875            list.push(self.parse_modifier()?);
876            if !self.eat(TokenKind::Comma) {
877                break;
878            }
879        }
880        Ok(self.alloc_smallvec(list))
881    }
882
883    /// Parses a storage layout specifier.
884    fn parse_storage_layout_specifier(&mut self) -> PResult<'sess, StorageLayoutSpecifier<'ast>> {
885        let lo = self.token.span;
886        self.expect_keyword(sym::layout)?;
887        self.expect_keyword(sym::at)?;
888        let slot = self.parse_expr()?;
889        Ok(StorageLayoutSpecifier { span: lo.to(self.prev_token.span), slot })
890    }
891
892    /// Parses a single modifier invocation.
893    fn parse_modifier(&mut self) -> PResult<'sess, Modifier<'ast>> {
894        let name = self.parse_path()?;
895        let arguments = if self.token.kind == TokenKind::OpenDelim(Delimiter::Parenthesis) {
896            self.parse_call_args()?
897        } else {
898            CallArgs::empty(name.span().shrink_to_hi())
899        };
900        Ok(Modifier { name, arguments })
901    }
902
903    /// Parses a single function override.
904    ///
905    /// Expects the `override` to have already been eaten.
906    fn parse_override(&mut self) -> PResult<'sess, Override<'ast>> {
907        debug_assert!(self.prev_token.is_keyword(kw::Override));
908        let lo = self.prev_token.span;
909        let paths = if self.token.is_open_delim(Delimiter::Parenthesis) {
910            self.parse_paren_comma_seq(false, Self::parse_path)?
911        } else {
912            Default::default()
913        };
914        let span = lo.to(self.prev_token.span);
915        Ok(Override { span, paths })
916    }
917
918    /// Parses a single string literal. This is only used in import paths and statements, not
919    /// expressions.
920    pub(super) fn parse_str_lit(&mut self) -> PResult<'sess, StrLit> {
921        match self.parse_str_lit_opt() {
922            Some(lit) => Ok(lit),
923            None => self.unexpected(),
924        }
925    }
926
927    /// Parses a single optional string literal. This is only used in import paths and statements,
928    /// not expressions.
929    pub(super) fn parse_str_lit_opt(&mut self) -> Option<StrLit> {
930        if !self.check_str_lit() {
931            return None;
932        }
933        let Token { kind: TokenKind::Literal(TokenLitKind::Str, symbol), span } = self.token else {
934            unreachable!()
935        };
936        self.bump();
937        Some(StrLit { span, value: symbol })
938    }
939
940    /// Parses a storage location: `storage | memory | calldata | transient`.
941    fn parse_data_location(&mut self) -> Option<DataLocation> {
942        if self.eat_keyword(kw::Storage) {
943            Some(DataLocation::Storage)
944        } else if self.eat_keyword(kw::Memory) {
945            Some(DataLocation::Memory)
946        } else if self.eat_keyword(kw::Calldata) {
947            Some(DataLocation::Calldata)
948        } else if self.check_keyword(sym::transient)
949            && !matches!(
950                self.look_ahead(1).kind,
951                TokenKind::Eq | TokenKind::Semi | TokenKind::CloseDelim(_) | TokenKind::Comma
952            )
953        {
954            self.bump(); // `transient`
955            Some(DataLocation::Transient)
956        } else {
957            None
958        }
959    }
960
961    /// Parses a visibility: `public | private | internal | external`.
962    pub(super) fn parse_visibility(&mut self) -> Option<Visibility> {
963        if self.eat_keyword(kw::Public) {
964            Some(Visibility::Public)
965        } else if self.eat_keyword(kw::Private) {
966            Some(Visibility::Private)
967        } else if self.eat_keyword(kw::Internal) {
968            Some(Visibility::Internal)
969        } else if self.eat_keyword(kw::External) {
970            Some(Visibility::External)
971        } else {
972            None
973        }
974    }
975
976    /// Parses state mutability: `payable | pure | view`.
977    pub(super) fn parse_state_mutability(&mut self) -> Option<StateMutability> {
978        if self.eat_keyword(kw::Payable) {
979            Some(StateMutability::Payable)
980        } else if self.eat_keyword(kw::Pure) {
981            Some(StateMutability::Pure)
982        } else if self.eat_keyword(kw::View) {
983            Some(StateMutability::View)
984        } else {
985            None
986        }
987    }
988}
989
990struct SemverVersionParser<'p, 'sess, 'ast> {
991    p: &'p mut Parser<'sess, 'ast>,
992    bumps: u32,
993    pos_inside: u32,
994}
995
996impl<'p, 'sess, 'ast> SemverVersionParser<'p, 'sess, 'ast> {
997    fn new(p: &'p mut Parser<'sess, 'ast>) -> Self {
998        Self { p, bumps: 0, pos_inside: 0 }
999    }
1000
1001    fn emit_err(&self, msg: impl Into<DiagMsg>) {
1002        self.p.dcx().err(msg).span(self.current_span()).emit();
1003    }
1004
1005    fn parse(mut self) -> SemverVersion {
1006        let lo = self.current_span();
1007        let major = self.parse_version_part();
1008        let mut minor = None;
1009        let mut patch = None;
1010        if self.eat_dot() {
1011            minor = Some(self.parse_version_part());
1012            if self.eat_dot() {
1013                patch = Some(self.parse_version_part());
1014            }
1015        }
1016        if self.pos_inside > 0 || self.bumps == 0 {
1017            self.emit_err("unexpected trailing characters");
1018            self.bump_token();
1019        }
1020        SemverVersion { span: lo.to(self.current_span()), major, minor, patch }
1021    }
1022
1023    fn eat_dot(&mut self) -> bool {
1024        let r = self.current_char() == Some('.');
1025        if r {
1026            self.bump_char();
1027        }
1028        r
1029    }
1030
1031    fn parse_version_part(&mut self) -> SemverVersionNumber {
1032        match self.current_char() {
1033            Some('*' | 'x' | 'X') => {
1034                self.bump_char();
1035                SemverVersionNumber::Wildcard
1036            }
1037            Some('0'..='9') => {
1038                let s = self.current_str().unwrap();
1039                let len = s.bytes().take_while(u8::is_ascii_digit).count();
1040                let result = s[..len].parse();
1041                self.bump_chars(len as u32);
1042                let Ok(n) = result else {
1043                    self.emit_err("version number too large");
1044                    return SemverVersionNumber::Wildcard;
1045                };
1046                SemverVersionNumber::Number(n)
1047            }
1048            _ => {
1049                self.emit_err("expected version number");
1050                self.bump_char();
1051                SemverVersionNumber::Wildcard
1052            }
1053        }
1054    }
1055
1056    fn current_char(&self) -> Option<char> {
1057        self.current_str()?.chars().next()
1058    }
1059
1060    fn current_str(&self) -> Option<&str> {
1061        self.current_token_str()?.get(self.pos_inside as usize..)
1062    }
1063
1064    fn current_token_str(&self) -> Option<&str> {
1065        Some(match &self.current_token().kind {
1066            TokenKind::Dot => ".",
1067            TokenKind::BinOp(BinOpToken::Star) => "*",
1068            TokenKind::Ident(s) | TokenKind::Literal(_, s) => s.as_str(),
1069            _ => return None,
1070        })
1071    }
1072
1073    fn current_token(&self) -> &Token {
1074        &self.p.token
1075    }
1076
1077    fn current_span(&self) -> Span {
1078        let mut s = self.current_token().span;
1079        if self.pos_inside > 0 {
1080            s = s.with_lo(s.lo() + self.pos_inside);
1081        }
1082        s
1083    }
1084
1085    fn bump_char(&mut self) {
1086        self.bump_chars(1);
1087    }
1088
1089    fn bump_chars(&mut self, n: u32) {
1090        if let Some(s) = self.current_token_str() {
1091            if self.pos_inside + n >= s.len() as u32 {
1092                self.bump_token();
1093            } else {
1094                self.pos_inside += n;
1095            }
1096        }
1097    }
1098
1099    fn bump_token(&mut self) {
1100        self.p.bump();
1101        self.bumps += 1;
1102        self.pos_inside = 0;
1103    }
1104}
1105
1106bitflags::bitflags! {
1107    /// Flags for parsing variable declarations.
1108    #[derive(Clone, Copy, PartialEq, Eq)]
1109    pub(super) struct VarFlags: u16 {
1110        // `ty` is always required. `name` is always optional, unless `NAME` is specified.
1111
1112        const DATALOC     = 1 << 1;
1113        const INDEXED     = 1 << 2;
1114
1115        const PRIVATE     = 1 << 3;
1116        const INTERNAL    = 1 << 4;
1117        const PUBLIC      = 1 << 5;
1118        const EXTERNAL    = 1 << 6; // Never accepted, just for error messages.
1119        const VISIBILITY  = Self::PRIVATE.bits()
1120                          | Self::INTERNAL.bits()
1121                          | Self::PUBLIC.bits()
1122                          | Self::EXTERNAL.bits();
1123
1124        const CONSTANT    = 1 << 7;
1125        const IMMUTABLE   = 1 << 8;
1126
1127        const OVERRIDE    = 1 << 9;
1128
1129        const NAME        = 1 << 10;
1130        const NAME_WARN   = 1 << 11;
1131
1132        const INITIALIZER = 1 << 12;
1133        const SEMI        = 1 << 13;
1134
1135        const STRUCT       = Self::NAME.bits();
1136        const ERROR        = 0;
1137        const EVENT        = Self::INDEXED.bits();
1138        const FUNCTION     = Self::DATALOC.bits();
1139        const FUNCTION_TY  = Self::DATALOC.bits() | Self::NAME_WARN.bits();
1140
1141        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.stateVariableDeclaration
1142        const STATE_VAR    = Self::DATALOC.bits()
1143                           | Self::PRIVATE.bits()
1144                           | Self::INTERNAL.bits()
1145                           | Self::PUBLIC.bits()
1146                           | Self::CONSTANT.bits()
1147                           | Self::IMMUTABLE.bits()
1148                           | Self::OVERRIDE.bits()
1149                           | Self::NAME.bits()
1150                           | Self::INITIALIZER.bits()
1151                           | Self::SEMI.bits();
1152
1153        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.constantVariableDeclaration
1154        const CONSTANT_VAR = Self::CONSTANT.bits()
1155                           | Self::NAME.bits()
1156                           | Self::INITIALIZER.bits()
1157                           | Self::SEMI.bits();
1158
1159        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.variableDeclarationStatement
1160        const VAR = Self::DATALOC.bits() | Self::INITIALIZER.bits();
1161    }
1162
1163    /// Flags for parsing function headers.
1164    #[derive(Clone, Copy, PartialEq, Eq)]
1165    pub(super) struct FunctionFlags: u16 {
1166        /// Name is required.
1167        const NAME             = 1 << 0;
1168        /// Function type: parameter names are parsed, but issue a warning.
1169        const PARAM_NAME       = 1 << 1;
1170        /// Parens can be omitted.
1171        const NO_PARENS        = 1 << 2;
1172
1173        // Visibility
1174        const PRIVATE          = 1 << 3;
1175        const INTERNAL         = 1 << 4;
1176        const PUBLIC           = 1 << 5;
1177        const EXTERNAL         = 1 << 6;
1178        const VISIBILITY       = Self::PRIVATE.bits()
1179                               | Self::INTERNAL.bits()
1180                               | Self::PUBLIC.bits()
1181                               | Self::EXTERNAL.bits();
1182
1183        // StateMutability
1184        const PURE             = 1 << 7;
1185        const VIEW             = 1 << 8;
1186        const PAYABLE          = 1 << 9;
1187        const STATE_MUTABILITY = Self::PURE.bits()
1188                               | Self::VIEW.bits()
1189                               | Self::PAYABLE.bits();
1190
1191        const MODIFIERS        = 1 << 10;
1192        const VIRTUAL          = 1 << 11;
1193        const OVERRIDE         = 1 << 12;
1194
1195        const RETURNS          = 1 << 13;
1196        /// Must be implemented, meaning it must end in a `{}` implementation block.
1197        const ONLY_BLOCK       = 1 << 14;
1198
1199        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.constructorDefinition
1200        const CONSTRUCTOR = Self::MODIFIERS.bits()
1201                          | Self::PAYABLE.bits()
1202                          | Self::INTERNAL.bits()
1203                          | Self::PUBLIC.bits()
1204                          | Self::ONLY_BLOCK.bits();
1205
1206        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.functionDefinition
1207        const FUNCTION    = Self::NAME.bits()
1208                          | Self::VISIBILITY.bits()
1209                          | Self::STATE_MUTABILITY.bits()
1210                          | Self::MODIFIERS.bits()
1211                          | Self::VIRTUAL.bits()
1212                          | Self::OVERRIDE.bits()
1213                          | Self::RETURNS.bits();
1214
1215        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.modifierDefinition
1216        const MODIFIER    = Self::NAME.bits()
1217                          | Self::NO_PARENS.bits()
1218                          | Self::VIRTUAL.bits()
1219                          | Self::OVERRIDE.bits();
1220
1221        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.fallbackFunctionDefinition
1222        const FALLBACK    = Self::EXTERNAL.bits()
1223                          | Self::STATE_MUTABILITY.bits()
1224                          | Self::MODIFIERS.bits()
1225                          | Self::VIRTUAL.bits()
1226                          | Self::OVERRIDE.bits()
1227                          | Self::RETURNS.bits();
1228
1229        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.receiveFunctionDefinition
1230        const RECEIVE     = Self::EXTERNAL.bits()
1231                          | Self::PAYABLE.bits()
1232                          | Self::MODIFIERS.bits()
1233                          | Self::VIRTUAL.bits()
1234                          | Self::OVERRIDE.bits();
1235
1236        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.functionTypeName
1237        const FUNCTION_TY = Self::PARAM_NAME.bits()
1238                          | Self::VISIBILITY.bits()
1239                          | Self::STATE_MUTABILITY.bits()
1240                          | Self::RETURNS.bits();
1241    }
1242}
1243
1244impl VarFlags {
1245    fn from_visibility(v: Visibility) -> Self {
1246        match v {
1247            Visibility::Private => Self::PRIVATE,
1248            Visibility::Internal => Self::INTERNAL,
1249            Visibility::Public => Self::PUBLIC,
1250            Visibility::External => Self::EXTERNAL,
1251        }
1252    }
1253
1254    fn into_visibility(self) -> Option<Visibility> {
1255        match self {
1256            Self::PRIVATE => Some(Visibility::Private),
1257            Self::INTERNAL => Some(Visibility::Internal),
1258            Self::PUBLIC => Some(Visibility::Public),
1259            Self::EXTERNAL => Some(Visibility::External),
1260            _ => None,
1261        }
1262    }
1263
1264    fn visibilities(self) -> Option<impl Iterator<Item = Visibility>> {
1265        self.supported(Self::VISIBILITY).map(|iter| iter.map(|x| x.into_visibility().unwrap()))
1266    }
1267
1268    fn from_varmut(v: VarMut) -> Self {
1269        match v {
1270            VarMut::Constant => Self::CONSTANT,
1271            VarMut::Immutable => Self::IMMUTABLE,
1272        }
1273    }
1274
1275    fn into_varmut(self) -> Option<VarMut> {
1276        match self {
1277            Self::CONSTANT => Some(VarMut::Constant),
1278            Self::IMMUTABLE => Some(VarMut::Immutable),
1279            _ => None,
1280        }
1281    }
1282
1283    fn varmuts(self) -> Option<impl Iterator<Item = VarMut>> {
1284        self.supported(Self::CONSTANT | Self::IMMUTABLE)
1285            .map(|iter| iter.map(|x| x.into_varmut().unwrap()))
1286    }
1287
1288    fn supported(self, what: Self) -> Option<impl Iterator<Item = Self>> {
1289        let s = self.intersection(what);
1290        if s.is_empty() { None } else { Some(s.iter()) }
1291    }
1292}
1293
1294impl FunctionFlags {
1295    fn from_kind(kind: FunctionKind) -> Self {
1296        match kind {
1297            FunctionKind::Constructor => Self::CONSTRUCTOR,
1298            FunctionKind::Function => Self::FUNCTION,
1299            FunctionKind::Modifier => Self::MODIFIER,
1300            FunctionKind::Receive => Self::RECEIVE,
1301            FunctionKind::Fallback => Self::FALLBACK,
1302        }
1303    }
1304
1305    fn from_visibility(visibility: Visibility) -> Self {
1306        match visibility {
1307            Visibility::Private => Self::PRIVATE,
1308            Visibility::Internal => Self::INTERNAL,
1309            Visibility::Public => Self::PUBLIC,
1310            Visibility::External => Self::EXTERNAL,
1311        }
1312    }
1313
1314    fn into_visibility(self) -> Option<Visibility> {
1315        match self {
1316            Self::PRIVATE => Some(Visibility::Private),
1317            Self::INTERNAL => Some(Visibility::Internal),
1318            Self::PUBLIC => Some(Visibility::Public),
1319            Self::EXTERNAL => Some(Visibility::External),
1320            _ => None,
1321        }
1322    }
1323
1324    fn visibilities(self) -> Option<impl Iterator<Item = Visibility>> {
1325        self.supported(Self::VISIBILITY).map(|iter| iter.map(|x| x.into_visibility().unwrap()))
1326    }
1327
1328    fn from_state_mutability(state_mutability: StateMutability) -> Self {
1329        match state_mutability {
1330            StateMutability::Pure => Self::PURE,
1331            StateMutability::View => Self::VIEW,
1332            StateMutability::Payable => Self::PAYABLE,
1333            StateMutability::NonPayable => unreachable!("NonPayable should not be parsed"),
1334        }
1335    }
1336
1337    fn into_state_mutability(self) -> Option<StateMutability> {
1338        match self {
1339            Self::PURE => Some(StateMutability::Pure),
1340            Self::VIEW => Some(StateMutability::View),
1341            Self::PAYABLE => Some(StateMutability::Payable),
1342            _ => None,
1343        }
1344    }
1345
1346    fn state_mutabilities(self) -> Option<impl Iterator<Item = StateMutability>> {
1347        self.supported(Self::STATE_MUTABILITY)
1348            .map(|iter| iter.map(|x| x.into_state_mutability().unwrap()))
1349    }
1350
1351    fn supported(self, what: Self) -> Option<impl Iterator<Item = Self>> {
1352        let s = self.intersection(what);
1353        if s.is_empty() { None } else { Some(s.iter()) }
1354    }
1355}
1356
1357fn visibility_error(v: Visibility, iter: Option<impl Iterator<Item = Visibility>>) -> String {
1358    common_flags_error(v, "visibility", iter)
1359}
1360
1361fn varmut_error(m: VarMut, iter: Option<impl Iterator<Item = VarMut>>) -> String {
1362    common_flags_error(m, "mutability", iter)
1363}
1364
1365fn state_mutability_error(
1366    m: StateMutability,
1367    iter: Option<impl Iterator<Item = StateMutability>>,
1368) -> String {
1369    common_flags_error(m, "state mutability", iter)
1370}
1371
1372fn common_flags_error<T: std::fmt::Display>(
1373    t: T,
1374    desc: &str,
1375    iter: Option<impl Iterator<Item = T>>,
1376) -> String {
1377    match iter {
1378        Some(iter) => format!("`{t}` not allowed here; allowed values: {}", iter.format(", ")),
1379        None => format!("{desc} is not allowed here"),
1380    }
1381}
1382
1383#[cfg(test)]
1384mod tests {
1385    use super::*;
1386    use solar_interface::{Result, Session, source_map::FileName};
1387
1388    fn assert_version_matches(tests: &[(&str, &str, bool)]) {
1389        let sess = Session::builder().with_test_emitter().build();
1390        sess.enter(|| -> Result {
1391            for (i, &(v, req_s, res)) in tests.iter().enumerate() {
1392                let name = i.to_string();
1393                let src = format!("{v} {req_s}");
1394                let arena = Arena::new();
1395                let mut parser =
1396                    Parser::from_source_code(&sess, &arena, FileName::Custom(name), src)?;
1397
1398                let version = parser.parse_semver_version().map_err(|e| e.emit()).unwrap();
1399                assert_eq!(version.to_string(), v);
1400                let req: SemverReq<'_> = parser.parse_semver_req().map_err(|e| e.emit()).unwrap();
1401                sess.dcx.has_errors().unwrap();
1402                assert_eq!(req.matches(&version), res, "v={v:?}, req={req_s:?}");
1403            }
1404            Ok(())
1405        })
1406        .unwrap();
1407    }
1408
1409    #[test]
1410    fn semver_matches() {
1411        assert_version_matches(&[
1412            // none = eq
1413            ("0.8.1", "0", true),
1414            ("0.8.1", "1", false),
1415            ("0.8.1", "1.0", false),
1416            ("0.8.1", "1.0.0", false),
1417            ("0.8.1", "0.7", false),
1418            ("0.8.1", "0.7.0", false),
1419            ("0.8.1", "0.7.1", false),
1420            ("0.8.1", "0.7.2", false),
1421            ("0.8.1", "0.8", true),
1422            ("0.8.1", "0.8.0", false),
1423            ("0.8.1", "0.8.1", true),
1424            ("0.8.1", "0.8.2", false),
1425            ("0.8.1", "0.9", false),
1426            ("0.8.1", "0.9.0", false),
1427            ("0.8.1", "0.9.1", false),
1428            ("0.8.1", "0.9.2", false),
1429            // eq
1430            ("0.8.1", "=0", true),
1431            ("0.8.1", "=1", false),
1432            ("0.8.1", "=1.0", false),
1433            ("0.8.1", "=1.0.0", false),
1434            ("0.8.1", "=0.7", false),
1435            ("0.8.1", "=0.7.0", false),
1436            ("0.8.1", "=0.7.1", false),
1437            ("0.8.1", "=0.7.2", false),
1438            ("0.8.1", "=0.8", true),
1439            ("0.8.1", "=0.8.0", false),
1440            ("0.8.1", "=0.8.1", true),
1441            ("0.8.1", "=0.8.2", false),
1442            ("0.8.1", "=0.9", false),
1443            ("0.8.1", "=0.9.0", false),
1444            ("0.8.1", "=0.9.1", false),
1445            ("0.8.1", "=0.9.2", false),
1446            // gt
1447            ("0.8.1", ">0", false),
1448            ("0.8.1", ">1", false),
1449            ("0.8.1", ">1.0", false),
1450            ("0.8.1", ">1.0.0", false),
1451            ("0.8.1", ">0.7", true),
1452            ("0.8.1", ">0.7.0", true),
1453            ("0.8.1", ">0.7.1", true),
1454            ("0.8.1", ">0.7.2", true),
1455            ("0.8.1", ">0.8", false),
1456            ("0.8.1", ">0.8.0", true),
1457            ("0.8.1", ">0.8.1", false),
1458            ("0.8.1", ">0.8.2", false),
1459            ("0.8.1", ">0.9", false),
1460            ("0.8.1", ">0.9.0", false),
1461            ("0.8.1", ">0.9.1", false),
1462            ("0.8.1", ">0.9.2", false),
1463            // ge
1464            ("0.8.1", ">=0", true),
1465            ("0.8.1", ">=1", false),
1466            ("0.8.1", ">=1.0", false),
1467            ("0.8.1", ">=1.0.0", false),
1468            ("0.8.1", ">=0.7", true),
1469            ("0.8.1", ">=0.7.0", true),
1470            ("0.8.1", ">=0.7.1", true),
1471            ("0.8.1", ">=0.7.2", true),
1472            ("0.8.1", ">=0.8", true),
1473            ("0.8.1", ">=0.8.0", true),
1474            ("0.8.1", ">=0.8.1", true),
1475            ("0.8.1", ">=0.8.2", false),
1476            ("0.8.1", ">=0.9", false),
1477            ("0.8.1", ">=0.9.0", false),
1478            ("0.8.1", ">=0.9.1", false),
1479            ("0.8.1", ">=0.9.2", false),
1480            // lt
1481            ("0.8.1", "<0", false),
1482            ("0.8.1", "<1", true),
1483            ("0.8.1", "<1.0", true),
1484            ("0.8.1", "<1.0.0", true),
1485            ("0.8.1", "<0.7", false),
1486            ("0.8.1", "<0.7.0", false),
1487            ("0.8.1", "<0.7.1", false),
1488            ("0.8.1", "<0.7.2", false),
1489            ("0.8.1", "<0.8", false),
1490            ("0.8.1", "<0.8.0", false),
1491            ("0.8.1", "<0.8.1", false),
1492            ("0.8.1", "<0.8.2", true),
1493            ("0.8.1", "<0.9", true),
1494            ("0.8.1", "<0.9.0", true),
1495            ("0.8.1", "<0.9.1", true),
1496            ("0.8.1", "<0.9.2", true),
1497            // le
1498            ("0.8.1", "<=0", true),
1499            ("0.8.1", "<=1", true),
1500            ("0.8.1", "<=1.0", true),
1501            ("0.8.1", "<=1.0.0", true),
1502            ("0.8.1", "<=0.7", false),
1503            ("0.8.1", "<=0.7.0", false),
1504            ("0.8.1", "<=0.7.1", false),
1505            ("0.8.1", "<=0.7.2", false),
1506            ("0.8.1", "<=0.8", true),
1507            ("0.8.1", "<=0.8.0", false),
1508            ("0.8.1", "<=0.8.1", true),
1509            ("0.8.1", "<=0.8.2", true),
1510            ("0.8.1", "<=0.9.0", true),
1511            ("0.8.1", "<=0.9.1", true),
1512            ("0.8.1", "<=0.9.2", true),
1513            // tilde
1514            ("0.8.1", "~0", true),
1515            ("0.8.1", "~1", false),
1516            ("0.8.1", "~1.0", false),
1517            ("0.8.1", "~1.0.0", false),
1518            ("0.8.1", "~0.7", false),
1519            ("0.8.1", "~0.7.0", false),
1520            ("0.8.1", "~0.7.1", false),
1521            ("0.8.1", "~0.7.2", false),
1522            ("0.8.1", "~0.8", true),
1523            ("0.8.1", "~0.8.0", true),
1524            ("0.8.1", "~0.8.1", true),
1525            ("0.8.1", "~0.8.2", false),
1526            ("0.8.1", "~0.9.0", false),
1527            ("0.8.1", "~0.9.1", false),
1528            ("0.8.1", "~0.9.2", false),
1529            // caret
1530            ("0.8.1", "^0", true),
1531            ("0.8.1", "^1", false),
1532            ("0.8.1", "^1.0", false),
1533            ("0.8.1", "^1.0.0", false),
1534            ("0.8.1", "^0.7", false),
1535            ("0.8.1", "^0.7.0", false),
1536            ("0.8.1", "^0.7.1", false),
1537            ("0.8.1", "^0.7.2", false),
1538            ("0.8.1", "^0.8", true),
1539            ("0.8.1", "^0.8.0", true),
1540            ("0.8.1", "^0.8.1", true),
1541            ("0.8.1", "^0.8.2", false),
1542            ("0.8.1", "^0.9.0", false),
1543            ("0.8.1", "^0.9.1", false),
1544            ("0.8.1", "^0.9.2", false),
1545            // ranges
1546            ("0.8.1", "0 - 1", true),
1547            ("0.8.1", "0.1 - 1.1", true),
1548            ("0.8.1", "0.1.1 - 1.1.1", true),
1549            ("0.8.1", "0 - 0.8.1", true),
1550            ("0.8.1", "0 - 0.8.2", true),
1551            ("0.8.1", "0.7 - 0.8.1", true),
1552            ("0.8.1", "0.7 - 0.8.2", true),
1553            ("0.8.1", "0.8 - 0.8.1", true),
1554            ("0.8.1", "0.8 - 0.8.2", true),
1555            ("0.8.1", "0.8.0 - 0.8.1", true),
1556            ("0.8.1", "0.8.0 - 0.8.2", true),
1557            ("0.8.1", "0.8.0 - 0.9.0", true),
1558            ("0.8.1", "0.8.0 - 1.0.0", true),
1559            ("0.8.1", "0.8.1 - 0.8.1", true),
1560            ("0.8.1", "0.8.1 - 0.8.2", true),
1561            ("0.8.1", "0.8.1 - 0.9.0", true),
1562            ("0.8.1", "0.8.1 - 1.0.0", true),
1563            ("0.8.1", "0.7 - 0.8", true),
1564            ("0.8.1", "0.7.0 - 0.8", true),
1565            ("0.8.1", "0.8 - 0.8", true),
1566            ("0.8.1", "0.8.0 - 0.8", true),
1567            ("0.8.1", "0.8 - 0.8.0", false),
1568            ("0.8.1", "0.8 - 0.8.1", true),
1569            // or
1570            ("0.8.1", "0 || 0", true),
1571            ("0.8.1", "0 || 1", true),
1572            ("0.8.1", "1 || 0", true),
1573            ("0.8.1", "0.0 || 0.0", false),
1574            ("0.8.1", "0.0 || 1.0", false),
1575            ("0.8.1", "1.0 || 0.0", false),
1576            ("0.8.1", "0.7 || 0.8", true),
1577            ("0.8.1", "0.8 || 0.8", true),
1578            ("0.8.1", "0.8 || 0.8.1", true),
1579            ("0.8.1", "0.8 || 0.8.2", true),
1580            ("0.8.1", "0.8 || 0.9", true),
1581        ]);
1582    }
1583
1584    #[test]
1585    /// Test if the span of a function header is correct (should start at the function-like kw and
1586    /// end at the last token)
1587    fn function_header_span() {
1588        let test_functions = [
1589            "function foo(uint256 a) public view returns (uint256) {
1590}",
1591            "modifier foo() {
1592    _;
1593}",
1594            "receive() external payable {
1595}",
1596            "fallback() external payable {
1597}",
1598            "constructor() {
1599}",
1600        ];
1601
1602        let test_function_headers = [
1603            "function foo(uint256 a) public view returns (uint256)",
1604            "modifier foo()",
1605            "receive() external payable",
1606            "fallback() external payable",
1607            "constructor()",
1608        ];
1609
1610        for (idx, src) in test_functions.iter().enumerate() {
1611            let sess = Session::builder().with_test_emitter().build();
1612            sess.enter(|| -> Result {
1613                let arena = Arena::new();
1614                let mut parser = Parser::from_source_code(
1615                    &sess,
1616                    &arena,
1617                    FileName::Custom(String::from("test")),
1618                    *src,
1619                )?;
1620
1621                parser.in_contract = true; // Silence the wrong scope error
1622
1623                let header_span = parser.parse_function().unwrap().header.span;
1624
1625                assert_eq!(
1626                    header_span,
1627                    Span::new(
1628                        solar_interface::BytePos(0),
1629                        solar_interface::BytePos(test_function_headers[idx].len() as u32,),
1630                    ),
1631                );
1632
1633                Ok(())
1634            })
1635            .unwrap();
1636        }
1637    }
1638
1639    #[test]
1640    /// Test if the individual spans in function headers are correct
1641    fn function_header_field_spans() {
1642        let test_cases = vec![
1643            ("function foo() public {}", Some("public"), None, None, "()", None),
1644            ("function foo() private view {}", Some("private"), Some("view"), None, "()", None),
1645            (
1646                "function foo() internal pure returns (uint) {}",
1647                Some("internal"),
1648                Some("pure"),
1649                None,
1650                "()",
1651                Some("(uint)"),
1652            ),
1653            (
1654                "function foo() external payable {}",
1655                Some("external"),
1656                Some("payable"),
1657                None,
1658                "()",
1659                None,
1660            ),
1661            ("function foo() pure {}", None, Some("pure"), None, "()", None),
1662            ("function foo() view {}", None, Some("view"), None, "()", None),
1663            ("function foo() payable {}", None, Some("payable"), None, "()", None),
1664            ("function foo() {}", None, None, None, "()", None),
1665            ("function foo(uint a) {}", None, None, None, "(uint a)", None),
1666            ("function foo(uint a, string b) {}", None, None, None, "(uint a, string b)", None),
1667            ("function foo() returns (uint) {}", None, None, None, "()", Some("(uint)")),
1668            (
1669                "function foo() returns (uint, bool) {}",
1670                None,
1671                None,
1672                None,
1673                "()",
1674                Some("(uint, bool)"),
1675            ),
1676            (
1677                "function foo(uint x) public view returns (bool) {}",
1678                Some("public"),
1679                Some("view"),
1680                None,
1681                "(uint x)",
1682                Some("(bool)"),
1683            ),
1684            ("function foo() public virtual {}", Some("public"), None, Some("virtual"), "()", None),
1685            ("function foo() virtual public {}", Some("public"), None, Some("virtual"), "()", None),
1686            (
1687                "function foo() public virtual view {}",
1688                Some("public"),
1689                Some("view"),
1690                Some("virtual"),
1691                "()",
1692                None,
1693            ),
1694            ("function foo() virtual override {}", None, None, Some("virtual"), "()", None),
1695            ("modifier bar() virtual {}", None, None, Some("virtual"), "()", None),
1696            (
1697                "function foo() public virtual returns (uint) {}",
1698                Some("public"),
1699                None,
1700                Some("virtual"),
1701                "()",
1702                Some("(uint)"),
1703            ),
1704        ];
1705
1706        let sess = Session::builder().with_test_emitter().build();
1707        sess.enter(|| -> Result {
1708            for (idx, (src, vis, sm, virt, params, returns)) in test_cases.iter().enumerate() {
1709                let arena = Arena::new();
1710                let mut parser = Parser::from_source_code(
1711                    &sess,
1712                    &arena,
1713                    FileName::Custom(format!("test_{idx}")),
1714                    *src,
1715                )?;
1716                parser.in_contract = true;
1717
1718                let func = parser.parse_function().unwrap();
1719                let header = &func.header;
1720
1721                if let Some(expected) = vis {
1722                    let vis_span = header.visibility.as_ref().expect("Expected visibility").span;
1723                    let vis_text = sess.source_map().span_to_snippet(vis_span).unwrap();
1724                    assert_eq!(vis_text, *expected, "Test {idx}: visibility span mismatch");
1725                }
1726                if let Some(expected) = sm
1727                    && let Some(state_mutability) = header.state_mutability
1728                {
1729                    assert_eq!(
1730                        *expected,
1731                        sess.source_map().span_to_snippet(state_mutability.span).unwrap(),
1732                        "Test {idx}: state mutability span mismatch",
1733                    );
1734                }
1735                if let Some(expected) = virt {
1736                    let virtual_span = header.virtual_.expect("Expected virtual span");
1737                    let virtual_text = sess.source_map().span_to_snippet(virtual_span).unwrap();
1738                    assert_eq!(virtual_text, *expected, "Test {idx}: virtual span mismatch");
1739                }
1740                let span = header.parameters.span;
1741                assert_eq!(
1742                    *params,
1743                    sess.source_map().span_to_snippet(span).unwrap(),
1744                    "Test {idx}: params span mismatch"
1745                );
1746                if let Some(expected) = returns {
1747                    let span = header.returns.as_ref().expect("Expected returns").span;
1748                    assert_eq!(
1749                        *expected,
1750                        sess.source_map().span_to_snippet(span).unwrap(),
1751                        "Test {idx}: returns span mismatch",
1752                    );
1753                }
1754            }
1755            Ok(())
1756        })
1757        .unwrap();
1758    }
1759}