diff --git a/crates/libs/interface/src/lib.rs b/crates/libs/interface/src/lib.rs index e1b3fd7881..929889f59f 100644 --- a/crates/libs/interface/src/lib.rs +++ b/crates/libs/interface/src/lib.rs @@ -341,41 +341,40 @@ impl Interface { } fn parent_vtable(&self) -> Option { - if let Some(i) = self.parent_ident() { - let i = quote::format_ident!("{}_Vtbl", i); - Some(quote!(#i)) + if let Some((ident, path)) = self.parent_path().split_last() { + let ident = quote::format_ident!("{}_Vtbl", ident); + Some(quote! { #(#path::)* #ident }) } else { None } } fn parent_is_iunknown(&self) -> bool { - if let Some(ident) = self.parent_ident() { + if let Some(ident) = self.parent_path().last() { ident == "IUnknown" } else { false } } - fn parent_ident(&self) -> Option<&syn::Ident> { + fn parent_path(&self) -> Vec { if let Some(parent) = &self.parent { - Some(&parent.segments.last().as_ref().expect("segements should never be empty").ident) + parent.segments.iter().map(|segment| segment.ident.clone()).collect() } else { - None + vec![] } } /// Gets the parent trait constrait which is nothing if the parent is IUnknown fn parent_trait_constraint(&self) -> proc_macro2::TokenStream { - if let Some(i) = self.parent_ident() { - if i == "IUnknown" { - return quote!(); + if let Some((ident, path)) = self.parent_path().split_last() { + if ident != "IUnknown" { + let ident = quote::format_ident!("{}_Impl", ident); + return quote! { #(#path::)* #ident }; } - let i = quote::format_ident!("{}_Impl", i); - quote!(#i) - } else { - quote!() } + + quote! {} } } diff --git a/crates/tests/interface/tests/no_use.rs b/crates/tests/interface/tests/no_use.rs new file mode 100644 index 0000000000..4cefc10549 --- /dev/null +++ b/crates/tests/interface/tests/no_use.rs @@ -0,0 +1,39 @@ +#![allow(non_snake_case)] + +// This is a variant of the interface_core/no_use.rs test for use with more complex paths provided by the windows crate. + +#[windows::core::interface("BD1AE5E0-A6AE-11CE-BD37-504200C10000")] +unsafe trait ITestPersistMemory: windows::Win32::System::Com::IPersist { + unsafe fn IsDirty(&self) -> windows::core::HRESULT; +} + +#[windows::core::implement(ITestPersistMemory, windows::Win32::System::Com::IPersist)] +struct Test; + +impl windows::Win32::System::Com::IPersist_Impl for Test { + fn GetClassID(&self) -> windows::core::Result { + Ok("CEE1D356-0860-4262-90D4-C77423F0E352".into()) + } +} + +impl ITestPersistMemory_Impl for Test { + unsafe fn IsDirty(&self) -> windows::core::HRESULT { + windows::Win32::Foundation::S_FALSE + } +} + +#[test] +fn test() -> windows::core::Result<()> { + unsafe { + let p: windows::Win32::System::Com::IPersist = Test.into(); + assert_eq!( + p.GetClassID()?, + "CEE1D356-0860-4262-90D4-C77423F0E352".into() + ); + + let m: ITestPersistMemory = windows_core::Interface::cast(&p)?; + assert_eq!(m.IsDirty(), windows::Win32::Foundation::S_FALSE); + + Ok(()) + } +} diff --git a/crates/tests/interface_core/tests/test.rs b/crates/tests/interface_core/tests/asterisk_use.rs similarity index 72% rename from crates/tests/interface_core/tests/test.rs rename to crates/tests/interface_core/tests/asterisk_use.rs index c256fb3625..f6df071852 100644 --- a/crates/tests/interface_core/tests/test.rs +++ b/crates/tests/interface_core/tests/asterisk_use.rs @@ -1,5 +1,8 @@ #![allow(non_snake_case)] +// This tests uses `windows_core` via an asterisk to test that the interface/implement macros support this mode +// as opposed to no_use.rs which tests the opposite. + use windows_core::*; #[interface("72cd87fa-9c99-42e0-8986-84a76f08fc5a")] diff --git a/crates/tests/interface/tests/deref.rs b/crates/tests/interface_core/tests/deref.rs similarity index 100% rename from crates/tests/interface/tests/deref.rs rename to crates/tests/interface_core/tests/deref.rs diff --git a/crates/tests/interface_core/tests/no_use.rs b/crates/tests/interface_core/tests/no_use.rs new file mode 100644 index 0000000000..24d62e28eb --- /dev/null +++ b/crates/tests/interface_core/tests/no_use.rs @@ -0,0 +1,26 @@ +#![allow(non_snake_case)] + +// This tests uses `windows_core` explicitly to test that the interface/implement macros support this mode +// as opposed to asterisk_use.rs which tests the opposite. + +#[windows_core::interface("72cd87fa-9c99-42e0-8986-84a76f08fc5a")] +unsafe trait ITest: windows_core::IUnknown { + unsafe fn Test(&self) -> windows_core::HRESULT; +} + +#[windows_core::implement(ITest)] +struct Test; + +impl ITest_Impl for Test { + unsafe fn Test(&self) -> windows_core::HRESULT { + windows_core::HRESULT(123) + } +} + +#[test] +fn test() { + unsafe { + let test: ITest = Test.into(); + assert_eq!(test.Test(), windows_core::HRESULT(123)); + } +}