From d7cf72165e9ebfe6465bc911bff09d0cac5ab045 Mon Sep 17 00:00:00 2001 From: Stephen Hawley Date: Fri, 14 Feb 2020 09:12:04 -0500 Subject: [PATCH 1/3] First step for prop support. --- SwiftReflector/NewClassCompiler.cs | 9 +++++++++ SwiftReflector/OverrideBuilder.cs | 11 +++++++++-- .../SwiftReflector/ProtocolConformanceTests.cs | 14 ++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/SwiftReflector/NewClassCompiler.cs b/SwiftReflector/NewClassCompiler.cs index 5c65800e..5d22fc4b 100644 --- a/SwiftReflector/NewClassCompiler.cs +++ b/SwiftReflector/NewClassCompiler.cs @@ -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), @@ -6330,6 +6333,12 @@ void SubstituteAssociatedTypeNamer (ProtocolDeclaration protocolDecl, CSMethod p SubstituteAssociatedTypeNamer (namer, parm.CSType); } + void SubstituteAssociatedTypeNamer (ProtocolDeclaration protocolDecl, CSProperty publicProperty) + { + var namer = MakeAssociatedTypeNamer (protocolDecl); + SubstituteAssociatedTypeNamer (namer, publicProperty.PropType); + } + void SubstituteAssociatedTypeNamer (Func 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); From 0caa9fe2229162506cd62c055059e77f8e06e25c Mon Sep 17 00:00:00 2001 From: Stephen Hawley Date: Fri, 14 Feb 2020 10:34:25 -0500 Subject: [PATCH 2/3] Now smoke testing properties --- SwiftReflector/MarshalEngineCSafeSwiftToCSharp.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) 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); } From d951ec75e5e7feff5f49ffb8a9862cd07f00f19e Mon Sep 17 00:00:00 2001 From: Stephen Hawley Date: Fri, 14 Feb 2020 11:02:55 -0500 Subject: [PATCH 3/3] Missed a change. --- SwiftReflector/NewClassCompiler.cs | 43 +++++++++++++++++++----------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/SwiftReflector/NewClassCompiler.cs b/SwiftReflector/NewClassCompiler.cs index 5d22fc4b..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); @@ -2583,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 (); @@ -2603,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}", @@ -2620,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); @@ -2647,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 && @@ -2688,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) { @@ -2714,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}", @@ -2844,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; @@ -2863,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; } @@ -2898,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); } @@ -5125,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; @@ -5193,6 +5203,7 @@ CSMethod ImplementOverloadFromKnownWrapper (CSClass cl, CSClass picl, List