diff --git a/src/Microsoft.Windows.CsWin32/Generator.FriendlyOverloads.cs b/src/Microsoft.Windows.CsWin32/Generator.FriendlyOverloads.cs index d2e2c5dd..ed9c86c5 100644 --- a/src/Microsoft.Windows.CsWin32/Generator.FriendlyOverloads.cs +++ b/src/Microsoft.Windows.CsWin32/Generator.FriendlyOverloads.cs @@ -14,6 +14,11 @@ private enum FriendlyOverloadOf private IEnumerable DeclareFriendlyOverloads(MethodDefinition methodDefinition, MethodDeclarationSyntax externMethodDeclaration, NameSyntax declaringTypeName, FriendlyOverloadOf overloadOf, HashSet 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)) ////{ diff --git a/src/Microsoft.Windows.CsWin32/GeneratorOptions.cs b/src/Microsoft.Windows.CsWin32/GeneratorOptions.cs index 67ed23fb..a060e415 100644 --- a/src/Microsoft.Windows.CsWin32/GeneratorOptions.cs +++ b/src/Microsoft.Windows.CsWin32/GeneratorOptions.cs @@ -41,6 +41,11 @@ public record GeneratorOptions /// The default value is . public bool AllowMarshaling { get; init; } = true; + /// + /// Gets options related to friendly overloads. + /// + public FriendlyOverloadOptions FriendlyOverloads { get; init; } = new(); + /// /// 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. @@ -83,4 +88,16 @@ public record ComInteropOptions /// public bool UseIntPtrForComOutPointers { get; init; } } + + /// + /// Options for friendly overloads. + /// + public record FriendlyOverloadOptions + { + /// + /// Gets a value indicating whether to generate method overloads that may be easier to consume or be more idiomatic C#. + /// + /// The default value is . + public bool Enabled { get; init; } = true; + } } diff --git a/src/Microsoft.Windows.CsWin32/settings.schema.json b/src/Microsoft.Windows.CsWin32/settings.schema.json index cca80f53..8ef51b15 100644 --- a/src/Microsoft.Windows.CsWin32/settings.schema.json +++ b/src/Microsoft.Windows.CsWin32/settings.schema.json @@ -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", diff --git a/test/Microsoft.Windows.CsWin32.Tests/FullGenerationTests.cs b/test/Microsoft.Windows.CsWin32.Tests/FullGenerationTests.cs index 1c7ea47b..d1a0cc71 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/FullGenerationTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/FullGenerationTests.cs @@ -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( @@ -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. @@ -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] @@ -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 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 generationCommands) + { this.compilation = this.starterCompilations[targetFramework]; this.compilation = this.compilation.WithOptions(this.compilation.Options.WithPlatform(platform));