Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate doc comment when type alias is hidden #3122

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions bindgen-tests/tests/headers/3119_overlapping_alias_comment.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// bindgen-flags: --no-layout-tests

/**
* This is a forward declared struct alias with overlapping names
* and documentation.
*/
typedef struct Struct Struct;
49 changes: 48 additions & 1 deletion bindgen/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2410,7 +2410,12 @@ impl CodeGenerator for CompInfo {
let mut needs_debug_impl = false;
let mut needs_partialeq_impl = false;
let needs_flexarray_impl = flex_array_generic.is_some();
if let Some(comment) = item.comment(ctx) {
let type_id = item.id().expect_type_id(ctx);

if let Some(comment) = item
.comment(ctx)
.or_else(|| Self::get_typedef_fallback_comment(ctx, &type_id))
{
attributes.push(attributes::doc(&comment));
}

Expand Down Expand Up @@ -2987,6 +2992,48 @@ impl CompInfo {
}
}
}

/// Use a fallback comment from a type alias to this type if necessary
///
/// The documentation for a type could get lost in the following circumstances:
///
/// - We have a type and a type alias with the same canonical path
/// - The Documentation is only associated with the type alias
///
/// In this case bindgen will not generate the type alias and the documentation would be lost.
/// To avoid this, we check here if there is any type alias to this type, which has
/// the same canonical path and return the comment as a fallback, if our type does
/// not have documentation.
fn get_typedef_fallback_comment(
ctx: &BindgenContext,
type_id: &crate::ir::context::TypeId,
) -> Option<String> {
if !ctx.options().generate_comments {
return None;
}
let type_alias_comment = ctx
.items()
.filter(|(_id, alias)| {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Iterating over all items seems not really fine, performance wise. Can we avoid it somehow?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm - I think since we are using this fallback for the case where typedef and struct declaration are at the same time, a potential type alias should always be at item_id + 1. I don't think we currently have a way to access the "next" item or do arithmetic on item ids, but this would avoid iterating through all items.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can do it the other way around? During the clang phase, go peek at the typedef's comment? Haven't tried it tho.

let Some(this_ty) = alias.as_type() else {
return false;
};
let TypeKind::Alias(alias_to) = this_ty.kind() else {
return false;
};
//
match ctx.resolve_type(*alias_to).kind() {
TypeKind::ResolvedTypeRef(resolved_typeid) => {
resolved_typeid == type_id &&
alias.canonical_path(ctx) ==
type_id.canonical_path(ctx)
}
_ => false,
}
})
.filter_map(|(_id, item)| item.comment(ctx));
let alias_comment: Vec<String> = type_alias_comment.collect();
alias_comment.get(0).cloned()
}
}

impl Method {
Expand Down