Skip to content
This repository was archived by the owner on Dec 12, 2024. It is now read-only.

Commit 3205777

Browse files
Merge pull request #314 from xamarin/pat-prop
Added Associated Type support in Get properties
2 parents 7b23044 + d951ec7 commit 3205777

File tree

4 files changed

+65
-23
lines changed

4 files changed

+65
-23
lines changed

SwiftReflector/MarshalEngineCSafeSwiftToCSharp.cs

+6-5
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ public List<ICodeElement> MarshalFromLambdaReceiverToCSFunc (CSType thisType, st
433433

434434

435435
public List<ICodeElement> MarshalFromLambdaReceiverToCSProp (CSProperty prop, CSType thisType, string csProxyName, CSParameterList delegateParams,
436-
FunctionDeclaration funcDecl, CSType methodType, bool isObjC)
436+
FunctionDeclaration funcDecl, CSType methodType, bool isObjC, bool hasAssociatedTypes)
437437
{
438438
bool forProtocol = csProxyName != null;
439439
bool needsReturn = funcDecl.IsGetter;
@@ -463,12 +463,13 @@ public List<ICodeElement> MarshalFromLambdaReceiverToCSProp (CSProperty prop, CS
463463

464464

465465
CSIdentifier csharpCall = null;
466-
if (forProtocol) {
467-
csharpCall = new CSIdentifier ($"SwiftObjectRegistry.Registry.InterfaceForExistentialContainer<{thisType.ToString()}> (self).{prop.Name.Name}");
466+
var thisTypeName = hasAssociatedTypes ? csProxyName : thisType.ToString ();
467+
if (forProtocol && !hasAssociatedTypes) {
468+
csharpCall = new CSIdentifier ($"SwiftObjectRegistry.Registry.InterfaceForExistentialContainer<{thisTypeName}> (self).{prop.Name.Name}");
468469
} else {
469470
var call = isObjC ?
470-
$"ObjCRuntime.Runtime.GetNSObject<{thisType.ToString ()}> (self).{prop.Name.Name}" :
471-
$"SwiftObjectRegistry.Registry.CSObjectForSwiftObject<{thisType.ToString ()}> (self).{prop.Name.Name}";
471+
$"ObjCRuntime.Runtime.GetNSObject<{thisTypeName}> (self).{prop.Name.Name}" :
472+
$"SwiftObjectRegistry.Registry.CSObjectForSwiftObject<{thisTypeName}> (self).{prop.Name.Name}";
472473

473474
csharpCall = new CSIdentifier (call);
474475
}

SwiftReflector/NewClassCompiler.cs

+36-16
Original file line numberDiff line numberDiff line change
@@ -2265,7 +2265,7 @@ CSProperty ImplementProtocolSubscriptEtter (WrappingResult wrapper,
22652265
List<CSLine> vtableAssignments, CSUsingPackages use, bool isSetter, CSProperty wrapperProp, string swiftLibraryPath)
22662266
{
22672267
CSDelegateTypeDecl etterDelegateDecl = DefineDelegateAndAddToVtable (vtable, etterFunc, use,
2268-
OverrideBuilder.VTableEntryIdentifier (vtableEntryIndex), true);
2268+
OverrideBuilder.VTableEntryIdentifier (vtableEntryIndex), !protocolDecl.HasAssociatedTypes);
22692269
vtable.Delegates.Add (etterDelegateDecl);
22702270

22712271
var etterWrapperFunc = FindProtocolWrapperFunction (etterFunc, wrapper);
@@ -2524,7 +2524,7 @@ int ImplementPropertyVtableForVirtualProperties (WrappingResult wrapper,
25242524
}
25252525
var wrapperProp = ImplementPropertyEtter (wrapper, classDecl, subclassDecl, classContents, cl, picl, usedPinvokeNames, virtFuncs,
25262526
getterFunc, tlSetter, vtableEntryIndex, vtableName, vtable, vtableAssignments, use,
2527-
false, null, swiftLibraryPath);
2527+
false, null, swiftLibraryPath, null);
25282528

25292529
if (hasSetter) {
25302530
wrapperProp = ImplementPropertyEtter (wrapper, classDecl, subclassDecl, classContents, cl, picl, usedPinvokeNames, virtFuncs,
@@ -2544,7 +2544,7 @@ CSProperty ImplementProtocolPropertyEtter (WrappingResult wrapper,
25442544
List<CSLine> vtableAssignments, CSUsingPackages use, bool isSetter, bool isObjC, CSProperty wrapperProp, string swiftLibraryPath)
25452545
{
25462546
var etterDelegateDecl = DefineDelegateAndAddToVtable (vtable, etterFunc, use,
2547-
OverrideBuilder.VTableEntryIdentifier (vtableEntryIndex), true);
2547+
OverrideBuilder.VTableEntryIdentifier (vtableEntryIndex), !protocolDecl.HasAssociatedTypes);
25482548
vtable.Delegates.Add (etterDelegateDecl);
25492549

25502550
var etterWrapperFunc = FindProtocolWrapperFunction (etterFunc, wrapper);
@@ -2561,7 +2561,7 @@ CSProperty ImplementProtocolPropertyEtter (WrappingResult wrapper,
25612561
piEtterName = Uniqueify (piEtterName, usedPinvokeNames);
25622562
usedPinvokeNames.Add (piEtterName);
25632563

2564-
string piEtterRef = PIClassName (TypeMapper.GetDotNetNameForSwiftClassName (protocolContents.Name)) + "." + piEtterName;
2564+
string piEtterRef = picl.Name + "." + piEtterName;
25652565
var piGetter = TLFCompiler.CompileMethod (etterWrapperFunc, use,
25662566
PInvokeName (wrapper.ModuleLibPath, swiftLibraryPath),
25672567
etterWrapper.MangledName, piEtterName, true, true, false);
@@ -2570,6 +2570,9 @@ CSProperty ImplementProtocolPropertyEtter (WrappingResult wrapper,
25702570

25712571
if (wrapperProp == null) {
25722572
wrapperProp = TLFCompiler.CompileProperty (use, propName, etterFunc, setter, CSMethodKind.None);
2573+
if (protocolDecl.HasAssociatedTypes) {
2574+
SubstituteAssociatedTypeNamer (protocolDecl, wrapperProp);
2575+
}
25732576

25742577
var ifaceProp = new CSProperty (wrapperProp.PropType, CSMethodKind.None,
25752578
new CSIdentifier (propName),
@@ -2580,6 +2583,8 @@ CSProperty ImplementProtocolPropertyEtter (WrappingResult wrapper,
25802583

25812584
var usedIds = new List<string> { propName };
25822585
var marshal = new MarshalEngine (use, usedIds, TypeMapper, wrapper.Module.SwiftCompilerVersion);
2586+
if (protocolDecl.HasAssociatedTypes)
2587+
marshal.GenericReferenceNamer = MakeAssociatedTypeNamer (protocolDecl);
25832588

25842589
var ifTest = kInterfaceImpl != CSConstant.Null;
25852590
var ifBlock = new CSCodeBlock ();
@@ -2600,12 +2605,16 @@ CSProperty ImplementProtocolPropertyEtter (WrappingResult wrapper,
26002605
etterFunc, etterFunc.ReturnTypeSpec, wrapperProp.PropType, etterFunc.ParameterLists [0] [0].TypeSpec, new CSSimpleType (iface.Name.Name), false, wrapper, etterFunc.HasThrows));
26012606
}
26022607

2603-
var ifElse = new CSIfElse (ifTest, ifBlock, elseBlock);
2604-
target.Add (ifElse);
2608+
if (protocolDecl.HasAssociatedTypes) {
2609+
target.AddRange (elseBlock);
2610+
} else {
2611+
var ifElse = new CSIfElse (ifTest, ifBlock, elseBlock);
2612+
target.Add (ifElse);
2613+
}
26052614

26062615
var recvr = ImplementVirtualPropertyStaticReceiver (new CSSimpleType (iface.Name.Name),
2607-
proxyClass.Name.Name, etterDelegateDecl, use,
2608-
etterFunc, wrapperProp, null, vtable.Name, isObjC);
2616+
proxyClass.ToCSType ().ToString (), etterDelegateDecl, use,
2617+
etterFunc, wrapperProp, null, vtable.Name, isObjC, protocolDecl.HasAssociatedTypes);
26092618
proxyClass.Methods.Add (recvr);
26102619

26112620
vtableAssignments.Add (CSAssignment.Assign (String.Format ("{0}.{1}",
@@ -2617,7 +2626,8 @@ CSProperty ImplementPropertyEtter (WrappingResult wrapper,
26172626
ClassDeclaration classDecl, ClassDeclaration subclassDecl,
26182627
ClassContents classContents, CSClass cl, CSClass picl, List<string> usedPinvokeNames, List<FunctionDeclaration> virtFuncs,
26192628
FunctionDeclaration etterFunc, TLFunction tlSetter, int vtableEntryIndex, string vtableName, CSStruct vtable,
2620-
List<CSLine> vtableAssignments, CSUsingPackages use, bool isSetter, CSProperty wrapperProp, string swiftLibraryPath)
2629+
List<CSLine> vtableAssignments, CSUsingPackages use, bool isSetter, CSProperty wrapperProp, string swiftLibraryPath,
2630+
Func<int, int, string> genericRenamer = null)
26212631
{
26222632
var swiftClassName = XmlToTLFunctionMapper.ToSwiftClassName (subclassDecl);
26232633
var tlEtter = XmlToTLFunctionMapper.ToTLFunction (etterFunc, classContents);
@@ -2644,7 +2654,8 @@ CSProperty ImplementPropertyEtter (WrappingResult wrapper,
26442654

26452655
var piGetter = TLFCompiler.CompileMethod (etterWrapperFunc, use,
26462656
PInvokeName (wrapper.ModuleLibPath, swiftLibraryPath),
2647-
etterWrapper.MangledName, piEtterName, true, true, false); picl.Methods.Add (piGetter);
2657+
etterWrapper.MangledName, piEtterName, true, true, false);
2658+
picl.Methods.Add (piGetter);
26482659

26492660
var superEtterFunc = subclassDecl.AllMethodsNoCDTor ().Where (fn =>
26502661
fn.Access == Accessibility.Internal && fn.IsProperty &&
@@ -2685,7 +2696,8 @@ CSProperty ImplementPropertyEtter (WrappingResult wrapper,
26852696
}
26862697
}
26872698

2688-
ImplementOverloadFromKnownWrapper (cl, picl, usedPinvokeNames, swiftClassName, superEtterTlf, superEtterFunc, use, true, wrapper, swiftLibraryPath, superEtterFuncWrapper, "", true);
2699+
ImplementOverloadFromKnownWrapper (cl, picl, usedPinvokeNames, swiftClassName, superEtterTlf, superEtterFunc, use, true, wrapper, swiftLibraryPath, superEtterFuncWrapper, "", true,
2700+
genericRenamer: genericRenamer);
26892701
var propertyImplMethod = cl.Methods.Last ();
26902702
CSMethod protoListMethod = null;
26912703
if (returnIsProtocolList) {
@@ -2711,7 +2723,7 @@ CSProperty ImplementPropertyEtter (WrappingResult wrapper,
27112723
}
27122724

27132725
var recvr = ImplementVirtualPropertyStaticReceiver (cl.ToCSType (), null, etterDelegateDecl, use, etterFunc,
2714-
wrapperProp, protoListMethod, vtable.Name, classDecl.IsObjC);
2726+
wrapperProp, protoListMethod, vtable.Name, classDecl.IsObjC, false);
27152727
cl.Methods.Add (recvr);
27162728

27172729
vtableAssignments.Add (CSAssignment.Assign (String.Format ("{0}.{1}",
@@ -2841,7 +2853,7 @@ CSMethod ImplementVirtualSubscriptStaticReceiver (CSType thisType, string csProx
28412853

28422854
CSMethod ImplementVirtualPropertyStaticReceiver (CSType thisType, string csProxyName, CSDelegateTypeDecl delType,
28432855
CSUsingPackages use, FunctionDeclaration funcDecl, CSProperty prop, CSMethod protoListMethod,
2844-
CSIdentifier vtableName, bool isObjC)
2856+
CSIdentifier vtableName, bool isObjC, bool hasAssociatedTypes)
28452857
{
28462858
var returnType = funcDecl.IsGetter ? delType.Type : CSSimpleType.Void;
28472859
CSParameterList pl = delType.Parameters;
@@ -2860,7 +2872,7 @@ CSMethod ImplementVirtualPropertyStaticReceiver (CSType thisType, string csProxy
28602872

28612873
var bodyContents = marshaler.MarshalFromLambdaReceiverToCSProp (prop, thisType, csProxyName,
28622874
delType.Parameters,
2863-
funcDecl, prop.PropType, isObjC);
2875+
funcDecl, prop.PropType, isObjC, hasAssociatedTypes);
28642876
body.AddRange (bodyContents);
28652877
recvrName = "xamVtable_recv_" + (funcDecl.IsGetter ? "get_" : "set_") + prop.Name.Name;
28662878
}
@@ -2895,7 +2907,7 @@ CSLambda ImplementVirtualPropertyReceiver (CSType thisType, string csProxyName,
28952907
var marshaler = new MarshalEngineCSafeSwiftToCSharp (use, usedIDs, TypeMapper);
28962908

28972909
var bodyContents = marshaler.MarshalFromLambdaReceiverToCSProp (prop, thisType, csProxyName, delType.Parameters,
2898-
funcDecl, prop.PropType, isObjC);
2910+
funcDecl, prop.PropType, isObjC, false);
28992911
var body = new CSCodeBlock (bodyContents);
29002912
return new CSLambda (pl, body);
29012913
}
@@ -5122,7 +5134,8 @@ CSIfElse InterfaceMethodRedirect (CSMethod publicMethod, IEnumerable<ICodeElemen
51225134
CSMethod ImplementOverloadFromKnownWrapper (CSClass cl, CSClass picl, List<string> usedPinvokeNames, SwiftClassName classForPI,
51235135
TLFunction methodToWrap, FunctionDeclaration funcToWrap, CSUsingPackages use, bool isFinal,
51245136
WrappingResult wrapper, string swiftLibraryPath, TLFunction wrapperFunction,
5125-
string homonymSuffix, bool forcePrivate = false, string alternativeName = null)
5137+
string homonymSuffix, bool forcePrivate = false, string alternativeName = null,
5138+
Func<int, int, string> genericRenamer = null)
51265139
{
51275140
var wrapperFuncDecl = FindEquivalentFunctionDeclarationForWrapperFunction (wrapperFunction, TypeMapper, wrapper);
51285141
var pinvokeMethodName = PIMethodName (classForPI, wrapperFunction.Name) + homonymSuffix;
@@ -5190,6 +5203,7 @@ CSMethod ImplementOverloadFromKnownWrapper (CSClass cl, CSClass picl, List<strin
51905203
};
51915204

51925205
var marshaler = new MarshalEngine (use, localIdentifiers, TypeMapper, wrapper.Module.SwiftCompilerVersion);
5206+
marshaler.GenericReferenceNamer = genericRenamer;
51935207

51945208
publicMethod.Body.AddRange (marshaler.MarshalFunctionCall (wrapperFuncDecl, false, pinvokeMethodRef,
51955209
publicMethod.Parameters, funcToWrap, funcToWrap.ReturnTypeSpec, publicMethod.Type, instanceTypeSpec, cl.ToCSType (),
@@ -6330,6 +6344,12 @@ void SubstituteAssociatedTypeNamer (ProtocolDeclaration protocolDecl, CSMethod p
63306344
SubstituteAssociatedTypeNamer (namer, parm.CSType);
63316345
}
63326346

6347+
void SubstituteAssociatedTypeNamer (ProtocolDeclaration protocolDecl, CSProperty publicProperty)
6348+
{
6349+
var namer = MakeAssociatedTypeNamer (protocolDecl);
6350+
SubstituteAssociatedTypeNamer (namer, publicProperty.PropType);
6351+
}
6352+
63336353
void SubstituteAssociatedTypeNamer (Func<int, int, string> namer, CSType ty)
63346354
{
63356355
if (ty is CSGenericReferenceType genType) {

SwiftReflector/OverrideBuilder.cs

+9-2
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,10 @@ ClassDeclaration BuildAssociatedTypeOverride (string name, ModuleDeclaration tar
255255
dtor.ReturnTypeName = "()";
256256
decl.Members.Add (dtor);
257257

258-
return decl.MakeUnrooted () as ClassDeclaration;
258+
decl = decl.MakeUnrooted () as ClassDeclaration;
259+
foreach (var member in decl.Members)
260+
member.Parent = decl;
261+
return decl;
259262
}
260263

261264
void CopyConstructors ()
@@ -837,7 +840,11 @@ SLProperty DefineOverrideProperty (FunctionDeclaration getter, FunctionDeclarati
837840
var ifelse = new SLIfElse (condition, ifblock, elseblock);
838841

839842
if (isProtocol) {
840-
getBlock = ifblock;
843+
if (getBlock.Count == 0)
844+
getBlock = ifblock;
845+
else {
846+
getBlock.AddRange (ifblock);
847+
}
841848
} else {
842849
getBlock.And (ifelse);
843850
}

tests/tom-swifty-test/SwiftReflector/ProtocolConformanceTests.cs

+14
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,20 @@ public protocol Iterator0 {
209209
associatedtype Elem
210210
func next () -> Elem
211211
}
212+
";
213+
var printer = CSFunctionCall.ConsoleWriteLine (CSConstant.Val ("OK"));
214+
var callingCode = CSCodeBlock.Create (printer);
215+
TestRunning.TestAndExecute (swiftCode, callingCode, "OK\n", platform: PlatformName.macOS);
216+
}
217+
218+
[Test]
219+
public void SmokeProtocolAssocGetProp ()
220+
{
221+
var swiftCode = @"
222+
public protocol Iterator1 {
223+
associatedtype Elem
224+
var next:Elem { get }
225+
}
212226
";
213227
var printer = CSFunctionCall.ConsoleWriteLine (CSConstant.Val ("OK"));
214228
var callingCode = CSCodeBlock.Create (printer);

0 commit comments

Comments
 (0)