diff --git a/com-scrape/src/clang.rs b/com-scrape/src/clang.rs index 73c6197d6..155c58444 100644 --- a/com-scrape/src/clang.rs +++ b/com-scrape/src/clang.rs @@ -146,6 +146,10 @@ impl<'a> Cursor<'a> { unsafe { StringRef::from_raw(clang_getCursorSpelling(self.cursor)) } } + pub fn is_anonymous(&self) -> bool { + unsafe { clang_Cursor_isAnonymous(self.cursor) != 0 } + } + pub fn location(&self) -> Location<'a> { unsafe { Location::from_raw(clang_getCursorLocation(self.cursor)) } } diff --git a/com-scrape/src/parse.rs b/com-scrape/src/parse.rs index de8e39339..1f3cc6ec0 100644 --- a/com-scrape/src/parse.rs +++ b/com-scrape/src/parse.rs @@ -73,7 +73,7 @@ pub struct Base { #[derive(Clone, Debug)] pub struct Field { - pub name: String, + pub name: Option, pub type_: Type, } @@ -162,14 +162,14 @@ impl<'a> Parser<'a> { match cursor.kind() { CursorKind::Namespace => { - let name = cursor.name(); - let name_str = name.to_str().unwrap(); - // Skip the contents of unnamed namespaces - if name_str.is_empty() { + if cursor.is_anonymous() { return Ok(()); } + let name = cursor.name(); + let name_str = name.to_str().unwrap(); + if !namespace.children.contains_key(name_str) { namespace .children @@ -192,9 +192,6 @@ impl<'a> Parser<'a> { }); } CursorKind::EnumDecl => { - let name = cursor.name(); - let name_str = name.to_str().unwrap(); - let int_type = self.parse_type(cursor.enum_integer_type().unwrap(), cursor.location())?; @@ -237,9 +234,12 @@ impl<'a> Parser<'a> { Ok(()) })?; - if name_str.is_empty() { + if cursor.is_anonymous() { namespace.constants.extend(constants); } else { + let name = cursor.name(); + let name_str = name.to_str().unwrap(); + let mut inner = Namespace::new(); inner.constants.extend(constants); @@ -286,7 +286,7 @@ impl<'a> Parser<'a> { CursorKind::StructDecl | CursorKind::UnionDecl | CursorKind::ClassDecl => { if cursor.is_definition() { // Skip unnamed records here, as parse_type will take care of them - if !cursor.name().to_str().unwrap().is_empty() { + if !cursor.is_anonymous() { let record = self.parse_record(cursor.type_().unwrap())?; namespace.records.push(record); } @@ -313,12 +313,15 @@ impl<'a> Parser<'a> { match cursor.kind() { // Check for UnionDecl to handle anonymous unions CursorKind::FieldDecl | CursorKind::UnionDecl => { + let name = if cursor.is_anonymous() { + None + } else { + Some(cursor.name().to_str().unwrap().to_string()) + }; + let type_ = self.parse_type(cursor.type_().unwrap(), cursor.location())?; - fields.push(Field { - name: cursor.name().to_str().unwrap().to_string(), - type_, - }); + fields.push(Field { name, type_ }); } CursorKind::CxxMethod => { if cursor.is_virtual() { @@ -441,10 +444,10 @@ impl<'a> Parser<'a> { } TypeKind::Record => { let decl = type_.declaration(); - let name = decl.name().to_str().unwrap().to_string(); - if name.is_empty() { + if decl.is_anonymous() { Ok(Type::UnnamedRecord(self.parse_record(type_)?)) } else { + let name = decl.name().to_str().unwrap().to_string(); Ok(Type::Record(name)) } // name = format!("__type{}", namespace.unnamed_record_counter); diff --git a/com-scrape/src/print.rs b/com-scrape/src/print.rs index 00b5a09a6..b6b8a982b 100644 --- a/com-scrape/src/print.rs +++ b/com-scrape/src/print.rs @@ -167,14 +167,15 @@ impl<'a, W: Write> RustPrinter<'a, W> { let mut anon_counter = 0; for field in &record.fields { - let field_name = &field.name; - if field.name.is_empty() { + if let Some(field_name) = &field.name { + if self.reserved.contains(&**field_name) { + write!(self.sink, "{indent} pub r#{field_name}: ")?; + } else { + write!(self.sink, "{indent} pub {field_name}: ")?; + } + } else { write!(self.sink, "{indent} pub __field{anon_counter}: ")?; anon_counter += 1; - } else if self.reserved.contains(&*field.name) { - write!(self.sink, "{indent} pub r#{field_name}: ")?; - } else { - write!(self.sink, "{indent} pub {field_name}: ")?; } self.print_type(&field.type_)?; writeln!(self.sink, ",")?;