Skip to content

Commit 59fd73f

Browse files
committed
Refactor class/protocol/category parsing a bit
1 parent dd6c804 commit 59fd73f

File tree

1 file changed

+120
-71
lines changed
  • crates/header-translator/src

1 file changed

+120
-71
lines changed

crates/header-translator/src/stmt.rs

Lines changed: 120 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,26 @@ fn parse_protocols(
6464
});
6565
}
6666

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+
6787
fn parse_superclass<'ty>(
6888
entity: &Entity<'ty>,
6989
context: &Context<'_>,
@@ -89,18 +109,28 @@ fn parse_superclass<'ty>(
89109
superclass.map(|entity| (entity, ItemIdentifier::new(&entity, context), generics))
90110
}
91111

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(
97130
entity: &Entity<'_>,
98-
superclass: bool,
99-
mut generics: Option<&mut Vec<String>>,
100131
get_data: impl Fn(&str) -> MethodData,
101132
context: &Context<'_>,
102-
) -> (BTreeSet<ItemIdentifier>, Vec<Method>, Vec<String>) {
103-
let mut protocols = BTreeSet::new();
133+
) -> (Vec<Method>, Vec<String>) {
104134
let mut methods = Vec::new();
105135
let mut designated_initializers = Vec::new();
106136

@@ -109,43 +139,6 @@ fn parse_objc_decl(
109139
let mut properties = HashSet::new();
110140

111141
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-
}
149142
EntityKind::ObjCInstanceMethodDecl | EntityKind::ObjCClassMethodDecl => {
150143
drop(span);
151144
let partial = Method::partial(entity);
@@ -184,18 +177,7 @@ fn parse_objc_decl(
184177
methods.push(setter);
185178
}
186179
}
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+
_ => {}
199181
});
200182

201183
if !properties.is_empty() {
@@ -206,7 +188,76 @@ fn parse_objc_decl(
206188
);
207189
}
208190

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+
});
210261
}
211262

212263
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
@@ -453,12 +504,11 @@ impl Stmt {
453504
}
454505

455506
let availability = Availability::parse(entity, context);
456-
let mut generics = Vec::new();
457507

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(
459511
entity,
460-
true,
461-
Some(&mut generics),
462512
|name| ClassData::get_method_data(data, name),
463513
context,
464514
);
@@ -532,12 +582,11 @@ impl Stmt {
532582
}
533583
}
534584

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(
538589
entity,
539-
false,
540-
Some(&mut generics),
541590
|name| ClassData::get_method_data(data, name),
542591
context,
543592
);
@@ -587,10 +636,10 @@ impl Stmt {
587636

588637
let availability = Availability::parse(entity, context);
589638

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(
591642
entity,
592-
false,
593-
None,
594643
|name| {
595644
data.and_then(|data| data.methods.get(name))
596645
.copied()

0 commit comments

Comments
 (0)