@@ -64,6 +64,26 @@ fn parse_protocols(
64
64
} ) ;
65
65
}
66
66
67
+ fn parse_direct_protocols ( entity : & Entity < ' _ > , context : & Context < ' _ > ) -> BTreeSet < ItemIdentifier > {
68
+ let mut protocols = BTreeSet :: new ( ) ;
69
+
70
+ #[ allow( clippy:: single_match) ]
71
+ immediate_children ( entity, |entity, _span| match entity. get_kind ( ) {
72
+ EntityKind :: ObjCProtocolRef => {
73
+ let entity = entity
74
+ . get_reference ( )
75
+ . expect ( "ObjCProtocolRef to reference entity" ) ;
76
+ protocols. insert (
77
+ ItemIdentifier :: new ( & entity, context)
78
+ . map_name ( |name| context. replace_protocol_name ( name) ) ,
79
+ ) ;
80
+ }
81
+ _ => { }
82
+ } ) ;
83
+
84
+ protocols
85
+ }
86
+
67
87
fn parse_superclass < ' ty > (
68
88
entity : & Entity < ' ty > ,
69
89
context : & Context < ' _ > ,
@@ -89,18 +109,28 @@ fn parse_superclass<'ty>(
89
109
superclass. map ( |entity| ( entity, ItemIdentifier :: new ( & entity, context) , generics) )
90
110
}
91
111
92
- /// Takes one of:
93
- /// - `EntityKind::ObjCInterfaceDecl`
94
- /// - `EntityKind::ObjCProtocolDecl`
95
- /// - `EntityKind::ObjCCategoryDecl`
96
- fn parse_objc_decl (
112
+ fn parse_class_generics ( entity : & Entity < ' _ > , _context : & Context < ' _ > ) -> Vec < String > {
113
+ let mut generics = Vec :: new ( ) ;
114
+
115
+ #[ allow( clippy:: single_match) ]
116
+ immediate_children ( entity, |entity, _span| match entity. get_kind ( ) {
117
+ EntityKind :: TemplateTypeParameter => {
118
+ // TODO: Generics with bounds (like NSMeasurement<UnitType: NSUnit *>)
119
+ // let ty = entity.get_type().expect("template type");
120
+ let name = entity. get_name ( ) . expect ( "template name" ) ;
121
+ generics. push ( name) ;
122
+ }
123
+ _ => { }
124
+ } ) ;
125
+
126
+ generics
127
+ }
128
+
129
+ fn parse_methods (
97
130
entity : & Entity < ' _ > ,
98
- superclass : bool ,
99
- mut generics : Option < & mut Vec < String > > ,
100
131
get_data : impl Fn ( & str ) -> MethodData ,
101
132
context : & Context < ' _ > ,
102
- ) -> ( BTreeSet < ItemIdentifier > , Vec < Method > , Vec < String > ) {
103
- let mut protocols = BTreeSet :: new ( ) ;
133
+ ) -> ( Vec < Method > , Vec < String > ) {
104
134
let mut methods = Vec :: new ( ) ;
105
135
let mut designated_initializers = Vec :: new ( ) ;
106
136
@@ -109,43 +139,6 @@ fn parse_objc_decl(
109
139
let mut properties = HashSet :: new ( ) ;
110
140
111
141
immediate_children ( entity, |entity, span| match entity. get_kind ( ) {
112
- EntityKind :: ObjCExplicitProtocolImpl if generics. is_none ( ) && !superclass => {
113
- // TODO NS_PROTOCOL_REQUIRES_EXPLICIT_IMPLEMENTATION
114
- }
115
- EntityKind :: ObjCIvarDecl | EntityKind :: StructDecl | EntityKind :: UnionDecl if superclass => {
116
- // Explicitly ignored
117
- }
118
- EntityKind :: ObjCSuperClassRef | EntityKind :: TypeRef if superclass => {
119
- // Parsed in parse_superclass
120
- }
121
- EntityKind :: ObjCSubclassingRestricted if superclass => {
122
- // TODO: https://clang.llvm.org/docs/AttributeReference.html#objc-subclassing-restricted
123
- }
124
- EntityKind :: ObjCRootClass => {
125
- debug ! ( "parsing root class" ) ;
126
- }
127
- EntityKind :: ObjCClassRef if generics. is_some ( ) => {
128
- // debug!("ObjCClassRef: {:?}", entity.get_display_name());
129
- }
130
- EntityKind :: TemplateTypeParameter => {
131
- if let Some ( generics) = & mut generics {
132
- // TODO: Generics with bounds (like NSMeasurement<UnitType: NSUnit *>)
133
- // let ty = entity.get_type().expect("template type");
134
- let name = entity. get_name ( ) . expect ( "template name" ) ;
135
- generics. push ( name) ;
136
- } else {
137
- error ! ( "unsupported generics" ) ;
138
- }
139
- }
140
- EntityKind :: ObjCProtocolRef => {
141
- let entity = entity
142
- . get_reference ( )
143
- . expect ( "ObjCProtocolRef to reference entity" ) ;
144
- protocols. insert (
145
- ItemIdentifier :: new ( & entity, context)
146
- . map_name ( |name| context. replace_protocol_name ( name) ) ,
147
- ) ;
148
- }
149
142
EntityKind :: ObjCInstanceMethodDecl | EntityKind :: ObjCClassMethodDecl => {
150
143
drop ( span) ;
151
144
let partial = Method :: partial ( entity) ;
@@ -184,18 +177,7 @@ fn parse_objc_decl(
184
177
methods. push ( setter) ;
185
178
}
186
179
}
187
- EntityKind :: VisibilityAttr => {
188
- // Already exposed as entity.get_visibility()
189
- }
190
- EntityKind :: ObjCException if superclass => {
191
- // Maybe useful for knowing when to implement `Error` for the type
192
- }
193
- EntityKind :: UnexposedAttr => {
194
- if let Some ( attr) = UnexposedAttr :: parse ( & entity, context) {
195
- error ! ( ?attr, "unknown attribute" ) ;
196
- }
197
- }
198
- _ => error ! ( "unknown" ) ,
180
+ _ => { }
199
181
} ) ;
200
182
201
183
if !properties. is_empty ( ) {
@@ -206,7 +188,76 @@ fn parse_objc_decl(
206
188
) ;
207
189
}
208
190
209
- ( protocols, methods, designated_initializers)
191
+ ( methods, designated_initializers)
192
+ }
193
+
194
+ /// Takes one of:
195
+ /// - `EntityKind::ObjCInterfaceDecl`
196
+ /// - `EntityKind::ObjCProtocolDecl`
197
+ /// - `EntityKind::ObjCCategoryDecl`
198
+ fn verify_objc_decl ( entity : & Entity < ' _ > , context : & Context < ' _ > ) {
199
+ let parent_kind = entity. get_kind ( ) ;
200
+
201
+ immediate_children ( entity, |entity, _span| {
202
+ match ( entity. get_kind ( ) , parent_kind) {
203
+ ( EntityKind :: ObjCExplicitProtocolImpl , EntityKind :: ObjCProtocolDecl ) => {
204
+ // TODO NS_PROTOCOL_REQUIRES_EXPLICIT_IMPLEMENTATION
205
+ }
206
+ (
207
+ EntityKind :: ObjCIvarDecl | EntityKind :: StructDecl | EntityKind :: UnionDecl ,
208
+ EntityKind :: ObjCInterfaceDecl ,
209
+ ) => {
210
+ // Explicitly ignored
211
+ }
212
+ (
213
+ EntityKind :: ObjCSuperClassRef | EntityKind :: TypeRef ,
214
+ EntityKind :: ObjCInterfaceDecl ,
215
+ ) => {
216
+ // Parsed in parse_superclass
217
+ }
218
+ ( EntityKind :: ObjCSubclassingRestricted , EntityKind :: ObjCInterfaceDecl ) => {
219
+ // TODO: https://clang.llvm.org/docs/AttributeReference.html#objc-subclassing-restricted
220
+ }
221
+ ( EntityKind :: ObjCRootClass , EntityKind :: ObjCInterfaceDecl ) => {
222
+ debug ! ( "parsing root class" ) ;
223
+ }
224
+ (
225
+ EntityKind :: ObjCClassRef ,
226
+ EntityKind :: ObjCInterfaceDecl | EntityKind :: ObjCCategoryDecl ,
227
+ ) => {
228
+ // debug!("ObjCClassRef: {:?}", entity.get_display_name());
229
+ }
230
+ (
231
+ EntityKind :: TemplateTypeParameter ,
232
+ EntityKind :: ObjCInterfaceDecl | EntityKind :: ObjCCategoryDecl ,
233
+ ) => {
234
+ // Parsed in parse_class_generics
235
+ }
236
+ ( EntityKind :: ObjCProtocolRef , _) => {
237
+ // Parsed in parse_protocols and parse_direct_protocols
238
+ }
239
+ (
240
+ EntityKind :: ObjCInstanceMethodDecl
241
+ | EntityKind :: ObjCClassMethodDecl
242
+ | EntityKind :: ObjCPropertyDecl ,
243
+ _,
244
+ ) => {
245
+ // Parsed in parse_methods
246
+ }
247
+ ( EntityKind :: VisibilityAttr , _) => {
248
+ // Already exposed as entity.get_visibility()
249
+ }
250
+ ( EntityKind :: ObjCException , EntityKind :: ObjCInterfaceDecl ) => {
251
+ // Maybe useful for knowing when to implement `Error` for the type
252
+ }
253
+ ( EntityKind :: UnexposedAttr , _) => {
254
+ if let Some ( attr) = UnexposedAttr :: parse ( & entity, context) {
255
+ error ! ( ?attr, "unknown attribute" ) ;
256
+ }
257
+ }
258
+ ( _, parent_kind) => error ! ( ?parent_kind, "unknown in parent" ) ,
259
+ }
260
+ } ) ;
210
261
}
211
262
212
263
#[ derive( Debug , Clone , PartialEq , Eq , Hash , Default ) ]
@@ -453,12 +504,11 @@ impl Stmt {
453
504
}
454
505
455
506
let availability = Availability :: parse ( entity, context) ;
456
- let mut generics = Vec :: new ( ) ;
457
507
458
- let ( _, methods, designated_initializers) = parse_objc_decl (
508
+ verify_objc_decl ( entity, context) ;
509
+ let generics = parse_class_generics ( entity, context) ;
510
+ let ( methods, designated_initializers) = parse_methods (
459
511
entity,
460
- true ,
461
- Some ( & mut generics) ,
462
512
|name| ClassData :: get_method_data ( data, name) ,
463
513
context,
464
514
) ;
@@ -532,12 +582,11 @@ impl Stmt {
532
582
}
533
583
}
534
584
535
- let mut generics = Vec :: new ( ) ;
536
-
537
- let ( protocols, methods, designated_initializers) = parse_objc_decl (
585
+ verify_objc_decl ( entity, context) ;
586
+ let generics = parse_class_generics ( entity, context) ;
587
+ let protocols = parse_direct_protocols ( entity, context) ;
588
+ let ( methods, designated_initializers) = parse_methods (
538
589
entity,
539
- false ,
540
- Some ( & mut generics) ,
541
590
|name| ClassData :: get_method_data ( data, name) ,
542
591
context,
543
592
) ;
@@ -587,10 +636,10 @@ impl Stmt {
587
636
588
637
let availability = Availability :: parse ( entity, context) ;
589
638
590
- let ( protocols, methods, designated_initializers) = parse_objc_decl (
639
+ verify_objc_decl ( entity, context) ;
640
+ let protocols = parse_direct_protocols ( entity, context) ;
641
+ let ( methods, designated_initializers) = parse_methods (
591
642
entity,
592
- false ,
593
- None ,
594
643
|name| {
595
644
data. and_then ( |data| data. methods . get ( name) )
596
645
. copied ( )
0 commit comments