wdpe_macros/lib.rs
1extern crate proc_macro;
2
3mod element;
4mod event;
5mod lsdata;
6mod subelement;
7pub(crate) mod utils;
8
9use proc_macro::TokenStream;
10
11/// Derive macro that generates deserialization, trait impls, and accessor
12/// methods for WebDynpro LsData structs.
13///
14/// The user writes a struct with `Option<T>` fields and
15/// `#[wd_lsdata(index = "N")]` attributes. The derive macro generates:
16///
17/// 1. A `serde::Deserialize` impl via a private shadow struct (with
18/// `#[serde(rename = "N")]` derived from `wd_lsdata(index)`)
19/// 2. `Clone`, `Debug`, and `Default` trait implementations
20/// 3. Accessor methods (`fn field(&self) -> Option<&T>`) for every field
21///
22/// # Example
23///
24/// ```ignore
25/// #[derive(WdLsData)]
26/// #[allow(unused)]
27/// pub struct ButtonLsData {
28/// #[wd_lsdata(index = "0")]
29/// text: Option<String>,
30/// #[wd_lsdata(index = "2")]
31/// design: Option<ButtonDesign>,
32/// }
33/// ```
34#[proc_macro_derive(WdLsData, attributes(wd_lsdata))]
35pub fn derive_wd_lsdata(input: TokenStream) -> TokenStream {
36 lsdata::derive_wd_lsdata_impl(input.into()).into()
37}
38
39/// Derive macro for WebDynpro elements.
40///
41/// Generates the definition struct, `Element` trait impl, optional
42/// `Interactable` trait impl, constructor, and `inventory::submit!`
43/// registration.
44///
45/// # Example
46///
47/// ```ignore
48/// #[derive(WdElement)]
49/// #[wd_element(control_id = "B", element_name = "Button")]
50/// #[wd_element(interactable)]
51/// #[wd_element(def = "ButtonDef", def_doc = "Button definition")]
52/// #[wd_element(lsdata = "ButtonLsData")]
53/// pub struct Button<'a> {
54/// id: Cow<'static, str>,
55/// #[wd_element(element_ref)]
56/// element_ref: scraper::ElementRef<'a>,
57/// #[wd_element(lsdata_field)]
58/// lsdata: OnceCell<ButtonLsData>,
59/// #[wd_element(lsevents_field)]
60/// lsevents: OnceCell<Option<EventParameterMap>>,
61/// }
62/// ```
63#[proc_macro_derive(WdElement, attributes(wd_element))]
64pub fn derive_wd_element(input: TokenStream) -> TokenStream {
65 element::derive_wd_element_impl(input.into()).into()
66}
67
68/// Derive macro for WebDynpro sub-elements.
69///
70/// Generates the sub-element definition struct, `SubElement` trait impl,
71/// and constructor.
72///
73/// # Example
74///
75/// ```ignore
76/// #[derive(WdSubElement)]
77/// #[wd_element(parent = "SapTable", parent_def = "SapTableDef")]
78/// #[wd_element(subcontrol_id = "HC", element_name = "SapTableHeaderCell")]
79/// #[wd_element(def = "SapTableHeaderCellDef")]
80/// #[wd_element(lsdata = "SapTableHeaderCellLsData")]
81/// pub struct SapTableHeaderCell<'a> {
82/// id: Cow<'static, str>,
83/// #[wd_element(element_ref)]
84/// element_ref: scraper::ElementRef<'a>,
85/// #[wd_element(lsdata_field)]
86/// lsdata: OnceCell<SapTableHeaderCellLsData>,
87/// }
88/// ```
89#[proc_macro_derive(WdSubElement, attributes(wd_element))]
90pub fn derive_wd_subelement(input: TokenStream) -> TokenStream {
91 subelement::derive_wd_subelement_impl(input.into()).into()
92}
93
94/// Attribute macro that generates event-firing method bodies for interactable elements.
95///
96/// **Note:** This macro must only be applied to methods on types that implement
97/// the `Interactable` trait, as the generated code calls `self.fire_event()`.
98/// Applying it to non-interactable elements will result in a compile error.
99///
100/// Replaces the function body and return type. Automatically inserts
101/// the `"Id"` parameter from `self.id` and any declared params.
102///
103/// # Example
104///
105/// ```ignore
106/// impl<'a> Button<'a> {
107/// #[wd_event(name = "Press")]
108/// pub fn press(&self) {}
109///
110/// #[wd_event(name = "Activate", params(ctrl: bool => "Ctrl", shift: bool => "Shift"))]
111/// pub fn activate(&self, ctrl: bool, shift: bool) {}
112/// }
113/// ```
114#[proc_macro_attribute]
115pub fn wd_event(attr: TokenStream, item: TokenStream) -> TokenStream {
116 event::wd_event_impl(attr.into(), item.into()).into()
117}