diff --git a/Buildenator/Buildenator.csproj b/Buildenator/Buildenator.csproj index 7152b0a..5cc7b8c 100644 --- a/Buildenator/Buildenator.csproj +++ b/Buildenator/Buildenator.csproj @@ -9,7 +9,7 @@ false true - 10.8.1.0 + 10.8.2.0 diff --git a/Buildenator/CodeAnalysis/TypedSymbol.cs b/Buildenator/CodeAnalysis/TypedSymbol.cs index 900bc7b..e1f179a 100644 --- a/Buildenator/CodeAnalysis/TypedSymbol.cs +++ b/Buildenator/CodeAnalysis/TypedSymbol.cs @@ -174,7 +174,7 @@ public string GenerateLazyFieldValueReturn() + (_nullableStrategy == NullableStrategy.Enabled ? "!" : "") : GetDefaultValueName() is { } defaultValueName ? defaultValueName - : $"default({TypeFullName})")})).Object"; + : $"default({TypeFullName})" + (_nullableStrategy == NullableStrategy.Enabled ? "!" : ""))})).Object"; public string GenerateFieldValueReturn() => IsMockable() diff --git a/Buildenator/Configuration/EntityToBuild.cs b/Buildenator/Configuration/EntityToBuild.cs index 8dffdb5..52aaa03 100644 --- a/Buildenator/Configuration/EntityToBuild.cs +++ b/Buildenator/Configuration/EntityToBuild.cs @@ -68,19 +68,12 @@ public string GenerateBuildsCode(bool shouldGenerateMethodsForUnreachablePropert if (ConstructorToBuild is null) return ""; - var disableWarning = NullableStrategy == NullableStrategy.Enabled - ? "#pragma warning disable CS8604\n" - : string.Empty; - var restoreWarning = NullableStrategy == NullableStrategy.Enabled - ? "#pragma warning restore CS8604\n" - : string.Empty; - - return $@"{disableWarning} public {FullName} {DefaultConstants.BuildMethodName}() + return $@" public {FullName} {DefaultConstants.BuildMethodName}() {{ {DefaultConstants.PreBuildMethodName}(); {GenerateLazyBuildEntityString(shouldGenerateMethodsForUnreachableProperties, ConstructorToBuild.Parameters)} }} -{restoreWarning} + "; } @@ -151,26 +144,21 @@ public string GenerateDefaultBuildsCode() .Aggregate(new StringBuilder(), (builder, s) => builder.AppendLine(s)) .ToString(); + var nullForgiving = NullableStrategy == NullableStrategy.Enabled ? "!" : string.Empty; var methodParameters = ConstructorToBuild.Parameters .Concat(_properties) .Select(s => { var fieldType = s.GenerateFieldType(); - return $"{fieldType} {s.UnderScoreName} = default({fieldType})"; + return $"{fieldType} {s.UnderScoreName} = default({fieldType}){nullForgiving}"; }).ComaJoin(); - var disableWarning = NullableStrategy == NullableStrategy.Enabled - ? "#pragma warning disable CS8625\n" - : string.Empty; - var restoreWarning = NullableStrategy == NullableStrategy.Enabled - ? "#pragma warning restore CS8625\n" - : string.Empty; - - return $@"{disableWarning} public static {FullName} BuildDefault({methodParameters}) + + return $@" public static {FullName} BuildDefault({methodParameters}) {{ {moqInit} {GenerateDefaultBuildEntityString(ConstructorToBuild.Parameters)} }} -{restoreWarning}"; +"; } private string GenerateDefaultBuildEntityString(IEnumerable parameters) diff --git a/CHANGELOG.md b/CHANGELOG.md index b82a19c..abf45a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 10.8.2.0 - 2026-8-31 + +### Fixed +- **CS8625/CS8604 nullable warnings in generated `Build()`/`BuildDefault()`**: Non-nullable reference properties without a fixture, mock, or `Default{PropertyName}` value fell back to `default(T)` in the generated code, which the compiler flags as a null-to-non-nullable-type conversion. `Build()` suppressed the resulting CS8604 with a pragma but never suppressed the underlying CS8625, so consumers with `WarningsAsErrors=nullable` (or similarly strict nullable settings) could hit a hard build error instead of a warning. The `default(T)` fallback now uses the null-forgiving operator (`!`) directly, the same pattern already used for the AutoFixture branch, instead of pragma-suppressing the whole method body. Both `Build()` and `BuildDefault()` are now generated warning-free with no pragmas needed. + ## 10.8.1.0 - 2026-4-12 ### Fixed diff --git a/Tests/Buildenator.IntegrationTests.SourceWithoutAssemblyInfo/Buildenator.IntegrationTests.SourceWithoutAssemblyInfo.csproj b/Tests/Buildenator.IntegrationTests.SourceWithoutAssemblyInfo/Buildenator.IntegrationTests.SourceWithoutAssemblyInfo.csproj index c4f96f8..433ec24 100644 --- a/Tests/Buildenator.IntegrationTests.SourceWithoutAssemblyInfo/Buildenator.IntegrationTests.SourceWithoutAssemblyInfo.csproj +++ b/Tests/Buildenator.IntegrationTests.SourceWithoutAssemblyInfo/Buildenator.IntegrationTests.SourceWithoutAssemblyInfo.csproj @@ -3,6 +3,7 @@ net10.0 false + enable diff --git a/Tests/Buildenator.IntegrationTests/BuildersGeneratorMandatoryParametersTests.cs b/Tests/Buildenator.IntegrationTests/BuildersGeneratorMandatoryParametersTests.cs index 56a768f..dc13915 100644 --- a/Tests/Buildenator.IntegrationTests/BuildersGeneratorMandatoryParametersTests.cs +++ b/Tests/Buildenator.IntegrationTests/BuildersGeneratorMandatoryParametersTests.cs @@ -51,4 +51,14 @@ public void BuildersGenerator_MandatoryParameters_NoStaticFactoryPropertyGenerat staticProperty.Should().BeNull("static factory property is incompatible with mandatory constructor parameters"); } + + [Fact] + public void BuildersGenerator_MandatoryParameters_BuildDefaultUsesDefaultValues() + { + var result = EntityWithMandatoryConstructorParametersBuilder.BuildDefault(); + + result.LineNumber.Should().Be(0); + result.Activity.Should().BeNull(); + result.Tags.Should().BeNull(); + } }