Skip to content

Commit

Permalink
Fix nested type names for properties
Browse files Browse the repository at this point in the history
  • Loading branch information
dpaoliello committed Dec 11, 2024
1 parent 7e211d6 commit be0b852
Show file tree
Hide file tree
Showing 18 changed files with 1,685 additions and 11 deletions.
23 changes: 12 additions & 11 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -969,12 +969,7 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl)

var isFixedSizedBuffer = IsTypeConstantOrIncompleteArray(indirectFieldDecl, type);
var generateCompatibleCode = _config.GenerateCompatibleCode;
var typeString = string.Empty;

if (!fieldDecl.IsBitField && (!isFixedSizedBuffer || generateCompatibleCode))
{
typeString = "ref ";
}
var typeStringBuilder = new StringBuilder();

if (IsType<RecordType>(indirectFieldDecl, type, out var recordType))
{
Expand All @@ -985,34 +980,40 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl)
var parentRecordDeclName = GetRemappedCursorName(parentRecordDecl);
var escapedParentRecordDeclName = EscapeName(parentRecordDeclName);

typeString += escapedParentRecordDeclName + '.';
_ = typeStringBuilder.Insert(0, '.').Insert(0, escapedParentRecordDeclName);

recordDecl = parentRecordDecl;
}
}

if (!fieldDecl.IsBitField && (!isFixedSizedBuffer || generateCompatibleCode))
{
_ = typeStringBuilder.Insert(0, "ref ");
}

var isSupportedFixedSizedBufferType = isFixedSizedBuffer && IsSupportedFixedSizedBufferType(typeName);

if (isFixedSizedBuffer)
{
if (!generateCompatibleCode)
{
_outputBuilder.EmitSystemSupport();
typeString += "Span<";
_ = typeStringBuilder.Append("Span<");
}
else if (!isSupportedFixedSizedBufferType)
{
typeString += contextType + '.';
_ = typeStringBuilder.Append(contextType).Append('.');
typeName = GetArtificialFixedSizedBufferName(fieldDecl);
}
}

typeString += typeName;
_ = typeStringBuilder.Append(typeName);
if (isFixedSizedBuffer && !generateCompatibleCode)
{
typeString += '>';
_ = typeStringBuilder.Append('>');
}

var typeString = typeStringBuilder.ToString();
_outputBuilder.WriteRegularField(typeString, escapedName);

var isIndirectPointerField = IsTypePointerOrReference(indirectFieldDecl, type) && !typeName.Equals("IntPtr", StringComparison.Ordinal) && !typeName.Equals("UIntPtr", StringComparison.Ordinal);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ public abstract class UnionDeclarationTest : PInvokeGeneratorTest
[TestCase("bool", "byte")]
public Task TypedefTest(string nativeType, string expectedManagedType) => TypedefTestImpl(nativeType, expectedManagedType);

[Test]
public Task UnionWithAnonStructWithAnonUnion() => UnionWithAnonStructWithAnonUnionImpl();

protected abstract Task BasicTestImpl(string nativeType, string expectedManagedType);

protected abstract Task BasicTestInCModeImpl(string nativeType, string expectedManagedType);
Expand Down Expand Up @@ -237,4 +240,6 @@ public abstract class UnionDeclarationTest : PInvokeGeneratorTest
protected abstract Task SkipNonDefinitionWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType);

protected abstract Task TypedefTestImpl(string nativeType, string expectedManagedType);

protected abstract Task UnionWithAnonStructWithAnonUnionImpl();
}
Original file line number Diff line number Diff line change
Expand Up @@ -1449,6 +1449,134 @@ public partial struct MyUnion
public {expectedManagedType} b;
}}
}}
";

return ValidateGeneratedCSharpCompatibleUnixBindingsAsync(inputContents, expectedOutputContents);
}

protected override Task UnionWithAnonStructWithAnonUnionImpl()
{
var inputContents = $@"typedef union _MY_UNION
{{
long AsArray[2];
struct
{{
long First;
union
{{
struct
{{
long Second;
}} A;
struct
{{
long Second;
}} B;
}};
}};
}} MY_UNION;";

var expectedOutputContents = $@"using System;
using System.Runtime.InteropServices;
namespace ClangSharp.Test
{{
[StructLayout(LayoutKind.Explicit)]
public unsafe partial struct _MY_UNION
{{
[FieldOffset(0)]
[NativeTypeName(""long[2]"")]
public _AsArray_e__FixedBuffer AsArray;
[FieldOffset(0)]
[NativeTypeName(""__AnonymousRecord_ClangUnsavedFile_L4_C5"")]
public _Anonymous_e__Struct Anonymous;
public ref IntPtr First
{{
get
{{
fixed (_Anonymous_e__Struct* pField = &Anonymous)
{{
return ref pField->First;
}}
}}
}}
public ref _Anonymous_e__Struct._Anonymous_e__Union._A_e__Struct A
{{
get
{{
fixed (_Anonymous_e__Struct._Anonymous_e__Union* pField = &Anonymous.Anonymous)
{{
return ref pField->A;
}}
}}
}}
public ref _Anonymous_e__Struct._Anonymous_e__Union._B_e__Struct B
{{
get
{{
fixed (_Anonymous_e__Struct._Anonymous_e__Union* pField = &Anonymous.Anonymous)
{{
return ref pField->B;
}}
}}
}}
public unsafe partial struct _Anonymous_e__Struct
{{
[NativeTypeName(""long"")]
public IntPtr First;
[NativeTypeName(""__AnonymousRecord_ClangUnsavedFile_L7_C9"")]
public _Anonymous_e__Union Anonymous;
[StructLayout(LayoutKind.Explicit)]
public partial struct _Anonymous_e__Union
{{
[FieldOffset(0)]
[NativeTypeName(""__AnonymousRecord_ClangUnsavedFile_L9_C13"")]
public _A_e__Struct A;
[FieldOffset(0)]
[NativeTypeName(""__AnonymousRecord_ClangUnsavedFile_L14_C13"")]
public _B_e__Struct B;
public partial struct _A_e__Struct
{{
[NativeTypeName(""long"")]
public IntPtr Second;
}}
public partial struct _B_e__Struct
{{
[NativeTypeName(""long"")]
public IntPtr Second;
}}
}}
}}
public partial struct _AsArray_e__FixedBuffer
{{
public IntPtr e0;
public IntPtr e1;
public unsafe ref IntPtr this[int index]
{{
get
{{
fixed (IntPtr* pThis = &e0)
{{
return ref pThis[index];
}}
}}
}}
}}
}}
}}
";

return ValidateGeneratedCSharpCompatibleUnixBindingsAsync(inputContents, expectedOutputContents);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1456,6 +1456,116 @@ public partial struct MyUnion
public {expectedManagedType} b;
}}
}}
";

return ValidateGeneratedCSharpCompatibleWindowsBindingsAsync(inputContents, expectedOutputContents);
}

protected override Task UnionWithAnonStructWithAnonUnionImpl()
{
var inputContents = $@"typedef union _MY_UNION
{{
long AsArray[2];
struct
{{
long First;
union
{{
struct
{{
long Second;
}} A;
struct
{{
long Second;
}} B;
}};
}};
}} MY_UNION;";

var expectedOutputContents = $@"using System.Runtime.InteropServices;
namespace ClangSharp.Test
{{
[StructLayout(LayoutKind.Explicit)]
public unsafe partial struct _MY_UNION
{{
[FieldOffset(0)]
[NativeTypeName(""long[2]"")]
public fixed int AsArray[2];
[FieldOffset(0)]
[NativeTypeName(""__AnonymousRecord_ClangUnsavedFile_L4_C5"")]
public _Anonymous_e__Struct Anonymous;
public ref int First
{{
get
{{
fixed (_Anonymous_e__Struct* pField = &Anonymous)
{{
return ref pField->First;
}}
}}
}}
public ref _Anonymous_e__Struct._Anonymous_e__Union._A_e__Struct A
{{
get
{{
fixed (_Anonymous_e__Struct._Anonymous_e__Union* pField = &Anonymous.Anonymous)
{{
return ref pField->A;
}}
}}
}}
public ref _Anonymous_e__Struct._Anonymous_e__Union._B_e__Struct B
{{
get
{{
fixed (_Anonymous_e__Struct._Anonymous_e__Union* pField = &Anonymous.Anonymous)
{{
return ref pField->B;
}}
}}
}}
public unsafe partial struct _Anonymous_e__Struct
{{
[NativeTypeName(""long"")]
public int First;
[NativeTypeName(""__AnonymousRecord_ClangUnsavedFile_L7_C9"")]
public _Anonymous_e__Union Anonymous;
[StructLayout(LayoutKind.Explicit)]
public partial struct _Anonymous_e__Union
{{
[FieldOffset(0)]
[NativeTypeName(""__AnonymousRecord_ClangUnsavedFile_L9_C13"")]
public _A_e__Struct A;
[FieldOffset(0)]
[NativeTypeName(""__AnonymousRecord_ClangUnsavedFile_L14_C13"")]
public _B_e__Struct B;
public partial struct _A_e__Struct
{{
[NativeTypeName(""long"")]
public int Second;
}}
public partial struct _B_e__Struct
{{
[NativeTypeName(""long"")]
public int Second;
}}
}}
}}
}}
}}
";

return ValidateGeneratedCSharpCompatibleWindowsBindingsAsync(inputContents, expectedOutputContents);
Expand Down
Loading

0 comments on commit be0b852

Please sign in to comment.