@@ -9,7 +9,8 @@ use crate::{
9
9
} ;
10
10
use core:: ops:: Deref ;
11
11
use std:: ops:: DerefMut ;
12
- use syn:: { spanned:: Spanned , Attribute , Error , ForeignItemFn , Result , Visibility } ;
12
+ use syn:: spanned:: Spanned ;
13
+ use syn:: { Attribute , Error , ForeignItemFn , Result , Visibility } ;
13
14
14
15
#[ derive( Clone ) ]
15
16
/// Describes an individual Signal
@@ -26,26 +27,35 @@ pub struct ParsedSignal {
26
27
pub cfgs : Vec < Attribute > ,
27
28
}
28
29
30
+ pub enum ImmutabilityConstraint {
31
+ Allowed ,
32
+ Disallowed ,
33
+ }
34
+
29
35
impl ParsedSignal {
30
36
const ALLOWED_ATTRS : [ & ' static str ; 6 ] =
31
37
[ "cfg" , "cxx_name" , "rust_name" , "inherit" , "doc" , "qsignal" ] ;
32
38
33
39
#[ cfg( test) ]
34
40
/// Test fn for creating a mocked signal from a method body
35
41
pub fn mock ( method : & ForeignItemFn ) -> Self {
36
- Self :: parse ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( )
42
+ Self :: parse_rust_qt_signal ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( )
37
43
}
38
44
39
- pub fn parse ( method : ForeignItemFn , auto_case : CaseConversion ) -> Result < Self > {
45
+ pub fn parse_with_mutability (
46
+ method : ForeignItemFn ,
47
+ auto_case : CaseConversion ,
48
+ immutability_allowed : ImmutabilityConstraint ,
49
+ ) -> Result < Self > {
40
50
let docs = extract_docs ( & method. attrs ) ;
41
51
let cfgs = extract_cfgs ( & method. attrs ) ;
42
52
let fields = MethodFields :: parse ( method, auto_case) ?;
43
53
let attrs = require_attributes ( & fields. method . attrs , & Self :: ALLOWED_ATTRS ) ?;
44
54
45
- if !fields. mutable {
55
+ if matches ! ( immutability_allowed , ImmutabilityConstraint :: Disallowed ) && !fields. mutable {
46
56
return Err ( Error :: new (
47
57
fields. method . span ( ) ,
48
- "signals must be mutable , use Pin<&mut T> instead of T for the self type" ,
58
+ "immutable signals can only be used in `unsafe extern \" C++Qt \" ` blocks , use Pin<&mut T> instead of T for the self type, or change the type of this extern block " ,
49
59
) ) ;
50
60
}
51
61
@@ -65,6 +75,10 @@ impl ParsedSignal {
65
75
cfgs,
66
76
} )
67
77
}
78
+
79
+ pub fn parse_rust_qt_signal ( method : ForeignItemFn , auto_case : CaseConversion ) -> Result < Self > {
80
+ Self :: parse_with_mutability ( method, auto_case, ImmutabilityConstraint :: Disallowed )
81
+ }
68
82
}
69
83
70
84
impl Deref for ParsedSignal {
@@ -94,28 +108,27 @@ mod tests {
94
108
#[ test]
95
109
fn test_parse_signal_invalid ( ) {
96
110
assert_parse_errors ! {
97
- |input| ParsedSignal :: parse ( input, CaseConversion :: none( ) ) =>
111
+ |input| ParsedSignal :: parse_rust_qt_signal ( input, CaseConversion :: none( ) ) =>
98
112
99
- // No immutable signals
100
- { fn ready( self : & MyObject ) ; }
113
+ // No namespaces
101
114
{
102
- // No namespaces
103
115
#[ namespace = "disallowed_namespace" ]
104
116
fn ready( self : Pin <& mut MyObject >) ;
105
117
}
106
118
// Missing self
107
119
{ fn ready( x: f64 ) ; }
108
- // Self needs to be receiver like self: &T instead of &self
120
+ // Immutable signals must be in "C++Qt" blocks
109
121
{ fn ready( & self ) ; }
110
- }
122
+ } ;
111
123
}
112
124
113
125
#[ test]
114
126
fn test_parse_signal ( ) {
115
127
let method: ForeignItemFn = parse_quote ! {
116
128
fn ready( self : Pin <& mut MyObject >) ;
117
129
} ;
118
- let signal = ParsedSignal :: parse ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( ) ;
130
+ let signal =
131
+ ParsedSignal :: parse_rust_qt_signal ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( ) ;
119
132
assert_eq ! ( signal. method, method) ;
120
133
assert_eq ! ( signal. qobject_ident, format_ident!( "MyObject" ) ) ;
121
134
assert ! ( signal. mutable) ;
@@ -132,7 +145,7 @@ mod tests {
132
145
#[ cxx_name = "cppReady" ]
133
146
fn ready( self : Pin <& mut MyObject >) ;
134
147
} ;
135
- let signal = ParsedSignal :: parse ( method, CaseConversion :: none ( ) ) . unwrap ( ) ;
148
+ let signal = ParsedSignal :: parse_rust_qt_signal ( method, CaseConversion :: none ( ) ) . unwrap ( ) ;
136
149
137
150
let expected_method: ForeignItemFn = parse_quote ! {
138
151
#[ cxx_name = "cppReady" ]
@@ -154,7 +167,8 @@ mod tests {
154
167
#[ inherit]
155
168
fn ready( self : Pin <& mut MyObject >) ;
156
169
} ;
157
- let signal = ParsedSignal :: parse ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( ) ;
170
+ let signal =
171
+ ParsedSignal :: parse_rust_qt_signal ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( ) ;
158
172
159
173
assert_eq ! ( signal. method, method) ;
160
174
assert_eq ! ( signal. qobject_ident, format_ident!( "MyObject" ) ) ;
@@ -171,7 +185,8 @@ mod tests {
171
185
let method: ForeignItemFn = parse_quote ! {
172
186
fn ready( self : Pin <& mut MyObject >, x: f64 , y: f64 ) ;
173
187
} ;
174
- let signal = ParsedSignal :: parse ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( ) ;
188
+ let signal =
189
+ ParsedSignal :: parse_rust_qt_signal ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( ) ;
175
190
assert_eq ! ( signal. method, method) ;
176
191
assert_eq ! ( signal. qobject_ident, format_ident!( "MyObject" ) ) ;
177
192
assert ! ( signal. mutable) ;
@@ -191,7 +206,8 @@ mod tests {
191
206
let method: ForeignItemFn = parse_quote ! {
192
207
pub ( self ) fn ready( self : Pin <& mut MyObject >) ;
193
208
} ;
194
- let signal = ParsedSignal :: parse ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( ) ;
209
+ let signal =
210
+ ParsedSignal :: parse_rust_qt_signal ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( ) ;
195
211
assert_eq ! ( signal. method, method) ;
196
212
assert_eq ! ( signal. qobject_ident, format_ident!( "MyObject" ) ) ;
197
213
assert ! ( signal. mutable) ;
@@ -207,7 +223,8 @@ mod tests {
207
223
let method: ForeignItemFn = parse_quote ! {
208
224
unsafe fn ready( self : Pin <& mut MyObject >) ;
209
225
} ;
210
- let signal = ParsedSignal :: parse ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( ) ;
226
+ let signal =
227
+ ParsedSignal :: parse_rust_qt_signal ( method. clone ( ) , CaseConversion :: none ( ) ) . unwrap ( ) ;
211
228
assert_eq ! ( signal. method, method) ;
212
229
assert_eq ! ( signal. qobject_ident, format_ident!( "MyObject" ) ) ;
213
230
assert ! ( signal. mutable) ;
0 commit comments