Skip to content

Commit 2ecbb6a

Browse files
committed
Update ObjectiveC support
1 parent 3081277 commit 2ecbb6a

File tree

8 files changed

+369
-140
lines changed

8 files changed

+369
-140
lines changed

src/CppAst.Tests/TestObjectiveC.cs

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ public void TestInterfaceWithInstanceType()
129129
ParseAssert("""
130130
@interface MyInterface
131131
+ (instancetype)getInstance;
132+
- (instancetype)get;
132133
@end
133134
""",
134135
compilation =>
@@ -138,12 +139,19 @@ @interface MyInterface
138139
var myInterface = compilation.Classes[0];
139140
Assert.AreEqual(CppClassKind.ObjCInterface, myInterface.ClassKind);
140141
Assert.AreEqual("MyInterface", myInterface.Name);
141-
Assert.AreEqual(1, myInterface.Functions.Count);
142+
Assert.AreEqual(2, myInterface.Functions.Count);
143+
142144
Assert.AreEqual("getInstance", myInterface.Functions[0].Name);
143145
Assert.IsTrue((myInterface.Functions[0].Flags & CppFunctionFlags.ClassMethod) != 0);
144-
var pointerType = myInterface.Functions[0].ReturnType as CppPointerType;
145-
Assert.IsNotNull(pointerType);
146-
Assert.AreEqual(myInterface, pointerType!.ElementType);
146+
var typedef = myInterface.Functions[0].ReturnType as CppTypedef;
147+
Assert.IsTrue(typedef is not null && typedef.ElementType is CppPrimitiveType prim && prim.Kind == CppPrimitiveKind.ObjCObject, $"Invalid return type found for getInstance {myInterface.Functions[0].ReturnType}");
148+
149+
Assert.AreEqual("get", myInterface.Functions[1].Name);
150+
Assert.IsTrue((myInterface.Functions[1].Flags & CppFunctionFlags.Method) != 0);
151+
Assert.IsTrue((myInterface.Functions[1].Flags & CppFunctionFlags.ClassMethod) == 0);
152+
var typedef2 = myInterface.Functions[1].ReturnType as CppTypedef;
153+
Assert.IsTrue(typedef2 is not null && typedef2.ElementType is CppPrimitiveType prim2 && prim2.Kind == CppPrimitiveKind.ObjCObject, $"Invalid return type found for getInstance {myInterface.Functions[1].ReturnType}");
154+
147155
}, GetDefaultObjCOptions()
148156
);
149157
}
@@ -357,7 +365,92 @@ @interface MyInterface (MyCategory)
357365
}, GetDefaultObjCOptions()
358366
);
359367
}
360-
368+
369+
[Test]
370+
public void TestInterfaceWithMethodsReturningObjects()
371+
{
372+
ParseAssert("""
373+
@interface MyInterface1
374+
+ (MyInterface1*)getInstance1;
375+
@end
376+
377+
@interface MyInterface2<T1> : MyInterface1
378+
@end
379+
380+
@interface MyInterface2NoGeneric
381+
@end
382+
383+
@protocol MyProtocol
384+
@end
385+
386+
@interface MyInterface3
387+
+ (MyInterface2<MyInterface1*>*)getInstance2;
388+
+ (MyInterface2NoGeneric<MyProtocol>*)getInstanceWithProtocol3;
389+
+ (id<MyProtocol>)getInstanceWithProtocol4;
390+
@end
391+
""",
392+
compilation =>
393+
{
394+
Assert.False(compilation.HasErrors);
395+
396+
Assert.AreEqual(5, compilation.Classes.Count);
397+
398+
var myInterface1 = compilation.Classes[0];
399+
Assert.AreEqual(CppClassKind.ObjCInterface, myInterface1.ClassKind);
400+
Assert.AreEqual("MyInterface1", myInterface1.Name);
401+
402+
var myInterface2 = compilation.Classes[1];
403+
Assert.AreEqual(CppClassKind.ObjCInterface, myInterface2.ClassKind);
404+
Assert.AreEqual("MyInterface2", myInterface2.Name);
405+
406+
var myInterface2NoGeneric = compilation.Classes[2];
407+
Assert.AreEqual(CppClassKind.ObjCInterface, myInterface2NoGeneric.ClassKind);
408+
Assert.AreEqual("MyInterface2NoGeneric", myInterface2NoGeneric.Name);
409+
410+
var myProtocol = compilation.Classes[3];
411+
Assert.AreEqual(CppClassKind.ObjCProtocol, myProtocol.ClassKind);
412+
Assert.AreEqual("MyProtocol", myProtocol.Name);
413+
414+
var myInterface3 = compilation.Classes[4];
415+
416+
Assert.AreEqual(CppClassKind.ObjCInterface, myInterface3.ClassKind);
417+
Assert.AreEqual("MyInterface3", myInterface3.Name);
418+
Assert.AreEqual(3, myInterface3.Functions.Count);
419+
Assert.AreEqual("getInstance2", myInterface3.Functions[0].Name);
420+
Assert.AreEqual("getInstanceWithProtocol3", myInterface3.Functions[1].Name);
421+
Assert.AreEqual("getInstanceWithProtocol4", myInterface3.Functions[2].Name);
422+
423+
Assert.IsTrue(myInterface3.Functions[0].ReturnType is CppPointerType pointerType &&
424+
pointerType.ElementType is CppObjCGenericType genericType &&
425+
ReferenceEquals(genericType.BaseType, myInterface2) &&
426+
genericType.GenericArguments.Count == 1 &&
427+
genericType.GenericArguments[0] is CppPointerType pointerType2 &&
428+
ReferenceEquals(pointerType2.ElementType, myInterface1),
429+
"Unable to resolve return type getInstance2. Must be MyInterface2<MyInterface1*>*"
430+
);
431+
432+
Assert.IsTrue(myInterface3.Functions[1].ReturnType is CppPointerType pointerType3 &&
433+
pointerType3.ElementType is CppObjCGenericType genericType2 &&
434+
ReferenceEquals(genericType2.BaseType, myInterface2NoGeneric) &&
435+
genericType2.ObjCProtocolRefs.Count == 1 &&
436+
ReferenceEquals(genericType2.ObjCProtocolRefs[0], myProtocol),
437+
"Unable to resolve return type getInstanceWithProtocol3. Must be MyInterface2NoGeneric<MyProtocol>*"
438+
);
439+
440+
Assert.IsTrue(myInterface3.Functions[2].ReturnType is CppPointerType pointerType4 &&
441+
pointerType4.ElementType is CppObjCGenericType genericType3 &&
442+
genericType3.BaseType is CppPrimitiveType primitiveType3 &&
443+
primitiveType3.Kind == CppPrimitiveKind.ObjCObject &&
444+
genericType3.ObjCProtocolRefs.Count == 1 &&
445+
ReferenceEquals(genericType3.ObjCProtocolRefs[0], myProtocol),
446+
"Unable to resolve return type getInstanceWithProtocol4. Must be id<MyProtocol>"
447+
);
448+
449+
}, GetDefaultObjCOptions()
450+
);
451+
}
452+
453+
361454
private static CppParserOptions GetDefaultObjCOptions()
362455
{
363456
return new CppParserOptions

0 commit comments

Comments
 (0)