Skip to content

Commit

Permalink
Add support for composable constructors (#3246)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Sep 4, 2024
1 parent ef0885d commit 143ab9b
Show file tree
Hide file tree
Showing 14 changed files with 902 additions and 24 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ jobs:
run: cargo clippy -p test_const_params
- name: Clippy test_const_ptrs
run: cargo clippy -p test_const_ptrs
- name: Clippy test_constructors
run: cargo clippy -p test_constructors
- name: Clippy test_constructors_client
run: cargo clippy -p test_constructors_client
- name: Clippy test_core
run: cargo clippy -p test_core
- name: Clippy test_debug
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ jobs:
run: cargo test -p test_const_params --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_const_ptrs
run: cargo test -p test_const_ptrs --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_constructors
run: cargo test -p test_constructors --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_constructors_client
run: cargo test -p test_constructors_client --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_core
run: cargo test -p test_core --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_debug
Expand Down Expand Up @@ -251,12 +255,12 @@ jobs:
run: cargo test -p test_resources --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_result
run: cargo test -p test_result --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Clean
run: cargo clean
- name: Test test_return_handle
run: cargo test -p test_return_handle --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_return_struct
run: cargo test -p test_return_struct --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Clean
run: cargo clean
- name: Test test_riddle
run: cargo test -p test_riddle --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_standalone
Expand Down
36 changes: 19 additions & 17 deletions crates/libs/bindgen/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub enum InterfaceKind {
Default,
Overridable,
Static,
Composable,
Base,
}

Expand Down Expand Up @@ -594,24 +595,25 @@ pub fn type_interfaces(ty: &Type) -> Vec<Interface> {
walk(&mut result, &Type::TypeDef(base, Vec::new()), true);
}
for attribute in row.attributes() {
match attribute.name() {
"StaticAttribute" | "ActivatableAttribute" => {
for (_, arg) in attribute.args() {
if let Value::TypeName(type_name) = arg {
let def = row
.reader()
.get_type_def(type_name.namespace(), type_name.name())
.next()
.expect("Type not found");
result.push(Interface {
ty: Type::TypeDef(def, Vec::new()),
kind: InterfaceKind::Static,
});
break;
}
}
let kind = match attribute.name() {
"StaticAttribute" | "ActivatableAttribute" => InterfaceKind::Static,
"ComposableAttribute" => InterfaceKind::Composable,
_ => continue,
};

for (_, arg) in attribute.args() {
if let Value::TypeName(type_name) = arg {
let def = row
.reader()
.get_type_def(type_name.namespace(), type_name.name())
.next()
.expect("Type not found");
result.push(Interface {
ty: Type::TypeDef(def, Vec::new()),
kind,
});
break;
}
_ => {}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/libs/bindgen/src/rust/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fn gen_class(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
}

let factories = interfaces.iter().filter_map(|interface| match interface.kind {
metadata::InterfaceKind::Static => {
metadata::InterfaceKind::Static | metadata::InterfaceKind::Composable => {
if let metadata::Type::TypeDef(def, generics) = &interface.ty {
if def.methods().next().is_some() {
let interface_type = writer.type_name(&interface.ty);
Expand Down
25 changes: 21 additions & 4 deletions crates/libs/bindgen/src/rust/winrt_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,33 @@ pub fn writer(
virtual_names: &mut MethodNames,
) -> TokenStream {
let signature = metadata::method_def_signature(def.namespace(), method, generic_types);
let params = &signature.params;
let name = method_names.add(method);
let params = if kind == metadata::InterfaceKind::Composable {
&signature.params[..signature.params.len() - 2]
} else {
&signature.params
};

let name = if kind == metadata::InterfaceKind::Composable && params.is_empty() {
quote!(new)
} else {
method_names.add(method)
};

let interface_name = writer.type_def_name(def, generic_types);
let vname = virtual_names.add(method);
let generics = writer.constraint_generics(params);
let where_clause = writer.where_clause(params);
let mut cfg = cfg::signature_cfg(writer, method);
cfg::type_def_cfg_combine(writer, def, generic_types, &mut cfg);
let features = writer.cfg_features(&cfg);
let args = gen_winrt_abi_args(writer, params);

let args = if kind == metadata::InterfaceKind::Composable {
let args = gen_winrt_abi_args(writer, params);
quote! { #args core::ptr::null_mut(), &mut core::ptr::null_mut(), }
} else {
gen_winrt_abi_args(writer, params)
};

let params = gen_winrt_params(writer, params);
let noexcept = metadata::method_def_is_noexcept(method);

Expand Down Expand Up @@ -141,7 +158,7 @@ pub fn writer(
}
}
}
metadata::InterfaceKind::Static => {
metadata::InterfaceKind::Static | metadata::InterfaceKind::Composable => {
quote! {
#features
pub fn #name<#generics>(#params) #return_type_tokens #where_clause {
Expand Down
24 changes: 24 additions & 0 deletions crates/tests/constructors/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "test_constructors"
version = "0.0.0"
edition = "2021"
publish = false

[lib]
crate-type = ["cdylib"]
doc = false
doctest = false

[build-dependencies.windows-bindgen]
path = "../../libs/bindgen"

[dependencies.windows-core]
path = "../../libs/core"

[dependencies.windows]
path = "../../libs/windows"
features = [
"implement",
"Foundation",
"Win32_System_WinRT",
]
33 changes: 33 additions & 0 deletions crates/tests/constructors/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
fn main() {
let mut command = std::process::Command::new("midlrt.exe");
command.args([
"/winrt",
"/nomidl",
"/h",
"nul",
"/metadata_dir",
"../../libs/bindgen/default",
"/reference",
"../../libs/bindgen/default/Windows.winmd",
"/winmd",
"metadata.winmd",
"src/metadata.idl",
]);

if !command.status().unwrap().success() {
panic!("Failed to run midlrt");
}

windows_bindgen::bindgen([
"--in",
"metadata.winmd",
"--out",
"src/bindings.rs",
"--filter",
"test_constructors",
"--config",
"implement",
"no-bindgen-comment",
])
.unwrap();
}
Loading

0 comments on commit 143ab9b

Please sign in to comment.