1use {
5 super::token,
6 rustidy_ast_util::{IdentifierOrKeyword, NonKeywordIdentifier},
7 rustidy_format::{Format, Formattable, WhitespaceFormat},
8 rustidy_parse::{Parse, Parser, ParserTag},
9 rustidy_print::Print,
10 rustidy_util::Whitespace,
11};
12
13#[derive(PartialEq, Eq, Clone, Debug)]
15#[derive(serde::Serialize, serde::Deserialize)]
16#[derive(Parse, Formattable, Format, Print)]
17pub struct Lifetime(LifetimeToken);
18
19#[derive(PartialEq, Eq, Clone, Debug)]
21#[derive(serde::Serialize, serde::Deserialize)]
22#[derive(Parse, Formattable, Format, Print)]
23pub enum LifetimeToken {
24 IdentOrKeyword(QuoteNotQuote<IdentifierOrKeyword>),
25 Underscore(QuoteNotQuote<token::Underscore>),
26 }
28
29#[derive(PartialEq, Eq, Clone, Debug)]
31#[derive(serde::Serialize, serde::Deserialize)]
32#[derive(Parse, Formattable, Format, Print)]
33pub enum LifetimeOrLabel {
34 IdentOrKeyword(QuoteNotQuote<NonKeywordIdentifier>),
35 Underscore(QuoteNotQuote<token::Underscore>),
36 }
38
39#[derive(PartialEq, Eq, Clone, Debug)]
40#[derive(serde::Serialize, serde::Deserialize)]
41#[derive(Parse, Formattable, Format, Print)]
42#[parse(name = "a lifetime token")]
43#[parse(error(name = SuffixQuote, fmt = "Unexpected `'`"))]
44#[parse(and_try_with = Self::check_suffix_quote)]
45pub struct QuoteNotQuote<T> {
46 pub quote: token::Quote,
47 #[parse(with_tag = ParserTag::SkipWhitespace)]
48 #[format(prefix_ws = Whitespace::REMOVE)]
49 pub value: T,
50}
51
52impl<T: Parse> QuoteNotQuote<T> {
53 pub fn check_suffix_quote(&mut self, parser: &mut Parser) -> Result<(), QuoteNotQuoteError<T>> {
54 if parser
57 .with_tag(
58 ParserTag::SkipWhitespace,
59 Parser::try_parse::<token::Quote>
60 )
61 .map_err(QuoteNotQuoteError::Quote)?
62 .is_ok() {
63 return Err(QuoteNotQuoteError::SuffixQuote);
64 }
65
66 Ok(())
67 }
68}