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, BoxSlice<'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/argotorg/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 TokenRepr { 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_label(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_label(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_label(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_label(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::<BoxSlice<'_, 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_label(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_label(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, BoxSlice<'ast, SemverReqCon<'ast>>> {
489        // https://github.com/argotorg/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.as_slice()),
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/argotorg/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/argotorg/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, BoxSlice<'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 TokenRepr { kind: TokenKind::Literal(TokenLitKind::Str, symbol), span } = *self.token
934        else {
935            unreachable!()
936        };
937        self.bump();
938        Some(StrLit { span, value: symbol })
939    }
940
941    /// Parses a storage location: `storage | memory | calldata | transient`.
942    fn parse_data_location(&mut self) -> Option<DataLocation> {
943        if self.eat_keyword(kw::Storage) {
944            Some(DataLocation::Storage)
945        } else if self.eat_keyword(kw::Memory) {
946            Some(DataLocation::Memory)
947        } else if self.eat_keyword(kw::Calldata) {
948            Some(DataLocation::Calldata)
949        } else if self.check_keyword(sym::transient)
950            && !matches!(
951                self.look_ahead(1).kind,
952                TokenKind::Eq | TokenKind::Semi | TokenKind::CloseDelim(_) | TokenKind::Comma
953            )
954        {
955            self.bump(); // `transient`
956            Some(DataLocation::Transient)
957        } else {
958            None
959        }
960    }
961
962    /// Parses a visibility: `public | private | internal | external`.
963    pub(super) fn parse_visibility(&mut self) -> Option<Visibility> {
964        if self.eat_keyword(kw::Public) {
965            Some(Visibility::Public)
966        } else if self.eat_keyword(kw::Private) {
967            Some(Visibility::Private)
968        } else if self.eat_keyword(kw::Internal) {
969            Some(Visibility::Internal)
970        } else if self.eat_keyword(kw::External) {
971            Some(Visibility::External)
972        } else {
973            None
974        }
975    }
976
977    /// Parses state mutability: `payable | pure | view`.
978    pub(super) fn parse_state_mutability(&mut self) -> Option<StateMutability> {
979        if self.eat_keyword(kw::Payable) {
980            Some(StateMutability::Payable)
981        } else if self.eat_keyword(kw::Pure) {
982            Some(StateMutability::Pure)
983        } else if self.eat_keyword(kw::View) {
984            Some(StateMutability::View)
985        } else {
986            None
987        }
988    }
989}
990
991struct SemverVersionParser<'p, 'sess, 'ast> {
992    p: &'p mut Parser<'sess, 'ast>,
993    bumps: u32,
994    pos_inside: u32,
995}
996
997impl<'p, 'sess, 'ast> SemverVersionParser<'p, 'sess, 'ast> {
998    fn new(p: &'p mut Parser<'sess, 'ast>) -> Self {
999        Self { p, bumps: 0, pos_inside: 0 }
1000    }
1001
1002    fn emit_err(&self, msg: impl Into<DiagMsg>) {
1003        self.p.dcx().err(msg).span(self.current_span()).emit();
1004    }
1005
1006    fn parse(mut self) -> SemverVersion {
1007        let lo = self.current_span();
1008        let major = self.parse_version_part();
1009        let mut minor = None;
1010        let mut patch = None;
1011        if self.eat_dot() {
1012            minor = Some(self.parse_version_part());
1013            if self.eat_dot() {
1014                patch = Some(self.parse_version_part());
1015            }
1016        }
1017        if self.pos_inside > 0 || self.bumps == 0 {
1018            self.emit_err("unexpected trailing characters");
1019            self.bump_token();
1020        }
1021        SemverVersion { span: lo.to(self.current_span()), major, minor, patch }
1022    }
1023
1024    fn eat_dot(&mut self) -> bool {
1025        let r = self.current_char() == Some('.');
1026        if r {
1027            self.bump_char();
1028        }
1029        r
1030    }
1031
1032    fn parse_version_part(&mut self) -> SemverVersionNumber {
1033        match self.current_char() {
1034            Some('*' | 'x' | 'X') => {
1035                self.bump_char();
1036                SemverVersionNumber::Wildcard
1037            }
1038            Some('0'..='9') => {
1039                let s = self.current_str().unwrap();
1040                let len = s.bytes().take_while(u8::is_ascii_digit).count();
1041                let result = s[..len].parse();
1042                self.bump_chars(len as u32);
1043                let Ok(n) = result else {
1044                    self.emit_err("version number too large");
1045                    return SemverVersionNumber::Wildcard;
1046                };
1047                SemverVersionNumber::Number(n)
1048            }
1049            _ => {
1050                self.emit_err("expected version number");
1051                self.bump_char();
1052                SemverVersionNumber::Wildcard
1053            }
1054        }
1055    }
1056
1057    fn current_char(&self) -> Option<char> {
1058        self.current_str()?.chars().next()
1059    }
1060
1061    fn current_str(&self) -> Option<&str> {
1062        self.current_token_str()?.get(self.pos_inside as usize..)
1063    }
1064
1065    fn current_token_str(&self) -> Option<&str> {
1066        Some(match &self.current_token().kind {
1067            TokenKind::Dot => ".",
1068            TokenKind::BinOp(BinOpToken::Star) => "*",
1069            TokenKind::Ident(s) | TokenKind::Literal(_, s) => s.as_str(),
1070            _ => return None,
1071        })
1072    }
1073
1074    fn current_token(&self) -> &Token {
1075        &self.p.token
1076    }
1077
1078    fn current_span(&self) -> Span {
1079        let mut s = self.current_token().span;
1080        if self.pos_inside > 0 {
1081            s = s.with_lo(s.lo() + self.pos_inside);
1082        }
1083        s
1084    }
1085
1086    fn bump_char(&mut self) {
1087        self.bump_chars(1);
1088    }
1089
1090    fn bump_chars(&mut self, n: u32) {
1091        if let Some(s) = self.current_token_str() {
1092            if self.pos_inside + n >= s.len() as u32 {
1093                self.bump_token();
1094            } else {
1095                self.pos_inside += n;
1096            }
1097        }
1098    }
1099
1100    fn bump_token(&mut self) {
1101        self.p.bump();
1102        self.bumps += 1;
1103        self.pos_inside = 0;
1104    }
1105}
1106
1107bitflags::bitflags! {
1108    /// Flags for parsing variable declarations.
1109    #[derive(Clone, Copy, PartialEq, Eq)]
1110    pub(super) struct VarFlags: u16 {
1111        // `ty` is always required. `name` is always optional, unless `NAME` is specified.
1112
1113        const DATALOC     = 1 << 1;
1114        const INDEXED     = 1 << 2;
1115
1116        const PRIVATE     = 1 << 3;
1117        const INTERNAL    = 1 << 4;
1118        const PUBLIC      = 1 << 5;
1119        const EXTERNAL    = 1 << 6; // Never accepted, just for error messages.
1120        const VISIBILITY  = Self::PRIVATE.bits()
1121                          | Self::INTERNAL.bits()
1122                          | Self::PUBLIC.bits()
1123                          | Self::EXTERNAL.bits();
1124
1125        const CONSTANT    = 1 << 7;
1126        const IMMUTABLE   = 1 << 8;
1127
1128        const OVERRIDE    = 1 << 9;
1129
1130        const NAME        = 1 << 10;
1131        const NAME_WARN   = 1 << 11;
1132
1133        const INITIALIZER = 1 << 12;
1134        const SEMI        = 1 << 13;
1135
1136        const STRUCT       = Self::NAME.bits();
1137        const ERROR        = 0;
1138        const EVENT        = Self::INDEXED.bits();
1139        const FUNCTION     = Self::DATALOC.bits();
1140        const FUNCTION_TY  = Self::DATALOC.bits() | Self::NAME_WARN.bits();
1141
1142        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.stateVariableDeclaration
1143        const STATE_VAR    = Self::DATALOC.bits()
1144                           | Self::PRIVATE.bits()
1145                           | Self::INTERNAL.bits()
1146                           | Self::PUBLIC.bits()
1147                           | Self::CONSTANT.bits()
1148                           | Self::IMMUTABLE.bits()
1149                           | Self::OVERRIDE.bits()
1150                           | Self::NAME.bits()
1151                           | Self::INITIALIZER.bits()
1152                           | Self::SEMI.bits();
1153
1154        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.constantVariableDeclaration
1155        const CONSTANT_VAR = Self::CONSTANT.bits()
1156                           | Self::NAME.bits()
1157                           | Self::INITIALIZER.bits()
1158                           | Self::SEMI.bits();
1159
1160        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.variableDeclarationStatement
1161        const VAR = Self::DATALOC.bits() | Self::INITIALIZER.bits();
1162    }
1163
1164    /// Flags for parsing function headers.
1165    #[derive(Clone, Copy, PartialEq, Eq)]
1166    pub(super) struct FunctionFlags: u16 {
1167        /// Name is required.
1168        const NAME             = 1 << 0;
1169        /// Function type: parameter names are parsed, but issue a warning.
1170        const PARAM_NAME       = 1 << 1;
1171        /// Parens can be omitted.
1172        const NO_PARENS        = 1 << 2;
1173
1174        // Visibility
1175        const PRIVATE          = 1 << 3;
1176        const INTERNAL         = 1 << 4;
1177        const PUBLIC           = 1 << 5;
1178        const EXTERNAL         = 1 << 6;
1179        const VISIBILITY       = Self::PRIVATE.bits()
1180                               | Self::INTERNAL.bits()
1181                               | Self::PUBLIC.bits()
1182                               | Self::EXTERNAL.bits();
1183
1184        // StateMutability
1185        const PURE             = 1 << 7;
1186        const VIEW             = 1 << 8;
1187        const PAYABLE          = 1 << 9;
1188        const STATE_MUTABILITY = Self::PURE.bits()
1189                               | Self::VIEW.bits()
1190                               | Self::PAYABLE.bits();
1191
1192        const MODIFIERS        = 1 << 10;
1193        const VIRTUAL          = 1 << 11;
1194        const OVERRIDE         = 1 << 12;
1195
1196        const RETURNS          = 1 << 13;
1197        /// Must be implemented, meaning it must end in a `{}` implementation block.
1198        const ONLY_BLOCK       = 1 << 14;
1199
1200        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.constructorDefinition
1201        const CONSTRUCTOR = Self::MODIFIERS.bits()
1202                          | Self::PAYABLE.bits()
1203                          | Self::INTERNAL.bits()
1204                          | Self::PUBLIC.bits()
1205                          | Self::ONLY_BLOCK.bits();
1206
1207        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.functionDefinition
1208        const FUNCTION    = Self::NAME.bits()
1209                          | Self::VISIBILITY.bits()
1210                          | Self::STATE_MUTABILITY.bits()
1211                          | Self::MODIFIERS.bits()
1212                          | Self::VIRTUAL.bits()
1213                          | Self::OVERRIDE.bits()
1214                          | Self::RETURNS.bits();
1215
1216        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.modifierDefinition
1217        const MODIFIER    = Self::NAME.bits()
1218                          | Self::NO_PARENS.bits()
1219                          | Self::VIRTUAL.bits()
1220                          | Self::OVERRIDE.bits();
1221
1222        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.fallbackFunctionDefinition
1223        const FALLBACK    = Self::EXTERNAL.bits()
1224                          | Self::STATE_MUTABILITY.bits()
1225                          | Self::MODIFIERS.bits()
1226                          | Self::VIRTUAL.bits()
1227                          | Self::OVERRIDE.bits()
1228                          | Self::RETURNS.bits();
1229
1230        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.receiveFunctionDefinition
1231        const RECEIVE     = Self::EXTERNAL.bits()
1232                          | Self::PAYABLE.bits()
1233                          | Self::MODIFIERS.bits()
1234                          | Self::VIRTUAL.bits()
1235                          | Self::OVERRIDE.bits();
1236
1237        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.functionTypeName
1238        const FUNCTION_TY = Self::PARAM_NAME.bits()
1239                          | Self::VISIBILITY.bits()
1240                          | Self::STATE_MUTABILITY.bits()
1241                          | Self::RETURNS.bits();
1242    }
1243}
1244
1245impl VarFlags {
1246    fn from_visibility(v: Visibility) -> Self {
1247        match v {
1248            Visibility::Private => Self::PRIVATE,
1249            Visibility::Internal => Self::INTERNAL,
1250            Visibility::Public => Self::PUBLIC,
1251            Visibility::External => Self::EXTERNAL,
1252        }
1253    }
1254
1255    fn into_visibility(self) -> Option<Visibility> {
1256        match self {
1257            Self::PRIVATE => Some(Visibility::Private),
1258            Self::INTERNAL => Some(Visibility::Internal),
1259            Self::PUBLIC => Some(Visibility::Public),
1260            Self::EXTERNAL => Some(Visibility::External),
1261            _ => None,
1262        }
1263    }
1264
1265    fn visibilities(self) -> Option<impl Iterator<Item = Visibility>> {
1266        self.supported(Self::VISIBILITY).map(|iter| iter.map(|x| x.into_visibility().unwrap()))
1267    }
1268
1269    fn from_varmut(v: VarMut) -> Self {
1270        match v {
1271            VarMut::Constant => Self::CONSTANT,
1272            VarMut::Immutable => Self::IMMUTABLE,
1273        }
1274    }
1275
1276    fn into_varmut(self) -> Option<VarMut> {
1277        match self {
1278            Self::CONSTANT => Some(VarMut::Constant),
1279            Self::IMMUTABLE => Some(VarMut::Immutable),
1280            _ => None,
1281        }
1282    }
1283
1284    fn varmuts(self) -> Option<impl Iterator<Item = VarMut>> {
1285        self.supported(Self::CONSTANT | Self::IMMUTABLE)
1286            .map(|iter| iter.map(|x| x.into_varmut().unwrap()))
1287    }
1288
1289    fn supported(self, what: Self) -> Option<impl Iterator<Item = Self>> {
1290        let s = self.intersection(what);
1291        if s.is_empty() { None } else { Some(s.iter()) }
1292    }
1293}
1294
1295impl FunctionFlags {
1296    fn from_kind(kind: FunctionKind) -> Self {
1297        match kind {
1298            FunctionKind::Constructor => Self::CONSTRUCTOR,
1299            FunctionKind::Function => Self::FUNCTION,
1300            FunctionKind::Modifier => Self::MODIFIER,
1301            FunctionKind::Receive => Self::RECEIVE,
1302            FunctionKind::Fallback => Self::FALLBACK,
1303        }
1304    }
1305
1306    fn from_visibility(visibility: Visibility) -> Self {
1307        match visibility {
1308            Visibility::Private => Self::PRIVATE,
1309            Visibility::Internal => Self::INTERNAL,
1310            Visibility::Public => Self::PUBLIC,
1311            Visibility::External => Self::EXTERNAL,
1312        }
1313    }
1314
1315    fn into_visibility(self) -> Option<Visibility> {
1316        match self {
1317            Self::PRIVATE => Some(Visibility::Private),
1318            Self::INTERNAL => Some(Visibility::Internal),
1319            Self::PUBLIC => Some(Visibility::Public),
1320            Self::EXTERNAL => Some(Visibility::External),
1321            _ => None,
1322        }
1323    }
1324
1325    fn visibilities(self) -> Option<impl Iterator<Item = Visibility>> {
1326        self.supported(Self::VISIBILITY).map(|iter| iter.map(|x| x.into_visibility().unwrap()))
1327    }
1328
1329    fn from_state_mutability(state_mutability: StateMutability) -> Self {
1330        match state_mutability {
1331            StateMutability::Pure => Self::PURE,
1332            StateMutability::View => Self::VIEW,
1333            StateMutability::Payable => Self::PAYABLE,
1334            StateMutability::NonPayable => unreachable!("NonPayable should not be parsed"),
1335        }
1336    }
1337
1338    fn into_state_mutability(self) -> Option<StateMutability> {
1339        match self {
1340            Self::PURE => Some(StateMutability::Pure),
1341            Self::VIEW => Some(StateMutability::View),
1342            Self::PAYABLE => Some(StateMutability::Payable),
1343            _ => None,
1344        }
1345    }
1346
1347    fn state_mutabilities(self) -> Option<impl Iterator<Item = StateMutability>> {
1348        self.supported(Self::STATE_MUTABILITY)
1349            .map(|iter| iter.map(|x| x.into_state_mutability().unwrap()))
1350    }
1351
1352    fn supported(self, what: Self) -> Option<impl Iterator<Item = Self>> {
1353        let s = self.intersection(what);
1354        if s.is_empty() { None } else { Some(s.iter()) }
1355    }
1356}
1357
1358fn visibility_error(v: Visibility, iter: Option<impl Iterator<Item = Visibility>>) -> String {
1359    common_flags_error(v, "visibility", iter)
1360}
1361
1362fn varmut_error(m: VarMut, iter: Option<impl Iterator<Item = VarMut>>) -> String {
1363    common_flags_error(m, "mutability", iter)
1364}
1365
1366fn state_mutability_error(
1367    m: StateMutability,
1368    iter: Option<impl Iterator<Item = StateMutability>>,
1369) -> String {
1370    common_flags_error(m, "state mutability", iter)
1371}
1372
1373fn common_flags_error<T: std::fmt::Display>(
1374    t: T,
1375    desc: &str,
1376    iter: Option<impl Iterator<Item = T>>,
1377) -> String {
1378    match iter {
1379        Some(iter) => format!("`{t}` not allowed here; allowed values: {}", iter.format(", ")),
1380        None => format!("{desc} is not allowed here"),
1381    }
1382}
1383
1384#[cfg(test)]
1385mod tests {
1386    use super::*;
1387    use solar_interface::{Result, Session, source_map::FileName};
1388
1389    fn session() -> Session {
1390        Session::builder().with_test_emitter().single_threaded().build()
1391    }
1392
1393    fn assert_version_matches(tests: &[(&str, &str, bool)]) {
1394        let sess = session();
1395        sess.enter(|| -> Result {
1396            for (i, &(v, req_s, res)) in tests.iter().enumerate() {
1397                let name = i.to_string();
1398                let src = format!("{v} {req_s}");
1399                let arena = Arena::new();
1400                let mut parser =
1401                    Parser::from_source_code(&sess, &arena, FileName::Custom(name), src)?;
1402
1403                let version = parser.parse_semver_version().map_err(|e| e.emit()).unwrap();
1404                assert_eq!(version.to_string(), v);
1405                let req: SemverReq<'_> = parser.parse_semver_req().map_err(|e| e.emit()).unwrap();
1406                sess.dcx.has_errors().unwrap();
1407                assert_eq!(req.matches(&version), res, "v={v:?}, req={req_s:?}");
1408            }
1409            Ok(())
1410        })
1411        .unwrap();
1412    }
1413
1414    #[test]
1415    fn semver_matches() {
1416        assert_version_matches(&[
1417            // none = eq
1418            ("0.8.1", "0", true),
1419            ("0.8.1", "1", false),
1420            ("0.8.1", "1.0", false),
1421            ("0.8.1", "1.0.0", false),
1422            ("0.8.1", "0.7", false),
1423            ("0.8.1", "0.7.0", false),
1424            ("0.8.1", "0.7.1", false),
1425            ("0.8.1", "0.7.2", false),
1426            ("0.8.1", "0.8", true),
1427            ("0.8.1", "0.8.0", false),
1428            ("0.8.1", "0.8.1", true),
1429            ("0.8.1", "0.8.2", false),
1430            ("0.8.1", "0.9", false),
1431            ("0.8.1", "0.9.0", false),
1432            ("0.8.1", "0.9.1", false),
1433            ("0.8.1", "0.9.2", false),
1434            // eq
1435            ("0.8.1", "=0", true),
1436            ("0.8.1", "=1", false),
1437            ("0.8.1", "=1.0", false),
1438            ("0.8.1", "=1.0.0", false),
1439            ("0.8.1", "=0.7", false),
1440            ("0.8.1", "=0.7.0", false),
1441            ("0.8.1", "=0.7.1", false),
1442            ("0.8.1", "=0.7.2", false),
1443            ("0.8.1", "=0.8", true),
1444            ("0.8.1", "=0.8.0", false),
1445            ("0.8.1", "=0.8.1", true),
1446            ("0.8.1", "=0.8.2", false),
1447            ("0.8.1", "=0.9", false),
1448            ("0.8.1", "=0.9.0", false),
1449            ("0.8.1", "=0.9.1", false),
1450            ("0.8.1", "=0.9.2", false),
1451            // gt
1452            ("0.8.1", ">0", false),
1453            ("0.8.1", ">1", false),
1454            ("0.8.1", ">1.0", false),
1455            ("0.8.1", ">1.0.0", false),
1456            ("0.8.1", ">0.7", true),
1457            ("0.8.1", ">0.7.0", true),
1458            ("0.8.1", ">0.7.1", true),
1459            ("0.8.1", ">0.7.2", true),
1460            ("0.8.1", ">0.8", false),
1461            ("0.8.1", ">0.8.0", true),
1462            ("0.8.1", ">0.8.1", false),
1463            ("0.8.1", ">0.8.2", false),
1464            ("0.8.1", ">0.9", false),
1465            ("0.8.1", ">0.9.0", false),
1466            ("0.8.1", ">0.9.1", false),
1467            ("0.8.1", ">0.9.2", false),
1468            // ge
1469            ("0.8.1", ">=0", true),
1470            ("0.8.1", ">=1", false),
1471            ("0.8.1", ">=1.0", false),
1472            ("0.8.1", ">=1.0.0", false),
1473            ("0.8.1", ">=0.7", true),
1474            ("0.8.1", ">=0.7.0", true),
1475            ("0.8.1", ">=0.7.1", true),
1476            ("0.8.1", ">=0.7.2", true),
1477            ("0.8.1", ">=0.8", true),
1478            ("0.8.1", ">=0.8.0", true),
1479            ("0.8.1", ">=0.8.1", true),
1480            ("0.8.1", ">=0.8.2", false),
1481            ("0.8.1", ">=0.9", false),
1482            ("0.8.1", ">=0.9.0", false),
1483            ("0.8.1", ">=0.9.1", false),
1484            ("0.8.1", ">=0.9.2", false),
1485            // lt
1486            ("0.8.1", "<0", false),
1487            ("0.8.1", "<1", true),
1488            ("0.8.1", "<1.0", true),
1489            ("0.8.1", "<1.0.0", true),
1490            ("0.8.1", "<0.7", false),
1491            ("0.8.1", "<0.7.0", false),
1492            ("0.8.1", "<0.7.1", false),
1493            ("0.8.1", "<0.7.2", false),
1494            ("0.8.1", "<0.8", false),
1495            ("0.8.1", "<0.8.0", false),
1496            ("0.8.1", "<0.8.1", false),
1497            ("0.8.1", "<0.8.2", true),
1498            ("0.8.1", "<0.9", true),
1499            ("0.8.1", "<0.9.0", true),
1500            ("0.8.1", "<0.9.1", true),
1501            ("0.8.1", "<0.9.2", true),
1502            // le
1503            ("0.8.1", "<=0", true),
1504            ("0.8.1", "<=1", true),
1505            ("0.8.1", "<=1.0", true),
1506            ("0.8.1", "<=1.0.0", true),
1507            ("0.8.1", "<=0.7", false),
1508            ("0.8.1", "<=0.7.0", false),
1509            ("0.8.1", "<=0.7.1", false),
1510            ("0.8.1", "<=0.7.2", false),
1511            ("0.8.1", "<=0.8", true),
1512            ("0.8.1", "<=0.8.0", false),
1513            ("0.8.1", "<=0.8.1", true),
1514            ("0.8.1", "<=0.8.2", true),
1515            ("0.8.1", "<=0.9.0", true),
1516            ("0.8.1", "<=0.9.1", true),
1517            ("0.8.1", "<=0.9.2", true),
1518            // tilde
1519            ("0.8.1", "~0", true),
1520            ("0.8.1", "~1", false),
1521            ("0.8.1", "~1.0", false),
1522            ("0.8.1", "~1.0.0", false),
1523            ("0.8.1", "~0.7", false),
1524            ("0.8.1", "~0.7.0", false),
1525            ("0.8.1", "~0.7.1", false),
1526            ("0.8.1", "~0.7.2", false),
1527            ("0.8.1", "~0.8", true),
1528            ("0.8.1", "~0.8.0", true),
1529            ("0.8.1", "~0.8.1", true),
1530            ("0.8.1", "~0.8.2", false),
1531            ("0.8.1", "~0.9.0", false),
1532            ("0.8.1", "~0.9.1", false),
1533            ("0.8.1", "~0.9.2", false),
1534            // caret
1535            ("0.8.1", "^0", true),
1536            ("0.8.1", "^1", false),
1537            ("0.8.1", "^1.0", false),
1538            ("0.8.1", "^1.0.0", false),
1539            ("0.8.1", "^0.7", false),
1540            ("0.8.1", "^0.7.0", false),
1541            ("0.8.1", "^0.7.1", false),
1542            ("0.8.1", "^0.7.2", false),
1543            ("0.8.1", "^0.8", true),
1544            ("0.8.1", "^0.8.0", true),
1545            ("0.8.1", "^0.8.1", true),
1546            ("0.8.1", "^0.8.2", false),
1547            ("0.8.1", "^0.9.0", false),
1548            ("0.8.1", "^0.9.1", false),
1549            ("0.8.1", "^0.9.2", false),
1550            // ranges
1551            ("0.8.1", "0 - 1", true),
1552            ("0.8.1", "0.1 - 1.1", true),
1553            ("0.8.1", "0.1.1 - 1.1.1", true),
1554            ("0.8.1", "0 - 0.8.1", true),
1555            ("0.8.1", "0 - 0.8.2", true),
1556            ("0.8.1", "0.7 - 0.8.1", true),
1557            ("0.8.1", "0.7 - 0.8.2", true),
1558            ("0.8.1", "0.8 - 0.8.1", true),
1559            ("0.8.1", "0.8 - 0.8.2", true),
1560            ("0.8.1", "0.8.0 - 0.8.1", true),
1561            ("0.8.1", "0.8.0 - 0.8.2", true),
1562            ("0.8.1", "0.8.0 - 0.9.0", true),
1563            ("0.8.1", "0.8.0 - 1.0.0", true),
1564            ("0.8.1", "0.8.1 - 0.8.1", true),
1565            ("0.8.1", "0.8.1 - 0.8.2", true),
1566            ("0.8.1", "0.8.1 - 0.9.0", true),
1567            ("0.8.1", "0.8.1 - 1.0.0", true),
1568            ("0.8.1", "0.7 - 0.8", true),
1569            ("0.8.1", "0.7.0 - 0.8", true),
1570            ("0.8.1", "0.8 - 0.8", true),
1571            ("0.8.1", "0.8.0 - 0.8", true),
1572            ("0.8.1", "0.8 - 0.8.0", false),
1573            ("0.8.1", "0.8 - 0.8.1", true),
1574            // or
1575            ("0.8.1", "0 || 0", true),
1576            ("0.8.1", "0 || 1", true),
1577            ("0.8.1", "1 || 0", true),
1578            ("0.8.1", "0.0 || 0.0", false),
1579            ("0.8.1", "0.0 || 1.0", false),
1580            ("0.8.1", "1.0 || 0.0", false),
1581            ("0.8.1", "0.7 || 0.8", true),
1582            ("0.8.1", "0.8 || 0.8", true),
1583            ("0.8.1", "0.8 || 0.8.1", true),
1584            ("0.8.1", "0.8 || 0.8.2", true),
1585            ("0.8.1", "0.8 || 0.9", true),
1586        ]);
1587    }
1588
1589    #[test]
1590    /// Test if the span of a function header is correct (should start at the function-like kw and
1591    /// end at the last token)
1592    fn function_header_span() {
1593        let test_functions = [
1594            "function foo(uint256 a) public view returns (uint256) {
1595}",
1596            "modifier foo() {
1597    _;
1598}",
1599            "receive() external payable {
1600}",
1601            "fallback() external payable {
1602}",
1603            "constructor() {
1604}",
1605        ];
1606
1607        let test_function_headers = [
1608            "function foo(uint256 a) public view returns (uint256)",
1609            "modifier foo()",
1610            "receive() external payable",
1611            "fallback() external payable",
1612            "constructor()",
1613        ];
1614
1615        for (idx, src) in test_functions.iter().enumerate() {
1616            let sess = session();
1617            sess.enter(|| -> Result {
1618                let arena = Arena::new();
1619                let mut parser = Parser::from_source_code(
1620                    &sess,
1621                    &arena,
1622                    FileName::Custom(String::from("test")),
1623                    *src,
1624                )?;
1625
1626                parser.in_contract = true; // Silence the wrong scope error
1627
1628                let header_span = parser.parse_function().unwrap().header.span;
1629
1630                assert_eq!(
1631                    header_span,
1632                    Span::new(
1633                        solar_interface::BytePos(0),
1634                        solar_interface::BytePos(test_function_headers[idx].len() as u32,),
1635                    ),
1636                );
1637
1638                Ok(())
1639            })
1640            .unwrap();
1641        }
1642    }
1643
1644    #[test]
1645    /// Test if the individual spans in function headers are correct
1646    fn function_header_field_spans() {
1647        let test_cases = vec![
1648            ("function foo() public {}", Some("public"), None, None, "()", None),
1649            ("function foo() private view {}", Some("private"), Some("view"), None, "()", None),
1650            (
1651                "function foo() internal pure returns (uint) {}",
1652                Some("internal"),
1653                Some("pure"),
1654                None,
1655                "()",
1656                Some("(uint)"),
1657            ),
1658            (
1659                "function foo() external payable {}",
1660                Some("external"),
1661                Some("payable"),
1662                None,
1663                "()",
1664                None,
1665            ),
1666            ("function foo() pure {}", None, Some("pure"), None, "()", None),
1667            ("function foo() view {}", None, Some("view"), None, "()", None),
1668            ("function foo() payable {}", None, Some("payable"), None, "()", None),
1669            ("function foo() {}", None, None, None, "()", None),
1670            ("function foo(uint a) {}", None, None, None, "(uint a)", None),
1671            ("function foo(uint a, string b) {}", None, None, None, "(uint a, string b)", None),
1672            ("function foo() returns (uint) {}", None, None, None, "()", Some("(uint)")),
1673            (
1674                "function foo() returns (uint, bool) {}",
1675                None,
1676                None,
1677                None,
1678                "()",
1679                Some("(uint, bool)"),
1680            ),
1681            (
1682                "function foo(uint x) public view returns (bool) {}",
1683                Some("public"),
1684                Some("view"),
1685                None,
1686                "(uint x)",
1687                Some("(bool)"),
1688            ),
1689            ("function foo() public virtual {}", Some("public"), None, Some("virtual"), "()", None),
1690            ("function foo() virtual public {}", Some("public"), None, Some("virtual"), "()", None),
1691            (
1692                "function foo() public virtual view {}",
1693                Some("public"),
1694                Some("view"),
1695                Some("virtual"),
1696                "()",
1697                None,
1698            ),
1699            ("function foo() virtual override {}", None, None, Some("virtual"), "()", None),
1700            ("modifier bar() virtual {}", None, None, Some("virtual"), "()", None),
1701            (
1702                "function foo() public virtual returns (uint) {}",
1703                Some("public"),
1704                None,
1705                Some("virtual"),
1706                "()",
1707                Some("(uint)"),
1708            ),
1709        ];
1710
1711        let sess = session();
1712        sess.enter(|| -> Result {
1713            for (idx, (src, vis, sm, virt, params, returns)) in test_cases.iter().enumerate() {
1714                let arena = Arena::new();
1715                let mut parser = Parser::from_source_code(
1716                    &sess,
1717                    &arena,
1718                    FileName::Custom(format!("test_{idx}")),
1719                    *src,
1720                )?;
1721                parser.in_contract = true;
1722
1723                let func = parser.parse_function().unwrap();
1724                let header = &func.header;
1725
1726                if let Some(expected) = vis {
1727                    let vis_span = header.visibility.as_ref().expect("Expected visibility").span;
1728                    let vis_text = sess.source_map().span_to_snippet(vis_span).unwrap();
1729                    assert_eq!(vis_text, *expected, "Test {idx}: visibility span mismatch");
1730                }
1731                if let Some(expected) = sm
1732                    && let Some(state_mutability) = header.state_mutability
1733                {
1734                    assert_eq!(
1735                        *expected,
1736                        sess.source_map().span_to_snippet(state_mutability.span).unwrap(),
1737                        "Test {idx}: state mutability span mismatch",
1738                    );
1739                }
1740                if let Some(expected) = virt {
1741                    let virtual_span = header.virtual_.expect("Expected virtual span");
1742                    let virtual_text = sess.source_map().span_to_snippet(virtual_span).unwrap();
1743                    assert_eq!(virtual_text, *expected, "Test {idx}: virtual span mismatch");
1744                }
1745                let span = header.parameters.span;
1746                assert_eq!(
1747                    *params,
1748                    sess.source_map().span_to_snippet(span).unwrap(),
1749                    "Test {idx}: params span mismatch"
1750                );
1751                if let Some(expected) = returns {
1752                    let span = header.returns.as_ref().expect("Expected returns").span;
1753                    assert_eq!(
1754                        *expected,
1755                        sess.source_map().span_to_snippet(span).unwrap(),
1756                        "Test {idx}: returns span mismatch",
1757                    );
1758                }
1759            }
1760            Ok(())
1761        })
1762        .unwrap();
1763    }
1764}