Skip to main content

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