From 9b76850889b5a85744bf3baf67dd18c2bda2e524 Mon Sep 17 00:00:00 2001 From: Layomi Akinrinade Date: Mon, 28 Aug 2023 14:14:38 -0700 Subject: [PATCH 1/4] Add comments to binding gen tests for invocations on new lines --- .../ConfigurationBinderTests.Generator.cs | 8 +++- .../Common/ConfigurationExtensionsTests.cs | 47 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs index 16390e054b87c2..0e63867161f42f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs @@ -8,8 +8,14 @@ namespace Microsoft.Extensions.SourceGeneration.Configuration.Binder.Tests { public partial class ConfigurationBinderTests : ConfigurationBinderTestsBase { + /// + /// This is a regression test for https://github.com/dotnet/runtime/issues/90851. + /// It asserts that the configuration binding source generator properly formats + /// binding invocation source locations that the generated interceptors replace. + /// Do not modify these tests if the change reduces coverage for this scenario. + /// [Fact] - public void GeneratorHandlesInvocationsOnNewline() + public void TestBindingInvocationsOnNewLines() { IConfiguration configuration = TestHelpers.GetConfigurationFromJsonString(@"{""Longitude"":1,""Latitude"":2}"); diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/Common/ConfigurationExtensionsTests.cs b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/Common/ConfigurationExtensionsTests.cs index 5396534935027f..74f9ea4fd36a57 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/Common/ConfigurationExtensionsTests.cs +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/Common/ConfigurationExtensionsTests.cs @@ -72,5 +72,52 @@ private static OptionsBuilder CreateOptionsBuilder() var services = new ServiceCollection(); return new OptionsBuilder(services, Options.DefaultName); } + + /// + /// This is a regression test for https://github.com/dotnet/runtime/issues/90851. + /// It asserts that the configuration binding source generator properly formats + /// binding invocation source locations that the generated interceptors replace. + /// Do not modify these tests if the change reduces coverage for this scenario. + /// + [Fact] + public void TestBindingInvocationsOnNewLines() + { + OptionsBuilder? optionsBuilder = CreateOptionsBuilder(); + + // Options builder extensions. + + optionsBuilder + .Bind(s_emptyConfig, configureBinder: null); + + optionsBuilder + .Bind(s_emptyConfig); + + optionsBuilder. + BindConfiguration(configSectionPath: "path", + _ => { }); + + optionsBuilder. + BindConfiguration( + configSectionPath: "path", + _ => { }); + + // Service collection extensions. + + IServiceCollection services = new ServiceCollection(); + + services + .Configure< + FakeOptions>( + name: null!, s_emptyConfig); + + services + .Configure(s_emptyConfig) + .AddOptions(); + + services. + Configure( + name: null, s_emptyConfig, + configureBinder: null); + } } } From 486b5c4baca4993137dd6e2b50f8025f8c84ee0d Mon Sep 17 00:00:00 2001 From: Layomi Akinrinade Date: Mon, 28 Aug 2023 20:04:29 -0700 Subject: [PATCH 2/4] Address feedback & test static method call syntax --- .../ConfigurationBinderTests.Generator.cs | 43 +++++++--- .../Common/ConfigurationExtensionsTests.cs | 49 +---------- .../ConfigurationExtensionsTest.Generator.cs | 83 +++++++++++++++++++ ...onExtensions.SourceGeneration.Tests.csproj | 1 + 4 files changed, 118 insertions(+), 58 deletions(-) create mode 100644 src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/ConfigurationExtensionsTest.Generator.cs diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs index 0e63867161f42f..1800caabd28396 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs @@ -12,22 +12,34 @@ public partial class ConfigurationBinderTests : ConfigurationBinderTestsBase /// This is a regression test for https://github.com/dotnet/runtime/issues/90851. /// It asserts that the configuration binding source generator properly formats /// binding invocation source locations that the generated interceptors replace. - /// Do not modify these tests if the change reduces coverage for this scenario. + /// A location issue that's surfaced is emitting the right location of invocations + /// that are on a different line than the containing binder type or the static + /// extension binder class (e.g. ConfigurationBinder.Bind). /// [Fact] - public void TestBindingInvocationsOnNewLines() + public void TestBindingInvocationsWithIrregularCSharpSyntax() { IConfiguration configuration = TestHelpers.GetConfigurationFromJsonString(@"{""Longitude"":1,""Latitude"":2}"); - GeolocationRecord record = configuration.Get< + // Tests a binding invocation variant that's on a separate line from source configuration. + + GeolocationRecord record = (GeolocationRecord)configuration + .Get(typeof(GeolocationRecord), _ => { }); + + Verify(); + + // Tests generic binding invocation variants with irregular C# syntax, interspersed with white space. + + record = configuration.Get< GeolocationRecord >(); - Verify(); - record = (GeolocationRecord)configuration - .Get(typeof(GeolocationRecord), _ => { }); + record = configuration.Get + (); Verify(); + // Tests binding invocation variants that are on a separate line from source configuration. + TestHelpers .GetConfigurationFromJsonString(@"{""Longitude"":3,""Latitude"":4}") .Bind(record); @@ -37,10 +49,6 @@ record = (GeolocationRecord)configuration .GetValue("Latitude"); Assert.Equal(2, lat); - record = configuration.Get - (); - Verify(); - record = (GeolocationRecord)configuration .Get( typeof(GeolocationRecord), _ => @@ -82,6 +90,21 @@ record = (GeolocationRecord) .Get(typeof(GeolocationRecord), _ => { }); Verify(); + // Tests binding invocation variants with static method call syntax, interspaced with whitespace. + ConfigurationBinder + .Bind(configuration, record); + Verify(); + + ConfigurationBinder.Bind( + configuration, record); + Verify(); + + ConfigurationBinder. + Bind(configuration + , record) + ; + Verify(); + void Verify(int longitude = 1, int latitude = 2) { Assert.Equal(longitude, record.Longitude); diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/Common/ConfigurationExtensionsTests.cs b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/Common/ConfigurationExtensionsTests.cs index 74f9ea4fd36a57..8c76472a2c339b 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/Common/ConfigurationExtensionsTests.cs +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/Common/ConfigurationExtensionsTests.cs @@ -8,7 +8,7 @@ namespace Microsoft.Extensions.Options.ConfigurationExtensions.Tests { - public class ConfigurationExtensionsTests + public partial class ConfigurationExtensionsTests { private static IConfiguration s_emptyConfig { get; } = new ConfigurationBuilder().Build(); @@ -72,52 +72,5 @@ private static OptionsBuilder CreateOptionsBuilder() var services = new ServiceCollection(); return new OptionsBuilder(services, Options.DefaultName); } - - /// - /// This is a regression test for https://github.com/dotnet/runtime/issues/90851. - /// It asserts that the configuration binding source generator properly formats - /// binding invocation source locations that the generated interceptors replace. - /// Do not modify these tests if the change reduces coverage for this scenario. - /// - [Fact] - public void TestBindingInvocationsOnNewLines() - { - OptionsBuilder? optionsBuilder = CreateOptionsBuilder(); - - // Options builder extensions. - - optionsBuilder - .Bind(s_emptyConfig, configureBinder: null); - - optionsBuilder - .Bind(s_emptyConfig); - - optionsBuilder. - BindConfiguration(configSectionPath: "path", - _ => { }); - - optionsBuilder. - BindConfiguration( - configSectionPath: "path", - _ => { }); - - // Service collection extensions. - - IServiceCollection services = new ServiceCollection(); - - services - .Configure< - FakeOptions>( - name: null!, s_emptyConfig); - - services - .Configure(s_emptyConfig) - .AddOptions(); - - services. - Configure( - name: null, s_emptyConfig, - configureBinder: null); - } } } diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/ConfigurationExtensionsTest.Generator.cs b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/ConfigurationExtensionsTest.Generator.cs new file mode 100644 index 00000000000000..12934d609ee8a5 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/ConfigurationExtensionsTest.Generator.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.Extensions.Options.ConfigurationExtensions.Tests +{ + public partial class ConfigurationExtensionsTests + { + /// + /// This is a regression test for https://github.com/dotnet/runtime/issues/90851. + /// It asserts that the configuration binding source generator properly formats + /// binding invocation source locations that the generated interceptors replace. + /// A location issue that's surfaced is emitting the right location of invocations + /// that are on a different line than the containing binder type or the static + /// extension binder class (e.g. ConfigurationBinder.Bind). + /// + [Fact] + public void TestBindingInvocationsWithIrregularCSharpSyntax() + { + // Tests binding invocation variants with irregular C# syntax, interspersed with white space. + + // Options builder extensions. + + OptionsBuilder? optionsBuilder = CreateOptionsBuilder(); + + optionsBuilder + .Bind(s_emptyConfig, configureBinder: null); + + optionsBuilder + .Bind(s_emptyConfig); + + optionsBuilder. + BindConfiguration(configSectionPath: "path", + _ => { }); + + optionsBuilder. + BindConfiguration( + configSectionPath: "path", + _ => { }); + + // Service collection extensions. + + IServiceCollection services = new ServiceCollection(); + + services + .Configure< + FakeOptions>( + name: null!, s_emptyConfig); + + services + .Configure(s_emptyConfig) + .AddOptions(); + + services. + Configure( + name: null, s_emptyConfig, + configureBinder: null); + + // Test extensions class syntax. + + OptionsBuilderConfigurationExtensions + .Bind(optionsBuilder, s_emptyConfig); + + OptionsBuilderConfigurationExtensions. + BindConfiguration(optionsBuilder, + "path"); + + OptionsConfigurationServiceCollectionExtensions + .Configure + (services, + s_emptyConfig); + + OptionsConfigurationServiceCollectionExtensions + .Configure( + services, s_emptyConfig + ); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/Microsoft.Extensions.Options.ConfigurationExtensions.SourceGeneration.Tests.csproj b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/Microsoft.Extensions.Options.ConfigurationExtensions.SourceGeneration.Tests.csproj index a0f0f094cb35d2..f08d2bd649bc3f 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/Microsoft.Extensions.Options.ConfigurationExtensions.SourceGeneration.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/Microsoft.Extensions.Options.ConfigurationExtensions.SourceGeneration.Tests.csproj @@ -25,6 +25,7 @@ + From dc3f0b2e6b1a04e275295d939e7790a270cbf4b8 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 29 Aug 2023 17:55:01 -0700 Subject: [PATCH 3/4] Reorganize and comment the newline/whitespace scenarios --- .../ConfigurationBinderTests.Generator.cs | 278 +++++++++++++----- 1 file changed, 208 insertions(+), 70 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs index 1800caabd28396..0e4a97b85b548a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBinderTests.Generator.cs @@ -8,108 +8,246 @@ namespace Microsoft.Extensions.SourceGeneration.Configuration.Binder.Tests { public partial class ConfigurationBinderTests : ConfigurationBinderTestsBase { - /// - /// This is a regression test for https://github.com/dotnet/runtime/issues/90851. - /// It asserts that the configuration binding source generator properly formats - /// binding invocation source locations that the generated interceptors replace. - /// A location issue that's surfaced is emitting the right location of invocations - /// that are on a different line than the containing binder type or the static - /// extension binder class (e.g. ConfigurationBinder.Bind). - /// + // These are regression tests for https://github.com/dotnet/runtime/issues/90851 + // Source Generator Interceptors rely on identifying an accurate invocation + // source location (line and character positions). These tests cover newline + // and whitespace scenarios to ensure the interceptors get wired up correctly. + [Fact] - public void TestBindingInvocationsWithIrregularCSharpSyntax() + public void TestBindingInvocationsWithNewlines_GetMethodTypeArg() { IConfiguration configuration = TestHelpers.GetConfigurationFromJsonString(@"{""Longitude"":1,""Latitude"":2}"); - // Tests a binding invocation variant that's on a separate line from source configuration. + // Newline between the configuration instance and the binding invocation (with the dot on the first line) + GeolocationRecord record1 = (GeolocationRecord)configuration. + Get(typeof(GeolocationRecord), _ => { }); + + AssertRecordIsBound(record1, 1, 2); - GeolocationRecord record = (GeolocationRecord)configuration + // Newline between the configuration instance and the binding invocation (with the dot on the second line) + GeolocationRecord record2 = (GeolocationRecord)configuration .Get(typeof(GeolocationRecord), _ => { }); - Verify(); + AssertRecordIsBound(record2, 1, 2); + + // Newlines between the instance, the invocation, and the arguments + GeolocationRecord record3 = (GeolocationRecord)configuration + .Get( + typeof(GeolocationRecord), + _ => { } + ); + + AssertRecordIsBound(record3, 1, 2); + + // Newlines before and after the instance (with the dot on the first line) + GeolocationRecord record4 = (GeolocationRecord) + configuration. + Get(typeof(GeolocationRecord), _ => { }); + + AssertRecordIsBound(record4, 1, 2); - // Tests generic binding invocation variants with irregular C# syntax, interspersed with white space. + // Newlines before and after the instance (with the dot on the second line) + GeolocationRecord record5 = (GeolocationRecord) + configuration + .Get(typeof(GeolocationRecord), _ => { }); + + AssertRecordIsBound(record5, 1, 2); + + // Newlines in every place possible + GeolocationRecord + record6 + = + ( + GeolocationRecord + ) + configuration + . + Get + ( + typeof + ( + GeolocationRecord + ) + , + _ + => + { + } + ) + ; + + AssertRecordIsBound(record6, 1, 2); + } + + [Fact] + public void TestBindingInvocationsWithNewlines_GetMethodGeneric() + { + IConfiguration configuration = TestHelpers.GetConfigurationFromJsonString(@"{""Longitude"":1,""Latitude"":2}"); - record = configuration.Get< + // Newline between the invocation method name and the generic type argument + GeolocationRecord record1 = configuration.Get + (); + + AssertRecordIsBound(record1, 1, 2); + + // Newlines on either side of the generic type argument + GeolocationRecord record2 = configuration.Get< GeolocationRecord >(); - record = configuration.Get - (); - Verify(); + AssertRecordIsBound(record2, 1, 2); - // Tests binding invocation variants that are on a separate line from source configuration. + // Newlines in every place possible + GeolocationRecord + record3 + = + configuration + . + Get + < + GeolocationRecord + > + () + ; - TestHelpers - .GetConfigurationFromJsonString(@"{""Longitude"":3,""Latitude"":4}") - .Bind(record); - Verify(3, 4); + AssertRecordIsBound(record3, 1, 2); + } - int lat = configuration - .GetValue("Latitude"); - Assert.Equal(2, lat); + [Fact] + public void TestBindingInvocationsWithNewlines_BindExtensionMethod() + { + // Newline between the configuration instance and the extension method invocation + GeolocationRecord record1 = new GeolocationRecord(); + TestHelpers.GetConfigurationFromJsonString(@"{""Longitude"":1,""Latitude"":2}") + .Bind(record1); - record = (GeolocationRecord)configuration - .Get( - typeof(GeolocationRecord), _ => - { }); - Verify(); + AssertRecordIsBound(record1, 1, 2); + // Newlines between the method that returns the instance and the extension method invocation + GeolocationRecord record2 = new GeolocationRecord(); TestHelpers - .GetConfigurationFromJsonString(@"{""Longitude"":3, -""Latitude"":4} -") + .GetConfigurationFromJsonString(@"{""Longitude"":1,""Latitude"":2}") + .Bind(record2); + + AssertRecordIsBound(record2, 1, 2); + + // Newlines within the argument to the method returning the configuration and around the extension method argument + GeolocationRecord record3 = new GeolocationRecord(); + TestHelpers + .GetConfigurationFromJsonString(@"{""Longitude"":1, + ""Latitude"":2} + ") .Bind( - record + record3 ); - Verify(3, 4); - long latLong = configuration - .GetValue< -#if DEBUG - int -#else - long -#endif - > - ("Latitude") + AssertRecordIsBound(record3, 1, 2); + + // Newlines in every place possible + GeolocationRecord record4 = new GeolocationRecord(); + TestHelpers + . + GetConfigurationFromJsonString + ( + @"{""Longitude"":1, ""Latitude"":2}" + ) + . + Bind + ( + record4 + ) ; - Assert.Equal(2, lat); - record = (GeolocationRecord)configuration. - Get(typeof(GeolocationRecord), _ => { }); - Verify(); + AssertRecordIsBound(record4, 1, 2); + } - record = (GeolocationRecord) - configuration. - Get(typeof(GeolocationRecord), _ => { }); - Verify(); + [Fact] + public void TestBindingInvocationsWithNewlines_BindStaticMethod() + { + IConfiguration configuration = TestHelpers.GetConfigurationFromJsonString(@"{""Longitude"":1,""Latitude"":2}"); - record = (GeolocationRecord) - configuration - .Get(typeof(GeolocationRecord), _ => { }); - Verify(); + // Newline between the class and the static method invocation (with the dot on the first line) + GeolocationRecord record1 = new GeolocationRecord(); + ConfigurationBinder. + Bind(configuration, record1); - // Tests binding invocation variants with static method call syntax, interspaced with whitespace. + // Newline between the class and the static method invocation (with the dot on the second line) + GeolocationRecord record2 = new GeolocationRecord(); ConfigurationBinder - .Bind(configuration, record); - Verify(); + .Bind(configuration, record2); + AssertRecordIsBound(record2, 1, 2); + + // Newline before the arguments + GeolocationRecord record3 = new GeolocationRecord(); ConfigurationBinder.Bind( - configuration, record); - Verify(); + configuration, record3); - ConfigurationBinder. - Bind(configuration - , record) + AssertRecordIsBound(record3, 1, 2); + + // Newlines in every place possible + GeolocationRecord record4 = new GeolocationRecord(); + ConfigurationBinder + . + Bind + ( + configuration + , + record4 + ) ; - Verify(); - void Verify(int longitude = 1, int latitude = 2) - { - Assert.Equal(longitude, record.Longitude); - Assert.Equal(latitude, record.Latitude); - } + AssertRecordIsBound(record4, 1, 2); + } + + [Fact] + public void TestBindingInvocationsWithNewlines_GetValueMethod() + { + IConfiguration configuration = TestHelpers.GetConfigurationFromJsonString(@"{""Longitude"":1,""Latitude"":2}"); + + // Newline between the configuration instance and the binding invocation (with the dot on the first line) + int lat1 = configuration. + GetValue("Latitude"); + + Assert.Equal(2, lat1); + + // Newline between the configuration instance and the binding invocation (with the dot on the second line) + int lat2 = configuration + .GetValue("Latitude"); + + Assert.Equal(2, lat2); + + // Newlines in every place possible + long + lat3 + = + configuration + . + GetValue + < + int + > + ( + "Latitude" + ) + ; + Assert.Equal(2, lat3); + + // Newlines and pragmas wrapped around the generic type argument + long lat4 = configuration.GetValue< +#if DEBUG + int +#else + long +#endif + >("Latitude"); + + Assert.Equal(2, lat4); + } + + private static void AssertRecordIsBound(GeolocationRecord record, int longitude, int latitude) + { + Assert.Equal((longitude, latitude), (record.Longitude, record.Latitude)); } } } From 5eccfa62f9c7bcf98977e9e4f7e82e0fe6a6a26a Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 29 Aug 2023 18:26:05 -0700 Subject: [PATCH 4/4] Reorganize and comment the newline/whitespace scenarios for ConfigurationExtensions --- .../ConfigurationExtensionsTest.Generator.cs | 153 +++++++++++++----- 1 file changed, 115 insertions(+), 38 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/ConfigurationExtensionsTest.Generator.cs b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/ConfigurationExtensionsTest.Generator.cs index 12934d609ee8a5..a18efc6909b71d 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/ConfigurationExtensionsTest.Generator.cs +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/tests/SourceGenerationTests/ConfigurationExtensionsTest.Generator.cs @@ -9,75 +9,152 @@ namespace Microsoft.Extensions.Options.ConfigurationExtensions.Tests { public partial class ConfigurationExtensionsTests { - /// - /// This is a regression test for https://github.com/dotnet/runtime/issues/90851. - /// It asserts that the configuration binding source generator properly formats - /// binding invocation source locations that the generated interceptors replace. - /// A location issue that's surfaced is emitting the right location of invocations - /// that are on a different line than the containing binder type or the static - /// extension binder class (e.g. ConfigurationBinder.Bind). - /// + // These are regression tests for https://github.com/dotnet/runtime/issues/90851 + // Source Generator Interceptors rely on identifying an accurate invocation + // source location (line and character positions). These tests cover newline + // and whitespace scenarios to ensure the interceptors get wired up correctly. + [Fact] - public void TestBindingInvocationsWithIrregularCSharpSyntax() + public void TestBindingInvocationsWithNewlines_BindExtension() { - // Tests binding invocation variants with irregular C# syntax, interspersed with white space. - - // Options builder extensions. - OptionsBuilder? optionsBuilder = CreateOptionsBuilder(); + // Newline between instance and invocation using configureBinder argument (with the dot on the first line) + optionsBuilder. + Bind(s_emptyConfig, configureBinder: null); + + // Newline between instance and invocation using configureBinder argument (with the dot on the second line) optionsBuilder .Bind(s_emptyConfig, configureBinder: null); + // Newline between instance and invocation (with the dot on the first line) + optionsBuilder. + Bind(s_emptyConfig); + + // Newline between instance and invocation (with the dot on the second line) optionsBuilder .Bind(s_emptyConfig); + // Newlines in every place possible + optionsBuilder + . + Bind + ( + s_emptyConfig + , + configureBinder + : + null + ) + ; + } + + [Fact] + public void TestBindingInvocationsWithNewlines_BindConfigurationExtension() + { + OptionsBuilder? optionsBuilder = CreateOptionsBuilder(); + + // Newline between instance and invocation using configureBinder argument (with the dot on the first line) optionsBuilder. BindConfiguration(configSectionPath: "path", _ => { }); + // Newline between instance and invocation using configureBinder argument (with the dot on the second line) + optionsBuilder + .BindConfiguration(configSectionPath: "path", + _ => { }); + + // Newlines between the instance and invocation and within the arguments. No indentation before invocation. optionsBuilder. BindConfiguration( configSectionPath: "path", _ => { }); - // Service collection extensions. + // Newlines in every place possible + optionsBuilder + . + BindConfiguration + ( + configSectionPath + : + "path" + , + _ + => + { + } + ) + ; + } + [Fact] + public void TestBindingInvocationsWithNewlines_ConfigureExtension() + { + OptionsBuilder? optionsBuilder = CreateOptionsBuilder(); IServiceCollection services = new ServiceCollection(); - services - .Configure< - FakeOptions>( - name: null!, s_emptyConfig); - + // Newlines between each method call services .Configure(s_emptyConfig) .AddOptions(); - services. - Configure( - name: null, s_emptyConfig, - configureBinder: null); + // Newlines in every place possible + services + . + Configure + < + FakeOptions + > + ( + name + : + null! + , + s_emptyConfig + ) + ; + } - // Test extensions class syntax. + [Fact] + public void TestBindingInvocationsWithNewlines_StaticCalls() + { + OptionsBuilder? optionsBuilder = CreateOptionsBuilder(); + IServiceCollection services = new ServiceCollection(); + // Bind: Newlines in every place possible OptionsBuilderConfigurationExtensions - .Bind(optionsBuilder, s_emptyConfig); - - OptionsBuilderConfigurationExtensions. - BindConfiguration(optionsBuilder, - "path"); - - OptionsConfigurationServiceCollectionExtensions - .Configure - (services, - s_emptyConfig); + . + Bind + ( + optionsBuilder + , + s_emptyConfig + ) + ; + + // // BindConfiguration: Newlines in every place possible + OptionsBuilderConfigurationExtensions + . + BindConfiguration + ( + optionsBuilder + , + "path" + ); + // Configure: Newlines in every place possible OptionsConfigurationServiceCollectionExtensions - .Configure( - services, s_emptyConfig - ); + . + Configure + < + FakeOptions + > + ( + services + , + s_emptyConfig + ) + ; } } }