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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use syn::{
bracketed, parenthesized,
parse::{Parse, ParseStream},
parse_macro_input,
spanned::Spanned,
token, Error, Expr, ExprMacro, Ident, Macro, Result, Token,
};
use crate::widgets::{Property, PropertyName, PropertyType};
impl Parse for Property {
fn parse(input: ParseStream) -> Result<Self> {
let name = input.parse()?;
let mut optional_assign = false;
let mut iterative = false;
let mut braced_args = false;
if input.peek(Token![!]) {
if let PropertyName::Ident(ref ident_name) = name {
if ident_name == "factory" {
let _exclm: Token![!] = input.parse()?;
let paren_input;
parenthesized!(paren_input in input);
return Ok(Property {
name,
ty: PropertyType::Factory(paren_input.parse()?),
generics: None,
optional_assign,
iterative,
args: None,
});
}
}
return Err(input.error("Expected factory macro"));
}
let args = if input.peek(token::Paren) {
let paren_input;
parenthesized!(paren_input in input);
Some(paren_input.parse()?)
}
else if input.peek(token::Bracket) {
let paren_input;
bracketed!(paren_input in input);
braced_args = true;
Some(paren_input.parse()?)
} else {
None
};
let generics = if input.peek(Token![<]) {
Some(input.parse()?)
} else {
None
};
let ty = if input.peek(Token! [=>]) {
let _arrow: Token![=>] = input.parse()?;
if braced_args {
input.parse().map(PropertyType::ConnectComponent)?
} else {
input.parse().map(PropertyType::Connect)?
}
}
else if (input.peek(Token![=])
|| input.peek3(Token![=])
|| (input.peek(Token![:]) && input.peek2(Token![mut]) && input.peek3(Ident)))
&& !input.peek3(Token![==])
{
if input.peek(Token![=]) {
let _token: Token![=] = input.parse()?;
} else {
let _colon: Token![:] = input.parse()?;
}
input.parse().map(PropertyType::Widget)?
}
else if input.peek(Token! [:]) || input.peek(Token! [?]) {
if input.peek(Token! [?]) {
let _question_mark: Token![?] = input.parse()?;
optional_assign = true;
}
let colon: Token! [:] = input.parse()?;
let colon_span = colon.span();
if input.peek2(Token![!]) && !input.peek3(Token![=]) {
let mac: Macro = input.parse()?;
let segs = &mac.path.segments;
if segs.len() == 1 {
let ident = &segs.first().expect("Macro has no segments").ident;
if ident == "track" {
let tokens = mac.tokens.into();
PropertyType::Track(parse_macro_input::parse(tokens)?)
} else if ident == "parent" {
let tokens = mac.tokens.into();
PropertyType::Parent(parse_macro_input::parse(tokens)?)
} else if ident == "args" {
let tokens = mac.tokens.into();
PropertyType::Args(parse_macro_input::parse(tokens)?)
} else if ident == "watch" {
PropertyType::Watch(mac.tokens)
} else if ident == "iterate" {
iterative = true;
let tokens = mac.tokens.into();
PropertyType::Expr(parse_macro_input::parse(tokens)?)
} else if ident == "iterate_watch" {
iterative = true;
let tokens = mac.tokens.into();
PropertyType::Watch(parse_macro_input::parse(tokens)?)
} else {
PropertyType::Expr(Expr::Macro(ExprMacro {
attrs: Vec::new(),
mac,
}))
}
} else {
input.parse().map(PropertyType::Expr)?
}
} else {
match input.parse().map(PropertyType::Expr) {
Ok(expr) => expr,
Err(parse_err) => {
let mut err = Error::new(colon_span, "Did you confuse `=` with`:`?");
err.combine(parse_err);
return Err(err);
}
}
}
} else {
return Err(input.error("Unexpected token. Expected =>, =, : or ?:"));
};
if !input.is_empty() && !input.peek(Token![,]) {
Err(input.error("expected `,`. Did you confuse `=` with`:`?"))
} else {
Ok(Property {
name,
ty,
generics,
args,
optional_assign,
iterative,
})
}
}
}