Skip to content
Open
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
16 changes: 14 additions & 2 deletions rclrs-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ mod errors;
mod parameter_set;
mod parameter_variant;

/// Declares a struct's fields as a group of ROS 2 parameters.
/// Declares a group of ROS 2 parameters: a struct whose fields are the parameters, or an enum
/// whose variants are the shapes the group can take.
///
/// See the `rclrs::ParameterSet` trait for the full description, and
/// `rclrs::NodeState::declare_parameters` for how to declare the result on a node.
Expand All @@ -22,7 +23,18 @@ mod parameter_variant;
/// must evaluate to `Self`, e.g. `Self::default()`. A field with its own
/// `#[param(default = ...)]` keeps that default.
/// * `#[parameters(handles = MyHandles)]`: name of the generated handles struct. Defaults to
/// the struct's own name with `Params` appended.
/// the type's own name with `Params` appended.
///
/// # Enum attributes
///
/// An enum set declares a read-only string parameter saying which variant is in use, and then
/// that variant's parameters.
///
/// * `#[parameters(tag = "type")]`: the name of that parameter. Defaults to `type`.
/// * `#[parameters(rename_all = "snake_case")]`: the naming convention for its values, one of
/// `snake_case`, `kebab-case`, `lowercase`, `UPPERCASE` or `SCREAMING_SNAKE_CASE`. Without it,
/// variant names are used as written. `#[param(rename = "...")]` on a variant sets its value
/// exactly.
///
/// # Field attributes
///
Expand Down
53 changes: 51 additions & 2 deletions rclrs-macros/src/parameter_set/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use syn::{spanned::Spanned, Attribute, Expr, ExprRange, Ident, LitStr, RangeLimits};

use crate::errors::Errors;
use crate::{errors::Errors, parameter_variant::attrs::RenameAll};

/// Struct-level configuration from `#[parameters(...)]`.
#[derive(Default)]
Expand All @@ -15,6 +15,10 @@ pub(crate) struct SetAttrs {
pub default: Option<Expr>,
/// Name for the generated handles struct.
pub handles: Option<Ident>,
/// Enum sets only: the name of the parameter that says which variant is in use.
pub tag: Option<LitStr>,
/// Enum sets only: the naming convention for tag values.
pub rename_all: Option<(RenameAll, LitStr)>,
}

impl SetAttrs {
Expand All @@ -32,10 +36,27 @@ impl SetAttrs {
parsed.default = Some(meta.value()?.parse()?);
} else if meta.path.is_ident("handles") {
parsed.handles = Some(meta.value()?.parse()?);
} else if meta.path.is_ident("tag") {
parsed.tag = Some(meta.value()?.parse()?);
} else if meta.path.is_ident("rename_all") {
let value: LitStr = meta.value()?.parse()?;
match RenameAll::parse(&value.value()) {
Some(convention) => parsed.rename_all = Some((convention, value)),
None => {
return Err(syn::Error::new(
value.span(),
format!(
"unknown naming convention {:?}; expected one of {}",
value.value(),
RenameAll::NAMES.join(", "),
),
))
}
}
} else {
return Err(meta.error(format!(
"unknown `parameters` option `{}`; expected one of `namespace`, \
`default`, `handles`",
`default`, `handles`, `tag`, `rename_all`",
path_name(&meta.path),
)));
}
Expand Down Expand Up @@ -199,6 +220,34 @@ impl FieldAttrs {
}
}

/// The span of any option other than `rename`, for reporting attributes that mean nothing on
/// an enum variant.
pub fn conflicts_with_rename(&self) -> Option<proc_macro2::Span> {
macro_rules! first_of {
($($field:ident),*) => {
$(if let Some(value) = &self.$field {
return Some(value.span());
})*
};
}
first_of!(
default,
description,
constraints,
range,
step,
read_only,
ignore_override,
discard_mismatching_prior_value,
validate,
on_change,
discriminate,
flatten,
skip
);
None
}

/// The span of any option other than `skip` itself, for reporting attributes that `skip`
/// makes meaningless.
pub fn conflicts_with_skip(&self) -> Option<proc_macro2::Span> {
Expand Down
Loading
Loading