From 179d0b935a325ac18399068ef1af347ba07838c9 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Mon, 14 Nov 2022 14:36:15 -0500 Subject: [PATCH 1/2] Add `ParseCallbacks::process_comment` --- CHANGELOG.md | 2 ++ bindgen/callbacks.rs | 9 +++++++++ bindgen/codegen/mod.rs | 11 ++++++----- bindgen/ir/item.rs | 4 ++-- bindgen/lib.rs | 9 +++++++++ 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 506878c408..a759f34686 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -152,6 +152,8 @@ matching a regular expression. * new feature: allow using the `C-unwind` ABI in `--override-abi` on nightly rust. + * new feature: `process_comments` method to the `ParseCallbacks` trait to + handle source code comments. ## Changed diff --git a/bindgen/callbacks.rs b/bindgen/callbacks.rs index fb84c8c331..606988663d 100644 --- a/bindgen/callbacks.rs +++ b/bindgen/callbacks.rs @@ -108,4 +108,13 @@ pub trait ParseCallbacks: fmt::Debug { fn add_derives(&self, _name: &str) -> Vec { vec![] } + + /// Process a source code comment. + fn process_comment( + &self, + _comment: &str, + _indentation_level: usize, + ) -> Option { + None + } } diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index c7ac59db42..00341c6dcd 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -20,7 +20,6 @@ use super::BindgenOptions; use crate::ir::analysis::{HasVtable, Sizedness}; use crate::ir::annotations::FieldAccessorKind; -use crate::ir::comment; use crate::ir::comp::{ Bitfield, BitfieldUnit, CompInfo, CompKind, Field, FieldData, FieldMethods, Method, MethodKind, @@ -1392,8 +1391,9 @@ impl<'a> FieldCodegen<'a> for FieldData { let mut field = quote! {}; if ctx.options().generate_comments { if let Some(raw_comment) = self.comment() { - let comment = - comment::preprocess(raw_comment, codegen_depth + 1); + let comment = ctx + .options() + .process_comment(raw_comment, codegen_depth + 1); field = attributes::doc(comment); } } @@ -2837,8 +2837,9 @@ impl<'a> EnumBuilder<'a> { let mut doc = quote! {}; if ctx.options().generate_comments { if let Some(raw_comment) = variant.comment() { - let comment = - comment::preprocess(raw_comment, self.codegen_depth()); + let comment = ctx + .options() + .process_comment(raw_comment, self.codegen_depth()); doc = attributes::doc(comment); } } diff --git a/bindgen/ir/item.rs b/bindgen/ir/item.rs index 446d78bda5..2d8fe617bd 100644 --- a/bindgen/ir/item.rs +++ b/bindgen/ir/item.rs @@ -3,7 +3,6 @@ use super::super::codegen::{EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME}; use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult}; use super::annotations::Annotations; -use super::comment; use super::comp::{CompKind, MethodKind}; use super::context::{BindgenContext, ItemId, PartialType, TypeId}; use super::derive::{ @@ -516,7 +515,8 @@ impl Item { } self.comment.as_ref().map(|comment| { - comment::preprocess(comment, self.codegen_depth(ctx)) + ctx.options() + .process_comment(comment, self.codegen_depth(ctx)) }) } diff --git a/bindgen/lib.rs b/bindgen/lib.rs index e18a2a992c..4c355b53fa 100644 --- a/bindgen/lib.rs +++ b/bindgen/lib.rs @@ -78,6 +78,8 @@ doc_mod!(ir, ir_docs); doc_mod!(parse, parse_docs); doc_mod!(regex_set, regex_set_docs); +use ir::comment; + pub use crate::codegen::{ AliasVariation, EnumVariation, MacroTypeVariation, NonCopyUnionStyle, }; @@ -2271,6 +2273,13 @@ impl BindgenOptions { .flat_map(|cb| f(cb.as_ref())) .collect() } + + fn process_comment(&self, comment: &str, indent: usize) -> String { + self.parse_callbacks + .last() + .and_then(|cb| cb.process_comment(comment, indent)) + .unwrap_or_else(|| comment::preprocess(comment, indent)) + } } impl Default for BindgenOptions { From 1eb93f332ff5d02da004f7b89d29312a37f50c81 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Tue, 22 Nov 2022 10:59:03 -0500 Subject: [PATCH 2/2] remove indentation logic --- bindgen/callbacks.rs | 6 +---- bindgen/codegen/helpers.rs | 8 +++--- bindgen/codegen/mod.rs | 53 +++----------------------------------- bindgen/ir/comment.rs | 51 ++++++++++++------------------------ bindgen/ir/item.rs | 7 +++-- bindgen/lib.rs | 7 ++--- 6 files changed, 33 insertions(+), 99 deletions(-) diff --git a/bindgen/callbacks.rs b/bindgen/callbacks.rs index 606988663d..e8b53ed211 100644 --- a/bindgen/callbacks.rs +++ b/bindgen/callbacks.rs @@ -110,11 +110,7 @@ pub trait ParseCallbacks: fmt::Debug { } /// Process a source code comment. - fn process_comment( - &self, - _comment: &str, - _indentation_level: usize, - ) -> Option { + fn process_comment(&self, _comment: &str) -> Option { None } } diff --git a/bindgen/codegen/helpers.rs b/bindgen/codegen/helpers.rs index 5bf36acb42..088c7f9363 100644 --- a/bindgen/codegen/helpers.rs +++ b/bindgen/codegen/helpers.rs @@ -55,9 +55,11 @@ pub mod attributes { } pub fn doc(comment: String) -> TokenStream { - // NOTE(emilio): By this point comments are already preprocessed and in - // `///` form. Quote turns them into `#[doc]` comments, but oh well. - TokenStream::from_str(&comment).unwrap() + if comment.is_empty() { + quote!() + } else { + quote!(#[doc = #comment]) + } } pub fn link_name(name: &str) -> TokenStream { diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index 00341c6dcd..0931d9fce5 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -1244,7 +1244,6 @@ trait FieldCodegen<'a> { &self, ctx: &BindgenContext, fields_should_be_private: bool, - codegen_depth: usize, accessor_kind: FieldAccessorKind, parent: &CompInfo, result: &mut CodegenResult, @@ -1264,7 +1263,6 @@ impl<'a> FieldCodegen<'a> for Field { &self, ctx: &BindgenContext, fields_should_be_private: bool, - codegen_depth: usize, accessor_kind: FieldAccessorKind, parent: &CompInfo, result: &mut CodegenResult, @@ -1281,7 +1279,6 @@ impl<'a> FieldCodegen<'a> for Field { data.codegen( ctx, fields_should_be_private, - codegen_depth, accessor_kind, parent, result, @@ -1295,7 +1292,6 @@ impl<'a> FieldCodegen<'a> for Field { unit.codegen( ctx, fields_should_be_private, - codegen_depth, accessor_kind, parent, result, @@ -1345,7 +1341,6 @@ impl<'a> FieldCodegen<'a> for FieldData { &self, ctx: &BindgenContext, fields_should_be_private: bool, - codegen_depth: usize, accessor_kind: FieldAccessorKind, parent: &CompInfo, result: &mut CodegenResult, @@ -1391,9 +1386,7 @@ impl<'a> FieldCodegen<'a> for FieldData { let mut field = quote! {}; if ctx.options().generate_comments { if let Some(raw_comment) = self.comment() { - let comment = ctx - .options() - .process_comment(raw_comment, codegen_depth + 1); + let comment = ctx.options().process_comment(raw_comment); field = attributes::doc(comment); } } @@ -1553,7 +1546,6 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { &self, ctx: &BindgenContext, fields_should_be_private: bool, - codegen_depth: usize, accessor_kind: FieldAccessorKind, parent: &CompInfo, result: &mut CodegenResult, @@ -1630,7 +1622,6 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { bf.codegen( ctx, fields_should_be_private, - codegen_depth, accessor_kind, parent, result, @@ -1705,7 +1696,6 @@ impl<'a> FieldCodegen<'a> for Bitfield { &self, ctx: &BindgenContext, fields_should_be_private: bool, - _codegen_depth: usize, _accessor_kind: FieldAccessorKind, parent: &CompInfo, _result: &mut CodegenResult, @@ -1883,7 +1873,6 @@ impl CodeGenerator for CompInfo { let mut methods = vec![]; if !is_opaque { - let codegen_depth = item.codegen_depth(ctx); let fields_should_be_private = item.annotations().private_fields().unwrap_or(false); let struct_accessor_kind = item @@ -1894,7 +1883,6 @@ impl CodeGenerator for CompInfo { field.codegen( ctx, fields_should_be_private, - codegen_depth, struct_accessor_kind, self, result, @@ -2701,14 +2689,12 @@ impl std::str::FromStr for EnumVariation { /// A helper type to construct different enum variations. enum EnumBuilder<'a> { Rust { - codegen_depth: usize, attrs: Vec, ident: Ident, tokens: proc_macro2::TokenStream, emitted_any_variants: bool, }, NewType { - codegen_depth: usize, canonical_name: &'a str, tokens: proc_macro2::TokenStream, is_bitfield: bool, @@ -2716,26 +2702,14 @@ enum EnumBuilder<'a> { }, Consts { variants: Vec, - codegen_depth: usize, }, ModuleConsts { - codegen_depth: usize, module_name: &'a str, module_items: Vec, }, } impl<'a> EnumBuilder<'a> { - /// Returns the depth of the code generation for a variant of this enum. - fn codegen_depth(&self) -> usize { - match *self { - EnumBuilder::Rust { codegen_depth, .. } | - EnumBuilder::NewType { codegen_depth, .. } | - EnumBuilder::ModuleConsts { codegen_depth, .. } | - EnumBuilder::Consts { codegen_depth, .. } => codegen_depth, - } - } - /// Returns true if the builder is for a rustified enum. fn is_rust_enum(&self) -> bool { matches!(*self, EnumBuilder::Rust { .. }) @@ -2748,7 +2722,6 @@ impl<'a> EnumBuilder<'a> { mut attrs: Vec, repr: proc_macro2::TokenStream, enum_variation: EnumVariation, - enum_codegen_depth: usize, ) -> Self { let ident = Ident::new(name, Span::call_site()); @@ -2757,7 +2730,6 @@ impl<'a> EnumBuilder<'a> { is_bitfield, is_global, } => EnumBuilder::NewType { - codegen_depth: enum_codegen_depth, canonical_name: name, tokens: quote! { #( #attrs )* @@ -2772,7 +2744,6 @@ impl<'a> EnumBuilder<'a> { attrs.insert(0, quote! { #[repr( #repr )] }); let tokens = quote!(); EnumBuilder::Rust { - codegen_depth: enum_codegen_depth + 1, attrs, ident, tokens, @@ -2788,10 +2759,7 @@ impl<'a> EnumBuilder<'a> { pub type #ident = #repr; }); - EnumBuilder::Consts { - variants, - codegen_depth: enum_codegen_depth, - } + EnumBuilder::Consts { variants } } EnumVariation::ModuleConsts => { @@ -2805,7 +2773,6 @@ impl<'a> EnumBuilder<'a> { }; EnumBuilder::ModuleConsts { - codegen_depth: enum_codegen_depth + 1, module_name: name, module_items: vec![type_definition], } @@ -2837,9 +2804,7 @@ impl<'a> EnumBuilder<'a> { let mut doc = quote! {}; if ctx.options().generate_comments { if let Some(raw_comment) = variant.comment() { - let comment = ctx - .options() - .process_comment(raw_comment, self.codegen_depth()); + let comment = ctx.options().process_comment(raw_comment); doc = attributes::doc(comment); } } @@ -2850,13 +2815,11 @@ impl<'a> EnumBuilder<'a> { ident, tokens, emitted_any_variants: _, - codegen_depth, } => { let name = ctx.rust_ident(variant_name); EnumBuilder::Rust { attrs, ident, - codegen_depth, tokens: quote! { #tokens #doc @@ -2917,7 +2880,6 @@ impl<'a> EnumBuilder<'a> { self } EnumBuilder::ModuleConsts { - codegen_depth, module_name, mut module_items, } => { @@ -2931,7 +2893,6 @@ impl<'a> EnumBuilder<'a> { EnumBuilder::ModuleConsts { module_name, module_items, - codegen_depth, } } } @@ -3209,13 +3170,7 @@ impl CodeGenerator for Enum { let repr = repr.to_rust_ty_or_opaque(ctx, item); - let mut builder = EnumBuilder::new( - &name, - attrs, - repr, - variation, - item.codegen_depth(ctx), - ); + let mut builder = EnumBuilder::new(&name, attrs, repr, variation); // A map where we keep a value -> variant relation. let mut seen_values = HashMap::<_, Ident>::default(); diff --git a/bindgen/ir/comment.rs b/bindgen/ir/comment.rs index c96e3ebb9e..3eb17aacb9 100644 --- a/bindgen/ir/comment.rs +++ b/bindgen/ir/comment.rs @@ -12,10 +12,10 @@ enum Kind { } /// Preprocesses a C/C++ comment so that it is a valid Rust comment. -pub fn preprocess(comment: &str, indent: usize) -> String { +pub fn preprocess(comment: &str) -> String { match self::kind(comment) { - Some(Kind::SingleLines) => preprocess_single_lines(comment, indent), - Some(Kind::MultiLine) => preprocess_multi_line(comment, indent), + Some(Kind::SingleLines) => preprocess_single_lines(comment), + Some(Kind::MultiLine) => preprocess_multi_line(comment), None => comment.to_owned(), } } @@ -31,56 +31,34 @@ fn kind(comment: &str) -> Option { } } -fn make_indent(indent: usize) -> String { - const RUST_INDENTATION: usize = 4; - " ".repeat(indent * RUST_INDENTATION) -} - /// Preprocesses multiple single line comments. /// /// Handles lines starting with both `//` and `///`. -fn preprocess_single_lines(comment: &str, indent: usize) -> String { +fn preprocess_single_lines(comment: &str) -> String { debug_assert!(comment.starts_with("//"), "comment is not single line"); - let indent = make_indent(indent); - let mut is_first = true; let lines: Vec<_> = comment .lines() .map(|l| l.trim().trim_start_matches('/')) - .map(|l| { - let indent = if is_first { "" } else { &*indent }; - is_first = false; - format!("{}///{}", indent, l) - }) .collect(); lines.join("\n") } -fn preprocess_multi_line(comment: &str, indent: usize) -> String { +fn preprocess_multi_line(comment: &str) -> String { let comment = comment .trim_start_matches('/') .trim_end_matches('/') .trim_end_matches('*'); - let indent = make_indent(indent); // Strip any potential `*` characters preceding each line. - let mut is_first = true; let mut lines: Vec<_> = comment .lines() .map(|line| line.trim().trim_start_matches('*').trim_start_matches('!')) .skip_while(|line| line.trim().is_empty()) // Skip the first empty lines. - .map(|line| { - let indent = if is_first { "" } else { &*indent }; - is_first = false; - format!("{}///{}", indent, line) - }) .collect(); // Remove the trailing line corresponding to the `*/`. - if lines - .last() - .map_or(false, |l| l.trim().is_empty() || l.trim() == "///") - { + if lines.last().map_or(false, |l| l.trim().is_empty()) { lines.pop(); } @@ -99,21 +77,24 @@ mod test { #[test] fn processes_single_lines_correctly() { - assert_eq!(preprocess("/// hello", 0), "/// hello"); - assert_eq!(preprocess("// hello", 0), "/// hello"); - assert_eq!(preprocess("// hello", 0), "/// hello"); + assert_eq!(preprocess("///"), ""); + assert_eq!(preprocess("/// hello"), " hello"); + assert_eq!(preprocess("// hello"), " hello"); + assert_eq!(preprocess("// hello"), " hello"); } #[test] fn processes_multi_lines_correctly() { + assert_eq!(preprocess("/**/"), ""); + assert_eq!( - preprocess("/** hello \n * world \n * foo \n */", 0), - "/// hello\n/// world\n/// foo" + preprocess("/** hello \n * world \n * foo \n */"), + " hello\n world\n foo" ); assert_eq!( - preprocess("/**\nhello\n*world\n*foo\n*/", 0), - "///hello\n///world\n///foo" + preprocess("/**\nhello\n*world\n*foo\n*/"), + "hello\nworld\nfoo" ); } } diff --git a/bindgen/ir/item.rs b/bindgen/ir/item.rs index 2d8fe617bd..5e9aff9102 100644 --- a/bindgen/ir/item.rs +++ b/bindgen/ir/item.rs @@ -514,10 +514,9 @@ impl Item { return None; } - self.comment.as_ref().map(|comment| { - ctx.options() - .process_comment(comment, self.codegen_depth(ctx)) - }) + self.comment + .as_ref() + .map(|comment| ctx.options().process_comment(comment)) } /// What kind of item is this? diff --git a/bindgen/lib.rs b/bindgen/lib.rs index 4c355b53fa..1527950d4a 100644 --- a/bindgen/lib.rs +++ b/bindgen/lib.rs @@ -2274,11 +2274,12 @@ impl BindgenOptions { .collect() } - fn process_comment(&self, comment: &str, indent: usize) -> String { + fn process_comment(&self, comment: &str) -> String { + let comment = comment::preprocess(comment); self.parse_callbacks .last() - .and_then(|cb| cb.process_comment(comment, indent)) - .unwrap_or_else(|| comment::preprocess(comment, indent)) + .and_then(|cb| cb.process_comment(&comment)) + .unwrap_or(comment) } }