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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,14 @@ private string GetRemappedTypeName(Cursor? cursor, Cursor? context, Type type, o

WithType(enumDecl, ref remappedName, ref nativeTypeName);
}
else if (cursor is FieldDecl fieldDecl)
{
// A field can have its emitted type overridden via `--with-type Struct.field=Type`.
// The `*` catch-all is intentionally not honored here, as rewriting every field to
// a single type is meaningless; the qualified `Struct.field` key must be explicit.

WithType(fieldDecl, ref remappedName, ref nativeTypeName, matchStar: false);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2399,9 +2399,9 @@ private void WithTestAssertTrue(string actual)
}
}

private void WithType(NamedDecl namedDecl, ref string integerTypeName, ref string nativeTypeName)
private void WithType(NamedDecl namedDecl, ref string integerTypeName, ref string nativeTypeName, bool matchStar = true)
{
if (TryGetRemappedValue(namedDecl, _config._withTypes, out var type, matchStar: true))
if (TryGetRemappedValue(namedDecl, _config._withTypes, out var type, matchStar))
{
if (string.IsNullOrWhiteSpace(nativeTypeName))
{
Expand Down
2 changes: 1 addition & 1 deletion sources/ClangSharpPInvokeGenerator/Program.Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ internal static partial class Program
private static readonly CommandLineOption s_withSetLastErrors = Multi(s_withSetLastErrorOptionAliases, "Add the SetLastError=true modifier or SetsSystemLastError attribute to a given DllImport or UnmanagedFunctionPointer. Supports wildcards.");
private static readonly CommandLineOption s_withSuppressGCTransitions = Multi(s_withSuppressGCTransitionOptionAliases, "Add the SuppressGCTransition calling convention to a given DllImport or UnmanagedFunctionPointer. Supports wildcards.");
private static readonly CommandLineOption s_withTransparentStructNameValuePairs = Multi(s_withTransparentStructOptionAliases, "A remapped type name to be treated as a transparent wrapper during binding generation. Supports wildcards.");
private static readonly CommandLineOption s_withTypeNameValuePairs = Multi(s_withTypeOptionAliases, "A type to be used for the given enum declaration during binding generation. Supports wildcards.");
private static readonly CommandLineOption s_withTypeNameValuePairs = Multi(s_withTypeOptionAliases, "A type to be used for the given enum declaration, macro constant, or struct field (using the qualified `Type.field`) during binding generation. Supports wildcards.");
private static readonly CommandLineOption s_withUsingNameValuePairs = Multi(s_withUsingOptionAliases, "A using directive to be included for the given remapped declaration name during binding generation. Supports wildcards.");
private static readonly CommandLineOption s_helpOption = Flag(s_helpOptionAliases, "Show help and usage information");

Expand Down
47 changes: 47 additions & 0 deletions tests/ClangSharp.PInvokeGenerator.UnitTests/WithTypeFieldTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.

using System.Collections.Generic;
using System.Threading.Tasks;
using NUnit.Framework;

namespace ClangSharp.UnitTests;

/// <summary>
/// Regression tests for https://github.com/dotnet/ClangSharp/issues/559.
/// The <c>--with-type</c> option is extended to accept a field-qualified key (<c>Struct.field=Type</c>)
/// so the emitted type of an individual struct field can be overridden. The original Clang type is
/// preserved as a <c>[NativeTypeName]</c> attribute and unrelated fields are left untouched.
/// </summary>
[Platform("win")]
public sealed class WithTypeFieldTest : PInvokeGeneratorTest
{
[Test]
public Task OverridesFieldType()
{
var inputContents = @"struct Something
{
int type;
int other;
};
";

var expectedOutputContents = @"namespace ClangSharp.Test
{
public partial struct Something
{
[NativeTypeName(""int"")]
public SomethingType type;

public int other;
}
}
";

var withTypes = new Dictionary<string, string>
{
["Something.type"] = "SomethingType",
};

return ValidateGeneratedCSharpLatestWindowsBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes);
}
}
Loading