diff --git a/Generator/Sources/SwiftWinRT/Writing/ClassDefinition.swift b/Generator/Sources/SwiftWinRT/Writing/ClassDefinition.swift index 7b97019..78c516b 100644 --- a/Generator/Sources/SwiftWinRT/Writing/ClassDefinition.swift +++ b/Generator/Sources/SwiftWinRT/Writing/ClassDefinition.swift @@ -296,12 +296,14 @@ fileprivate func writeComposableInitializers( let propertyName = SecondaryInterfaces.getPropertyName(factoryInterface.bind()) for method in factoryInterface.methods { + // Swift requires "override" on initializers iff the same initializer is defined in the direct base class + let `override` = try base != nil && hasComposableConstructor(classDefinition: base!, paramTypes: method.params.map { try $0.type }) // The last 2 params should be the IInspectable outer and inner pointers let (params, returnParam) = try projection.getParamBindings(method: method, genericTypeArgs: [], abiKind: .composableFactory) try writer.writeInit( documentation: try projection.getDocumentationComment(abiMember: method, classDefinition: classDefinition), visibility: .public, - override: params.count == 2 && base != nil, // Hack: assume all base classes have a default initializer we are overriding + override: `override`, params: params.dropLast(2).map { $0.toSwiftParam() }, // Drop inner and outer pointer params throws: true) { writer in let output = writer.output @@ -319,6 +321,21 @@ fileprivate func writeComposableInitializers( } } +fileprivate func hasComposableConstructor(classDefinition: ClassDefinition, paramTypes: [TypeNode]) throws -> Bool { + if classDefinition.fullName == "System.Object" { + return paramTypes.count == 2 // Default composable constructor with Inner and Outer pointers + } + + for composableAttribute in try classDefinition.getAttributes(ComposableAttribute.self) { + for composableConstructor in composableAttribute.factory.methods { + guard try composableConstructor.arity == paramTypes.count else { continue } + if try composableConstructor.params.map({ try $0.type }) == paramTypes { return true } + } + } + + return false +} + fileprivate func writeDefaultActivatableInitializer( _ classDefinition: ClassDefinition, projection: Projection, to writer: SwiftTypeDefinitionWriter) throws { diff --git a/InteropTests/WinRTComponent/Dll/CMakeLists.txt b/InteropTests/WinRTComponent/Dll/CMakeLists.txt index 7bfb828..0a246ed 100644 --- a/InteropTests/WinRTComponent/Dll/CMakeLists.txt +++ b/InteropTests/WinRTComponent/Dll/CMakeLists.txt @@ -1,3 +1,6 @@ +cmake_minimum_required(VERSION 3.21.0) +project(WinRTComponentDll LANGUAGES CXX) + if(NOT DEFINED WINRTCOMPONENT_WINMD) message(FATAL_ERROR "WINRTCOMPONENT_WINMD must be defined") endif() @@ -13,6 +16,7 @@ cmake_path(CONVERT "${WINRTCOMPONENT_WINMD}" TO_NATIVE_PATH_LIST WINRTCOMPONENT_ string(REPLACE "\\" "" WINSDK_VERSION "$ENV{WindowsSDKVersion}") set(CPPWINRT_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/CppWinRT") cmake_path(CONVERT "${CPPWINRT_GENERATED_DIR}" TO_NATIVE_PATH_LIST CPPWINRT_GENERATED_DIR_NATIVE) +file(REMOVE_RECURSE "${CPPWINRT_GENERATED_DIR}") execute_process( COMMAND "${CPPWINRT_EXE_NATIVE}" -input "${WINRTCOMPONENT_WINMD_NATIVE}" diff --git a/InteropTests/WinRTComponent/Dll/ShadowingConstructors.cpp b/InteropTests/WinRTComponent/Dll/ShadowingConstructors.cpp new file mode 100644 index 0000000..a76df06 --- /dev/null +++ b/InteropTests/WinRTComponent/Dll/ShadowingConstructors.cpp @@ -0,0 +1,6 @@ +#include "pch.h" + +// C++/WinRT struggles with a derived class having a default constructor which delegates to a base class constructor with a parameter. +// So just stub out the exports here as we won't instantiate the classes anyways. +void * __cdecl winrt_make_WinRTComponent_ShadowingConstructorsBase() { return nullptr; } +void * __cdecl winrt_make_WinRTComponent_ShadowingConstructorsDerived() { return nullptr; } diff --git a/InteropTests/WinRTComponent/GenerateProjection.cmake b/InteropTests/WinRTComponent/GenerateProjection.cmake index c4de7c5..d6b4d58 100644 --- a/InteropTests/WinRTComponent/GenerateProjection.cmake +++ b/InteropTests/WinRTComponent/GenerateProjection.cmake @@ -49,9 +49,7 @@ function(generate_projection) endif() # Delete the previous projection files - execute_process( - COMMAND ${CMAKE_COMMAND} -E remove_directory "${ARG_PROJECTION_DIR}" - COMMAND_ERROR_IS_FATAL ANY) + file(REMOVE_RECURSE "${ARG_PROJECTION_DIR}") # Generate the projection cmake_path(CONVERT "${ARG_PROJECTION_JSON}" TO_NATIVE_PATH_LIST PROJECTION_JSON_NATIVE) diff --git a/InteropTests/WinRTComponent/IDL/ManualAsyncOperation.idl b/InteropTests/WinRTComponent/IDL/ManualAsyncOperation.idl index 0b550cc..9bd756f 100644 --- a/InteropTests/WinRTComponent/IDL/ManualAsyncOperation.idl +++ b/InteropTests/WinRTComponent/IDL/ManualAsyncOperation.idl @@ -1,6 +1,7 @@ namespace WinRTComponent { - runtimeclass ManualAsyncOperation : Windows.Foundation.IAsyncOperation { + runtimeclass ManualAsyncOperation : Windows.Foundation.IAsyncOperation + { ManualAsyncOperation(Int32 id); void Complete(Int32 result); void CompleteWithError(HRESULT errorCode); diff --git a/InteropTests/WinRTComponent/IDL/ShadowingConstructors.idl b/InteropTests/WinRTComponent/IDL/ShadowingConstructors.idl new file mode 100644 index 0000000..12fe34c --- /dev/null +++ b/InteropTests/WinRTComponent/IDL/ShadowingConstructors.idl @@ -0,0 +1,14 @@ +namespace WinRTComponent +{ + unsealed runtimeclass ShadowingConstructorsBase + { + ShadowingConstructorsBase(Int32 param); // "value" name is reserved (due to generated COM code?) + }; + + unsealed runtimeclass ShadowingConstructorsDerived : ShadowingConstructorsBase + { + // Regression test for https://github.com/tristanlabelle/swift-winrt/issues/360 + ShadowingConstructorsDerived(); // Does not directly shadow + ShadowingConstructorsDerived(Int32 param); // Shadows + }; +} \ No newline at end of file diff --git a/InteropTests/WinRTComponent/IDL/WinRTComponent.idl b/InteropTests/WinRTComponent/IDL/WinRTComponent.idl index 7422fc9..ccb1f09 100644 --- a/InteropTests/WinRTComponent/IDL/WinRTComponent.idl +++ b/InteropTests/WinRTComponent/IDL/WinRTComponent.idl @@ -25,6 +25,7 @@ #include "OverloadedSum.idl" #include "ReferenceBoxing.idl" #include "ReturnArgument.idl" +#include "ShadowingConstructors.idl" #include "Strings.idl" #include "Structs.idl" #include "SwiftAttributes.idl"