Skip to content

Commit

Permalink
Allow for arbitrary BindingGenerator
Browse files Browse the repository at this point in the history
De-couple TargetLanguage from the `generate_external_bindings` calls.
This will allow 3rd-party BindingGenerators to use the methods.

The `try_format_code` boolean had to be punched through (for now) to
keep the API as similar as possible. I think a follow-up action should
be to move the boolean to the Config.
  • Loading branch information
SalvatoreT committed Mar 19, 2024
1 parent 6ddd8cd commit a3479ac
Show file tree
Hide file tree
Showing 16 changed files with 352 additions and 212 deletions.
59 changes: 50 additions & 9 deletions fixtures/docstring-proc-macro/tests/test_generated_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ uniffi::build_foreign_language_testcases!(

#[cfg(test)]
mod tests {
use uniffi_bindgen::bindings::KotlinBindingGenerator;
use uniffi_bindgen::bindings::PythonBindingGenerator;
use uniffi_bindgen::bindings::RubyBindingGenerator;
use uniffi_bindgen::bindings::SwiftBindingGenerator;
use uniffi_bindgen::bindings::TargetLanguage;
use uniffi_testing::UniFFITestHelper;

Expand Down Expand Up @@ -47,15 +51,52 @@ mod tests {

let cdylib_path = test_helper.copy_cdylib_to_out_dir(&out_dir).unwrap();

uniffi_bindgen::library_mode::generate_bindings(
&cdylib_path,
None,
&[language],
None,
&out_dir,
false,
)
.unwrap();
match language {
TargetLanguage::Kotlin => {
uniffi_bindgen::library_mode::generate_bindings(
&cdylib_path,
None,
&KotlinBindingGenerator,
None,
&out_dir,
false,
)
.unwrap();
}
TargetLanguage::Swift => {
uniffi_bindgen::library_mode::generate_bindings(
&cdylib_path,
None,
&SwiftBindingGenerator,
None,
&out_dir,
false,
)
.unwrap();
}
TargetLanguage::Python => {
uniffi_bindgen::library_mode::generate_bindings(
&cdylib_path,
None,
&PythonBindingGenerator,
None,
&out_dir,
false,
)
.unwrap();
}
TargetLanguage::Ruby => {
uniffi_bindgen::library_mode::generate_bindings(
&cdylib_path,
None,
&RubyBindingGenerator,
None,
&out_dir,
false,
)
.unwrap();
}
}

let glob_pattern = out_dir.join(format!("**/*.{}", file_extension));

Expand Down
64 changes: 54 additions & 10 deletions fixtures/docstring/tests/test_generated_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ uniffi::build_foreign_language_testcases!(
#[cfg(test)]
mod tests {
use camino::Utf8PathBuf;
use uniffi_bindgen::bindings::KotlinBindingGenerator;
use uniffi_bindgen::bindings::PythonBindingGenerator;
use uniffi_bindgen::bindings::RubyBindingGenerator;
use uniffi_bindgen::bindings::SwiftBindingGenerator;
use uniffi_bindgen::bindings::TargetLanguage;
use uniffi_testing::UniFFITestHelper;

Expand Down Expand Up @@ -45,16 +49,56 @@ mod tests {
)
.unwrap();

uniffi_bindgen::generate_bindings(
&Utf8PathBuf::from("src/docstring.udl"),
None,
vec![language],
Some(&out_dir),
None,
None,
false,
)
.unwrap();
match language {
TargetLanguage::Kotlin => {
uniffi_bindgen::generate_bindings(
&Utf8PathBuf::from("src/docstring.udl"),
None,
KotlinBindingGenerator,
Some(&out_dir),
None,
None,
false,
)
.unwrap();
}
TargetLanguage::Swift => {
uniffi_bindgen::generate_bindings(
&Utf8PathBuf::from("src/docstring.udl"),
None,
SwiftBindingGenerator,
Some(&out_dir),
None,
None,
false,
)
.unwrap();
}
TargetLanguage::Python => {
uniffi_bindgen::generate_bindings(
&Utf8PathBuf::from("src/docstring.udl"),
None,
PythonBindingGenerator,
Some(&out_dir),
None,
None,
false,
)
.unwrap();
}
TargetLanguage::Ruby => {
uniffi_bindgen::generate_bindings(
&Utf8PathBuf::from("src/docstring.udl"),
None,
RubyBindingGenerator,
Some(&out_dir),
None,
None,
false,
)
.unwrap();
}
}

let glob_pattern = out_dir.join(format!("**/*.{}", file_extension));

Expand Down
4 changes: 2 additions & 2 deletions fixtures/swift-bridging-header-compile/tests/clang.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use camino::Utf8PathBuf;
use std::process::Command;
use uniffi::TargetLanguage;
use uniffi::SwiftBindingGenerator;
use uniffi_testing::UniFFITestHelper;

#[test]
Expand All @@ -14,7 +14,7 @@ fn clang() -> Result<(), anyhow::Error> {
uniffi::generate_bindings(
&Utf8PathBuf::from("src/swift-bridging-header-compile.udl"),
None,
vec![TargetLanguage::Swift],
SwiftBindingGenerator,
Some(&out_dir),
None,
None,
Expand Down
115 changes: 97 additions & 18 deletions uniffi/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

use camino::Utf8PathBuf;
use clap::{Parser, Subcommand};
use uniffi_bindgen::bindings::TargetLanguage;

use uniffi_bindgen::bindings::{
KotlinBindingGenerator, PythonBindingGenerator, RubyBindingGenerator, SwiftBindingGenerator,
TargetLanguage,
};

// Structs to help our cmdline parsing. Note that docstrings below form part
// of the "help" output.
Expand Down Expand Up @@ -99,24 +103,99 @@ pub fn run_main() -> anyhow::Result<()> {
if language.is_empty() {
panic!("please specify at least one language with --language")
}
uniffi_bindgen::library_mode::generate_bindings(
&source,
crate_name,
&language,
config.as_deref(),
&out_dir,
!no_format,
)?;
for lang in language {
match lang {
TargetLanguage::Kotlin => {
uniffi_bindgen::library_mode::generate_bindings(
&source,
crate_name.clone(),
&KotlinBindingGenerator,
config.as_deref(),
&out_dir,
!no_format,
)?;
}
TargetLanguage::Swift => {
uniffi_bindgen::library_mode::generate_bindings(
&source,
crate_name.clone(),
&SwiftBindingGenerator,
config.as_deref(),
&out_dir,
!no_format,
)?;
}
TargetLanguage::Python => {
uniffi_bindgen::library_mode::generate_bindings(
&source,
crate_name.clone(),
&PythonBindingGenerator,
config.as_deref(),
&out_dir,
!no_format,
)?;
}
TargetLanguage::Ruby => {
uniffi_bindgen::library_mode::generate_bindings(
&source,
crate_name.clone(),
&RubyBindingGenerator,
config.as_deref(),
&out_dir,
!no_format,
)?;
}
}
}
} else {
uniffi_bindgen::generate_bindings(
&source,
config.as_deref(),
language,
out_dir.as_deref(),
lib_file.as_deref(),
crate_name.as_deref(),
!no_format,
)?;
for lang in language {
match lang {
TargetLanguage::Kotlin => {
uniffi_bindgen::generate_bindings(
&source,
config.as_deref(),
KotlinBindingGenerator,
out_dir.as_deref(),
lib_file.as_deref(),
crate_name.as_deref(),
!no_format,
)?;
}
TargetLanguage::Swift => {
uniffi_bindgen::generate_bindings(
&source,
config.as_deref(),
SwiftBindingGenerator,
out_dir.as_deref(),
lib_file.as_deref(),
crate_name.as_deref(),
!no_format,
)?;
}
TargetLanguage::Python => {
uniffi_bindgen::generate_bindings(
&source,
config.as_deref(),
PythonBindingGenerator,
out_dir.as_deref(),
lib_file.as_deref(),
crate_name.as_deref(),
!no_format,
)?;
}
TargetLanguage::Ruby => {
uniffi_bindgen::generate_bindings(
&source,
config.as_deref(),
RubyBindingGenerator,
out_dir.as_deref(),
lib_file.as_deref(),
crate_name.as_deref(),
!no_format,
)?;
}
}
}
}
}
Commands::Scaffolding {
Expand Down
7 changes: 5 additions & 2 deletions uniffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ pub use uniffi_bindgen::bindings::ruby::run_test as ruby_run_test;
pub use uniffi_bindgen::bindings::swift::run_test as swift_run_test;
#[cfg(feature = "bindgen")]
pub use uniffi_bindgen::{
bindings::TargetLanguage, generate_bindings, generate_component_scaffolding,
generate_component_scaffolding_for_crate, print_repr,
bindings::kotlin::gen_kotlin::KotlinBindingGenerator,
bindings::python::gen_python::PythonBindingGenerator,
bindings::ruby::gen_ruby::RubyBindingGenerator,
bindings::swift::gen_swift::SwiftBindingGenerator, bindings::TargetLanguage, generate_bindings,
generate_component_scaffolding, generate_component_scaffolding_for_crate, print_repr,
};
#[cfg(feature = "build")]
pub use uniffi_build::{generate_scaffolding, generate_scaffolding_for_crate};
Expand Down
28 changes: 26 additions & 2 deletions uniffi_bindgen/src/bindings/kotlin/gen_kotlin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ use std::cell::RefCell;
use std::collections::{BTreeSet, HashMap, HashSet};
use std::fmt::Debug;

use anyhow::{Context, Result};
use anyhow::{bail, Context, Result};
use askama::Template;
use camino::Utf8Path;
use heck::{ToLowerCamelCase, ToShoutySnakeCase, ToUpperCamelCase};
use serde::{Deserialize, Serialize};

use crate::backend::TemplateExpression;
use crate::bindings::kotlin;
use crate::interface::*;
use crate::BindingsConfig;
use crate::{BindingGenerator, BindingsConfig};

mod callback_interface;
mod compounds;
Expand All @@ -27,6 +29,28 @@ mod primitives;
mod record;
mod variant;

pub struct KotlinBindingGenerator;
impl BindingGenerator for KotlinBindingGenerator {
type Config = Config;

fn write_bindings(
&self,
ci: &ComponentInterface,
config: &Config,
out_dir: &Utf8Path,
try_format_code: bool,
) -> Result<()> {
kotlin::write_bindings(config, ci, out_dir, try_format_code)
}

fn check_library_path(&self, library_path: &Utf8Path, cdylib_name: Option<&str>) -> Result<()> {
if cdylib_name.is_none() {
bail!("Generate bindings for Kotlin requires a cdylib, but {library_path} was given");
}
Ok(())
}
}

trait CodeType: Debug {
/// The language specific label used to reference this type. This will be used in
/// method signatures and property declarations.
Expand Down
8 changes: 3 additions & 5 deletions uniffi_bindgen/src/bindings/kotlin/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::{
bindings::{RunScriptOptions, TargetLanguage},
library_mode::generate_bindings,
};
use crate::bindings::kotlin::gen_kotlin::KotlinBindingGenerator;
use crate::{bindings::RunScriptOptions, library_mode::generate_bindings};
use anyhow::{bail, Context, Result};
use camino::{Utf8Path, Utf8PathBuf};
use std::env;
Expand Down Expand Up @@ -40,7 +38,7 @@ pub fn run_script(
generate_bindings(
&cdylib_path,
None,
&[TargetLanguage::Kotlin],
&KotlinBindingGenerator,
None,
&out_dir,
false,
Expand Down
Loading

0 comments on commit a3479ac

Please sign in to comment.