1use crate::nodes::{
2 Identifier, LiteralExpression, LiteralTable, StringExpression, Token, Trivia,
3 TupleArgumentsTokens,
4};
5
6#[derive(Clone, Debug, Default, PartialEq, Eq)]
11pub struct Attributes {
12 attributes: Vec<Attribute>,
13}
14
15impl Attributes {
16 pub fn new() -> Self {
18 Self {
19 attributes: Vec::new(),
20 }
21 }
22
23 pub fn with_attribute(mut self, attribute: impl Into<Attribute>) -> Self {
25 self.attributes.push(attribute.into());
26 self
27 }
28
29 pub fn append_attribute(&mut self, attribute: impl Into<Attribute>) {
33 let attribute = attribute.into();
34 if let Attribute::Group(list) = &attribute {
35 if list.is_empty() {
36 return;
38 }
39 }
40 self.attributes.push(attribute);
41 }
42
43 pub fn iter_attributes(&self) -> impl Iterator<Item = &Attribute> {
45 self.attributes.iter()
46 }
47
48 pub fn iter_mut_attributes(&mut self) -> impl Iterator<Item = &mut Attribute> {
50 self.attributes.iter_mut()
51 }
52
53 pub fn clear_attributes(&mut self) {
55 self.attributes.clear();
56 }
57
58 pub fn is_empty(&self) -> bool {
60 self.attributes.is_empty()
61 }
62
63 pub fn len(&self) -> usize {
65 self.attributes.len()
66 }
67
68 pub fn has_attribute(&self, name: &str) -> bool {
70 self.attributes.iter().any(|attr| match attr {
71 Attribute::Name(named) => named.get_identifier().get_name() == name,
72 Attribute::Group(group) => group.has_attribute(name),
73 })
74 }
75
76 pub fn filter_attributes<F>(&mut self, predicate: F)
79 where
80 F: Fn(&Attribute) -> bool,
81 {
82 self.attributes.retain(predicate);
83 }
84
85 pub fn filter_mut_attributes<F>(&mut self, predicate: F)
88 where
89 F: FnMut(&mut Attribute) -> bool,
90 {
91 self.attributes.retain_mut(predicate);
92 }
93
94 super::impl_token_fns!(iter = [attributes]);
95}
96
97#[derive(Clone, Debug, PartialEq, Eq)]
103pub enum Attribute {
104 Name(NamedAttribute),
106 Group(AttributeGroup),
108}
109
110impl Attribute {
111 pub fn clear_comments(&mut self) {
113 match self {
114 Self::Name(name) => name.clear_comments(),
115 Self::Group(list) => list.clear_comments(),
116 }
117 }
118
119 pub fn clear_whitespaces(&mut self) {
121 match self {
122 Self::Name(name) => name.clear_whitespaces(),
123 Self::Group(list) => list.clear_whitespaces(),
124 }
125 }
126
127 pub(crate) fn replace_referenced_tokens(&mut self, code: &str) {
128 match self {
129 Self::Name(name) => name.replace_referenced_tokens(code),
130 Self::Group(list) => list.replace_referenced_tokens(code),
131 }
132 }
133
134 pub(crate) fn shift_token_line(&mut self, amount: isize) {
135 match self {
136 Self::Name(name) => name.shift_token_line(amount),
137 Self::Group(list) => list.shift_token_line(amount),
138 }
139 }
140
141 pub(crate) fn filter_comments(&mut self, filter: impl Fn(&Trivia) -> bool) {
142 match self {
143 Self::Name(name) => name.filter_comments(filter),
144 Self::Group(list) => list.filter_comments(filter),
145 }
146 }
147}
148
149impl From<AttributeGroup> for Attribute {
150 fn from(v: AttributeGroup) -> Self {
151 Self::Group(v)
152 }
153}
154
155impl From<AttributeGroupElement> for Attribute {
156 fn from(v: AttributeGroupElement) -> Self {
157 Self::Group(AttributeGroup::new(v))
158 }
159}
160
161impl From<NamedAttribute> for Attribute {
162 fn from(v: NamedAttribute) -> Self {
163 Self::Name(v)
164 }
165}
166
167#[derive(Clone, Debug, PartialEq, Eq)]
171pub struct NamedAttribute {
172 name: Identifier,
173 token: Option<Token>,
174}
175
176impl NamedAttribute {
177 pub fn new(name: impl Into<Identifier>) -> Self {
179 Self {
180 name: name.into(),
181 token: None,
182 }
183 }
184
185 pub fn with_token(mut self, token: Token) -> Self {
187 self.token = Some(token);
188 self
189 }
190
191 #[inline]
193 pub fn set_token(&mut self, token: Token) {
194 self.token = Some(token);
195 }
196
197 #[inline]
199 pub fn get_token(&self) -> Option<&Token> {
200 self.token.as_ref()
201 }
202
203 #[inline]
205 pub fn get_identifier(&self) -> &Identifier {
206 &self.name
207 }
208
209 #[inline]
211 pub fn mutate_identifier(&mut self) -> &mut Identifier {
212 &mut self.name
213 }
214
215 super::impl_token_fns!(target = [name] iter = [token]);
216}
217
218#[derive(Clone, Debug, PartialEq, Eq)]
222pub struct AttributeGroup {
223 attributes: Vec<AttributeGroupElement>,
224 tokens: Option<AttributeGroupTokens>,
225}
226
227impl AttributeGroup {
228 pub fn new(attribute: impl Into<AttributeGroupElement>) -> Self {
230 Self {
231 attributes: vec![attribute.into()],
232 tokens: None,
233 }
234 }
235
236 pub fn with_attribute(mut self, attribute: impl Into<AttributeGroupElement>) -> Self {
238 self.attributes.push(attribute.into());
239 self
240 }
241
242 pub fn append_attribute(&mut self, attribute: impl Into<AttributeGroupElement>) {
244 self.attributes.push(attribute.into());
245 }
246
247 pub fn iter_attributes(&self) -> impl Iterator<Item = &AttributeGroupElement> {
249 self.attributes.iter()
250 }
251
252 pub fn iter_mut_attributes(&mut self) -> impl Iterator<Item = &mut AttributeGroupElement> {
254 self.attributes.iter_mut()
255 }
256
257 pub fn with_tokens(mut self, tokens: AttributeGroupTokens) -> Self {
259 self.tokens = Some(tokens);
260 self
261 }
262
263 pub fn set_tokens(&mut self, tokens: AttributeGroupTokens) {
265 self.tokens = Some(tokens);
266 }
267
268 pub fn get_tokens(&self) -> Option<&AttributeGroupTokens> {
270 self.tokens.as_ref()
271 }
272
273 pub fn mutate_tokens(&mut self) -> Option<&mut AttributeGroupTokens> {
275 self.tokens.as_mut()
276 }
277
278 pub fn is_empty(&self) -> bool {
280 self.attributes.is_empty()
281 }
282
283 pub fn len(&self) -> usize {
285 self.attributes.len()
286 }
287
288 pub fn has_attribute(&self, name: &str) -> bool {
290 self.attributes
291 .iter()
292 .any(|elem| elem.name().get_name() == name)
293 }
294
295 pub fn remove(&mut self, index: usize) {
298 if index < self.attributes.len() {
299 self.attributes.remove(index);
300
301 if let Some(tokens) = &mut self.tokens {
303 if index < tokens.separators.len() {
304 tokens.separators.remove(index);
305 }
306 }
307 }
308 }
309
310 pub fn filter_attributes<F>(&mut self, mut predicate: F)
313 where
314 F: FnMut(&AttributeGroupElement) -> bool,
315 {
316 let mut i = 0;
317 while i < self.attributes.len() {
318 if predicate(&self.attributes[i]) {
319 i += 1;
320 } else {
321 self.remove(i);
322 }
323 }
324 }
325
326 pub fn filter_mut_attributes<F>(&mut self, mut predicate: F)
329 where
330 F: FnMut(&mut AttributeGroupElement) -> bool,
331 {
332 let mut i = 0;
333 while i < self.attributes.len() {
334 if predicate(&mut self.attributes[i]) {
335 i += 1;
336 } else {
337 self.remove(i);
338 }
339 }
340 }
341
342 super::impl_token_fns!(iter = [tokens, attributes]);
343}
344
345#[derive(Clone, Debug, PartialEq, Eq)]
347pub struct AttributeGroupTokens {
348 pub opening_attribute_list: Token,
350 pub closing_bracket: Token,
352 pub separators: Vec<Token>,
354}
355
356impl AttributeGroupTokens {
357 super::impl_token_fns!(
358 target = [opening_attribute_list, closing_bracket]
359 iter = [separators]
360 );
361}
362
363#[derive(Clone, Debug, PartialEq, Eq)]
367pub struct AttributeGroupElement {
368 name: Identifier,
369 arguments: Option<AttributeArguments>,
370}
371
372impl AttributeGroupElement {
373 pub fn new(name: impl Into<Identifier>) -> Self {
375 Self {
376 name: name.into(),
377 arguments: None,
378 }
379 }
380
381 pub fn with_arguments(mut self, arguments: impl Into<AttributeArguments>) -> Self {
383 self.arguments = Some(arguments.into());
384 self
385 }
386
387 pub fn name(&self) -> &Identifier {
389 &self.name
390 }
391
392 pub fn mutate_name(&mut self) -> &mut Identifier {
394 &mut self.name
395 }
396
397 pub fn get_arguments(&self) -> Option<&AttributeArguments> {
399 self.arguments.as_ref()
400 }
401
402 pub fn mutate_arguments(&mut self) -> Option<&mut AttributeArguments> {
404 self.arguments.as_mut()
405 }
406
407 pub fn set_arguments(&mut self, arguments: impl Into<AttributeArguments>) {
409 self.arguments = Some(arguments.into());
410 }
411
412 pub fn remove_arguments(&mut self) {
414 self.arguments = None;
415 }
416
417 super::impl_token_fns!(target = [name] iter = [arguments]);
418}
419
420#[derive(Clone, Debug, PartialEq, Eq)]
427pub enum AttributeArguments {
428 Tuple(AttributeTupleArguments),
430 String(StringExpression),
432 Table(LiteralTable),
434}
435
436impl AttributeArguments {
437 pub fn clear_comments(&mut self) {
439 match self {
440 Self::Tuple(tuple) => tuple.clear_comments(),
441 Self::String(string) => string.clear_comments(),
442 Self::Table(table) => table.clear_comments(),
443 }
444 }
445
446 pub fn clear_whitespaces(&mut self) {
448 match self {
449 Self::Tuple(tuple) => tuple.clear_whitespaces(),
450 Self::String(string) => string.clear_whitespaces(),
451 Self::Table(table) => table.clear_whitespaces(),
452 }
453 }
454
455 pub(crate) fn replace_referenced_tokens(&mut self, code: &str) {
456 match self {
457 Self::Tuple(tuple) => tuple.replace_referenced_tokens(code),
458 Self::String(string) => string.replace_referenced_tokens(code),
459 Self::Table(table) => table.replace_referenced_tokens(code),
460 }
461 }
462
463 pub(crate) fn shift_token_line(&mut self, amount: isize) {
464 match self {
465 Self::Tuple(tuple) => tuple.shift_token_line(amount),
466 Self::String(string) => string.shift_token_line(amount),
467 Self::Table(table) => table.shift_token_line(amount),
468 }
469 }
470
471 pub(crate) fn filter_comments(&mut self, filter: impl Fn(&Trivia) -> bool) {
472 match self {
473 Self::Tuple(tuple) => tuple.filter_comments(filter),
474 Self::String(string) => string.filter_comments(filter),
475 Self::Table(table) => table.filter_comments(filter),
476 }
477 }
478}
479
480impl From<LiteralTable> for AttributeArguments {
481 fn from(v: LiteralTable) -> Self {
482 Self::Table(v)
483 }
484}
485
486impl From<StringExpression> for AttributeArguments {
487 fn from(v: StringExpression) -> Self {
488 Self::String(v)
489 }
490}
491
492impl From<AttributeTupleArguments> for AttributeArguments {
493 fn from(v: AttributeTupleArguments) -> Self {
494 Self::Tuple(v)
495 }
496}
497
498#[derive(Clone, Debug, Default, PartialEq, Eq)]
500pub struct AttributeTupleArguments {
501 values: Vec<LiteralExpression>,
502 tokens: Option<TupleArgumentsTokens>,
503}
504
505impl AttributeTupleArguments {
506 pub fn with_value(mut self, value: impl Into<LiteralExpression>) -> Self {
507 self.push(value.into());
508 self
509 }
510
511 pub fn push(&mut self, argument: impl Into<LiteralExpression>) {
512 let argument = argument.into();
513 let initial_len = self.values.len();
514
515 self.values.push(argument);
516
517 if initial_len != 0 {
518 if let Some(tokens) = &mut self.tokens {
519 if tokens.commas.len() == initial_len - 1 {
520 tokens.commas.push(Token::from_content(","));
521 }
522 }
523 }
524 }
525
526 pub fn insert(&mut self, index: usize, argument: impl Into<LiteralExpression>) {
528 if index >= self.values.len() {
529 self.push(argument.into());
530 } else {
531 self.values.insert(index, argument.into());
532
533 if let Some(tokens) = &mut self.tokens {
534 if index <= tokens.commas.len() {
535 tokens.commas.insert(index, Token::from_content(","));
536 }
537 }
538 }
539 }
540
541 pub fn len(&self) -> usize {
543 self.values.len()
544 }
545
546 pub fn is_empty(&self) -> bool {
548 self.values.is_empty()
549 }
550
551 pub fn iter_values(&self) -> impl Iterator<Item = &LiteralExpression> {
553 self.values.iter()
554 }
555
556 pub fn iter_mut_values(&mut self) -> impl Iterator<Item = &mut LiteralExpression> {
558 self.values.iter_mut()
559 }
560
561 pub fn get_tokens(&self) -> Option<&TupleArgumentsTokens> {
563 self.tokens.as_ref()
564 }
565
566 pub fn set_tokens(&mut self, tokens: TupleArgumentsTokens) {
568 self.tokens = Some(tokens);
569 }
570
571 pub fn with_tokens(mut self, tokens: TupleArgumentsTokens) -> Self {
573 self.tokens = Some(tokens);
574 self
575 }
576
577 super::impl_token_fns!(iter = [tokens]);
578}