1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use syn::parse::ParseStream;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{token, Ident, Path, Token};
use crate::widgets::{parse_util, ParseError, WidgetFunc};
impl WidgetFunc {
pub(super) fn parse_with_path(input: ParseStream<'_>, path: &Path) -> Result<Self, ParseError> {
match Self::parse_with_path_internal(input, path) {
Ok(func) => Ok(func),
Err(err) => Err(err.add_path(path)),
}
}
fn parse_with_path_internal(input: ParseStream<'_>, path: &Path) -> Result<Self, ParseError> {
if input.peek(Ident) {
return Err(ParseError::Generic(
syn::Error::new(
path.span()
.join(input.span())
.unwrap_or_else(|| input.span()),
"A path must not be followed by an identifier",
)
.into_compile_error(),
)
.add_path(path));
}
let args = if input.peek(token::Paren) {
let paren_input = parse_util::parens(input)?;
Some(paren_input.call(Punctuated::parse_terminated)?)
} else {
None
};
let method_chain = if input.peek(token::Dot) {
let _dot: token::Dot = input.parse()?;
Some(Punctuated::parse_separated_nonempty(input)?)
} else {
None
};
let ty = if input.peek(Token! [->]) {
let _token: Token! [->] = input.parse()?;
Some(input.parse()?)
} else {
None
};
Ok(WidgetFunc {
path: path.clone(),
args,
method_chain,
ty,
})
}
}
impl WidgetFunc {
pub(super) fn parse(input: ParseStream<'_>) -> Result<Self, ParseError> {
let path = &input.parse()?;
Self::parse_with_path(input, path)
}
}