Skip to content

Commit

Permalink
Merge pull request #1117 from microsoft/friendlyOverloads
Browse files Browse the repository at this point in the history
Allow disabling of friendly overload generation
  • Loading branch information
AArnott committed Jan 12, 2024
2 parents e0351f9 + 429d881 commit 6d384e2
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 11 deletions.
5 changes: 5 additions & 0 deletions src/Microsoft.Windows.CsWin32/Generator.FriendlyOverloads.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ private enum FriendlyOverloadOf

private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverloads(MethodDefinition methodDefinition, MethodDeclarationSyntax externMethodDeclaration, NameSyntax declaringTypeName, FriendlyOverloadOf overloadOf, HashSet<string> helperMethodsAdded)
{
if (!this.options.FriendlyOverloads.Enabled)
{
yield break;
}

// If/when we ever need helper methods for the friendly overloads again, they can be added when used with code like this:
////if (helperMethodsAdded.Add(SomeHelperMethodName))
////{
Expand Down
17 changes: 17 additions & 0 deletions src/Microsoft.Windows.CsWin32/GeneratorOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public record GeneratorOptions
/// <value>The default value is <see langword="true"/>.</value>
public bool AllowMarshaling { get; init; } = true;

/// <summary>
/// Gets options related to friendly overloads.
/// </summary>
public FriendlyOverloadOptions FriendlyOverloads { get; init; } = new();

/// <summary>
/// Gets a value indicating whether to generate APIs judged to be unnecessary or redundant given the target framework
/// because the project multi-targets to frameworks that need the APIs consistently for easier coding.
Expand Down Expand Up @@ -83,4 +88,16 @@ public record ComInteropOptions
/// </remarks>
public bool UseIntPtrForComOutPointers { get; init; }
}

/// <summary>
/// Options for friendly overloads.
/// </summary>
public record FriendlyOverloadOptions
{
/// <summary>
/// Gets a value indicating whether to generate method overloads that may be easier to consume or be more idiomatic C#.
/// </summary>
/// <value>The default value is <see langword="true" />.</value>
public bool Enabled { get; init; } = true;
}
}
11 changes: 11 additions & 0 deletions src/Microsoft.Windows.CsWin32/settings.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@
"type": "boolean",
"default": true
},
"friendlyOverloads": {
"description": "An object with properties that control generation of friendly overloads.",
"type": "object",
"properties": {
"enabled": {
"description": "A value indicating whether to generate method overloads that may be easier to consume or be more idiomatic C#. These may use fewer pointers, accept or return SafeHandles, etc.",
"type": "boolean",
"default": true
}
}
},
"multiTargetingFriendlyAPIs": {
"description": "A value indicating whether to generate APIs judged to be unnecessary or redundant given the target framework. This is useful for multi-targeting projects that need a consistent set of APIs across target frameworks to avoid too many conditional compilation regions.",
"type": "boolean",
Expand Down
33 changes: 22 additions & 11 deletions test/Microsoft.Windows.CsWin32.Tests/FullGenerationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ public FullGenerationTests(ITestOutputHelper logger)
{
}

[Trait("TestCategory", "FailsInCloudTest")] // these take ~4GB of memory to run.
[Fact]
public void Everything_NoFriendlyOverloads()
{
this.TestHelper(new GeneratorOptions { FriendlyOverloads = new() { Enabled = false } }, Platform.X64, "net7.0", generator => generator.GenerateAll(CancellationToken.None));
}

[Trait("TestCategory", "FailsInCloudTest")] // these take ~4GB of memory to run.
[Theory, PairwiseData]
public void Everything(
Expand All @@ -26,7 +33,7 @@ public FullGenerationTests(ITestOutputHelper logger)
[CombinatorialMemberData(nameof(AnyCpuArchitectures))] Platform platform,
[CombinatorialMemberData(nameof(TFMDataNoNetFx35))] string tfm)
{
this.TestHelper(marshaling, useIntPtrForComOutPtr, platform, tfm, generator => generator.GenerateAll(CancellationToken.None));
this.TestHelper(OptionsForMarshaling(marshaling, useIntPtrForComOutPtr), platform, tfm, generator => generator.GenerateAll(CancellationToken.None));
}

[Trait("TestCategory", "FailsInCloudTest")] // these take ~4GB of memory to run.
Expand All @@ -36,13 +43,13 @@ public FullGenerationTests(ITestOutputHelper logger)
bool useIntPtrForComOutPtr,
[CombinatorialMemberData(nameof(TFMDataNoNetFx35))] string tfm)
{
this.TestHelper(marshaling, useIntPtrForComOutPtr, Platform.X64, tfm, generator => generator.GenerateAllInteropTypes(CancellationToken.None));
this.TestHelper(OptionsForMarshaling(marshaling, useIntPtrForComOutPtr), Platform.X64, tfm, generator => generator.GenerateAllInteropTypes(CancellationToken.None));
}

[Fact]
public void Constants()
{
this.TestHelper(marshaling: MarshalingOptions.FullMarshaling, useIntPtrForComOutPtr: false, Platform.X64, DefaultTFM, generator => generator.GenerateAllConstants(CancellationToken.None));
this.TestHelper(new GeneratorOptions(), Platform.X64, DefaultTFM, generator => generator.GenerateAllConstants(CancellationToken.None));
}

[Theory, PairwiseData]
Expand All @@ -52,23 +59,27 @@ public void Constants()
[CombinatorialMemberData(nameof(SpecificCpuArchitectures))] Platform platform,
[CombinatorialMemberData(nameof(TFMDataNoNetFx35))] string tfm)
{
this.TestHelper(marshaling, useIntPtrForComOutPtr, platform, tfm, generator => generator.GenerateAllExternMethods(CancellationToken.None));
this.TestHelper(OptionsForMarshaling(marshaling, useIntPtrForComOutPtr), platform, tfm, generator => generator.GenerateAllExternMethods(CancellationToken.None));
}

[Fact]
public void Macros()
{
this.TestHelper(marshaling: MarshalingOptions.FullMarshaling, useIntPtrForComOutPtr: false, Platform.X64, DefaultTFM, generator => generator.GenerateAllMacros(CancellationToken.None));
this.TestHelper(new GeneratorOptions(), Platform.X64, DefaultTFM, generator => generator.GenerateAllMacros(CancellationToken.None));
}

private void TestHelper(MarshalingOptions marshaling, bool useIntPtrForComOutPtr, Platform platform, string targetFramework, Action<IGenerator> generationCommands)
private static GeneratorOptions OptionsForMarshaling(MarshalingOptions marshaling, bool useIntPtrForComOutPtr) => new()
{
var generatorOptions = new GeneratorOptions
AllowMarshaling = marshaling >= MarshalingOptions.MarshalingWithoutSafeHandles,
UseSafeHandles = marshaling == MarshalingOptions.FullMarshaling,
ComInterop = new()
{
AllowMarshaling = marshaling >= MarshalingOptions.MarshalingWithoutSafeHandles,
UseSafeHandles = marshaling == MarshalingOptions.FullMarshaling,
ComInterop = new() { UseIntPtrForComOutPointers = useIntPtrForComOutPtr },
};
UseIntPtrForComOutPointers = useIntPtrForComOutPtr,
},
};

private void TestHelper(GeneratorOptions generatorOptions, Platform platform, string targetFramework, Action<IGenerator> generationCommands)
{
this.compilation = this.starterCompilations[targetFramework];
this.compilation = this.compilation.WithOptions(this.compilation.Options.WithPlatform(platform));

Expand Down

0 comments on commit 6d384e2

Please sign in to comment.