diff --git a/SwiftReflector/MarshalEngineCSafeSwiftToCSharp.cs b/SwiftReflector/MarshalEngineCSafeSwiftToCSharp.cs index 884e2b44..75247305 100644 --- a/SwiftReflector/MarshalEngineCSafeSwiftToCSharp.cs +++ b/SwiftReflector/MarshalEngineCSafeSwiftToCSharp.cs @@ -433,7 +433,7 @@ public List MarshalFromLambdaReceiverToCSFunc (CSType thisType, st public List MarshalFromLambdaReceiverToCSProp (CSProperty prop, CSType thisType, string csProxyName, CSParameterList delegateParams, - FunctionDeclaration funcDecl, CSType methodType, bool isObjC) + FunctionDeclaration funcDecl, CSType methodType, bool isObjC, bool hasAssociatedTypes) { bool forProtocol = csProxyName != null; bool needsReturn = funcDecl.IsGetter; @@ -463,12 +463,13 @@ public List MarshalFromLambdaReceiverToCSProp (CSProperty prop, CS CSIdentifier csharpCall = null; - if (forProtocol) { - csharpCall = new CSIdentifier ($"SwiftObjectRegistry.Registry.InterfaceForExistentialContainer<{thisType.ToString()}> (self).{prop.Name.Name}"); + var thisTypeName = hasAssociatedTypes ? csProxyName : thisType.ToString (); + if (forProtocol && !hasAssociatedTypes) { + csharpCall = new CSIdentifier ($"SwiftObjectRegistry.Registry.InterfaceForExistentialContainer<{thisTypeName}> (self).{prop.Name.Name}"); } else { var call = isObjC ? - $"ObjCRuntime.Runtime.GetNSObject<{thisType.ToString ()}> (self).{prop.Name.Name}" : - $"SwiftObjectRegistry.Registry.CSObjectForSwiftObject<{thisType.ToString ()}> (self).{prop.Name.Name}"; + $"ObjCRuntime.Runtime.GetNSObject<{thisTypeName}> (self).{prop.Name.Name}" : + $"SwiftObjectRegistry.Registry.CSObjectForSwiftObject<{thisTypeName}> (self).{prop.Name.Name}"; csharpCall = new CSIdentifier (call); } diff --git a/SwiftReflector/NewClassCompiler.cs b/SwiftReflector/NewClassCompiler.cs index 5c65800e..e38d75ad 100644 --- a/SwiftReflector/NewClassCompiler.cs +++ b/SwiftReflector/NewClassCompiler.cs @@ -2265,7 +2265,7 @@ CSProperty ImplementProtocolSubscriptEtter (WrappingResult wrapper, List vtableAssignments, CSUsingPackages use, bool isSetter, CSProperty wrapperProp, string swiftLibraryPath) { CSDelegateTypeDecl etterDelegateDecl = DefineDelegateAndAddToVtable (vtable, etterFunc, use, - OverrideBuilder.VTableEntryIdentifier (vtableEntryIndex), true); + OverrideBuilder.VTableEntryIdentifier (vtableEntryIndex), !protocolDecl.HasAssociatedTypes); vtable.Delegates.Add (etterDelegateDecl); var etterWrapperFunc = FindProtocolWrapperFunction (etterFunc, wrapper); @@ -2524,7 +2524,7 @@ int ImplementPropertyVtableForVirtualProperties (WrappingResult wrapper, } var wrapperProp = ImplementPropertyEtter (wrapper, classDecl, subclassDecl, classContents, cl, picl, usedPinvokeNames, virtFuncs, getterFunc, tlSetter, vtableEntryIndex, vtableName, vtable, vtableAssignments, use, - false, null, swiftLibraryPath); + false, null, swiftLibraryPath, null); if (hasSetter) { wrapperProp = ImplementPropertyEtter (wrapper, classDecl, subclassDecl, classContents, cl, picl, usedPinvokeNames, virtFuncs, @@ -2544,7 +2544,7 @@ CSProperty ImplementProtocolPropertyEtter (WrappingResult wrapper, List vtableAssignments, CSUsingPackages use, bool isSetter, bool isObjC, CSProperty wrapperProp, string swiftLibraryPath) { var etterDelegateDecl = DefineDelegateAndAddToVtable (vtable, etterFunc, use, - OverrideBuilder.VTableEntryIdentifier (vtableEntryIndex), true); + OverrideBuilder.VTableEntryIdentifier (vtableEntryIndex), !protocolDecl.HasAssociatedTypes); vtable.Delegates.Add (etterDelegateDecl); var etterWrapperFunc = FindProtocolWrapperFunction (etterFunc, wrapper); @@ -2561,7 +2561,7 @@ CSProperty ImplementProtocolPropertyEtter (WrappingResult wrapper, piEtterName = Uniqueify (piEtterName, usedPinvokeNames); usedPinvokeNames.Add (piEtterName); - string piEtterRef = PIClassName (TypeMapper.GetDotNetNameForSwiftClassName (protocolContents.Name)) + "." + piEtterName; + string piEtterRef = picl.Name + "." + piEtterName; var piGetter = TLFCompiler.CompileMethod (etterWrapperFunc, use, PInvokeName (wrapper.ModuleLibPath, swiftLibraryPath), etterWrapper.MangledName, piEtterName, true, true, false); @@ -2570,6 +2570,9 @@ CSProperty ImplementProtocolPropertyEtter (WrappingResult wrapper, if (wrapperProp == null) { wrapperProp = TLFCompiler.CompileProperty (use, propName, etterFunc, setter, CSMethodKind.None); + if (protocolDecl.HasAssociatedTypes) { + SubstituteAssociatedTypeNamer (protocolDecl, wrapperProp); + } var ifaceProp = new CSProperty (wrapperProp.PropType, CSMethodKind.None, new CSIdentifier (propName), @@ -2580,6 +2583,8 @@ CSProperty ImplementProtocolPropertyEtter (WrappingResult wrapper, var usedIds = new List { propName }; var marshal = new MarshalEngine (use, usedIds, TypeMapper, wrapper.Module.SwiftCompilerVersion); + if (protocolDecl.HasAssociatedTypes) + marshal.GenericReferenceNamer = MakeAssociatedTypeNamer (protocolDecl); var ifTest = kInterfaceImpl != CSConstant.Null; var ifBlock = new CSCodeBlock (); @@ -2600,12 +2605,16 @@ CSProperty ImplementProtocolPropertyEtter (WrappingResult wrapper, etterFunc, etterFunc.ReturnTypeSpec, wrapperProp.PropType, etterFunc.ParameterLists [0] [0].TypeSpec, new CSSimpleType (iface.Name.Name), false, wrapper, etterFunc.HasThrows)); } - var ifElse = new CSIfElse (ifTest, ifBlock, elseBlock); - target.Add (ifElse); + if (protocolDecl.HasAssociatedTypes) { + target.AddRange (elseBlock); + } else { + var ifElse = new CSIfElse (ifTest, ifBlock, elseBlock); + target.Add (ifElse); + } var recvr = ImplementVirtualPropertyStaticReceiver (new CSSimpleType (iface.Name.Name), - proxyClass.Name.Name, etterDelegateDecl, use, - etterFunc, wrapperProp, null, vtable.Name, isObjC); + proxyClass.ToCSType ().ToString (), etterDelegateDecl, use, + etterFunc, wrapperProp, null, vtable.Name, isObjC, protocolDecl.HasAssociatedTypes); proxyClass.Methods.Add (recvr); vtableAssignments.Add (CSAssignment.Assign (String.Format ("{0}.{1}", @@ -2617,7 +2626,8 @@ CSProperty ImplementPropertyEtter (WrappingResult wrapper, ClassDeclaration classDecl, ClassDeclaration subclassDecl, ClassContents classContents, CSClass cl, CSClass picl, List usedPinvokeNames, List virtFuncs, FunctionDeclaration etterFunc, TLFunction tlSetter, int vtableEntryIndex, string vtableName, CSStruct vtable, - List vtableAssignments, CSUsingPackages use, bool isSetter, CSProperty wrapperProp, string swiftLibraryPath) + List vtableAssignments, CSUsingPackages use, bool isSetter, CSProperty wrapperProp, string swiftLibraryPath, + Func genericRenamer = null) { var swiftClassName = XmlToTLFunctionMapper.ToSwiftClassName (subclassDecl); var tlEtter = XmlToTLFunctionMapper.ToTLFunction (etterFunc, classContents); @@ -2644,7 +2654,8 @@ CSProperty ImplementPropertyEtter (WrappingResult wrapper, var piGetter = TLFCompiler.CompileMethod (etterWrapperFunc, use, PInvokeName (wrapper.ModuleLibPath, swiftLibraryPath), - etterWrapper.MangledName, piEtterName, true, true, false); picl.Methods.Add (piGetter); + etterWrapper.MangledName, piEtterName, true, true, false); + picl.Methods.Add (piGetter); var superEtterFunc = subclassDecl.AllMethodsNoCDTor ().Where (fn => fn.Access == Accessibility.Internal && fn.IsProperty && @@ -2685,7 +2696,8 @@ CSProperty ImplementPropertyEtter (WrappingResult wrapper, } } - ImplementOverloadFromKnownWrapper (cl, picl, usedPinvokeNames, swiftClassName, superEtterTlf, superEtterFunc, use, true, wrapper, swiftLibraryPath, superEtterFuncWrapper, "", true); + ImplementOverloadFromKnownWrapper (cl, picl, usedPinvokeNames, swiftClassName, superEtterTlf, superEtterFunc, use, true, wrapper, swiftLibraryPath, superEtterFuncWrapper, "", true, + genericRenamer: genericRenamer); var propertyImplMethod = cl.Methods.Last (); CSMethod protoListMethod = null; if (returnIsProtocolList) { @@ -2711,7 +2723,7 @@ CSProperty ImplementPropertyEtter (WrappingResult wrapper, } var recvr = ImplementVirtualPropertyStaticReceiver (cl.ToCSType (), null, etterDelegateDecl, use, etterFunc, - wrapperProp, protoListMethod, vtable.Name, classDecl.IsObjC); + wrapperProp, protoListMethod, vtable.Name, classDecl.IsObjC, false); cl.Methods.Add (recvr); vtableAssignments.Add (CSAssignment.Assign (String.Format ("{0}.{1}", @@ -2841,7 +2853,7 @@ CSMethod ImplementVirtualSubscriptStaticReceiver (CSType thisType, string csProx CSMethod ImplementVirtualPropertyStaticReceiver (CSType thisType, string csProxyName, CSDelegateTypeDecl delType, CSUsingPackages use, FunctionDeclaration funcDecl, CSProperty prop, CSMethod protoListMethod, - CSIdentifier vtableName, bool isObjC) + CSIdentifier vtableName, bool isObjC, bool hasAssociatedTypes) { var returnType = funcDecl.IsGetter ? delType.Type : CSSimpleType.Void; CSParameterList pl = delType.Parameters; @@ -2860,7 +2872,7 @@ CSMethod ImplementVirtualPropertyStaticReceiver (CSType thisType, string csProxy var bodyContents = marshaler.MarshalFromLambdaReceiverToCSProp (prop, thisType, csProxyName, delType.Parameters, - funcDecl, prop.PropType, isObjC); + funcDecl, prop.PropType, isObjC, hasAssociatedTypes); body.AddRange (bodyContents); recvrName = "xamVtable_recv_" + (funcDecl.IsGetter ? "get_" : "set_") + prop.Name.Name; } @@ -2895,7 +2907,7 @@ CSLambda ImplementVirtualPropertyReceiver (CSType thisType, string csProxyName, var marshaler = new MarshalEngineCSafeSwiftToCSharp (use, usedIDs, TypeMapper); var bodyContents = marshaler.MarshalFromLambdaReceiverToCSProp (prop, thisType, csProxyName, delType.Parameters, - funcDecl, prop.PropType, isObjC); + funcDecl, prop.PropType, isObjC, false); var body = new CSCodeBlock (bodyContents); return new CSLambda (pl, body); } @@ -5122,7 +5134,8 @@ CSIfElse InterfaceMethodRedirect (CSMethod publicMethod, IEnumerable usedPinvokeNames, SwiftClassName classForPI, TLFunction methodToWrap, FunctionDeclaration funcToWrap, CSUsingPackages use, bool isFinal, WrappingResult wrapper, string swiftLibraryPath, TLFunction wrapperFunction, - string homonymSuffix, bool forcePrivate = false, string alternativeName = null) + string homonymSuffix, bool forcePrivate = false, string alternativeName = null, + Func genericRenamer = null) { var wrapperFuncDecl = FindEquivalentFunctionDeclarationForWrapperFunction (wrapperFunction, TypeMapper, wrapper); var pinvokeMethodName = PIMethodName (classForPI, wrapperFunction.Name) + homonymSuffix; @@ -5190,6 +5203,7 @@ CSMethod ImplementOverloadFromKnownWrapper (CSClass cl, CSClass picl, List namer, CSType ty) { if (ty is CSGenericReferenceType genType) { diff --git a/SwiftReflector/OverrideBuilder.cs b/SwiftReflector/OverrideBuilder.cs index 136e268e..bd924de5 100644 --- a/SwiftReflector/OverrideBuilder.cs +++ b/SwiftReflector/OverrideBuilder.cs @@ -255,7 +255,10 @@ ClassDeclaration BuildAssociatedTypeOverride (string name, ModuleDeclaration tar dtor.ReturnTypeName = "()"; decl.Members.Add (dtor); - return decl.MakeUnrooted () as ClassDeclaration; + decl = decl.MakeUnrooted () as ClassDeclaration; + foreach (var member in decl.Members) + member.Parent = decl; + return decl; } void CopyConstructors () @@ -837,7 +840,11 @@ SLProperty DefineOverrideProperty (FunctionDeclaration getter, FunctionDeclarati var ifelse = new SLIfElse (condition, ifblock, elseblock); if (isProtocol) { - getBlock = ifblock; + if (getBlock.Count == 0) + getBlock = ifblock; + else { + getBlock.AddRange (ifblock); + } } else { getBlock.And (ifelse); } diff --git a/tests/tom-swifty-test/SwiftReflector/ProtocolConformanceTests.cs b/tests/tom-swifty-test/SwiftReflector/ProtocolConformanceTests.cs index 38356a12..87ad2ce7 100644 --- a/tests/tom-swifty-test/SwiftReflector/ProtocolConformanceTests.cs +++ b/tests/tom-swifty-test/SwiftReflector/ProtocolConformanceTests.cs @@ -209,6 +209,20 @@ public protocol Iterator0 { associatedtype Elem func next () -> Elem } +"; + var printer = CSFunctionCall.ConsoleWriteLine (CSConstant.Val ("OK")); + var callingCode = CSCodeBlock.Create (printer); + TestRunning.TestAndExecute (swiftCode, callingCode, "OK\n", platform: PlatformName.macOS); + } + + [Test] + public void SmokeProtocolAssocGetProp () + { + var swiftCode = @" +public protocol Iterator1 { + associatedtype Elem + var next:Elem { get } +} "; var printer = CSFunctionCall.ConsoleWriteLine (CSConstant.Val ("OK")); var callingCode = CSCodeBlock.Create (printer);