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);