diff --git a/src/cs/production/c2ffi.Data/CFfiCrossPlatform.cs b/src/cs/production/c2ffi.Data/CFfiCrossPlatform.cs
index a4dd116..bb8f076 100644
--- a/src/cs/production/c2ffi.Data/CFfiCrossPlatform.cs
+++ b/src/cs/production/c2ffi.Data/CFfiCrossPlatform.cs
@@ -25,7 +25,7 @@ public record CFfiCrossPlatform
///
/// Gets or sets the macro objects.
///
- [JsonPropertyName("macroObjects")]
+ [JsonPropertyName("macro_objects")]
public ImmutableSortedDictionary MacroObjects { get; set; } =
ImmutableSortedDictionary.Empty;
@@ -60,21 +60,21 @@ public record CFfiCrossPlatform
///
/// Gets or sets the type aliases.
///
- [JsonPropertyName("typeAliases")]
+ [JsonPropertyName("aliases")]
public ImmutableSortedDictionary TypeAliases { get; set; } =
ImmutableSortedDictionary.Empty;
///
/// Gets or sets the opaque types.
///
- [JsonPropertyName("opaqueTypes")]
+ [JsonPropertyName("opaques")]
public ImmutableSortedDictionary OpaqueTypes { get; set; } =
ImmutableSortedDictionary.Empty;
///
/// Gets or sets the function pointers.
///
- [JsonPropertyName("functionPointers")]
+ [JsonPropertyName("function_pointers")]
public ImmutableSortedDictionary FunctionPointers { get; set; } =
ImmutableSortedDictionary.Empty;
}
diff --git a/src/cs/production/c2ffi.Data/CFfiTargetPlatform.cs b/src/cs/production/c2ffi.Data/CFfiTargetPlatform.cs
index 26d75ac..163b112 100644
--- a/src/cs/production/c2ffi.Data/CFfiTargetPlatform.cs
+++ b/src/cs/production/c2ffi.Data/CFfiTargetPlatform.cs
@@ -19,49 +19,49 @@ public record CFfiTargetPlatform
///
/// Gets or sets the file name of the C header file.
///
- [JsonPropertyName("fileName")]
+ [JsonPropertyName("file_name")]
public string FileName { get; set; } = string.Empty;
///
/// Gets or sets the target platform requested to be used by Clang.
///
- [JsonPropertyName("platformRequested")]
+ [JsonPropertyName("platform_requested")]
public TargetPlatform PlatformRequested { get; set; } = TargetPlatform.Unknown;
///
/// Gets or sets the target platform used by Clang.
///
- [JsonPropertyName("platformActual")]
+ [JsonPropertyName("platform_actual")]
public TargetPlatform PlatformActual { get; set; } = TargetPlatform.Unknown;
///
/// Gets or sets the arguments passed to Clang.
///
- [JsonPropertyName("clangArguments")]
+ [JsonPropertyName("clang_arguments")]
public ImmutableArray ClangArguments;
///
/// Gets or sets the system include directories used.
///
- [JsonPropertyName("systemIncludeDirectories")]
+ [JsonPropertyName("system_include_directories")]
public ImmutableArray SystemIncludeDirectories { get; set; } = ImmutableArray.Empty;
///
/// Gets or sets the user include directories used.
///
- [JsonPropertyName("userIncludeDirectories")]
+ [JsonPropertyName("user_include_directories")]
public ImmutableArray UserIncludeDirectories { get; set; } = ImmutableArray.Empty;
///
/// Gets or sets the pointer size in bytes.
///
- [JsonPropertyName("pointerSize")]
+ [JsonPropertyName("pointer_size")]
public int PointerSize { get; set; }
///
/// Gets or sets the macro objects.
///
- [JsonPropertyName("macroObjects")]
+ [JsonPropertyName("macro_objects")]
public ImmutableSortedDictionary MacroObjects { get; set; } =
ImmutableSortedDictionary.Empty;
@@ -96,21 +96,21 @@ public record CFfiTargetPlatform
///
/// Gets or sets the type aliases.
///
- [JsonPropertyName("typeAliases")]
+ [JsonPropertyName("aliases")]
public ImmutableSortedDictionary TypeAliases { get; set; } =
ImmutableSortedDictionary.Empty;
///
/// Gets or sets the opaque types.
///
- [JsonPropertyName("opaqueTypes")]
+ [JsonPropertyName("opaques")]
public ImmutableSortedDictionary OpaqueTypes { get; set; } =
ImmutableSortedDictionary.Empty;
///
/// Gets or sets the function pointers.
///
- [JsonPropertyName("functionPointers")]
+ [JsonPropertyName("function_pointers")]
public ImmutableSortedDictionary FunctionPointers { get; set; } =
ImmutableSortedDictionary.Empty;
}
diff --git a/src/cs/production/c2ffi.Data/Nodes/CRecord.cs b/src/cs/production/c2ffi.Data/Nodes/CRecord.cs
index 2a7e31c..28b3658 100644
--- a/src/cs/production/c2ffi.Data/Nodes/CRecord.cs
+++ b/src/cs/production/c2ffi.Data/Nodes/CRecord.cs
@@ -46,6 +46,12 @@ public class CRecord : CNodeWithLocation
[JsonPropertyName("fields")]
public ImmutableArray Fields { get; set; } = ImmutableArray.Empty;
+ ///
+ /// Gets or sets the nested records.
+ ///
+ [JsonPropertyName("nested")]
+ public ImmutableArray NestedRecords { get; set; } = ImmutableArray.Empty;
+
///
[ExcludeFromCodeCoverage]
public override string ToString()
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/ExploreContext.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/ExploreContext.cs
index c6f1d4c..13eca39 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/ExploreContext.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/ExploreContext.cs
@@ -5,6 +5,7 @@
using bottlenoselabs;
using c2ffi.Clang;
using c2ffi.Data;
+using c2ffi.Data.Nodes;
using c2ffi.Extract.Parse;
using Microsoft.Extensions.DependencyInjection;
@@ -38,10 +39,14 @@ public void TryEnqueueNode(NodeInfo info)
_frontier.EnqueueNode(info);
}
- public void TryExplore(NodeInfo info)
+ public CNode? Explore(NodeInfo info)
{
var handler = GetHandler(info.NodeKind);
- var node = handler.ExploreInternal(this, info);
+ return handler.ExploreInternal(this, info);
+ }
+
+ public void AddNode(CNode? node)
+ {
if (node != null)
{
_ffiBuilder.AddNode(node);
@@ -79,33 +84,86 @@ public CType VisitType(
return string.IsNullOrEmpty(commentString) ? null : commentString;
}
- public NodeInfo CreateTopLevelNodeInfo(
- CNodeKind nodeKind,
- clang.CXCursor clangCursor)
+ public NodeInfo CreateNodeInfoFunction(clang.CXCursor clangCursor)
{
var clangCursorName = clangCursor.Spelling();
var clangCursorType = clang.clang_getCursorType(clangCursor);
+ var clangTypeInfo = ClangTypeInfoProvider.GetTypeInfo(clangCursorType);
- if (nodeKind == CNodeKind.MacroObject)
- {
- return CreateNodeInfo(
- nodeKind,
- clangCursorName,
- clangCursorType.Spelling(),
- clangCursor,
- clangCursorType,
- null);
- }
+ var nodeInfo = CreateNodeInfo(
+ CNodeKind.Function,
+ clangCursorName,
+ clangTypeInfo.Name,
+ clangCursor,
+ clangTypeInfo.ClangType,
+ null);
+ return nodeInfo;
+ }
+
+ public NodeInfo CreateNodeInfoMacroObject(clang.CXCursor clangCursor)
+ {
+ var clangCursorName = clangCursor.Spelling();
+ var clangCursorType = clang.clang_getCursorType(clangCursor);
+
+ var nodeInfo = CreateNodeInfo(
+ CNodeKind.MacroObject,
+ clangCursorName,
+ clangCursorType.Spelling(),
+ clangCursor,
+ clangCursorType,
+ null);
+ return nodeInfo;
+ }
+ public NodeInfo CreateNodeInfoVariable(clang.CXCursor clangCursor)
+ {
+ var clangCursorName = clangCursor.Spelling();
+ var clangCursorType = clang.clang_getCursorType(clangCursor);
var clangTypeInfo = ClangTypeInfoProvider.GetTypeInfo(clangCursorType);
- return CreateNodeInfo(
+ var nodeInfo = CreateNodeInfo(
+ CNodeKind.Variable,
+ clangCursorName,
+ clangTypeInfo.Name,
+ clangCursor,
+ clangTypeInfo.ClangType,
+ null);
+ return nodeInfo;
+ }
+
+ public NodeInfo CreateNodeInfoExplicitlyIncluded(CNodeKind nodeKind, clang.CXCursor clangCursor)
+ {
+ var clangCursorName = clangCursor.Spelling();
+ var clangCursorType = clang.clang_getCursorType(clangCursor);
+ var clangTypeInfo = ClangTypeInfoProvider.GetTypeInfo(clangCursorType);
+
+ var nodeInfo = CreateNodeInfo(
nodeKind,
clangCursorName,
clangTypeInfo.Name,
clangCursor,
clangTypeInfo.ClangType,
null);
+ return nodeInfo;
+ }
+
+ public NodeInfo CreateNodeInfoRecordNested(
+ CNodeKind nodeKind,
+ string typeName,
+ clang.CXCursor clangCursor,
+ clang.CXType clangType,
+ NodeInfo parentInfo)
+ {
+ var clangCursorName = clangCursor.Spelling();
+
+ var nodeInfo = CreateNodeInfo(
+ nodeKind,
+ clangCursorName,
+ typeName,
+ clangCursor,
+ clangType,
+ parentInfo);
+ return nodeInfo;
}
public void Dispose()
@@ -131,13 +189,41 @@ public string GetFieldName(clang.CXCursor clangCursor)
return name;
}
+ private NodeInfo CreateNodeInfo(
+ CNodeKind kind,
+ string name,
+ string typeName,
+ clang.CXCursor clangCursor,
+ clang.CXType clangType,
+ NodeInfo? parentInfo)
+ {
+ var location = ParseContext.Location(clangCursor, out _);
+ var sizeOf = ParseContext.SizeOf(kind, clangType);
+ var alignOf = ParseContext.AlignOf(kind, clangType);
+
+ var result = new NodeInfo
+ {
+ NodeKind = kind,
+ Name = name,
+ TypeName = typeName,
+ ClangType = clangType,
+ ClangCursor = clangCursor,
+ Location = location,
+ Parent = parentInfo,
+ SizeOf = sizeOf,
+ AlignOf = alignOf
+ };
+
+ return result;
+ }
+
private CType VisitTypeInternal(
CNodeKind nodeKind,
string typeName,
clang.CXType clangType,
clang.CXType clangContainerType,
clang.CXCursor clangCursor,
- NodeInfo? rootNode)
+ NodeInfo? parentInfo)
{
var clangCursorLocation = clang.clang_getTypeDeclaration(clangType);
var location = ParseContext.Location(clangCursorLocation, out _);
@@ -150,17 +236,17 @@ private CType VisitTypeInternal(
#pragma warning restore IDE0010
{
case CNodeKind.Pointer:
- innerType = VisitTypeInternalPointer(nodeKind, clangType, rootNode);
+ innerType = VisitTypeInternalPointer(nodeKind, clangType, parentInfo);
sizeOf = ParseContext.PointerSize;
alignOf = ParseContext.PointerSize;
break;
case CNodeKind.Array:
- innerType = VisitTypeInternalArray(nodeKind, clangType, rootNode);
+ innerType = VisitTypeInternalArray(nodeKind, clangType, parentInfo);
sizeOf = ParseContext.PointerSize;
alignOf = ParseContext.PointerSize;
break;
case CNodeKind.TypeAlias:
- innerType = VisitTypeInternalTypeAlias(nodeKind, clangCursor, rootNode);
+ innerType = VisitTypeInternalTypeAlias(nodeKind, clangCursor, parentInfo);
sizeOf = innerType.SizeOf;
alignOf = innerType.AlignOf;
break;
@@ -208,12 +294,17 @@ private CType VisitTypeInternal(
return type;
}
- if (location.IsSystem && nodeKind != CNodeKind.FunctionPointer)
+ if (nodeKind is CNodeKind.Union or CNodeKind.Struct && isAnonymous)
{
return type;
}
- var info = CreateNodeInfo(type.NodeKind, type.Name, type.Name, clangCursor, clangType, rootNode);
+ if (nodeKind != CNodeKind.FunctionPointer && location.IsSystem)
+ {
+ return type;
+ }
+
+ var info = CreateNodeInfo(type.NodeKind, type.Name, type.Name, clangCursor, clangType, parentInfo);
TryEnqueueNode(info);
return type;
}
@@ -221,7 +312,7 @@ private CType VisitTypeInternal(
private CType VisitTypeInternalPointer(
CNodeKind nodeKind,
clang.CXType clangType,
- NodeInfo? rootNode)
+ NodeInfo? parentInfo)
{
var pointeeTypeCandidate = clang.clang_getPointeeType(clangType);
var pointeeTypeInfo = ClangTypeInfoProvider.GetTypeInfo(pointeeTypeCandidate, nodeKind);
@@ -232,14 +323,14 @@ private CType VisitTypeInternalPointer(
pointeeTypeInfo.ClangType,
pointeeTypeCandidate,
pointeeTypeInfo.ClangCursor,
- rootNode);
+ parentInfo);
return innerType;
}
private CType VisitTypeInternalArray(
CNodeKind nodeKind,
clang.CXType clangType,
- NodeInfo? rootNode)
+ NodeInfo? parentInfo)
{
var elementTypeCandidate = clang.clang_getArrayElementType(clangType);
var elementTypeInfo = ClangTypeInfoProvider.GetTypeInfo(elementTypeCandidate, nodeKind);
@@ -250,14 +341,14 @@ private CType VisitTypeInternalArray(
elementTypeInfo.ClangType,
elementTypeCandidate,
elementTypeInfo.ClangCursor,
- rootNode);
+ parentInfo);
return innerType;
}
private CType VisitTypeInternalTypeAlias(
CNodeKind nodeKind,
clang.CXCursor clangCursor,
- NodeInfo? rootNode)
+ NodeInfo? parentInfo)
{
var aliasTypeCandidate = clang.clang_getTypedefDeclUnderlyingType(clangCursor);
var aliasTypeInfo = ClangTypeInfoProvider.GetTypeInfo(aliasTypeCandidate, nodeKind);
@@ -268,39 +359,11 @@ private CType VisitTypeInternalTypeAlias(
aliasTypeInfo.ClangType,
aliasTypeCandidate,
aliasTypeInfo.ClangCursor,
- rootNode);
+ parentInfo);
return innerType;
}
- private NodeInfo CreateNodeInfo(
- CNodeKind kind,
- string name,
- string typeName,
- clang.CXCursor clangCursor,
- clang.CXType clangType,
- NodeInfo? parentInfo)
- {
- var location = ParseContext.Location(clangCursor, out _);
- var sizeOf = ParseContext.SizeOf(kind, clangType);
- var alignOf = ParseContext.AlignOf(kind, clangType);
-
- var result = new NodeInfo
- {
- NodeKind = kind,
- Name = name,
- TypeName = typeName,
- ClangType = clangType,
- ClangCursor = clangCursor,
- Location = location,
- Parent = parentInfo,
- SizeOf = sizeOf,
- AlignOf = alignOf
- };
-
- return result;
- }
-
private static ImmutableDictionary GetNodeHandlers(IServiceProvider services)
{
var result = new Dictionary
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/ExploreContextFrontier.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/ExploreContextFrontier.cs
index d271349..26d67d3 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/ExploreContextFrontier.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/ExploreContextFrontier.cs
@@ -84,8 +84,9 @@ private void Explore(ExploreContext exploreContext, ArrayDeque frontie
{
while (frontier.Count > 0)
{
- var node = frontier.PopFront()!;
- exploreContext.TryExplore(node);
+ var nodeInfo = frontier.PopFront()!;
+ var node = exploreContext.Explore(nodeInfo);
+ exploreContext.AddNode(node);
}
}
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/Explorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/Explorer.cs
index 600eb30..78882aa 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/Explorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/Explorer.cs
@@ -80,40 +80,40 @@ private void VisitFunctions(ExploreContext exploreContext, ParseContext parseCon
}
}
- private void VisitFunction(ExploreContext exploreContext, clang.CXCursor clangCursor)
+ private void VisitFunction(ExploreContext context, clang.CXCursor clangCursor)
{
- var info = exploreContext.CreateTopLevelNodeInfo(CNodeKind.Function, clangCursor);
- exploreContext.TryEnqueueNode(info);
+ var info = context.CreateNodeInfoFunction(clangCursor);
+ context.TryEnqueueNode(info);
}
- private void VisitVariables(ExploreContext exploreContext, ParseContext parseContext)
+ private void VisitVariables(ExploreContext context, ParseContext parseContext)
{
var variableCursors = parseContext.GetExternalVariables();
foreach (var cursor in variableCursors)
{
- VisitVariable(exploreContext, cursor);
+ VisitVariable(context, cursor);
}
}
- private void VisitVariable(ExploreContext exploreContext, clang.CXCursor clangCursor)
+ private void VisitVariable(ExploreContext context, clang.CXCursor clangCursor)
{
- var info = exploreContext.CreateTopLevelNodeInfo(CNodeKind.Variable, clangCursor);
- exploreContext.TryEnqueueNode(info);
+ var info = context.CreateNodeInfoVariable(clangCursor);
+ context.TryEnqueueNode(info);
}
- private void VisitMacroObjects(ExploreContext exploreContext, ParseContext parseContext)
+ private void VisitMacroObjects(ExploreContext context, ParseContext parseContext)
{
var macroObjectCursors = parseContext.GetMacroObjects();
foreach (var cursor in macroObjectCursors)
{
- VisitMacroObject(exploreContext, cursor);
+ VisitMacroObject(context, cursor);
}
}
- private void VisitMacroObject(ExploreContext exploreContext, clang.CXCursor clangCursor)
+ private void VisitMacroObject(ExploreContext context, clang.CXCursor clangCursor)
{
- var info = exploreContext.CreateTopLevelNodeInfo(CNodeKind.MacroObject, clangCursor);
- exploreContext.TryEnqueueNode(info);
+ var info = context.CreateNodeInfoMacroObject(clangCursor);
+ context.TryEnqueueNode(info);
}
private void VisitExplicitIncludedNames(ExploreContext exploreContext, ParseContext parseContext)
@@ -125,7 +125,7 @@ private void VisitExplicitIncludedNames(ExploreContext exploreContext, ParseCont
}
}
- private void VisitExplicitlyIncludedName(ExploreContext exploreContext, clang.CXCursor clangCursor)
+ private void VisitExplicitlyIncludedName(ExploreContext context, clang.CXCursor clangCursor)
{
#pragma warning disable IDE0072
var nodeKind = clangCursor.kind switch
@@ -141,20 +141,20 @@ private void VisitExplicitlyIncludedName(ExploreContext exploreContext, clang.CX
return;
}
- var info = exploreContext.CreateTopLevelNodeInfo(nodeKind, clangCursor);
- exploreContext.TryEnqueueNode(info);
+ var info = context.CreateNodeInfoExplicitlyIncluded(nodeKind, clangCursor);
+ context.TryEnqueueNode(info);
}
- private void VisitIncludes(ExploreContext exploreContext, ParseContext parseContext)
+ private void VisitIncludes(ExploreContext context, ParseContext parseContext)
{
var includeCursors = parseContext.GetIncludes();
foreach (var includeCursor in includeCursors)
{
- VisitInclude(exploreContext, includeCursor);
+ VisitInclude(context, includeCursor);
}
}
- private void VisitInclude(ExploreContext exploreContext, clang.CXCursor clangCursor)
+ private void VisitInclude(ExploreContext context, clang.CXCursor clangCursor)
{
var clangFile = clang.clang_getIncludedFile(clangCursor);
var stringFile = clang.clang_getFileName(clangFile).String();
@@ -164,7 +164,7 @@ private void VisitInclude(ExploreContext exploreContext, clang.CXCursor clangCur
}
var filePath = Path.GetFullPath(stringFile);
- foreach (var systemIncludeDirectory in exploreContext.ParseContext.SystemIncludeDirectories)
+ foreach (var systemIncludeDirectory in context.ParseContext.SystemIncludeDirectories)
{
if (filePath.Contains(systemIncludeDirectory, StringComparison.InvariantCulture))
{
@@ -173,7 +173,7 @@ private void VisitInclude(ExploreContext exploreContext, clang.CXCursor clangCur
}
}
- if (exploreContext.IsIncludeIgnored(filePath))
+ if (context.IsIncludeIgnored(filePath))
{
LogIgnoredInclude(filePath);
return;
@@ -187,12 +187,12 @@ private void VisitInclude(ExploreContext exploreContext, clang.CXCursor clangCur
var parseContext2 = clangTranslationUnitParser.ParseTranslationUnit(
filePath,
- exploreContext.ParseContext.InputSanitized,
+ context.ParseContext.InputSanitized,
false,
true);
_parseContexts.Add(parseContext2);
- VisitTranslationUnit(exploreContext, parseContext2);
+ VisitTranslationUnit(context, parseContext2);
}
private ExploreContext CreateExploreContext(string filePath, InputSanitizedTargetPlatform input)
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorer.cs
index 2d64c26..b401da9 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorer.cs
@@ -23,14 +23,14 @@ internal abstract partial class NodeExplorer(
protected abstract KindTypes ExpectedTypes { get; }
- internal CNode? ExploreInternal(ExploreContext exploreContext, NodeInfo info)
+ internal CNode? ExploreInternal(ExploreContext context, NodeInfo info)
{
LogExploring(info.NodeKind.ToString(), info.Name, info.Location);
CNode? result;
try
{
- result = GetNode(exploreContext, info);
+ result = GetNode(context, info);
}
#pragma warning disable CA1031
catch (Exception e)
@@ -77,7 +77,7 @@ internal bool CanVisitInternal(NodeInfo info)
return true;
}
- protected abstract CNode? GetNode(ExploreContext exploreContext, NodeInfo info);
+ protected abstract CNode? GetNode(ExploreContext context, NodeInfo info);
private bool IsAlreadyVisited(NodeInfo info, out CLocation? firstLocation)
{
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/ArrayExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/ArrayExplorer.cs
index 6d15933..0001c16 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/ArrayExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/ArrayExplorer.cs
@@ -18,9 +18,9 @@ internal sealed class ArrayExplorer(ILogger logger) : NodeExplore
protected override KindTypes ExpectedTypes { get; } = KindTypes.Either(
CXTypeKind.CXType_ConstantArray, CXTypeKind.CXType_IncompleteArray);
- protected override CNode GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode GetNode(ExploreContext context, NodeInfo info)
{
- return Array(exploreContext, info);
+ return Array(context, info);
}
private static CArray Array(ExploreContext exploreContext, NodeInfo info)
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/EnumExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/EnumExplorer.cs
index 8c5e1fc..790d9e0 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/EnumExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/EnumExplorer.cs
@@ -23,9 +23,9 @@ internal sealed class EnumExplorer(ILogger logger)
protected override KindTypes ExpectedTypes { get; } = KindTypes.Is(CXTypeKind.CXType_Enum);
- protected override CNode GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode GetNode(ExploreContext context, NodeInfo info)
{
- return Enum(exploreContext, info);
+ return Enum(context, info);
}
private CEnum Enum(ExploreContext exploreContext, NodeInfo info)
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/FunctionExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/FunctionExplorer.cs
index 553fcea..e38bf18 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/FunctionExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/FunctionExplorer.cs
@@ -29,9 +29,9 @@ internal sealed class FunctionExplorer(ILogger logger)
protected override KindTypes ExpectedTypes { get; } = KindTypes.Either(
CXTypeKind.CXType_FunctionProto, CXTypeKind.CXType_FunctionNoProto);
- protected override CNode GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode GetNode(ExploreContext context, NodeInfo info)
{
- var function = Function(exploreContext, info);
+ var function = Function(context, info);
return function;
}
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/FunctionPointerExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/FunctionPointerExplorer.cs
index 112602e..39ec3ab 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/FunctionPointerExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/FunctionPointerExplorer.cs
@@ -33,9 +33,9 @@ internal sealed class FunctionPointerExplorer(ILogger l
protected override KindTypes ExpectedTypes { get; } = KindTypes.Either(
CXTypeKind.CXType_FunctionProto, CXTypeKind.CXType_FunctionNoProto);
- protected override CNode GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode GetNode(ExploreContext context, NodeInfo info)
{
- return FunctionPointer(exploreContext, info);
+ return FunctionPointer(context, info);
}
private static CFunctionPointer FunctionPointer(ExploreContext exploreContext, NodeInfo info)
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/MacroObjectExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/MacroObjectExplorer.cs
index 3b2076a..43f6da4 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/MacroObjectExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/MacroObjectExplorer.cs
@@ -30,9 +30,9 @@ internal sealed class MacroObjectExplorer(
protected override KindTypes ExpectedTypes => KindTypes.Any;
- protected override CNode? GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode? GetNode(ExploreContext context, NodeInfo info)
{
- return MacroObject(exploreContext, info);
+ return MacroObject(context, info);
}
private CMacroObject? MacroObject(ExploreContext exploreContext, NodeInfo info)
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/OpaqueTypeExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/OpaqueTypeExplorer.cs
index 3262195..a4eb6b8 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/OpaqueTypeExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/OpaqueTypeExplorer.cs
@@ -17,9 +17,9 @@ internal sealed class OpaqueTypeExplorer(ILogger logger)
protected override KindTypes ExpectedTypes => KindTypes.Any;
- protected override CNode GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode GetNode(ExploreContext context, NodeInfo info)
{
- return OpaqueDataType(exploreContext, info);
+ return OpaqueDataType(context, info);
}
private static COpaqueType OpaqueDataType(ExploreContext exploreContext, NodeInfo info)
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/PointerExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/PointerExplorer.cs
index e8302c9..a3d2d65 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/PointerExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/PointerExplorer.cs
@@ -18,9 +18,9 @@ internal sealed class PointerExplorer(ILogger logger)
protected override KindTypes ExpectedTypes { get; } = KindTypes.Is(CXTypeKind.CXType_Pointer);
- protected override CNode GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode GetNode(ExploreContext context, NodeInfo info)
{
- var pointer = Pointer(exploreContext, info);
+ var pointer = Pointer(context, info);
return pointer;
}
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/PrimitiveExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/PrimitiveExplorer.cs
index 52e8879..d5b4e18 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/PrimitiveExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/PrimitiveExplorer.cs
@@ -40,9 +40,9 @@ internal sealed class PrimitiveExplorer(ILogger logger)
CXTypeKind.CXType_Double,
CXTypeKind.CXType_LongDouble);
- protected override CNode GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode GetNode(ExploreContext context, NodeInfo info)
{
- return Primitive(exploreContext, info);
+ return Primitive(context, info);
}
private static CPrimitive Primitive(ExploreContext exploreContext, NodeInfo info)
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/StructExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/StructExplorer.cs
index 3f4de28..304484f 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/StructExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/StructExplorer.cs
@@ -18,15 +18,16 @@ internal sealed class StructExplorer(ILogger logger) : RecordExp
protected override KindCursors ExpectedCursors { get; } =
KindCursors.Is(CXCursorKind.CXCursor_StructDecl);
- protected override CNode GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode GetNode(ExploreContext context, NodeInfo info)
{
- return Struct(exploreContext, info);
+ return Struct(context, info);
}
- private CRecord Struct(ExploreContext exploreContext, NodeInfo info)
+ private CRecord Struct(ExploreContext context, NodeInfo info)
{
- var fields = StructFields(exploreContext, info);
- var comment = exploreContext.Comment(info.ClangCursor);
+ var nestedRecords = ImmutableArray.CreateBuilder();
+ var fields = StructFields(context, info, nestedRecords);
+ var comment = context.Comment(info.ClangCursor);
var isAnonymous = clang_Cursor_isAnonymous(info.ClangCursor) > 0;
var record = new CRecord
@@ -38,15 +39,17 @@ private CRecord Struct(ExploreContext exploreContext, NodeInfo info)
SizeOf = info.SizeOf!.Value,
AlignOf = info.AlignOf!.Value,
IsAnonymous = isAnonymous,
- Comment = comment
+ Comment = comment,
+ NestedRecords = nestedRecords.ToImmutable()
};
return record;
}
private ImmutableArray StructFields(
- ExploreContext exploreContext,
- NodeInfo structInfo)
+ ExploreContext context,
+ NodeInfo structInfo,
+ ImmutableArray.Builder nestedRecords)
{
var builder = ImmutableArray.CreateBuilder();
var fieldCursors = FieldCursors(structInfo.ClangType);
@@ -56,7 +59,7 @@ private ImmutableArray StructFields(
for (var i = 0; i < fieldCursors.Length; i++)
{
var clangCursor = fieldCursors[i];
- var field = StructField(exploreContext, structInfo, clangCursor);
+ var field = StructField(context, structInfo, clangCursor, nestedRecords);
builder.Add(field);
}
}
@@ -66,18 +69,28 @@ private ImmutableArray StructFields(
}
private CRecordField StructField(
- ExploreContext exploreContext,
+ ExploreContext context,
NodeInfo structInfo,
- CXCursor clangCursor)
+ CXCursor clangCursor,
+ ImmutableArray.Builder nestedRecords)
{
- var fieldName = exploreContext.GetFieldName(clangCursor);
+ var fieldName = context.GetFieldName(clangCursor);
var clangType = clang_getCursorType(clangCursor);
- var location = exploreContext.ParseContext.Location(clangCursor, out _);
- var type = exploreContext.VisitType(clangType, structInfo);
+ var location = context.ParseContext.Location(clangCursor, out _);
+ var type = context.VisitType(clangType, structInfo);
var offsetOf = (int)clang_Cursor_getOffsetOfField(clangCursor) / 8;
- var comment = exploreContext.Comment(clangCursor);
+ var comment = context.Comment(clangCursor);
+
+ if ((type.IsAnonymous ?? false) && type.NodeKind is CNodeKind.Union or CNodeKind.Struct)
+ {
+ var clangCursorRecordNested = clang_getTypeDeclaration(clangType);
+ var nodeInfo =
+ context.CreateNodeInfoRecordNested(type.NodeKind, type.Name, clangCursorRecordNested, clangType, structInfo);
+ var node = (CRecord)context.Explore(nodeInfo)!;
+ nestedRecords.Add(node);
+ }
- return new CRecordField
+ var structField = new CRecordField
{
Name = fieldName,
Location = location,
@@ -85,5 +98,7 @@ private CRecordField StructField(
OffsetOf = offsetOf,
Comment = comment
};
+
+ return structField;
}
}
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/TypeAliasExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/TypeAliasExplorer.cs
index 5177dd0..9cdded1 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/TypeAliasExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/TypeAliasExplorer.cs
@@ -18,9 +18,9 @@ internal sealed class TypeAliasExplorer(ILogger logger) : Nod
protected override KindTypes ExpectedTypes { get; } = KindTypes.Is(CXTypeKind.CXType_Typedef);
- protected override CNode GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode GetNode(ExploreContext context, NodeInfo info)
{
- return TypeAlias(exploreContext, info);
+ return TypeAlias(context, info);
}
private static CTypeAlias TypeAlias(ExploreContext exploreContext, NodeInfo info)
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/UnionExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/UnionExplorer.cs
index c31f594..23d905b 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/UnionExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/UnionExplorer.cs
@@ -18,15 +18,16 @@ internal sealed class UnionExplorer(ILogger logger) : RecordExplo
protected override KindCursors ExpectedCursors { get; } =
KindCursors.Is(CXCursorKind.CXCursor_UnionDecl);
- protected override CNode GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode GetNode(ExploreContext context, NodeInfo info)
{
- return Union(exploreContext, info);
+ return Union(context, info);
}
- private CRecord Union(ExploreContext exploreContext, NodeInfo info)
+ private CRecord Union(ExploreContext context, NodeInfo info)
{
- var fields = UnionFields(exploreContext, info.ClangType, info);
- var comment = exploreContext.Comment(info.ClangCursor);
+ var nestedRecords = ImmutableArray.CreateBuilder();
+ var fields = UnionFields(context, info.ClangType, info, nestedRecords);
+ var comment = context.Comment(info.ClangCursor);
var isAnonymous = clang_Cursor_isAnonymous(info.ClangCursor) > 0;
var record = new CRecord
@@ -38,7 +39,8 @@ private CRecord Union(ExploreContext exploreContext, NodeInfo info)
SizeOf = info.SizeOf!.Value,
AlignOf = info.AlignOf!.Value,
Comment = comment,
- IsAnonymous = isAnonymous
+ IsAnonymous = isAnonymous,
+ NestedRecords = nestedRecords.ToImmutable()
};
return record;
@@ -47,7 +49,8 @@ private CRecord Union(ExploreContext exploreContext, NodeInfo info)
private ImmutableArray UnionFields(
ExploreContext exploreContext,
CXType clangType,
- NodeInfo parentInfo)
+ NodeInfo parentInfo,
+ ImmutableArray.Builder nestedRecords)
{
var builder = ImmutableArray.CreateBuilder();
var fieldCursors = FieldCursors(clangType);
@@ -55,7 +58,7 @@ private ImmutableArray UnionFields(
for (var i = 0; i < fieldCursors.Length; i++)
{
var clangCursor = fieldCursors[i];
- var field = UnionField(exploreContext, clangCursor, parentInfo);
+ var field = UnionField(exploreContext, clangCursor, parentInfo, nestedRecords);
builder.Add(field);
}
@@ -64,17 +67,27 @@ private ImmutableArray UnionFields(
}
private CRecordField UnionField(
- ExploreContext exploreContext,
+ ExploreContext context,
CXCursor clangCursor,
- NodeInfo parentInfo)
+ NodeInfo parentInfo,
+ ImmutableArray.Builder nestedRecords)
{
- var name = exploreContext.GetFieldName(clangCursor);
+ var name = context.GetFieldName(clangCursor);
var clangType = clang_getCursorType(clangCursor);
- var location = exploreContext.ParseContext.Location(clangCursor, out _);
- var type = exploreContext.VisitType(clangType, parentInfo);
- var comment = exploreContext.Comment(clangCursor);
+ var location = context.ParseContext.Location(clangCursor, out _);
+ var type = context.VisitType(clangType, parentInfo);
+ var comment = context.Comment(clangCursor);
- var result = new CRecordField
+ if ((type.IsAnonymous ?? false) && type.NodeKind is CNodeKind.Union or CNodeKind.Struct)
+ {
+ var clangCursorRecordNested = clang_getTypeDeclaration(clangType);
+ var nodeInfo =
+ context.CreateNodeInfoRecordNested(type.NodeKind, type.Name, clangCursorRecordNested, clangType, parentInfo);
+ var node = (CRecord)context.Explore(nodeInfo)!;
+ nestedRecords.Add(node);
+ }
+
+ var unionField = new CRecordField
{
Name = name,
Location = location,
@@ -82,6 +95,6 @@ private CRecordField UnionField(
Comment = comment
};
- return result;
+ return unionField;
}
}
diff --git a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/VariableExplorer.cs b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/VariableExplorer.cs
index e68b2e8..c4d5b60 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/VariableExplorer.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Explore/NodeExplorers/VariableExplorer.cs
@@ -19,9 +19,9 @@ internal sealed class VariableExplorer(ILogger logger)
protected override KindTypes ExpectedTypes => KindTypes.Any;
- protected override CNode GetNode(ExploreContext exploreContext, NodeInfo info)
+ protected override CNode GetNode(ExploreContext context, NodeInfo info)
{
- return Variable(exploreContext, info);
+ return Variable(context, info);
}
private static CVariable Variable(ExploreContext exploreContext, NodeInfo info)
diff --git a/src/cs/production/c2ffi.Tool/Extract/Parse/ClangTypeInfoProvider.cs b/src/cs/production/c2ffi.Tool/Extract/Parse/ClangTypeInfoProvider.cs
index c128669..23262cb 100644
--- a/src/cs/production/c2ffi.Tool/Extract/Parse/ClangTypeInfoProvider.cs
+++ b/src/cs/production/c2ffi.Tool/Extract/Parse/ClangTypeInfoProvider.cs
@@ -179,39 +179,11 @@ private static string GetTypeName(clang.CXType clangType, clang.CXCursor clangCu
{
var isAnonymous = clang.clang_Cursor_isAnonymous(clangCursor) > 0;
var isRecord = clangCursor.kind is clang.CXCursorKind.CXCursor_StructDecl or clang.CXCursorKind.CXCursor_UnionDecl;
- if (!isRecord || !isAnonymous)
+ if (isRecord && isAnonymous)
{
- return clangType.Spelling();
+ return string.Empty;
}
- var clangCursorParent = clang.clang_getCursorSemanticParent(clangCursor);
- var clangTypeParent = clang.clang_getCursorType(clangCursorParent);
- var parentName = GetTypeName(clangTypeParent, clangCursorParent);
-
- var clangCursorFields = clangTypeParent.GetFields();
- var index = -1;
- for (var i = 0; i < clangCursorFields.Length; i++)
- {
- var clangCursorField = clangCursorFields[i];
- var clangTypeField = clang.clang_getCursorType(clangCursorField);
- if (clangTypeField.kind == clang.CXTypeKind.CXType_Elaborated)
- {
- clangTypeField = clang.clang_Type_getNamedType(clangTypeField);
- }
-
- var areEqual = clang.clang_equalTypes(clangType, clangTypeField) > 0;
- if (areEqual)
- {
- index = i;
- }
- }
-
- if (index == -1)
- {
- var name = clangType.Spelling();
- throw new InvalidOperationException($"Could not find anonymous record declaration for type '{name}' in parent record '{parentName}'.");
- }
-
- return $"{parentName}_ANONYMOUS_{index}";
+ return clangType.Spelling();
}
}
diff --git a/src/cs/production/c2ffi.Tool/Merge/Tool.cs b/src/cs/production/c2ffi.Tool/Merge/Tool.cs
index 6c06866..3354d13 100644
--- a/src/cs/production/c2ffi.Tool/Merge/Tool.cs
+++ b/src/cs/production/c2ffi.Tool/Merge/Tool.cs
@@ -56,7 +56,7 @@ protected override void Execute(InputSanitized inputSanitized, Output output)
var ffi = CreateCrossPlatformFfi(platforms, platformNodesByKey);
Json.WriteFfiCrossPlatform(_fileSystem, inputSanitized.OutputFilePath, ffi);
- LogWriteAbstractSyntaxTreeSuccess(string.Join(", ", platforms), inputSanitized.OutputFilePath);
+ LogWriteFfiSuccess(string.Join(", ", platforms), inputSanitized.OutputFilePath);
}
private CFfiCrossPlatform CreateCrossPlatformFfi(
@@ -306,7 +306,7 @@ private ImmutableArray GetPlatformFfis(ImmutableArray GetPlatformFfis(ImmutableArray Fields { get; } = [..record.Fields.Select(field => new CTestRecordField(field))];
+ public ImmutableArray NestedRecords { get; } = [..record.NestedRecords.Select(record => new CTestRecord(record))];
+
public override string ToString()
{
return Name;
diff --git a/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Structs/struct_anonymous_char_int/Test.cs b/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Structs/struct_anonymous_char_int/Test.cs
index 381b224..523d285 100644
--- a/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Structs/struct_anonymous_char_int/Test.cs
+++ b/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Structs/struct_anonymous_char_int/Test.cs
@@ -38,13 +38,14 @@ private void StructExists(CTestFfiTargetPlatform ffi)
_ = field.OffsetOf.Should().Be(0);
var fieldType = field.Type;
- _ = fieldType.Name.Should().Be(name + "_ANONYMOUS_0");
+ _ = fieldType.Name.Should().Be(string.Empty);
_ = fieldType.SizeOf.Should().Be(8);
_ = fieldType.AlignOf.Should().Be(4);
_ = fieldType.IsAnonymous.Should().BeTrue();
_ = fieldType.InnerType.Should().BeNull();
- var anonymousStruct = ffi.GetRecord(fieldType.Name);
+ _ = @struct.NestedRecords.Should().HaveCount(1);
+ var anonymousStruct = @struct.NestedRecords[0];
_ = anonymousStruct.IsStruct.Should().BeTrue();
_ = anonymousStruct.IsUnion.Should().BeFalse();
_ = anonymousStruct.SizeOf.Should().Be(8);
diff --git a/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Structs/struct_anonymous_nested/Test.cs b/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Structs/struct_anonymous_nested/Test.cs
index 97b56e2..8cfa4a2 100644
--- a/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Structs/struct_anonymous_nested/Test.cs
+++ b/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Structs/struct_anonymous_nested/Test.cs
@@ -38,13 +38,14 @@ private void StructExists(CTestFfiTargetPlatform ffi)
_ = field.OffsetOf.Should().Be(0);
var fieldType = field.Type;
- _ = fieldType.Name.Should().Be(name + "_ANONYMOUS_0");
+ _ = fieldType.Name.Should().Be(string.Empty);
_ = fieldType.SizeOf.Should().Be(16);
_ = fieldType.AlignOf.Should().Be(4);
_ = fieldType.IsAnonymous.Should().BeTrue();
_ = fieldType.InnerType.Should().BeNull();
- var anonymousStruct = ffi.GetRecord(fieldType.Name);
+ _ = @struct.NestedRecords.Should().HaveCount(1);
+ var anonymousStruct = @struct.NestedRecords[0];
_ = anonymousStruct.IsStruct.Should().BeTrue();
_ = anonymousStruct.IsUnion.Should().BeFalse();
_ = anonymousStruct.SizeOf.Should().Be(16);
@@ -55,7 +56,7 @@ private void StructExists(CTestFfiTargetPlatform ffi)
var anonymousField1 = anonymousStruct.Fields[0];
_ = anonymousField1.Name.Should().BeEmpty();
_ = anonymousField1.OffsetOf.Should().Be(0);
- _ = anonymousField1.Type.Name.Should().Be(anonymousStruct.Name + "_ANONYMOUS_0");
+ _ = anonymousField1.Type.Name.Should().Be(string.Empty);
_ = anonymousField1.Type.SizeOf.Should().Be(8);
_ = anonymousField1.Type.AlignOf.Should().Be(4);
_ = anonymousField1.Type.IsAnonymous.Should().BeTrue();
@@ -64,13 +65,14 @@ private void StructExists(CTestFfiTargetPlatform ffi)
var anonymousField2 = anonymousStruct.Fields[1];
_ = anonymousField2.Name.Should().BeEmpty();
_ = anonymousField2.OffsetOf.Should().Be(8);
- _ = anonymousField2.Type.Name.Should().Be(anonymousStruct.Name + "_ANONYMOUS_1");
+ _ = anonymousField2.Type.Name.Should().Be(string.Empty);
_ = anonymousField2.Type.SizeOf.Should().Be(8);
_ = anonymousField2.Type.AlignOf.Should().Be(4);
_ = anonymousField2.Type.IsAnonymous.Should().BeTrue();
_ = anonymousField2.Type.InnerType.Should().BeNull();
- var nestedAnonymousStruct1 = ffi.GetRecord(anonymousField1.Type.Name);
+ _ = anonymousStruct.NestedRecords.Should().HaveCount(2);
+ var nestedAnonymousStruct1 = anonymousStruct.NestedRecords[0];
_ = nestedAnonymousStruct1.IsStruct.Should().BeTrue();
_ = nestedAnonymousStruct1.IsUnion.Should().BeFalse();
_ = nestedAnonymousStruct1.SizeOf.Should().Be(8);
@@ -88,7 +90,7 @@ private void StructExists(CTestFfiTargetPlatform ffi)
nestedAnonymousStruct1Field2.Type.Should().BeInt();
_ = nestedAnonymousStruct1Field2.OffsetOf.Should().Be(4);
- var nestedAnonymousStruct2 = ffi.GetRecord(anonymousField2.Type.Name);
+ var nestedAnonymousStruct2 = anonymousStruct.NestedRecords[1];
_ = nestedAnonymousStruct2.IsStruct.Should().BeTrue();
_ = nestedAnonymousStruct2.IsUnion.Should().BeFalse();
_ = nestedAnonymousStruct2.SizeOf.Should().Be(8);
diff --git a/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Unions/union_anonymous_char_int/Test.cs b/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Unions/union_anonymous_char_int/Test.cs
index b3af46e..527209e 100644
--- a/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Unions/union_anonymous_char_int/Test.cs
+++ b/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Unions/union_anonymous_char_int/Test.cs
@@ -38,13 +38,14 @@ private void UnionExists(CTestFfiTargetPlatform ffi)
_ = field.OffsetOf.Should().Be(0);
var fieldType = field.Type;
- _ = fieldType.Name.Should().Be($"{name}_ANONYMOUS_0");
+ _ = fieldType.Name.Should().Be(string.Empty);
_ = fieldType.SizeOf.Should().Be(4);
_ = fieldType.AlignOf.Should().Be(4);
_ = fieldType.IsAnonymous.Should().BeTrue();
_ = fieldType.InnerType.Should().BeNull();
- var anonymousUnion = ffi.GetRecord(fieldType.Name);
+ _ = union.NestedRecords.Should().HaveCount(1);
+ var anonymousUnion = union.NestedRecords[0];
_ = anonymousUnion.IsStruct.Should().BeFalse();
_ = anonymousUnion.IsUnion.Should().BeTrue();
_ = anonymousUnion.SizeOf.Should().Be(4);
diff --git a/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Unions/union_anonymous_nested/Test.cs b/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Unions/union_anonymous_nested/Test.cs
index f73d382..71e5671 100644
--- a/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Unions/union_anonymous_nested/Test.cs
+++ b/src/cs/tests/c2ffi.Tests.EndToEnd.Extract/Unions/union_anonymous_nested/Test.cs
@@ -38,13 +38,14 @@ private void UnionExists(CTestFfiTargetPlatform ffi)
_ = field.OffsetOf.Should().Be(0);
var fieldType = field.Type;
- _ = fieldType.Name.Should().Be(name + "_ANONYMOUS_0");
+ _ = fieldType.Name.Should().Be(string.Empty);
_ = fieldType.SizeOf.Should().Be(4);
_ = fieldType.AlignOf.Should().Be(4);
_ = fieldType.IsAnonymous.Should().BeTrue();
_ = fieldType.InnerType.Should().BeNull();
- var anonymousUnion = ffi.GetRecord(fieldType.Name);
+ _ = union.NestedRecords.Should().HaveCount(1);
+ var anonymousUnion = union.NestedRecords[0];
_ = anonymousUnion.IsStruct.Should().BeFalse();
_ = anonymousUnion.IsUnion.Should().BeTrue();
_ = anonymousUnion.SizeOf.Should().Be(4);
@@ -55,7 +56,7 @@ private void UnionExists(CTestFfiTargetPlatform ffi)
var anonymousField1 = anonymousUnion.Fields[0];
_ = anonymousField1.Name.Should().BeEmpty();
_ = anonymousField1.OffsetOf.Should().Be(0);
- _ = anonymousField1.Type.Name.Should().Be(anonymousUnion.Name + "_ANONYMOUS_0");
+ _ = anonymousField1.Type.Name.Should().Be(string.Empty);
_ = anonymousField1.Type.SizeOf.Should().Be(4);
_ = anonymousField1.Type.AlignOf.Should().Be(4);
_ = anonymousField1.Type.IsAnonymous.Should().BeTrue();
@@ -64,13 +65,14 @@ private void UnionExists(CTestFfiTargetPlatform ffi)
var anonymousField2 = anonymousUnion.Fields[1];
_ = anonymousField2.Name.Should().BeEmpty();
_ = anonymousField2.OffsetOf.Should().Be(0);
- _ = anonymousField2.Type.Name.Should().Be(anonymousUnion.Name + "_ANONYMOUS_1");
+ _ = anonymousField2.Type.Name.Should().Be(string.Empty);
_ = anonymousField2.Type.SizeOf.Should().Be(4);
_ = anonymousField2.Type.AlignOf.Should().Be(4);
_ = anonymousField2.Type.IsAnonymous.Should().BeTrue();
_ = anonymousField2.Type.InnerType.Should().BeNull();
- var nestedAnonymousUnion1 = ffi.GetRecord(anonymousField1.Type.Name);
+ _ = anonymousUnion.NestedRecords.Should().HaveCount(2);
+ var nestedAnonymousUnion1 = anonymousUnion.NestedRecords[0];
_ = nestedAnonymousUnion1.IsStruct.Should().BeFalse();
_ = nestedAnonymousUnion1.IsUnion.Should().BeTrue();
_ = nestedAnonymousUnion1.SizeOf.Should().Be(4);
@@ -88,7 +90,7 @@ private void UnionExists(CTestFfiTargetPlatform ffi)
nestedAnonymousUnion1Field2.Type.Should().BeInt();
_ = nestedAnonymousUnion1Field2.OffsetOf.Should().Be(0);
- var nestedAnonymousUnion2 = ffi.GetRecord(anonymousField2.Type.Name);
+ var nestedAnonymousUnion2 = anonymousUnion.NestedRecords[1];
_ = nestedAnonymousUnion2.IsStruct.Should().BeFalse();
_ = nestedAnonymousUnion2.IsUnion.Should().BeTrue();
_ = nestedAnonymousUnion2.SizeOf.Should().Be(4);
diff --git a/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Structs/struct_anonymous_char_int/Test.cs b/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Structs/struct_anonymous_char_int/Test.cs
index 09d0b73..6b1c6bd 100644
--- a/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Structs/struct_anonymous_char_int/Test.cs
+++ b/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Structs/struct_anonymous_char_int/Test.cs
@@ -39,7 +39,8 @@ private void StructExists(CTestFfiCrossPlatform ffi)
_ = fieldType.IsAnonymous.Should().BeTrue();
_ = fieldType.InnerType.Should().BeNull();
- var anonymousStruct = ffi.GetRecord(fieldType.Name);
+ _ = @struct.NestedRecords.Should().HaveCount(1);
+ var anonymousStruct = @struct.NestedRecords[0];
_ = anonymousStruct.IsStruct.Should().BeTrue();
_ = anonymousStruct.IsUnion.Should().BeFalse();
_ = anonymousStruct.SizeOf.Should().Be(8);
diff --git a/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Structs/struct_anonymous_nested/Test.cs b/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Structs/struct_anonymous_nested/Test.cs
index bb4ea6b..91a5d81 100644
--- a/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Structs/struct_anonymous_nested/Test.cs
+++ b/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Structs/struct_anonymous_nested/Test.cs
@@ -34,13 +34,14 @@ private void StructExists(CTestFfiCrossPlatform ffi)
_ = field.OffsetOf.Should().Be(0);
var fieldType = field.Type;
- _ = fieldType.Name.Should().Be(name + "_ANONYMOUS_0");
+ _ = fieldType.Name.Should().Be(string.Empty);
_ = fieldType.SizeOf.Should().Be(16);
_ = fieldType.AlignOf.Should().Be(4);
_ = fieldType.IsAnonymous.Should().BeTrue();
_ = fieldType.InnerType.Should().BeNull();
- var anonymousStruct = ffi.GetRecord(fieldType.Name);
+ _ = @struct.NestedRecords.Should().HaveCount(1);
+ var anonymousStruct = @struct.NestedRecords[0];
_ = anonymousStruct.IsStruct.Should().BeTrue();
_ = anonymousStruct.IsUnion.Should().BeFalse();
_ = anonymousStruct.SizeOf.Should().Be(16);
@@ -51,7 +52,7 @@ private void StructExists(CTestFfiCrossPlatform ffi)
var anonymousField1 = anonymousStruct.Fields[0];
_ = anonymousField1.Name.Should().BeEmpty();
_ = anonymousField1.OffsetOf.Should().Be(0);
- _ = anonymousField1.Type.Name.Should().Be(anonymousStruct.Name + "_ANONYMOUS_0");
+ _ = anonymousField1.Type.Name.Should().Be(string.Empty);
_ = anonymousField1.Type.SizeOf.Should().Be(8);
_ = anonymousField1.Type.AlignOf.Should().Be(4);
_ = anonymousField1.Type.IsAnonymous.Should().BeTrue();
@@ -60,13 +61,14 @@ private void StructExists(CTestFfiCrossPlatform ffi)
var anonymousField2 = anonymousStruct.Fields[1];
_ = anonymousField2.Name.Should().BeEmpty();
_ = anonymousField2.OffsetOf.Should().Be(8);
- _ = anonymousField2.Type.Name.Should().Be(anonymousStruct.Name + "_ANONYMOUS_1");
+ _ = anonymousField2.Type.Name.Should().Be(string.Empty);
_ = anonymousField2.Type.SizeOf.Should().Be(8);
_ = anonymousField2.Type.AlignOf.Should().Be(4);
_ = anonymousField2.Type.IsAnonymous.Should().BeTrue();
_ = anonymousField2.Type.InnerType.Should().BeNull();
- var nestedAnonymousStruct1 = ffi.GetRecord(anonymousField1.Type.Name);
+ _ = anonymousStruct.NestedRecords.Should().HaveCount(2);
+ var nestedAnonymousStruct1 = anonymousStruct.NestedRecords[0];
_ = nestedAnonymousStruct1.IsStruct.Should().BeTrue();
_ = nestedAnonymousStruct1.IsUnion.Should().BeFalse();
_ = nestedAnonymousStruct1.SizeOf.Should().Be(8);
@@ -84,7 +86,7 @@ private void StructExists(CTestFfiCrossPlatform ffi)
nestedAnonymousStruct1Field2.Type.Should().BeInt();
_ = nestedAnonymousStruct1Field2.OffsetOf.Should().Be(4);
- var nestedAnonymousStruct2 = ffi.GetRecord(anonymousField2.Type.Name);
+ var nestedAnonymousStruct2 = anonymousStruct.NestedRecords[1];
_ = nestedAnonymousStruct2.IsStruct.Should().BeTrue();
_ = nestedAnonymousStruct2.IsUnion.Should().BeFalse();
_ = nestedAnonymousStruct2.SizeOf.Should().Be(8);
diff --git a/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Unions/union_anonymous_char_int/Test.cs b/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Unions/union_anonymous_char_int/Test.cs
index 73ae02d..0dee605 100644
--- a/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Unions/union_anonymous_char_int/Test.cs
+++ b/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Unions/union_anonymous_char_int/Test.cs
@@ -34,13 +34,14 @@ private void UnionExists(CTestFfiCrossPlatform ffi)
_ = field.OffsetOf.Should().Be(0);
var fieldType = field.Type;
- _ = fieldType.Name.Should().Be($"{name}_ANONYMOUS_0");
+ _ = fieldType.Name.Should().Be(string.Empty);
_ = fieldType.SizeOf.Should().Be(4);
_ = fieldType.AlignOf.Should().Be(4);
_ = fieldType.IsAnonymous.Should().BeTrue();
_ = fieldType.InnerType.Should().BeNull();
- var anonymousUnion = ffi.GetRecord(fieldType.Name);
+ _ = union.NestedRecords.Should().HaveCount(1);
+ var anonymousUnion = union.NestedRecords[0];
_ = anonymousUnion.IsStruct.Should().BeFalse();
_ = anonymousUnion.IsUnion.Should().BeTrue();
_ = anonymousUnion.SizeOf.Should().Be(4);
diff --git a/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Unions/union_anonymous_nested/Test.cs b/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Unions/union_anonymous_nested/Test.cs
index 76ca339..c66ab45 100644
--- a/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Unions/union_anonymous_nested/Test.cs
+++ b/src/cs/tests/c2ffi.Tests.EndToEnd.Merge/Unions/union_anonymous_nested/Test.cs
@@ -33,13 +33,14 @@ private void UnionExists(CTestFfiCrossPlatform ffi)
_ = field.OffsetOf.Should().Be(0);
var fieldType = field.Type;
- _ = fieldType.Name.Should().Be(name + "_ANONYMOUS_0");
+ _ = fieldType.Name.Should().Be(string.Empty);
_ = fieldType.SizeOf.Should().Be(4);
_ = fieldType.AlignOf.Should().Be(4);
_ = fieldType.IsAnonymous.Should().BeTrue();
_ = fieldType.InnerType.Should().BeNull();
- var anonymousUnion = ffi.GetRecord(fieldType.Name);
+ _ = union.NestedRecords.Should().HaveCount(1);
+ var anonymousUnion = union.NestedRecords[0];
_ = anonymousUnion.IsStruct.Should().BeFalse();
_ = anonymousUnion.IsUnion.Should().BeTrue();
_ = anonymousUnion.SizeOf.Should().Be(4);
@@ -50,7 +51,7 @@ private void UnionExists(CTestFfiCrossPlatform ffi)
var anonymousField1 = anonymousUnion.Fields[0];
_ = anonymousField1.Name.Should().BeEmpty();
_ = anonymousField1.OffsetOf.Should().Be(0);
- _ = anonymousField1.Type.Name.Should().Be(anonymousUnion.Name + "_ANONYMOUS_0");
+ _ = anonymousField1.Type.Name.Should().Be(string.Empty);
_ = anonymousField1.Type.SizeOf.Should().Be(4);
_ = anonymousField1.Type.AlignOf.Should().Be(4);
_ = anonymousField1.Type.IsAnonymous.Should().BeTrue();
@@ -59,13 +60,14 @@ private void UnionExists(CTestFfiCrossPlatform ffi)
var anonymousField2 = anonymousUnion.Fields[1];
_ = anonymousField2.Name.Should().BeEmpty();
_ = anonymousField2.OffsetOf.Should().Be(0);
- _ = anonymousField2.Type.Name.Should().Be(anonymousUnion.Name + "_ANONYMOUS_1");
+ _ = anonymousField2.Type.Name.Should().Be(string.Empty);
_ = anonymousField2.Type.SizeOf.Should().Be(4);
_ = anonymousField2.Type.AlignOf.Should().Be(4);
_ = anonymousField2.Type.IsAnonymous.Should().BeTrue();
_ = anonymousField2.Type.InnerType.Should().BeNull();
- var nestedAnonymousUnion1 = ffi.GetRecord(anonymousField1.Type.Name);
+ _ = anonymousUnion.NestedRecords.Should().HaveCount(2);
+ var nestedAnonymousUnion1 = anonymousUnion.NestedRecords[0];
_ = nestedAnonymousUnion1.IsStruct.Should().BeFalse();
_ = nestedAnonymousUnion1.IsUnion.Should().BeTrue();
_ = nestedAnonymousUnion1.SizeOf.Should().Be(4);
@@ -83,7 +85,7 @@ private void UnionExists(CTestFfiCrossPlatform ffi)
nestedAnonymousUnion1Field2.Type.Should().BeInt();
_ = nestedAnonymousUnion1Field2.OffsetOf.Should().Be(0);
- var nestedAnonymousUnion2 = ffi.GetRecord(anonymousField2.Type.Name);
+ var nestedAnonymousUnion2 = anonymousUnion.NestedRecords[1];
_ = nestedAnonymousUnion2.IsStruct.Should().BeFalse();
_ = nestedAnonymousUnion2.IsUnion.Should().BeTrue();
_ = nestedAnonymousUnion2.SizeOf.Should().Be(4);