kas_macros/lib.rs
1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! KAS macros
7//!
8//! This crate extends [`impl-tools`](https://docs.rs/impl-tools/).
9
10extern crate proc_macro;
11
12use impl_tools_lib::{anon, autoimpl, scope};
13use proc_macro::TokenStream;
14use proc_macro_error2::{emit_call_site_error, emit_error, proc_macro_error};
15use syn::parse_macro_input;
16use syn::spanned::Spanned;
17
18mod collection;
19mod extends;
20mod make_layout;
21mod scroll_traits;
22mod visitors;
23mod widget;
24mod widget_args;
25mod widget_derive;
26
27/// Implement `Default`
28///
29/// See [`impl_tools::impl_default`](https://docs.rs/impl-tools/latest/impl_tools/attr.impl_default.html)
30/// for full documentation.
31#[proc_macro_attribute]
32#[proc_macro_error]
33pub fn impl_default(attr: TokenStream, item: TokenStream) -> TokenStream {
34    let mut toks = item.clone();
35    match syn::parse::<impl_tools_lib::ImplDefault>(attr) {
36        Ok(attr) => toks.extend(TokenStream::from(attr.expand(item.into()))),
37        Err(err) => {
38            emit_call_site_error!(err);
39            // Since this form of invocation only adds implementations, we can
40            // safely output the original item, thus reducing secondary errors.
41        }
42    }
43    toks
44}
45
46/// A variant of the standard `derive` macro
47///
48/// See [`impl_tools::autoimpl`](https://docs.rs/impl-tools/latest/impl_tools/attr.autoimpl.html)
49/// for full documentation.
50///
51/// The following traits are supported:
52///
53/// | Path | *ignore* | *using* | *notes* |
54/// |----- |--- |--- |--- |
55/// | [`::core::borrow::Borrow<T>`] | - | borrow target | `T` is type of target field |
56/// | [`::core::borrow::BorrowMut<T>`] | - | borrow target | `T` is type of target field |
57/// | [`::core::clone::Clone`] | yes | - | ignored fields use `Default::default()` |
58/// | [`::core::cmp::Eq`] | * | - | *allowed with `PartialEq` |
59/// | [`::core::cmp::Ord`] | yes | - | |
60/// | [`::core::cmp::PartialEq`] | yes | - | |
61/// | [`::core::cmp::PartialOrd`] | yes | - | |
62/// | [`::core::convert::AsRef<T>`] | - | ref target | `T` is type of target field |
63/// | [`::core::convert::AsMut<T>`] | - | ref target | `T` is type of target field |
64/// | [`::core::default::Default`] | - | - | [`macro@impl_default`] is a more flexible alternative |
65/// | [`::core::fmt::Debug`] | yes | - | |
66/// | [`::core::hash::Hash`] | yes | - | |
67/// | [`::core::marker::Copy`] | * | - | *allowed with `Clone` |
68/// | [`::core::ops::Deref`] | - | deref target | `type Target` is type of target field |
69/// | [`::core::ops::DerefMut`] | - | deref target | `type Target` is type of target field |
70#[proc_macro_attribute]
71#[proc_macro_error]
72pub fn autoimpl(attr: TokenStream, item: TokenStream) -> TokenStream {
73    use autoimpl::ImplTrait;
74    use scroll_traits::ImplScrollable;
75    use std::iter::once;
76
77    let mut toks = item.clone();
78    match syn::parse::<autoimpl::Attr>(attr) {
79        Ok(autoimpl::Attr::ForDeref(ai)) => toks.extend(TokenStream::from(ai.expand(item.into()))),
80        Ok(autoimpl::Attr::ImplTraits(ai)) => {
81            // We could use lazy_static to construct a HashMap for fast lookups,
82            // but given the small number of impls a "linear map" is fine.
83            let find_impl = |path: &syn::Path| {
84                autoimpl::STD_IMPLS
85                    .iter()
86                    .cloned()
87                    .chain(once(&ImplScrollable as &dyn ImplTrait))
88                    .find(|impl_| impl_.path().matches_ident_or_path(path))
89            };
90            toks.extend(TokenStream::from(ai.expand(item.into(), find_impl)))
91        }
92        Err(err) => {
93            emit_call_site_error!(err);
94            // Since autoimpl only adds implementations, we can safely output
95            // the original item, thus reducing secondary errors.
96        }
97    }
98    toks
99}
100
101const IMPL_SCOPE_RULES: [&dyn scope::ScopeAttr; 3] = [
102    &scope::AttrImplDefault,
103    &widget_args::AttrImplWidget,
104    &widget_derive::AttrDeriveWidget,
105];
106
107fn find_attr(path: &syn::Path) -> Option<&'static dyn scope::ScopeAttr> {
108    IMPL_SCOPE_RULES
109        .iter()
110        .cloned()
111        .find(|rule| rule.path().matches(path))
112}
113
114/// Scope supporting `impl Self` and advanced attribute macros
115///
116/// This macro facilitates definition of a type (struct, enum or union) plus
117/// implementations via `impl Self { .. }` syntax: `Self` is expanded to the
118/// type's name, including generics and bounds (as defined on the type).
119///
120/// Caveat: `rustfmt` can not yet format contents (see
121/// [rustfmt#5254](https://github.com/rust-lang/rustfmt/issues/5254),
122/// [rustfmt#5538](https://github.com/rust-lang/rustfmt/pull/5538)).
123///
124/// Note: prefer [`macro@impl_self`] over this macro unless using
125/// [`macro@impl_default`]. This macro will be removed once
126/// [RFC 3681](https://github.com/rust-lang/rfcs/pull/3681) (default field
127/// values) is stable in this crate's MSRV.
128///
129/// See [`impl_tools::impl_scope`](https://docs.rs/impl-tools/latest/impl_tools/macro.impl_scope.html)
130/// for full documentation.
131///
132/// ## Special attribute macros
133///
134/// Additionally, `impl_scope!` supports special attribute macros evaluated
135/// within its scope:
136///
137/// -   [`#[impl_default]`](macro@impl_default): implement [`Default`] using
138///     field initializers (which are not legal syntax outside of `impl_scope!`)
139/// -   [`#[widget]`](macro@widget): implement `kas::Widget` trait family
140///
141/// Note: matching these macros within `impl_scope!` does not use path
142/// resolution. Using `#[kas_macros::impl_default]` would resolve the variant
143/// of this macro which *doesn't support* field initializers.
144#[proc_macro_error]
145#[proc_macro]
146pub fn impl_scope(input: TokenStream) -> TokenStream {
147    let mut scope = parse_macro_input!(input as scope::Scope);
148    scope.apply_attrs(find_attr);
149    scope.expand().into()
150}
151
152fn find_impl_self_attrs(path: &syn::Path) -> Option<&'static dyn scope::ScopeAttr> {
153    use scope::ScopeAttr;
154    if widget_args::AttrImplWidget.path().matches(path) {
155        Some(&widget_args::AttrImplWidget)
156    } else if widget_derive::AttrDeriveWidget.path().matches(path) {
157        Some(&widget_derive::AttrDeriveWidget)
158    } else {
159        None
160    }
161}
162
163/// Implement a type with `impl Self` syntax
164///
165/// This attribute macro supports a type (struct, enum, type alias or union)
166/// definition plus associated `impl` items within a `mod`.
167///
168/// Macro expansion discards the `mod` entirely, placing all contents into the
169/// outer scope. This simplifies privacy rules in many use-cases, and highlights
170/// that the usage of `mod` is purely a hack to make the macro input valid Rust
171/// syntax (and thus compatible with `rustfmt`).
172///
173/// ## Special attribute macros
174///
175/// Additionally, `#[impl_self]` supports special attribute macros evaluated
176/// within its scope:
177///
178/// -   [`#[widget]`](macro@widget): implement `kas::Widget` trait family
179///
180/// ## Syntax
181///
182/// > _ImplSelf_ :\
183/// >    `#[impl_self]` `mod` _Name_ `{` _ScopeItem_ _ItemImpl_ * `}`
184/// >
185/// > _ScopeItem_ :\
186/// >    _ItemEnum_ | _ItemStruct_ | _ItemType_ | _ItemUnion_
187///
188/// Here, _ItemEnum_, _ItemStruct_, _ItemType_ and _ItemUnion_ are `enum`,
189/// `struct`, `type` alias and `union` definitions respectively. Whichever of
190/// these is used, it must match the module name _Name_.
191///
192/// _ItemImpl_ is an `impl` item. It may use the standard implementation syntax
193/// (e.g. `impl Debug for MyType { .. }`) or `impl Self` syntax (see below).
194///
195/// The `mod` may not contain any other items, except `doc` items (documentation
196/// on the module itself is ignored in favour of documentation on the defined
197/// type) and attributes (which apply as usual).
198///
199/// ### `impl Self` syntax
200///
201/// `impl Self` "syntax" is syntactically-valid (but not semantically-valid)
202/// Rust syntax for writing inherent and trait `impl` blocks:
203///
204/// -   `impl Self { ... }` — an inherent `impl` item on the defined type
205/// -   `impl Debug for Self { ... }` — a trait `impl` item on the defined type
206///
207/// Generic parameters and bounds are copied from the type definition.
208/// Additional generic parameters may be specified; these extend the list of
209/// generic parameters on the type itself, and thus must have distinct names.
210/// Additional bounds (where clauses) may be specified; these extend the list of
211/// bounds on the type itself.
212///
213/// ## Example
214///
215/// ```
216/// #[kas_macros::impl_self]
217/// mod Pair {
218///     /// A pair of values of type `T`
219///     pub struct Pair<T>(T, T);
220///
221///     impl Self {
222///         pub fn new(a: T, b: T) -> Self {
223///             Pair(a, b)
224///         }
225///     }
226///
227///     impl Self where T: Clone {
228///         pub fn splat(a: T) -> Self {
229///             let b = a.clone();
230///             Pair(a, b)
231///         }
232///     }
233/// }
234/// ```
235#[proc_macro_attribute]
236#[proc_macro_error]
237pub fn impl_self(attr: TokenStream, input: TokenStream) -> TokenStream {
238    let _ = parse_macro_input!(attr as scope::ScopeModAttrs);
239    let mut scope = parse_macro_input!(input as scope::ScopeMod).contents;
240    scope.apply_attrs(find_impl_self_attrs);
241    scope.expand().into()
242}
243
244/// Attribute to implement the `kas::Widget` family of traits
245///
246/// This may *only* be used within the [`macro@impl_self`], [`impl_scope!`]
247/// and [`impl_anon!`] macros. It does not need to be imported (it is resolved
248/// by the afore-mentioned macros).
249///
250/// Assists implementation of the [`Widget`], [`Events`], [`Layout`] and [`Tile`] traits.
251/// Implementations of these traits are generated if missing or augmented with
252/// missing method implementations.
253///
254/// This macro may inject methods into existing [`Layout`] / [`Tile`] /
255/// [`Events`] / [`Widget`] implementations.
256/// (In the case of multiple implementations of the same trait, as used for
257/// specialization, only the first implementation of each trait is extended.)
258///
259/// See also the [`macro@layout`] attribute which assists in implementing
260/// [`Layout`].
261///
262/// ## Fields
263///
264/// The struct must contain a field of type `widget_core!()` (usually named
265/// `core`). The macro `widget_core!()` is a placeholder, expanded by
266/// `#[widget]` and used to identify the field used (any name may be used).
267/// This type implements [`Default`] and [`Clone`], though the clone is not an
268/// exact clone (cloned widgets must still be configured).
269///
270/// Assuming the deriving type is a `struct` or `tuple struct`, fields support
271/// the following attributes:
272///
273/// -   `#[widget]`: marks the field as a [`Widget`] to be configured, enumerated by
274///     [`Widget::get_child`] and included by glob layouts
275/// -   `#[widget(expr)]`: the same, but maps the data reference type; `expr` is
276///     an expression returning a reference to the child widget's input data;
277///     available inputs are `self`, `data` (own input data) and `index`
278///     (of the child).
279/// -   `#[widget = expr]`: an alternative way of writing the above
280/// -   `#[collection]`: the field is a [`Collection`] of widgets
281///
282/// ## Examples
283///
284/// A simple example is the
285/// [`Frame`](https://docs.rs/kas-widgets/latest/kas_widgets/struct.Frame.html) widget:
286///
287/// ```ignore
288/// #[impl_self]
289/// mod Frame {
290///     /// A frame around content
291///     #[derive(Clone, Default)]
292///     #[widget]
293///     #[layout(frame!(self.inner))]
294///     pub struct Frame<W: Widget> {
295///         core: widget_core!(),
296///         #[widget]
297///         pub inner: W,
298///     }
299///
300///     impl Self {
301///         /// Construct a frame
302///         #[inline]
303///         pub fn new(inner: W) -> Self {
304///             Frame {
305///                 core: Default::default(),
306///                 inner,
307///             }
308///         }
309///     }
310/// }
311/// ```
312///
313/// ## Method modification
314///
315/// As a policy, this macro *may* inject code into user-defined methods of
316/// `Widget` and its super traits, such that:
317///
318/// -   The modification cannot have harmful side effects (other than reported
319///     errors).
320/// -   All side effects observable outside of reported error cases must be
321///     documented in the widget method documentation.
322///
323/// As an example, status checks are injected into some `Layout` methods to
324/// enforce the expected call order of methods at runtime in debug builds.
325///
326/// ## Debugging
327///
328/// To inspect the output of this macro, set the environment variable
329/// `KAS_DEBUG_WIDGET` to the name of the widget concerned, dump the output to
330/// a temporary file and format. For example:
331/// ```sh
332/// KAS_DEBUG_WIDGET=Border cargo build > temp.rs
333/// rustfmt temp.rs
334/// ```
335///
336/// [`Widget`]: https://docs.rs/kas/latest/kas/trait.Widget.html
337/// [`Widget::get_child`]: https://docs.rs/kas/latest/kas/trait.Widget.html#method.get_child
338/// [`Layout`]: https://docs.rs/kas/latest/kas/trait.Layout.html
339/// [`Tile`]: https://docs.rs/kas/latest/kas/trait.Tile.html
340/// [`Events`]: https://docs.rs/kas/latest/kas/trait.Events.html
341/// [`Collection`]: https://docs.rs/kas/latest/kas/trait.Collection.html
342#[proc_macro_attribute]
343#[proc_macro_error]
344pub fn widget(_: TokenStream, item: TokenStream) -> TokenStream {
345    emit_call_site_error!("must be used within scope of #[impl_self], impl_scope! or impl_anon!");
346    item
347}
348
349/// Provide a default implementation of the [`Layout`] trait for a widget
350///
351/// The [`macro@widget`] macro uses this attribute to implement
352/// [`MacroDefinedLayout`] for the widget, then adjusts the default
353/// implementations of each [`Layout`] method to call the corresponding
354/// [`MacroDefinedLayout`] method.
355///
356/// This attribute may *only* appear after the [`macro@widget`] attribute (it is
357/// not a stand-alone macro). It does not need to be imported (it is resolved by
358/// [`macro@widget`]).
359///
360/// ## Layout
361///
362/// Widget layout may be specified by implementing the `Layout` trait and/or
363/// with a `#[layout(...)]` attribute (this must appear after `#[widget]` on the
364/// type definition). The latter accepts the following
365/// syntax, where _Layout_ is any of the below.
366///
367/// Using the `#[layout]` attribute will also generate a corresponding
368/// implementation of `Tile::nav_next`, with a couple of exceptions
369/// (where macro-time analysis is insufficient to implement this method).
370///
371/// > [_Column_], [_Row_], [_List_] [_AlignedColumn_], [_AlignedRow_], [_Grid_],
372/// > [_Float_], [_Frame_] :\
373/// >    These stand-alone macros are explicitly supported in this position.\
374/// >
375/// > _Single_ :\
376/// >    `self` `.` _Member_\
377/// >    A named child: `self.foo` (more precisely, this matches any
378/// > expression starting `self`, and uses `&mut (#expr)`).
379/// >
380/// > _WidgetConstructor_ :\
381/// >    _Expr_\
382/// >    An expression yielding a widget, e.g.
383/// > `Label::new("Hello world")`. The result must be an object of some type
384/// > `W: Widget<Data = ()>`. This widget will be stored in a hidden field and
385/// > is accessible through `Tile::get_child` but does not receive input data.
386/// >
387/// > _LabelLit_ :\
388/// >    _StrLit_\
389/// >    A string literal generates a label widget, e.g. "Hello
390/// > world". This is an internal type without text wrapping.
391///
392/// Additional syntax rules (not layout items):
393///
394/// > _Member_ :\
395/// >    _Ident_ | _Index_\
396/// >    The name of a struct field or an index into a tuple struct.
397///
398/// [`Layout`]: https://docs.rs/kas/latest/kas/trait.Layout.html
399/// [`MacroDefinedLayout`]: https://docs.rs/kas/latest/kas/trait.MacroDefinedLayout.html
400/// [_Column_]: https://docs.rs/kas-widgets/latest/kas_widgets/macro.column.html
401/// [_Row_]: https://docs.rs/kas-widgets/latest/kas_widgets/macro.row.html
402/// [_List_]: https://docs.rs/kas-widgets/latest/kas_widgets/macro.list.html
403/// [_Float_]: https://docs.rs/kas-widgets/latest/kas_widgets/macro.float.html
404/// [_Frame_]: https://docs.rs/kas-widgets/latest/kas_widgets/macro.frame.html
405/// [_Grid_]: https://docs.rs/kas-widgets/latest/kas_widgets/macro.grid.html
406/// [_AlignedColumn_]: https://docs.rs/kas-widgets/latest/kas_widgets/macro.aligned_column.html
407/// [_AlignedRow_]: https://docs.rs/kas-widgets/latest/kas_widgets/macro.aligned_row.html
408#[proc_macro_attribute]
409#[proc_macro_error]
410pub fn layout(_: TokenStream, item: TokenStream) -> TokenStream {
411    emit_call_site_error!("must follow use of #[widget]");
412    item
413}
414
415/// Derive the [`Widget`] family of traits
416///
417/// This may *only* be used within the [`macro@impl_self`], [`impl_scope!`]
418/// and [`impl_anon!`] macros.
419///
420/// This macro derives a [`Widget`] implementation from the inner field
421/// annotated with `#[widget]`.
422///
423/// ## Example
424///
425/// ```ignore
426/// #[impl_self]
427/// mod ScrollBarRegion {
428///     #[autoimpl(Deref, DerefMut using self.0)]
429///     #[derive(Clone, Default)]
430///     #[derive_widget]
431///     pub struct ScrollBarRegion<W: Widget>(#[widget] ScrollBars<ScrollRegion<W>>);
432/// }
433/// ```
434///
435/// ### Example mapping data
436///
437/// This macro supports mapping the data passed to the inner widget. The
438/// attribute annotating the inner field specifies the data map. It is required
439/// to specify the data type, either via an explicit `impl` of `Widget` or as
440/// below.
441///
442/// ```ignore
443/// #[impl_self]
444/// mod Map {
445///     #[autoimpl(Deref, DerefMut using self.inner)]
446///     #[autoimpl(Scrollable using self.inner where W: trait)]
447///     #[derive_widget(type Data = A)]
448///     pub struct Map<A, W: Widget, F>
449///     where
450///         F: for<'a> Fn(&'a A) -> &'a W::Data,
451///     {
452///         #[widget((self.map_fn)(data))]
453///         pub inner: W,
454///         map_fn: F,
455///         _data: PhantomData<A>,
456///     }
457/// }
458/// ```
459///
460/// ### A note on `Deref`
461///
462/// The above examples implement [`Deref`] over the inner widget. This is
463/// acceptable for a simple wrapping "derive widget". It is not recommended to
464/// implement [`Deref`] for non-derived widgets (i.e. when the outer widget has
465/// its own `Id`) due to the potential for method collision (e.g. `outer.id()`
466/// may resolve to `outer.deref().id()` when the trait providing `fn id` is not
467/// in scope, yet is available through a bound on the field).
468///
469/// [`Widget`]: https://docs.rs/kas/latest/kas/trait.Widget.html
470/// [`Deref`]: std::ops::Deref
471#[proc_macro_attribute]
472#[proc_macro_error]
473pub fn derive_widget(_: TokenStream, item: TokenStream) -> TokenStream {
474    emit_call_site_error!("must be used within scope of #[impl_self], impl_scope! or impl_anon!");
475    item
476}
477
478/// Construct a single-instance struct
479///
480/// Rust doesn't currently support [`impl Trait { ... }` expressions](https://github.com/canndrew/rfcs/blob/impl-trait-expressions/text/0000-impl-trait-expressions.md)
481/// or implicit typing of struct fields. This macro is a **hack** allowing that.
482///
483/// Example:
484/// ```
485/// # use kas_macros as kas;
486/// use std::fmt;
487/// fn main() {
488///     let world = "world";
489///     let says_hello_world = kas::impl_anon! {
490///         struct(&'static str = world);
491///         impl fmt::Display for Self {
492///             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
493///                 write!(f, "hello {}", self.0)
494///             }
495///         }
496///     };
497///     assert_eq!(format!("{}", says_hello_world), "hello world");
498/// }
499/// ```
500///
501/// That is, this macro creates an anonymous struct type (must be a struct),
502/// which may have trait implementations, then creates an instance of that
503/// struct.
504///
505/// Struct fields may have a fixed type or may be generic. Syntax is as follows:
506///
507/// -   **regular struct:** `ident: ty = value`
508/// -   **regular struct:** `ident: ty` (uses `Default` to construct value)
509/// -   **tuple struct:** `ty = value`
510/// -   **tuple struct:** `ty` (uses `Default` to construct value)
511///
512/// The field name, `ident`, may be `_` (anonymous field).
513///
514/// Refer to [examples](https://github.com/search?q=impl_anon+repo%3Akas-gui%2Fkas+path%3Aexamples&type=Code) for usage.
515#[proc_macro_error]
516#[proc_macro]
517pub fn impl_anon(input: TokenStream) -> TokenStream {
518    let mut input = parse_macro_input!(input as anon::Anon);
519    for field in input.fields.iter_mut() {
520        if matches!(&field.ty, syn::Type::Infer(_)) {
521            let span = if let Some(ref ident) = field.ident {
522                ident.span()
523            } else if let Some((ref eq, _)) = field.assignment {
524                eq.span()
525            } else {
526                // This is always available and should be the first choice,
527                // but it may be synthesized (thus no useful span).
528                // We can't test since Span::eq is unstable!
529                field.ty.span()
530            };
531            emit_error!(span, "expected `: TYPE`");
532        }
533    }
534    let mut scope = input.into_scope();
535    scope.apply_attrs(find_attr);
536    scope.expand().into()
537}
538
539/// Index of a child widget
540///
541/// This macro is usable only within an [`macro@impl_self`], [`impl_scope!`] or
542/// [`impl_anon!`] macro using the [`macro@widget`] attribute.
543///
544/// Example usage: `widget_index![self.a]`. If `a` is a child widget (a field
545/// marked with the `#[widget]` attribute), then this expands to the child
546/// widget's index (as used by [`Widget::get_child`]). Otherwise, this is an error.
547///
548/// [`Widget::get_child`]: https://docs.rs/kas/latest/kas/trait.Widget.html#method.get_child
549#[proc_macro_error]
550#[proc_macro]
551pub fn widget_index(input: TokenStream) -> TokenStream {
552    let input = parse_macro_input!(input as visitors::UnscopedInput);
553    input.into_token_stream().into()
554}
555
556/// Macro to set the `rect` stored in the widget core
557///
558/// Widgets have a hidden field of type [`Rect`] in their `widget_core!()`, used
559/// to implement method [`Layout::rect`]. This macro assigns to that field.
560///
561/// This macro is usable only within the definition of `Layout::set_rect` within
562/// an [`macro@impl_self`], [`impl_scope!`] or [`impl_anon!`] macro using the
563/// [`macro@widget`] attribute.
564///
565/// The method `Layout::rect` will be generated if this macro is used by the
566/// widget, otherwise a definition of the method must be provided.
567///
568/// Example usage:
569/// ```ignore
570/// fn set_rect(&mut self, _: &mut ConfigCx, rect: Rect, _: AlignHints) {
571///     widget_set_rect!(rect);
572/// }
573/// ```
574///
575/// [`Rect`]: https://docs.rs/kas/latest/kas/geom/struct.Rect.html
576/// [`Layout::rect`]: https://docs.rs/kas/latest/kas/trait.Layout.html#method.rect
577#[proc_macro_error]
578#[proc_macro]
579pub fn widget_set_rect(input: TokenStream) -> TokenStream {
580    let input = parse_macro_input!(input as visitors::UnscopedInput);
581    input.into_token_stream().into()
582}
583
584/// Generate an anonymous struct which implements [`kas::Collection`]
585///
586/// # Syntax
587///
588/// > _Collection_ :\
589/// >    `collection!` `[` _Items_<sup>\?</sup> `]`
590/// >
591/// > _Items_ :\
592/// >    (_Item_ `,`)<sup>\*</sup> _Item_ `,`<sup>\?</sup>
593///
594/// In this case, _Item_ may be:
595///
596/// -   A string literal (interpreted as a label widget), optionally followed by
597///     an [`align`] or [`pack`] method call
598/// -   An expression yielding an object implementing `Widget<Data = _A>`
599///
600/// In case all _Item_ instances are a string literal, the data type of the
601/// `collection!` widget will be `()`; otherwise the data type of the widget is `_A`
602/// where `_A` is a generic type parameter of the widget.
603///
604/// For example usage, see [`List`](https://docs.rs/kas/latest/kas/widgets/struct.List.html).
605///
606/// [`kas::Collection`]: https://docs.rs/kas/latest/kas/trait.Collection.html
607/// [`align`]: https://docs.rs/kas/latest/kas/widgets/adapt/trait.AdaptWidget.html#method.align
608/// [`pack`]: https://docs.rs/kas/latest/kas/widgets/adapt/trait.AdaptWidget.html#method.pack
609#[proc_macro_error]
610#[proc_macro]
611pub fn collection(input: TokenStream) -> TokenStream {
612    parse_macro_input!(input as collection::Collection)
613        .expand()
614        .into()
615}
616
617/// Generate an anonymous struct which implements [`kas::CellCollection`]
618///
619/// # Syntax
620///
621/// > _Collection_ :\
622/// >    `collection!` `[` _ItemArms_<sup>\?</sup> `]`
623/// >
624/// > _ItemArms_ :\
625/// >    (_ItemArm_ `,`)<sup>\*</sup> _ItemArm_ `,`<sup>\?</sup>
626/// >
627/// > _ItemArm_ :\
628/// >    `(` _Column_ `,` _Row_ `)` `=>` _Item_
629/// >
630/// > _Column_, _Row_ :\
631/// >    _LitInt_ | ( _LitInt_ `..` `+` _LitInt_ ) | ( _LitInt_ `..`
632/// > _LitInt_ ) | ( _LitInt_ `..=` _LitInt_ )
633///
634/// Here, _Column_ and _Row_ are selected via an index (from 0), a range of
635/// indices, or a start + increment. For example, `2` = `2..+1` = `2..3` =
636/// `2..=2` while `5..+2` = `5..7` = `5..=6`.
637///
638/// _Item_ may be:
639///
640/// -   A string literal (interpreted as a label widget), optionally followed by
641///     an [`align`] or [`pack`] method call
642/// -   An expression yielding an object implementing `Widget<Data = _A>`
643///
644/// In case all _Item_ instances are a string literal, the data type of the
645/// `collection!` widget will be `()`; otherwise the data type of the widget is `_A`
646/// where `_A` is a generic type parameter of the widget.
647///
648/// For example usage, see [`Grid`](https://docs.rs/kas/latest/kas/widgets/struct.Grid.html).
649///
650/// [`kas::CellCollection`]: https://docs.rs/kas/latest/kas/trait.CellCollection.html
651/// [`align`]: https://docs.rs/kas/latest/kas/widgets/adapt/trait.AdaptWidget.html#method.align
652/// [`pack`]: https://docs.rs/kas/latest/kas/widgets/adapt/trait.AdaptWidget.html#method.pack
653#[proc_macro_error]
654#[proc_macro]
655pub fn cell_collection(input: TokenStream) -> TokenStream {
656    parse_macro_input!(input as collection::CellCollection)
657        .expand()
658        .into()
659}
660
661/// A trait implementation is an extension over some base
662///
663/// Usage as follows:
664/// ```ignore
665/// #[extends(ThemeDraw, base = self.base())]
666/// impl ThemeDraw for Object {
667///     // All methods not present are implemented automatically over
668///     // `self.base()`, which mut return an object implementing ThemeDraw
669/// }
670/// ```
671///
672/// Note: this is a very limited macro which *only* supports `ThemeDraw`.
673#[proc_macro_attribute]
674#[proc_macro_error]
675pub fn extends(attr: TokenStream, item: TokenStream) -> TokenStream {
676    match syn::parse::<extends::Extends>(attr) {
677        Ok(extends) => match extends.extend(item.into()) {
678            Ok(result) => result.into(),
679            Err(err) => {
680                emit_call_site_error!(err);
681                TokenStream::new()
682            }
683        },
684        Err(err) => {
685            emit_call_site_error!(err);
686            item
687        }
688    }
689}