Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions sources/ClangSharp.Interop/Extensions/CXCursor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,8 @@ public readonly CXCursor DefaultArg

public readonly int NumTemplateParameterLists => clangsharp.Cursor_getNumTemplateParameterLists(this);

public readonly int NumTypeParams => clangsharp.Cursor_getNumTypeParams(this);

public readonly int NumVBases => clangsharp.Cursor_getNumVBases(this);

public readonly CXObjCDeclQualifierKind ObjCDeclQualifiers => (CXObjCDeclQualifierKind)clang.Cursor_getObjCDeclQualifiers(this);
Expand Down Expand Up @@ -1911,6 +1913,8 @@ public readonly int GetPlatformAvailability(out bool alwaysDeprecated, out CXStr

public readonly long GetTemplateArgumentValue(uint i) => clang.Cursor_getTemplateArgumentValue(this, i);

public readonly CXCursor GetTypeParam(uint index) => clangsharp.Cursor_getTypeParam(this, index);

public readonly CXCursor GetVBase(uint index) => clangsharp.Cursor_getVBase(this, index);

public override readonly string ToString() => Spelling.ToString();
Expand Down
6 changes: 6 additions & 0 deletions sources/ClangSharp.Interop/clangsharp/clangsharp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,9 @@ public static partial class @clangsharp
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getNumTemplateParameterLists", ExactSpelling = true)]
public static extern int Cursor_getNumTemplateParameterLists(CXCursor C);

[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getNumTypeParams", ExactSpelling = true)]
public static extern int Cursor_getNumTypeParams(CXCursor C);

[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getNumVBases", ExactSpelling = true)]
public static extern int Cursor_getNumVBases(CXCursor C);

Expand Down Expand Up @@ -869,6 +872,9 @@ public static partial class @clangsharp
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getTypeOperand", ExactSpelling = true)]
public static extern CXType Cursor_getTypeOperand(CXCursor C);

[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getTypeParam", ExactSpelling = true)]
public static extern CXCursor Cursor_getTypeParam(CXCursor C, [NativeTypeName("unsigned int")] uint i);

[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getUnaryExprOrTypeTraitKind", ExactSpelling = true)]
public static extern CX_UnaryExprOrTypeTrait Cursor_getUnaryExprOrTypeTraitKind(CXCursor C);

Expand Down
2 changes: 1 addition & 1 deletion sources/ClangSharp/Cursors/Decls/ObjCCategoryDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal ObjCCategoryDecl(CXCursor handle) : base(handle, CXCursor_ObjCCategoryD
_nextClassCategory = new ValueLazy<ObjCCategoryDecl>(() => TranslationUnit.GetOrCreate<ObjCCategoryDecl>(Handle.GetSubDecl(2)));
_nextClassCategoryRaw = new ValueLazy<ObjCCategoryDecl>(() => TranslationUnit.GetOrCreate<ObjCCategoryDecl>(Handle.GetSubDecl(3)));
_protocols = LazyList.Create<ObjCProtocolDecl>(Handle.NumProtocols, (i) => TranslationUnit.GetOrCreate<ObjCProtocolDecl>(Handle.GetProtocol(unchecked((uint)i))));
_typeParamList = LazyList.Create<ObjCTypeParamDecl>(Handle.NumArguments, (i) => TranslationUnit.GetOrCreate<ObjCTypeParamDecl>(Handle.GetArgument(unchecked((uint)i))));
_typeParamList = LazyList.Create<ObjCTypeParamDecl>(Handle.NumTypeParams, (i) => TranslationUnit.GetOrCreate<ObjCTypeParamDecl>(Handle.GetTypeParam(unchecked((uint)i))));
}

public ObjCInterfaceDecl ClassInterface => _classInterface.Value;
Expand Down
2 changes: 1 addition & 1 deletion sources/ClangSharp/Cursors/Decls/ObjCInterfaceDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ internal ObjCInterfaceDecl(CXCursor handle) : base(handle, CXCursor_ObjCInterfac
_superClass = new ValueLazy<ObjCInterfaceDecl>(() => TranslationUnit.GetOrCreate<ObjCInterfaceDecl>(Handle.GetSubDecl(2)));
_superClassType = new ValueLazy<ObjCObjectType>(() => TranslationUnit.GetOrCreate<ObjCObjectType>(Handle.TypeOperand));
_typeForDecl = new ValueLazy<Type>(() => TranslationUnit.GetOrCreate<Type>(Handle.ThisType));
_typeParamList = LazyList.Create<ObjCTypeParamDecl>(Handle.NumArguments, (i) => TranslationUnit.GetOrCreate<ObjCTypeParamDecl>(Handle.GetArgument(unchecked((uint)i))));
_typeParamList = LazyList.Create<ObjCTypeParamDecl>(Handle.NumTypeParams, (i) => TranslationUnit.GetOrCreate<ObjCTypeParamDecl>(Handle.GetTypeParam(unchecked((uint)i))));
_visibleCategories = new ValueLazy<List<ObjCCategoryDecl>>(() => [.. CategoryList.Where((category) => category.IsUnconditionallyVisible)]);
_visibleExtensions = new ValueLazy<List<ObjCCategoryDecl>>(() => [.. CategoryList.Where((category) => category.IsClassExtension && category.IsUnconditionallyVisible)]);
}
Expand Down
2 changes: 1 addition & 1 deletion sources/ClangSharp/Cursors/Decls/ObjCTypeParamDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace ClangSharp;

public sealed class ObjCTypeParamDecl : TypedefNameDecl
{
internal ObjCTypeParamDecl(CXCursor handle) : base(handle, CXCursor_UnexposedDecl, CX_DeclKind_ObjCTypeParam)
internal ObjCTypeParamDecl(CXCursor handle) : base(handle, CXCursor_TemplateTypeParameter, CX_DeclKind_ObjCTypeParam)
{
}

Expand Down
59 changes: 59 additions & 0 deletions sources/libClangSharp/ClangSharp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3626,6 +3626,29 @@ int clangsharp_Cursor_getNumTemplateParameterLists(CXCursor C) {
return -1;
}

int clangsharp_Cursor_getNumTypeParams(CXCursor C)
{
if (isDeclOrTU(C.kind)) {
const Decl* D = getCursorDecl(C);

if (const ObjCCategoryDecl* OCCD = dyn_cast<ObjCCategoryDecl>(D)) {
ObjCTypeParamList* typeParamList = OCCD->getTypeParamList();
if (typeParamList)
return typeParamList->size();
return 0;
}

if (const ObjCInterfaceDecl* OCID = dyn_cast<ObjCInterfaceDecl>(D)) {
ObjCTypeParamList* typeParamList = OCID->getTypeParamList();
if (typeParamList)
return typeParamList->size();
return 0;
}
}

return 0;
}

int clangsharp_Cursor_getNumVBases(CXCursor C) {
if (isDeclOrTU(C.kind)) {
const Decl* D = getCursorDecl(C);
Expand Down Expand Up @@ -4743,6 +4766,42 @@ CXType clangsharp_Cursor_getTypeOperand(CXCursor C) {
return MakeCXType(QualType(), getCursorTU(C));
}

CXCursor clangsharp_Cursor_getTypeParam(CXCursor C, unsigned i) {
if (isDeclOrTU(C.kind)) {
const Decl* D = getCursorDecl(C);

if (const ObjCCategoryDecl* OCCD = dyn_cast<ObjCCategoryDecl>(D)) {
ObjCTypeParamList* typeParamList = OCCD->getTypeParamList();

unsigned int n = 0;
if (i < typeParamList->size()) {
for (auto d : *typeParamList) {
if (n == i) {
return MakeCXCursor(d, getCursorTU(C));
}
n++;
}
}
}

if (const ObjCInterfaceDecl* OCID = dyn_cast<ObjCInterfaceDecl>(D)) {
ObjCTypeParamList* typeParamList = OCID->getTypeParamList();

unsigned int n = 0;
if (i < typeParamList->size()) {
for (auto d : *typeParamList) {
if (n == i) {
return MakeCXCursor(d, getCursorTU(C));
}
n++;
}
}
}
}

return clang_getNullCursor();
}

CX_UnaryExprOrTypeTrait clangsharp_Cursor_getUnaryExprOrTypeTraitKind(CXCursor C) {
if (isStmtOrExpr(C.kind)) {
const Stmt* S = getCursorStmt(C);
Expand Down
4 changes: 4 additions & 0 deletions sources/libClangSharp/ClangSharp.h
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,8 @@ CLANGSHARP_LINKAGE int clangsharp_Cursor_getNumTemplateParameters(CXCursor C, un

CLANGSHARP_LINKAGE int clangsharp_Cursor_getNumTemplateParameterLists(CXCursor C);

CLANGSHARP_LINKAGE int clangsharp_Cursor_getNumTypeParams(CXCursor C);

CLANGSHARP_LINKAGE int clangsharp_Cursor_getNumVBases(CXCursor C);

CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getOpaqueValue(CXCursor C);
Expand Down Expand Up @@ -737,6 +739,8 @@ CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getTypedefNameForAnonDecl(CXCursor

CLANGSHARP_LINKAGE CXType clangsharp_Cursor_getTypeOperand(CXCursor C);

CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getTypeParam(CXCursor C, unsigned i);

CLANGSHARP_LINKAGE CX_UnaryExprOrTypeTrait clangsharp_Cursor_getUnaryExprOrTypeTraitKind(CXCursor C);

CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getUnderlyingDecl(CXCursor C);
Expand Down
48 changes: 48 additions & 0 deletions tests/ClangSharp.UnitTests/ObjectiveCTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public sealed class ObjectiveCTest : TranslationUnitTest
[Test]
public void Method_Selector()
{
AssertNeedNewClangSharp();

var inputContents = $@"
@interface MyClass
@property int P1;
Expand Down Expand Up @@ -48,6 +50,8 @@ @interface MyClass
[Test]
public void Category_TypeParamList()
{
AssertNeedNewClangSharp();

var inputContents = $@"
@interface MyClass
@end
Expand All @@ -67,6 +71,8 @@ @interface MyClass (MyCategory)
[Test]
public void Method_IsPropertyAccessor()
{
AssertNeedNewClangSharp();

var inputContents = $@"
@interface MyClass
@property int P1;
Expand Down Expand Up @@ -99,9 +105,49 @@ @interface MyClass
Assert.That(methodStaticMethod.IsPropertyAccessor, Is.False, "methodStaticMethod.IsPropertyAccessor");
}

[Test]
public void TypeParams()
{
AssertNeedNewClangSharp();

var inputContents = $$"""
@interface NSObject
@end

@interface MyClass<A, B> : NSObject
@end

@interface MyClass<T, Y> (MyCategory)
@end

""";
using var translationUnit = CreateTranslationUnit(inputContents, "objective-c++");

var classes = translationUnit.TranslationUnitDecl.Decls.OfType<ObjCInterfaceDecl>().ToList();

var myClass = classes.SingleOrDefault(v => v.Name == "MyClass")!;
Assert.That(myClass, Is.Not.Null, "MyClass");
Assert.That(myClass.TypeParamList, Is.Not.Null, "myClass TypeParamList");
var myClassTypeParams = myClass.TypeParamList.ToList();
Assert.That(myClassTypeParams.Count, Is.EqualTo(2), "myClassTypeParams.Count");
Assert.That(myClassTypeParams[0].Name, Is.EqualTo("A"), "myClassTypeParams[0].Name");
Assert.That(myClassTypeParams[1].Name, Is.EqualTo("B"), "myClassTypeParams[1].Name");

var categories = translationUnit.TranslationUnitDecl.Decls.OfType<ObjCCategoryDecl>().ToList();
var myCategory = categories.SingleOrDefault(v => v.Name == "MyCategory")!;
Assert.That(myCategory, Is.Not.Null, "MyCategory");
Assert.That(myCategory.TypeParamList, Is.Not.Null, "myCategory TypeParamList");
var myCategoryTypeParams = myCategory.TypeParamList.ToList();
Assert.That(myCategoryTypeParams.Count, Is.EqualTo(2), "myCategoryTypeParams.Count");
Assert.That(myCategoryTypeParams[0].Name, Is.EqualTo("T"), "myCategoryTypeParams[0].Name");
Assert.That(myCategoryTypeParams[1].Name, Is.EqualTo("Y"), "myCategoryTypeParams[1].Name");
}

[Test]
public void PointerTypes()
{
AssertNeedNewClangSharp();

var inputContents = """
@interface MyClass
-(void)instanceMethod:(MyClass **)ptrToPtrToMyClass;
Expand Down Expand Up @@ -131,6 +177,8 @@ @interface MyClass
[Test]
public void BlockTypes()
{
AssertNeedNewClangSharp();

var inputContents = $$"""
@interface MyClass
-(MyClass *(^)(id))instanceMethod1;
Expand Down