Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions crates/stackable-versioned-macros/src/attrs/item/field.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use darling::{Error, FromField, Result, util::Flag};
use syn::{Attribute, Ident};

use crate::{attrs::item::CommonItemAttributes, codegen::VersionDefinition, utils::FieldIdent};
use crate::{
attrs::item::CommonItemAttributes,
codegen::{VersionDefinition, item::FieldIdents},
};

/// This struct describes all available field attributes, as well as the field
/// name to display better diagnostics.
Expand Down Expand Up @@ -57,7 +60,9 @@ impl FieldAttributes {
.expect("internal error: field must have an ident")
.clone();

self.common.validate(FieldIdent::from(ident), &self.attrs)?;
self.common
.validate(FieldIdents::from(ident), &self.attrs)?;

Ok(self)
}

Expand Down
57 changes: 29 additions & 28 deletions crates/stackable-versioned-macros/src/attrs/item/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use syn::{Attribute, Path, Type, spanned::Spanned};

use crate::{
codegen::{VersionDefinition, item::ItemStatus},
utils::ItemIdentExt,
utils::ItemIdents,
};

mod field;
Expand Down Expand Up @@ -50,14 +50,14 @@ pub struct CommonItemAttributes {
// it contains functions which can only be called after the initial parsing and validation because
// they need additional context, namely the list of versions defined on the container or module.
impl CommonItemAttributes {
pub fn validate(&self, item_ident: impl ItemIdentExt, item_attrs: &[Attribute]) -> Result<()> {
pub fn validate(&self, item_idents: impl ItemIdents, item_attrs: &[Attribute]) -> Result<()> {
let mut errors = Error::accumulator();

errors.handle(self.validate_action_combinations(&item_ident));
errors.handle(self.validate_action_order(&item_ident));
errors.handle(self.validate_item_name(&item_ident));
errors.handle(self.validate_action_combinations(&item_idents));
errors.handle(self.validate_action_order(&item_idents));
errors.handle(self.validate_item_name(&item_idents));
errors.handle(self.validate_added_action());
errors.handle(self.validate_changed_action(&item_ident));
errors.handle(self.validate_changed_action(&item_idents));
errors.handle(self.validate_item_attributes(item_attrs));

errors.finish()
Expand Down Expand Up @@ -106,23 +106,23 @@ impl CommonItemAttributes {
/// at least one version before being changed.
/// - `changed` and `deprecated` using the same version: Again, the same
/// rules from above apply here as well.
fn validate_action_combinations(&self, item_ident: &impl ItemIdentExt) -> Result<()> {
fn validate_action_combinations(&self, item_idents: &impl ItemIdents) -> Result<()> {
match (&self.added, &self.changes, &self.deprecated) {
(Some(added), _, Some(deprecated)) if *added.since == *deprecated.since => Err(
Error::custom("cannot be marked as `added` and `deprecated` in the same version")
.with_span(item_ident),
.with_span(item_idents.original()),
),
(Some(added), changed, _) if changed.iter().any(|r| *r.since == *added.since) => Err(
Error::custom("cannot be marked as `added` and `changed` in the same version")
.with_span(item_ident),
.with_span(item_idents.original()),
),
(_, changed, Some(deprecated))
if changed.iter().any(|r| *r.since == *deprecated.since) =>
{
Err(Error::custom(
"cannot be marked as `deprecated` and `changed` in the same version",
)
.with_span(item_ident))
.with_span(item_idents.original()))
}
_ => Ok(()),
}
Expand All @@ -140,7 +140,7 @@ impl CommonItemAttributes {
/// version of the added action.
/// - All `changed` actions must use a greater version than `added` but a
/// lesser version than `deprecated`.
fn validate_action_order(&self, item_ident: &impl ItemIdentExt) -> Result<()> {
fn validate_action_order(&self, item_idents: &impl ItemIdents) -> Result<()> {
let added_version = self.added.as_ref().map(|a| *a.since);
let deprecated_version = self.deprecated.as_ref().map(|d| *d.since);

Expand All @@ -152,7 +152,7 @@ impl CommonItemAttributes {
if added_version > deprecated_version {
return Err(Error::custom(format!(
"cannot marked as `added` in version `{added_version}` while being marked as `deprecated` in an earlier version `{deprecated_version}`"
)).with_span(item_ident));
)).with_span(item_idents.original()));
}
}

Expand All @@ -165,7 +165,7 @@ impl CommonItemAttributes {
return Err(Error::custom(
"all changes must use versions higher than `added` and lower than `deprecated`",
)
.with_span(item_ident));
.with_span(item_idents.original()));
}

Ok(())
Expand All @@ -180,21 +180,22 @@ impl CommonItemAttributes {
/// - Fields or variants marked as deprecated need to include the
/// deprecation prefix in their name. The prefix must not be included for
/// fields or variants which are not deprecated.
fn validate_item_name(&self, item_ident: &impl ItemIdentExt) -> Result<()> {
let starts_with_deprecated = item_ident.starts_with_deprecated_prefix();
fn validate_item_name(&self, item_idents: &impl ItemIdents) -> Result<()> {
let starts_with_deprecated = item_idents.starts_with_deprecation_prefix();

if self.deprecated.is_some() && !starts_with_deprecated {
return Err(Error::custom(format!(
"marked as `deprecated` and thus must include the `{deprecated_prefix}` prefix",
deprecated_prefix = item_ident.deprecated_prefix()
"marked as `deprecated` and thus must include the `{deprecation_prefix}` prefix",
deprecation_prefix = item_idents.deprecation_prefix()
))
.with_span(item_ident));
.with_span(item_idents.original()));
}

if self.deprecated.is_none() && starts_with_deprecated {
return Err(Error::custom(
format!("not marked as `deprecated` and thus must not include the `{deprecated_prefix}` prefix", deprecated_prefix = item_ident.deprecated_prefix())
).with_span(item_ident));
return Err(Error::custom(format!(
"not marked as `deprecated` and thus must not include the `{deprecation_prefix}` prefix",
deprecation_prefix = item_idents.deprecation_prefix()
)).with_span(item_idents.original()));
}

Ok(())
Expand All @@ -218,7 +219,7 @@ impl CommonItemAttributes {
/// This associated function is called by the top-level validation function
/// and validates that parameters provided to the `changed` actions are
/// valid.
fn validate_changed_action(&self, item_ident: &impl ItemIdentExt) -> Result<()> {
fn validate_changed_action(&self, item_ident: &impl ItemIdents) -> Result<()> {
let mut errors = Error::accumulator();

for change in &self.changes {
Expand All @@ -230,7 +231,7 @@ impl CommonItemAttributes {

// This ensures that `from_name` doesn't include the deprecation prefix.
if let Some(from_name) = change.from_name.as_ref() {
if from_name.starts_with(item_ident.deprecated_prefix()) {
if from_name.starts_with(item_ident.deprecation_prefix()) {
errors.push(
Error::custom(
"the previous name must not start with the deprecation prefix",
Expand Down Expand Up @@ -291,17 +292,17 @@ impl CommonItemAttributes {
impl CommonItemAttributes {
pub fn into_changeset(
self,
ident: &impl ItemIdentExt,
idents: &impl ItemIdents,
ty: Type,
) -> Option<BTreeMap<Version, ItemStatus>> {
// TODO (@Techassi): Use Change instead of ItemStatus
if let Some(deprecated) = self.deprecated {
let deprecated_ident = ident.deref();
let deprecated_ident = idents.original();

// When the item is deprecated, any change which occurred beforehand
// requires access to the item ident to infer the item ident for
// the latest change.
let mut ident = ident.as_cleaned_ident();
let mut ident = idents.cleaned().clone();
let mut ty = ty;

let mut actions = BTreeMap::new();
Expand Down Expand Up @@ -361,7 +362,7 @@ impl CommonItemAttributes {

Some(actions)
} else if !self.changes.is_empty() {
let mut ident = ident.deref().clone();
let mut ident = idents.original().clone();
let mut ty = ty;

let mut actions = BTreeMap::new();
Expand Down Expand Up @@ -419,7 +420,7 @@ impl CommonItemAttributes {
*added.since,
ItemStatus::Addition {
default_fn: added.default_fn.deref().clone(),
ident: ident.deref().clone(),
ident: idents.original().clone(),
ty: Box::new(ty),
},
);
Expand Down
7 changes: 5 additions & 2 deletions crates/stackable-versioned-macros/src/attrs/item/variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use convert_case::{Case, Casing};
use darling::{Error, FromVariant, Result};
use syn::{Attribute, Ident};

use crate::{attrs::item::CommonItemAttributes, codegen::VersionDefinition, utils::VariantIdent};
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.
Expand Down Expand Up @@ -51,7 +54,7 @@ impl VariantAttributes {

errors.handle(
self.common
.validate(VariantIdent::from(self.ident.clone()), &self.attrs),
.validate(VariantIdents::from(self.ident.clone()), &self.attrs),
);

// Validate names of renames
Expand Down
Loading