Skip to content

Commit fb3917e

Browse files
committed
Change selector syntax in declare_class! macro
1 parent 909bffa commit fb3917e

File tree

4 files changed

+143
-44
lines changed

4 files changed

+143
-44
lines changed

objc2-foundation/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1313
* Implemented `Extend` for `NSMutableArray`.
1414
* Add extra `Extend<&u8>` impl for `NSMutableData`.
1515

16+
### Changed
17+
* Change selector syntax in `declare_class!` macro to be more Rust-like.
18+
1619
### Fixed
1720
* Made `Debug` impls for all objects print something useful.
1821

objc2-foundation/examples/declaration.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ declare_class! {
2020
}
2121

2222
unsafe impl {
23-
@sel(initWith:another:)
23+
#[sel(initWith:another:)]
2424
fn init_with(
2525
self: &mut Self,
2626
ivar: u8,
@@ -37,7 +37,7 @@ declare_class! {
3737
this
3838
}
3939

40-
@sel(myClassMethod)
40+
#[sel(myClassMethod)]
4141
fn my_class_method() {
4242
println!("A class method!");
4343
}
@@ -49,12 +49,14 @@ declare_class! {
4949
//
5050
// TODO: Investigate this!
5151
unsafe impl {
52-
@sel(applicationDidFinishLaunching:)
52+
#[sel(applicationDidFinishLaunching:)]
5353
fn did_finish_launching(&self, _sender: *mut Object) {
5454
println!("Did finish launching!");
5555
}
5656

57-
@sel(applicationWillTerminate:)
57+
/// Some comment before `sel`.
58+
#[sel(applicationWillTerminate:)]
59+
/// Some comment after `sel`.
5860
fn will_terminate(&self, _: *mut Object) {
5961
println!("Will terminate!");
6062
}

objc2-foundation/src/declare_macro.rs

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ macro_rules! __inner_declare_class {
77
@$output_type:ident
88
@$builder:ident
99

10-
$(#[$m:meta])*
11-
@sel($($sel:tt)+)
10+
$(#[$($m:tt)*])*
1211
fn $name:ident($($args:tt)*) $(-> $ret:ty)? $body:block
1312

1413
$($rest:tt)*
@@ -21,8 +20,7 @@ macro_rules! __inner_declare_class {
2120
// it as a function argument
2221
($($args)*)
2322

24-
$(#[$m])*
25-
@sel($($sel)+)
23+
$(#[$($m)*])*
2624
fn $name($($args)*) $(-> $ret)? $body
2725
}
2826

@@ -42,8 +40,7 @@ macro_rules! __inner_declare_class {
4240
@$builder:ident
4341
(&mut self $($__rest_args:tt)*)
4442

45-
$(#[$m:meta])*
46-
@sel($($sel:tt)+)
43+
$(#[$($m:tt)*])*
4744
fn $name:ident(
4845
&mut $self:ident
4946
$(, $($rest_args:tt)*)?
@@ -52,12 +49,11 @@ macro_rules! __inner_declare_class {
5249
$crate::__inner_declare_class! {
5350
@$output_type
5451
@instance_method
55-
@sel($($sel)*)
5652
@$name
5753
@$builder
5854
@($($($rest_args)*)?)
5955

60-
$(#[$m])*
56+
$(#[$($m)*])*
6157
extern "C" fn $name(
6258
&mut $self,
6359
_: $crate::objc2::runtime::Sel,
@@ -71,8 +67,7 @@ macro_rules! __inner_declare_class {
7167
@$builder:ident
7268
(&self $($__rest_args:tt)*)
7369

74-
$(#[$m:meta])*
75-
@sel($($sel:tt)+)
70+
$(#[$($m:tt)*])*
7671
fn $name:ident(
7772
&$self:ident
7873
$(, $($rest_args:tt)*)?
@@ -81,12 +76,11 @@ macro_rules! __inner_declare_class {
8176
$crate::__inner_declare_class! {
8277
@$output_type
8378
@instance_method
84-
@sel($($sel)*)
8579
@$name
8680
@$builder
8781
@($($($rest_args)*)?)
8882

89-
$(#[$m])*
83+
$(#[$($m)*])*
9084
extern "C" fn $name(
9185
&$self,
9286
_: $crate::objc2::runtime::Sel,
@@ -103,8 +97,7 @@ macro_rules! __inner_declare_class {
10397
$(, $($__rest_args:tt)*)?
10498
)
10599

106-
$(#[$m:meta])*
107-
@sel($($sel:tt)+)
100+
$(#[$($m:tt)*])*
108101
fn $name:ident(
109102
mut $self:ident: $self_ty:ty
110103
$(, $($rest_args:tt)*)?
@@ -113,12 +106,11 @@ macro_rules! __inner_declare_class {
113106
$crate::__inner_declare_class! {
114107
@$output_type
115108
@instance_method
116-
@sel($($sel)*)
117109
@$name
118110
@$builder
119111
@($($($rest_args)*)?)
120112

121-
$(#[$m])*
113+
$(#[$($m)*])*
122114
extern "C" fn $name(
123115
mut $self: $self_ty,
124116
_: $crate::objc2::runtime::Sel,
@@ -135,8 +127,7 @@ macro_rules! __inner_declare_class {
135127
$(, $($__rest_args:tt)*)?
136128
)
137129

138-
$(#[$m:meta])*
139-
@sel($($sel:tt)+)
130+
$(#[$($m:tt)*])*
140131
fn $name:ident(
141132
$self:ident: $self_ty:ty
142133
$(, $($rest_args:tt)*)?
@@ -145,12 +136,11 @@ macro_rules! __inner_declare_class {
145136
$crate::__inner_declare_class! {
146137
@$output_type
147138
@instance_method
148-
@sel($($sel)*)
149139
@$name
150140
@$builder
151141
@($($($rest_args)*)?)
152142

153-
$(#[$m])*
143+
$(#[$($m)*])*
154144
extern "C" fn $name(
155145
$self: $self_ty,
156146
_: $crate::objc2::runtime::Sel,
@@ -166,21 +156,19 @@ macro_rules! __inner_declare_class {
166156
@$builder:ident
167157
($($__args:tt)*)
168158

169-
$(#[$m:meta])*
170-
@sel($($sel:tt)+)
159+
$(#[$($m:tt)*])*
171160
fn $name:ident(
172161
$($args:tt)*
173162
) $(-> $ret:ty)? $body:block
174163
} => {
175164
$crate::__inner_declare_class! {
176165
@$output_type
177166
@class_method
178-
@sel($($sel)*)
179167
@$name
180168
@$builder
181169
@($($args)*)
182170

183-
$(#[$m])*
171+
$(#[$($m)*])*
184172
extern "C" fn $name(
185173
_: &$crate::objc2::runtime::Class,
186174
_: $crate::objc2::runtime::Sel,
@@ -192,27 +180,35 @@ macro_rules! __inner_declare_class {
192180
{
193181
@method_out
194182
@$method_type:ident
195-
@sel($($sel:tt)*)
196-
@$name:ident
183+
@$_name:ident
197184
@$builder:ident
198185
@($($builder_args:tt)*)
199186

200-
$method:item
187+
$(#[$($m:tt)*])*
188+
extern "C" fn $($fn:tt)*
201189
} => {
202-
$method
190+
$crate::__attribute_helper! {
191+
@strip_sel
192+
$(@[$($m)*])*
193+
(extern "C" fn $($fn)*)
194+
}
203195
};
196+
204197
{
205198
@register_out
206199
@class_method
207-
@sel($($sel:tt)*)
208200
@$name:ident
209201
@$builder:ident
210202
@($($builder_args:tt)*)
211203

212-
$method:item
204+
$(#[$($m:tt)*])*
205+
extern "C" fn $($fn:tt)*
213206
} => {
214207
$builder.add_class_method(
215-
$crate::objc2::sel!($($sel)*),
208+
$crate::__attribute_helper! {
209+
@extract_sel
210+
$(#[$($m)*])*
211+
},
216212
$crate::__inner_declare_class! {
217213
@cast_extern_fn
218214
@$name
@@ -223,15 +219,18 @@ macro_rules! __inner_declare_class {
223219
{
224220
@register_out
225221
@instance_method
226-
@sel($($sel:tt)*)
227222
@$name:ident
228223
@$builder:ident
229224
@($($builder_args:tt)*)
230225

231-
$method:item
226+
$(#[$($m:tt)*])*
227+
extern "C" fn $($fn:tt)*
232228
} => {
233229
$builder.add_method(
234-
$crate::objc2::sel!($($sel)*),
230+
$crate::__attribute_helper! {
231+
@extract_sel
232+
$(#[$($m)*])*
233+
},
235234
$crate::__inner_declare_class! {
236235
@cast_extern_fn
237236
@$name
@@ -454,8 +453,8 @@ macro_rules! __inner_declare_class {
454453
/// particular, if you use `self` your method will be registered as an
455454
/// instance method, and if you don't it will be registered as a class method.
456455
///
457-
/// The desired selector can be specified using a special `@sel(my:selector:)`
458-
/// directive directly before the function definition.
456+
/// The desired selector can be specified using the `#[sel(my:selector:)]`
457+
/// attribute.
459458
///
460459
/// A transformation step is performed on the functions (to make them have the
461460
/// correct ABI) and hence they shouldn't really be called manually. (You
@@ -520,7 +519,7 @@ macro_rules! __inner_declare_class {
520519
/// }
521520
///
522521
/// unsafe impl {
523-
/// @sel(initWithFoo:)
522+
/// #[sel(initWithFoo:)]
524523
/// fn init_with(&mut self, foo: u8) -> Option<&mut Self> {
525524
/// let this: Option<&mut Self> = unsafe {
526525
/// msg_send![super(self, NSObject::class()), init]
@@ -535,19 +534,19 @@ macro_rules! __inner_declare_class {
535534
/// })
536535
/// }
537536
///
538-
/// @sel(foo)
537+
/// #[sel(foo)]
539538
/// fn __get_foo(&self) -> u8 {
540539
/// *self.foo
541540
/// }
542541
///
543-
/// @sel(myClassMethod)
542+
/// #[sel(myClassMethod)]
544543
/// fn __my_class_method() -> Bool {
545544
/// Bool::YES
546545
/// }
547546
/// }
548547
///
549548
/// unsafe impl protocol NSCopying {
550-
/// @sel(copyWithZone:)
549+
/// #[sel(copyWithZone:)]
551550
/// fn copy_with_zone(&self, _zone: *const NSZone) -> *mut Self {
552551
/// let mut obj = Self::new(*self.foo);
553552
/// *obj.bar = *self.bar;

objc2-foundation/src/macros.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,98 @@ macro_rules! __inner_extern_class {
292292
$crate::__impl_as_ref_borrow!($name<$($t $(: $b)?),*>, $inherits, $($inheritance_rest,)*);
293293
};
294294
}
295+
296+
#[doc(hidden)]
297+
#[macro_export]
298+
macro_rules! __attribute_helper {
299+
// Convert a set of attributes described with `@[...]` to `#[...]`, while
300+
// parsing out the `sel(...)` attribute.
301+
{
302+
@strip_sel
303+
@[sel($($_sel_args:tt)*)]
304+
$(@[$($m_rest:tt)*])*
305+
306+
$(#[$($m:tt)*])*
307+
($($fn:tt)*)
308+
} => {
309+
$crate::__attribute_helper! {
310+
@strip_sel
311+
$(@[$($m_rest)*])*
312+
313+
$(#[$($m)*])*
314+
($($fn)*)
315+
}
316+
};
317+
{
318+
@strip_sel
319+
@[$($m_checked:tt)*]
320+
$(@[$($m_rest:tt)*])*
321+
322+
$(#[$($m:tt)*])*
323+
($($fn:tt)*)
324+
} => {
325+
$crate::__attribute_helper! {
326+
@strip_sel
327+
$(@[$($m_rest)*])*
328+
329+
$(#[$($m)*])*
330+
#[$($m_checked)*]
331+
($($fn)*)
332+
}
333+
};
334+
{
335+
@strip_sel
336+
$(#[$($m:tt)*])*
337+
($($fn:tt)*)
338+
} => {
339+
$(#[$($m)*])*
340+
$($fn)*
341+
};
342+
343+
// Extract and convert the `#[sel(...)]` attribute to a `sel!` invocation.
344+
{
345+
@extract_sel
346+
#[sel($($sel:tt)*)]
347+
$($rest:tt)*
348+
} => {{
349+
$crate::__attribute_helper! {
350+
@extract_sel_duplicate
351+
$($rest)*
352+
}
353+
354+
$crate::objc2::sel!($($sel)*)
355+
}};
356+
{
357+
@extract_sel
358+
#[$($m_checked:tt)*]
359+
$($rest:tt)*
360+
} => {{
361+
$crate::__attribute_helper! {
362+
@extract_sel
363+
$($rest)*
364+
}
365+
}};
366+
{@extract_sel} => {{
367+
compile_error!("Must specify the desired selector using `#[sel(...)]`");
368+
}};
369+
370+
{
371+
@extract_sel_duplicate
372+
#[sel($($_sel_args:tt)*)]
373+
$($rest:tt)*
374+
} => {{
375+
compile_error!("Cannot not specify a selector twice!");
376+
}};
377+
{
378+
@extract_sel_duplicate
379+
#[$($m_checked:tt)*]
380+
$($rest:tt)*
381+
} => {{
382+
$crate::__attribute_helper! {
383+
@extract_sel_duplicate
384+
$($rest)*
385+
}
386+
}};
387+
{@extract_sel_duplicate} => {};
388+
389+
}

0 commit comments

Comments
 (0)