diff --git a/src/bindgen/cdecl.rs b/src/bindgen/cdecl.rs index c4bef9346..fc96042cc 100644 --- a/src/bindgen/cdecl.rs +++ b/src/bindgen/cdecl.rs @@ -184,7 +184,7 @@ impl CDecl { }); self.declarators.push(CDeclarator::Func { args, - layout: config.function.args.clone(), + layout: config.function.args, never_return: *never_return, }); self.build_type(ret, false, config); diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs index dc5fa4635..c28c2aa67 100644 --- a/src/bindgen/config.rs +++ b/src/bindgen/config.rs @@ -134,7 +134,7 @@ impl FromStr for Braces { deserialize_enum_str!(Braces); /// A type of layout to use when generating long lines of code. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Layout { Horizontal, Vertical, diff --git a/src/bindgen/language_backend/clike.rs b/src/bindgen/language_backend/clike.rs index ff23d7c35..a2e3e5515 100644 --- a/src/bindgen/language_backend/clike.rs +++ b/src/bindgen/language_backend/clike.rs @@ -1,12 +1,12 @@ use crate::bindgen::ir::{ to_known_assoc_constant, ConditionWrite, DeprecatedNoteKind, Documentation, Enum, EnumVariant, - Field, Function, GenericParams, Item, Literal, OpaqueItem, ReprAlign, Static, Struct, - ToCondition, Type, Typedef, Union, + Field, GenericParams, Item, Literal, OpaqueItem, ReprAlign, Static, Struct, ToCondition, Type, + Typedef, Union, }; use crate::bindgen::language_backend::LanguageBackend; use crate::bindgen::rename::IdentifierType; use crate::bindgen::writer::{ListType, SourceWriter}; -use crate::bindgen::{cdecl, Bindings, Config, Language, Layout}; +use crate::bindgen::{cdecl, Bindings, Config, Language}; use crate::bindgen::{DocumentationLength, DocumentationStyle}; use std::io::Write; @@ -780,6 +780,7 @@ impl LanguageBackend for CLikeLanguageBackend<'_> { } fn write_static(&mut self, out: &mut SourceWriter, s: &Static) { + self.write_documentation(out, &s.documentation); out.write("extern "); if let Type::Ptr { is_const: true, .. } = s.ty { } else if !s.mutable { @@ -789,135 +790,6 @@ impl LanguageBackend for CLikeLanguageBackend<'_> { out.write(";"); } - fn write_function(&mut self, out: &mut SourceWriter, f: &Function) { - fn write_1( - func: &Function, - language_backend: &mut CLikeLanguageBackend, - out: &mut SourceWriter, - ) { - let prefix = language_backend.config.function.prefix(&func.annotations); - let postfix = language_backend.config.function.postfix(&func.annotations); - - let condition = func.cfg.to_condition(language_backend.config); - condition.write_before(language_backend.config, out); - - language_backend.write_documentation(out, &func.documentation); - - if func.extern_decl { - out.write("extern "); - } else { - if let Some(ref prefix) = prefix { - write!(out, "{} ", prefix); - } - if func.annotations.must_use(language_backend.config) { - if let Some(ref anno) = language_backend.config.function.must_use { - write!(out, "{} ", anno); - } - } - if let Some(note) = func - .annotations - .deprecated_note(language_backend.config, DeprecatedNoteKind::Function) - { - write!(out, "{} ", note); - } - } - cdecl::write_func( - language_backend, - out, - func, - Layout::Horizontal, - language_backend.config, - ); - - if !func.extern_decl { - if let Some(ref postfix) = postfix { - write!(out, " {}", postfix); - } - } - - if let Some(ref swift_name_macro) = language_backend.config.function.swift_name_macro { - if let Some(swift_name) = func.swift_name(language_backend.config) { - write!(out, " {}({})", swift_name_macro, swift_name); - } - } - - out.write(";"); - - condition.write_after(language_backend.config, out); - } - - fn write_2( - func: &Function, - language_backend: &mut CLikeLanguageBackend, - out: &mut SourceWriter, - ) { - let prefix = language_backend.config.function.prefix(&func.annotations); - let postfix = language_backend.config.function.postfix(&func.annotations); - - let condition = func.cfg.to_condition(language_backend.config); - - condition.write_before(language_backend.config, out); - - language_backend.write_documentation(out, &func.documentation); - - if func.extern_decl { - out.write("extern "); - } else { - if let Some(ref prefix) = prefix { - write!(out, "{}", prefix); - out.new_line(); - } - if func.annotations.must_use(language_backend.config) { - if let Some(ref anno) = language_backend.config.function.must_use { - write!(out, "{}", anno); - out.new_line(); - } - } - if let Some(note) = func - .annotations - .deprecated_note(language_backend.config, DeprecatedNoteKind::Function) - { - write!(out, "{}", note); - out.new_line(); - } - } - cdecl::write_func( - language_backend, - out, - func, - Layout::Vertical, - language_backend.config, - ); - if !func.extern_decl { - if let Some(ref postfix) = postfix { - out.new_line(); - write!(out, "{}", postfix); - } - } - - if let Some(ref swift_name_macro) = language_backend.config.function.swift_name_macro { - if let Some(swift_name) = func.swift_name(language_backend.config) { - write!(out, " {}({})", swift_name_macro, swift_name); - } - } - - out.write(";"); - - condition.write_after(language_backend.config, out); - } - - match self.config.function.args { - Layout::Horizontal => write_1(f, self, out), - Layout::Vertical => write_2(f, self, out), - Layout::Auto => { - let max_line_length = self.config.line_length; - if !out.try_write(|out| write_1(f, self, out), max_line_length) { - write_2(f, self, out) - } - } - } - } - fn write_type(&mut self, out: &mut SourceWriter, t: &Type) { cdecl::write_type(self, out, t, self.config); } @@ -1116,7 +988,7 @@ impl LanguageBackend for CLikeLanguageBackend<'_> { } fn write_functions(&mut self, out: &mut SourceWriter, b: &Bindings) { - // Override default method to close various blocs containing both globals and functions + // Override default method to close various blocks containing both globals and functions // these blocks are opened in [`write_globals`] that is also overridden if !b.functions.is_empty() || !b.globals.is_empty() { self.write_functions_default(out, b); diff --git a/src/bindgen/language_backend/cython.rs b/src/bindgen/language_backend/cython.rs index 56392c1c2..eaa666920 100644 --- a/src/bindgen/language_backend/cython.rs +++ b/src/bindgen/language_backend/cython.rs @@ -1,12 +1,10 @@ use crate::bindgen::ir::{ to_known_assoc_constant, ConditionWrite, DeprecatedNoteKind, Documentation, Enum, EnumVariant, - Field, Function, Item, Literal, OpaqueItem, ReprAlign, Static, Struct, ToCondition, Type, - Typedef, Union, + Field, Item, Literal, OpaqueItem, ReprAlign, Static, Struct, ToCondition, Type, Typedef, Union, }; use crate::bindgen::language_backend::LanguageBackend; use crate::bindgen::writer::{ListType, SourceWriter}; use crate::bindgen::DocumentationLength; -use crate::bindgen::Layout; use crate::bindgen::{cdecl, Bindings, Config}; use std::io::Write; @@ -323,6 +321,7 @@ impl LanguageBackend for CythonLanguageBackend<'_> { } fn write_static(&mut self, out: &mut SourceWriter, s: &Static) { + self.write_documentation(out, &s.documentation); out.write("extern "); if let Type::Ptr { is_const: true, .. } = s.ty { } else if !s.mutable { @@ -332,134 +331,6 @@ impl LanguageBackend for CythonLanguageBackend<'_> { out.write(";"); } - fn write_function(&mut self, out: &mut SourceWriter, f: &Function) { - fn write_1( - func: &Function, - language_backend: &mut CythonLanguageBackend, - out: &mut SourceWriter, - ) { - let prefix = language_backend.config.function.prefix(&func.annotations); - let postfix = language_backend.config.function.postfix(&func.annotations); - - let condition = func.cfg.to_condition(language_backend.config); - condition.write_before(language_backend.config, out); - - language_backend.write_documentation(out, &func.documentation); - - if func.extern_decl { - out.write("extern "); - } else { - if let Some(ref prefix) = prefix { - write!(out, "{} ", prefix); - } - if func.annotations.must_use(language_backend.config) { - if let Some(ref anno) = language_backend.config.function.must_use { - write!(out, "{} ", anno); - } - } - if let Some(note) = func - .annotations - .deprecated_note(language_backend.config, DeprecatedNoteKind::Function) - { - write!(out, "{} ", note); - } - } - cdecl::write_func( - language_backend, - out, - func, - Layout::Horizontal, - language_backend.config, - ); - - if !func.extern_decl { - if let Some(ref postfix) = postfix { - write!(out, " {}", postfix); - } - } - - if let Some(ref swift_name_macro) = language_backend.config.function.swift_name_macro { - if let Some(swift_name) = func.swift_name(language_backend.config) { - write!(out, " {}({})", swift_name_macro, swift_name); - } - } - - out.write(";"); - - condition.write_after(language_backend.config, out); - } - - fn write_2( - func: &Function, - language_backend: &mut CythonLanguageBackend, - out: &mut SourceWriter, - ) { - let prefix = language_backend.config.function.prefix(&func.annotations); - let postfix = language_backend.config.function.postfix(&func.annotations); - - let condition = func.cfg.to_condition(language_backend.config); - - condition.write_before(language_backend.config, out); - - language_backend.write_documentation(out, &func.documentation); - - if func.extern_decl { - out.write("extern "); - } else { - if let Some(ref prefix) = prefix { - write!(out, "{}", prefix); - out.new_line(); - } - if func.annotations.must_use(language_backend.config) { - if let Some(ref anno) = language_backend.config.function.must_use { - write!(out, "{}", anno); - out.new_line(); - } - } - if let Some(note) = func - .annotations - .deprecated_note(language_backend.config, DeprecatedNoteKind::Function) - { - write!(out, "{} ", note); - } - } - cdecl::write_func( - language_backend, - out, - func, - Layout::Vertical, - language_backend.config, - ); - if !func.extern_decl { - if let Some(ref postfix) = postfix { - out.new_line(); - write!(out, "{}", postfix); - } - } - - if let Some(ref swift_name_macro) = language_backend.config.function.swift_name_macro { - if let Some(swift_name) = func.swift_name(language_backend.config) { - write!(out, " {}({})", swift_name_macro, swift_name); - } - } - - out.write(";"); - - condition.write_after(language_backend.config, out); - } - - match &self.config.function.args { - Layout::Horizontal => write_1(f, self, out), - Layout::Vertical => write_2(f, self, out), - Layout::Auto => { - let max_line_length = self.config.line_length; - if !out.try_write(|out| write_1(f, self, out), max_line_length) { - write_2(f, self, out) - } - } - } - } - fn write_type(&mut self, out: &mut SourceWriter, t: &Type) { cdecl::write_type(self, out, t, self.config); } diff --git a/src/bindgen/language_backend/mod.rs b/src/bindgen/language_backend/mod.rs index ffd7f1236..adb7d8507 100644 --- a/src/bindgen/language_backend/mod.rs +++ b/src/bindgen/language_backend/mod.rs @@ -1,9 +1,10 @@ use crate::bindgen::ir::{ - Documentation, Enum, Function, ItemContainer, Literal, OpaqueItem, Static, Struct, Type, - Typedef, Union, + cfg::ConditionWrite, DeprecatedNoteKind, Documentation, Enum, Function, ItemContainer, Literal, + OpaqueItem, Static, Struct, ToCondition, Type, Typedef, Union, }; use crate::bindgen::writer::SourceWriter; -use crate::bindgen::Bindings; +use crate::bindgen::{cdecl, Bindings, Layout}; +use crate::Config; use std::io::Write; @@ -13,7 +14,7 @@ mod cython; pub use clike::CLikeLanguageBackend; pub use cython::CythonLanguageBackend; -pub trait LanguageBackend { +pub trait LanguageBackend: Sized { fn open_namespaces(&mut self, out: &mut SourceWriter); fn close_namespaces(&mut self, out: &mut SourceWriter); fn write_headers(&self, out: &mut SourceWriter, package_version: &str); @@ -24,40 +25,111 @@ pub trait LanguageBackend { fn write_opaque_item(&mut self, out: &mut SourceWriter, o: &OpaqueItem); fn write_type_def(&mut self, out: &mut SourceWriter, t: &Typedef); fn write_static(&mut self, out: &mut SourceWriter, s: &Static); - fn write_function(&mut self, out: &mut SourceWriter, f: &Function); + + fn write_function( + &mut self, + config: &Config, + out: &mut SourceWriter, + f: &Function, + ) { + match config.function.args { + Layout::Horizontal => { + self.write_function_with_layout(config, out, f, Layout::Horizontal) + } + Layout::Vertical => self.write_function_with_layout(config, out, f, Layout::Vertical), + Layout::Auto => { + let max_line_length = config.line_length; + if !out.try_write( + |out| self.write_function_with_layout(config, out, f, Layout::Horizontal), + max_line_length, + ) { + self.write_function_with_layout(config, out, f, Layout::Vertical); + } + } + } + } + + fn write_function_with_layout( + &mut self, + config: &Config, + out: &mut SourceWriter, + func: &Function, + layout: Layout, + ) { + let prefix = config.function.prefix(&func.annotations); + let postfix = config.function.postfix(&func.annotations); + + let condition = func.cfg.to_condition(config); + condition.write_before(config, out); + + self.write_documentation(out, &func.documentation); + + fn write_space(layout: Layout, out: &mut SourceWriter) { + if layout == Layout::Vertical { + out.new_line(); + } else { + out.write(" ") + } + } + if func.extern_decl { + out.write("extern "); + } else { + if let Some(ref prefix) = prefix { + write!(out, "{}", prefix); + write_space(layout, out); + } + if func.annotations.must_use(config) { + if let Some(ref anno) = config.function.must_use { + write!(out, "{}", anno); + write_space(layout, out); + } + } + if let Some(note) = func + .annotations + .deprecated_note(config, DeprecatedNoteKind::Function) + { + write!(out, "{}", note); + write_space(layout, out); + } + } + cdecl::write_func(self, out, func, layout, config); + + if !func.extern_decl { + if let Some(ref postfix) = postfix { + write_space(layout, out); + write!(out, "{}", postfix); + } + } + + if let Some(ref swift_name_macro) = config.function.swift_name_macro { + if let Some(swift_name) = func.swift_name(config) { + // XXX Should this account for `layout`? + write!(out, " {}({})", swift_name_macro, swift_name); + } + } + + out.write(";"); + condition.write_after(config, out); + } + fn write_type(&mut self, out: &mut SourceWriter, t: &Type); fn write_documentation(&mut self, out: &mut SourceWriter, d: &Documentation); fn write_literal(&mut self, out: &mut SourceWriter, l: &Literal); - fn write_bindings(&mut self, out: &mut SourceWriter, b: &Bindings) - where - Self: Sized, - { + fn write_bindings(&mut self, out: &mut SourceWriter, b: &Bindings) { self.write_headers(out, &b.package_version); - self.open_namespaces(out); - self.write_primitive_constants(out, b); - self.write_items(out, b); - self.write_non_primitive_constants(out, b); - self.write_globals(out, b); - self.write_functions(out, b); - self.close_namespaces(out); - self.write_footers(out); - self.write_trailer(out, b); } - fn write_primitive_constants(&mut self, out: &mut SourceWriter, b: &Bindings) - where - Self: Sized, - { + fn write_primitive_constants(&mut self, out: &mut SourceWriter, b: &Bindings) { for constant in &b.constants { if constant.uses_only_primitive_types() { out.new_line_if_not_start(); @@ -92,10 +164,7 @@ pub trait LanguageBackend { } } - fn write_non_primitive_constants(&mut self, out: &mut SourceWriter, b: &Bindings) - where - Self: Sized, - { + fn write_non_primitive_constants(&mut self, out: &mut SourceWriter, b: &Bindings) { for constant in &b.constants { if !constant.uses_only_primitive_types() { out.new_line_if_not_start(); @@ -124,7 +193,7 @@ pub trait LanguageBackend { fn write_functions_default(&mut self, out: &mut SourceWriter, b: &Bindings) { for function in &b.functions { out.new_line_if_not_start(); - self.write_function(out, function); + self.write_function(&b.config, out, function); out.new_line(); } }