-
-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathvariant.rs
More file actions
79 lines (70 loc) · 2.73 KB
/
Copy pathvariant.rs
File metadata and controls
79 lines (70 loc) · 2.73 KB
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
use convert_case::Case;
use convert_case_extras::is_case;
use darling::{Error, FromVariant, Result};
use syn::{Attribute, Ident};
use crate::{
attrs::item::CommonItemAttributes,
codegen::{VersionDefinition, item::VariantIdents},
};
/// This struct describes all available variant attributes, as well as the
/// variant name to display better diagnostics.
///
/// Data stored in this struct is validated using darling's `and_then` attribute.
/// During darlings validation, it is not possible to validate that action
/// versions match up with declared versions on the container. This validation
/// can be done using the associated [`VariantAttributes::validate_versions`][1]
/// function.
///
/// Rules shared across fields and variants can be found [here][2].
///
/// [1]: crate::attrs::item::VariantAttributes::validate_versions
/// [2]: crate::attrs::item::CommonItemAttributes
#[derive(Debug, FromVariant)]
#[darling(
attributes(versioned),
forward_attrs,
and_then = VariantAttributes::validate
)]
pub struct VariantAttributes {
#[darling(flatten)]
pub common: CommonItemAttributes,
// The ident (automatically extracted by darling) cannot be moved into the
// shared item attributes because for struct fields, the type is
// `Option<Ident>`, while for enum variants, the type is `Ident`.
pub ident: Ident,
// This must be named `attrs` for darling to populate it accordingly, and
// cannot live in common because Vec<Attribute> is not implemented for
// FromMeta.
/// The original attributes for the field.
pub attrs: Vec<Attribute>,
}
impl VariantAttributes {
/// This associated function is called by darling (see and_then attribute)
/// after it successfully parsed the attribute. This allows custom
/// validation of the attribute which extends the validation already in
/// place by darling.
///
/// Internally, it calls out to other specialized validation functions.
fn validate(self) -> Result<Self> {
let mut errors = Error::accumulator();
errors.handle(
self.common
.validate(VariantIdents::from(self.ident.clone()), &self.attrs),
);
// Validate names of renames
for change in &self.common.changes {
if let Some(from_name) = &change.from_name
&& !is_case(from_name.as_str(), Case::Pascal)
{
errors.push(
Error::custom("renamed variant must use PascalCase")
.with_span(&from_name.span()),
)
}
}
errors.finish_with(self)
}
pub fn validate_versions(&self, versions: &[VersionDefinition]) -> Result<()> {
self.common.validate_versions(versions)
}
}