diff --git a/Build.ps1 b/Build.ps1 index 449c3b11d42..c86c91c13ec 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -19,10 +19,14 @@ function BuildWith([string]$configuration) exec { & dotnet build src/Vogen/Vogen.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.4 --verbosity $verbosity} exec { & dotnet build src/Vogen/Vogen.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.6 --verbosity $verbosity} exec { & dotnet build src/Vogen/Vogen.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.8 --verbosity $verbosity} + exec { & dotnet build src/Vogen/Vogen.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.11 --verbosity $verbosity} + exec { & dotnet build src/Vogen/Vogen.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.12 --verbosity $verbosity} exec { & dotnet build src/Vogen.CodeFixers/Vogen.CodeFixers.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.4 --verbosity $verbosity} exec { & dotnet build src/Vogen.CodeFixers/Vogen.CodeFixers.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.6 --verbosity $verbosity} exec { & dotnet build src/Vogen.CodeFixers/Vogen.CodeFixers.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.8 --verbosity $verbosity} + exec { & dotnet build src/Vogen.CodeFixers/Vogen.CodeFixers.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.11 --verbosity $verbosity} + exec { & dotnet build src/Vogen.CodeFixers/Vogen.CodeFixers.csproj -c $configuration -p Thorough=true -p RoslynVersion=roslyn4.12 --verbosity $verbosity} } function Get999VersionWithUniquePatch() @@ -157,4 +161,3 @@ WriteStage("Finally, packing the release version into " + $artifacts) exec { & dotnet pack src/Vogen.Pack/Vogen.Pack.csproj -c Release -o $artifacts --no-build --verbosity $verbosity } WriteStage("Done! Package generated at " + $artifacts) - diff --git a/Directory.Build.targets b/Directory.Build.targets index 2bd5e625ec2..d689dd99905 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -13,12 +13,15 @@ - + + + + + - @@ -32,7 +35,6 @@ - @@ -46,7 +48,6 @@ - @@ -58,9 +59,8 @@ - + - @@ -70,6 +70,19 @@ $(DefineConstants);CSHARP9_OR_GREATER;CSHARP10_OR_GREATER;CSHARP11_OR_GREATER;CSHARP12_OR_GREATER;CSHARP13_OR_GREATER $(NoWarn);CS0618 + + + + + + + + + + $(DefineConstants);ROSLYN4_12;ROSLYN_4_2_OR_GREATER;ROSLYN_4_4_OR_GREATER;ROSLYN_4_5_OR_GREATER;ROSLYN_4_6_OR_GREATER;ROSLYN_4_8_OR_GREATER;ROSLYN_4_10_OR_GREATER;ROSLYN_4_12_OR_GREATER + $(DefineConstants);CSHARP9_OR_GREATER;CSHARP10_OR_GREATER;CSHARP11_OR_GREATER;CSHARP12_OR_GREATER;CSHARP13_OR_GREATER + $(NoWarn);CS0618 + diff --git a/src/Vogen.Pack/Vogen.Pack.csproj b/src/Vogen.Pack/Vogen.Pack.csproj index 7158a532fb4..8ca6f3a84d2 100644 --- a/src/Vogen.Pack/Vogen.Pack.csproj +++ b/src/Vogen.Pack/Vogen.Pack.csproj @@ -58,12 +58,17 @@ - + + - - - - + + + + + + + + diff --git a/src/Vogen/BuildWorkItems.cs b/src/Vogen/BuildWorkItems.cs index e8504a452d4..7a501afe0ec 100644 --- a/src/Vogen/BuildWorkItems.cs +++ b/src/Vogen/BuildWorkItems.cs @@ -96,6 +96,9 @@ internal static class BuildWorkItems UserProvidedOverloads userProvidedOverloads = DiscoverUserProvidedOverloads.Discover(voSymbolInformation, underlyingType); + UserProvidedPartials userProvidedPartials = + DiscoverUserProvidedPartials.Discover(voSymbolInformation, underlyingType); + ThrowIfAnyToStringOverrideOnRecordIsUnsealed(target, context, userProvidedOverloads.ToStringOverloads); MethodDeclarationSyntax? validateMethod = null; @@ -150,6 +153,7 @@ RecordDeclarationSyntax rds when rds.IsKind(SyntaxKind.RecordStructDeclaration) Config = config, UserProvidedOverloads = userProvidedOverloads, + UserProvidedPartials = userProvidedPartials, UnderlyingType = underlyingType, ValidateMethod = validateMethod, diff --git a/src/Vogen/DiscoverUserProvidedPartials.cs b/src/Vogen/DiscoverUserProvidedPartials.cs new file mode 100644 index 00000000000..e96e0b24f2e --- /dev/null +++ b/src/Vogen/DiscoverUserProvidedPartials.cs @@ -0,0 +1,47 @@ +using Microsoft.CodeAnalysis; +using System.Linq; + +namespace Vogen; + +internal class DiscoverUserProvidedPartials +{ + public static UserProvidedPartials Discover(INamedTypeSymbol vo, INamedTypeSymbol underlyingType) => + new() + { + PartialValue = TryGetPartialProperty(vo, "Value"), + PartialFrom = TryGetPartialMethod(vo, "From", [underlyingType]), + PartialBoolTryFrom = TryGetPartialMethod(vo, "TryFrom", [underlyingType, vo]), + PartialErrorTryFrom = TryGetPartialMethod(vo, "TryFrom", [underlyingType]), + }; + + private static UserProvidedPartial? TryGetPartialProperty(ITypeSymbol vo, string propertyName) + { +#if ROSLYN_4_12_OR_GREATER + var property = vo.GetMembers(propertyName) + .OfType() + .SingleOrDefault(x => x.IsPartialDefinition); + + if (property is null) + return null; + + return new(property.DeclaredAccessibility); +#else + return null; +#endif + } + + private static UserProvidedPartial? TryGetPartialMethod(ITypeSymbol vo, string methodName, ITypeSymbol[] parameterTypes) + { + var method = vo.GetMembers(methodName) + .OfType() + .Where(x => x.IsPartialDefinition) + .SingleOrDefault(x => + x.Parameters.Select(y => y.Type).SequenceEqual(parameterTypes, SymbolEqualityComparer.Default) + ); + + if (method is null) + return null; + + return new(method.DeclaredAccessibility); + } +} \ No newline at end of file diff --git a/src/Vogen/GenerateCodeForTryFrom.cs b/src/Vogen/GenerateCodeForTryFrom.cs index ad4f30bb55c..e58c8c495f4 100644 --- a/src/Vogen/GenerateCodeForTryFrom.cs +++ b/src/Vogen/GenerateCodeForTryFrom.cs @@ -34,7 +34,7 @@ private static string Generate(VoWorkItem item, SyntaxToken className, string it /// An instance of the value object. /// True if the value object can be built, otherwise false. #pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member because of nullability attributes. - public static bool TryFrom({{Util.GenerateNotNullWhenTrueAttribute()}} {{itemUnderlyingType}}{{underlyingNullable}} value, {{Util.GenerateMaybeNullWhenFalse()}} out {{className}} vo) + {{Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialBoolTryFrom)}} bool TryFrom({{Util.GenerateNotNullWhenTrueAttribute()}} {{itemUnderlyingType}}{{underlyingNullable}} value, {{Util.GenerateMaybeNullWhenFalse()}} out {{className}} vo) #pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member because of nullability attributes. { {{GenerateNullCheckAndReturnFalseIfNeeded(item)}} @@ -59,7 +59,7 @@ public static bool TryFrom({{Util.GenerateNotNullWhenTrueAttribute()}} {{itemUnd /// /// The primitive value. /// A containing either the value object, or an error. - public static Vogen.ValueObjectOrError<{{className}}> TryFrom({{itemUnderlyingType}} value) + {{Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialErrorTryFrom)}} Vogen.ValueObjectOrError<{{className}}> TryFrom({{itemUnderlyingType}} value) { {{GenerateNullCheckAndReturnErrorIfNeeded(className, item)}} diff --git a/src/Vogen/Generators/ClassGenerator.cs b/src/Vogen/Generators/ClassGenerator.cs index e0364dede20..7082815f20b 100644 --- a/src/Vogen/Generators/ClassGenerator.cs +++ b/src/Vogen/Generators/ClassGenerator.cs @@ -49,7 +49,7 @@ string GenerateCode() => $@" private {readonlyForValueAndIsInitialized} {itemUnderlyingType}{underlyingNullAnnotation} _value; {Util.GenerateCommentForValueProperty(item)} - public {itemUnderlyingType} Value + {Util.GenerateMethodModifiers(Accessibility.Public, [], item.UserProvidedPartials.PartialValue)} {itemUnderlyingType} Value {{ [global::System.Diagnostics.DebuggerStepThroughAttribute] [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] @@ -90,7 +90,7 @@ string GenerateCode() => $@" /// The underlying type. /// An instance of this type. [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] - public static {wrapperName} From({itemUnderlyingType} value) + {Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialFrom)} {wrapperName} From({itemUnderlyingType} value) {{ {Util.GenerateNullCheckAndThrowIfNeeded(item, generateReturnDefault: true)} diff --git a/src/Vogen/Generators/RecordClassGenerator.cs b/src/Vogen/Generators/RecordClassGenerator.cs index 21053b8ef2d..8ecea72cda7 100644 --- a/src/Vogen/Generators/RecordClassGenerator.cs +++ b/src/Vogen/Generators/RecordClassGenerator.cs @@ -48,7 +48,7 @@ string GenerateCode() => $@" private {readonlyForValueAndIsInitialized} {itemUnderlyingType}{underlyingNullAnnotation} _value; {Util.GenerateCommentForValueProperty(item)} - public {itemUnderlyingType} Value + {Util.GenerateMethodModifiers(Accessibility.Public, [], item.UserProvidedPartials.PartialValue)} {itemUnderlyingType} Value {{ [global::System.Diagnostics.DebuggerStepThroughAttribute] [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] @@ -100,7 +100,7 @@ string GenerateCode() => $@" /// The underlying type. /// An instance of this type. [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] - public static {wrapperName} From({itemUnderlyingType} value) + {Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialFrom)} {wrapperName} From({itemUnderlyingType} value) {{ {Util.GenerateNullCheckAndThrowIfNeeded(item, generateReturnDefault: true)} diff --git a/src/Vogen/Generators/RecordStructGenerator.cs b/src/Vogen/Generators/RecordStructGenerator.cs index 70bb861e263..e39e8658261 100644 --- a/src/Vogen/Generators/RecordStructGenerator.cs +++ b/src/Vogen/Generators/RecordStructGenerator.cs @@ -48,7 +48,7 @@ string GenerateCode() => $@" private {readonlyForValueAndIsInitialized} {itemUnderlyingType}{underlyingNullAnnotation} _value; {Util.GenerateCommentForValueProperty(item)} - public readonly {itemUnderlyingType} Value + {Util.GenerateMethodModifiers(Accessibility.Public, ["readonly"], item.UserProvidedPartials.PartialValue)} {itemUnderlyingType} Value {{ [global::System.Diagnostics.DebuggerStepThroughAttribute] [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] @@ -88,7 +88,7 @@ public readonly {itemUnderlyingType} Value /// The underlying type. /// An instance of this type. [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] - public static {wrapperName} From({itemUnderlyingType} value) + {Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialFrom)} {wrapperName} From({itemUnderlyingType} value) {{ {Util.GenerateNullCheckAndThrowIfNeeded(item, generateReturnDefault: true)} diff --git a/src/Vogen/Generators/StructGenerator.cs b/src/Vogen/Generators/StructGenerator.cs index 47ca7b8d6c3..aee3c6be116 100644 --- a/src/Vogen/Generators/StructGenerator.cs +++ b/src/Vogen/Generators/StructGenerator.cs @@ -49,7 +49,7 @@ string GenerateCode() => $@" private {readonlyForValueAndIsInitialized} {itemUnderlyingType}{underlyingNullAnnotation} _value; {Util.GenerateCommentForValueProperty(item)} - public readonly {itemUnderlyingType} Value + {Util.GenerateMethodModifiers(Accessibility.Public, ["readonly"], item.UserProvidedPartials.PartialValue)} {itemUnderlyingType} Value {{ [global::System.Diagnostics.DebuggerStepThroughAttribute] [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] @@ -81,7 +81,7 @@ public readonly {itemUnderlyingType} Value /// The underlying type. /// An instance of this type. [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] - public static {wrapperName} From({itemUnderlyingType} value) + {Util.GenerateMethodModifiers(Accessibility.Public, ["static"], item.UserProvidedPartials.PartialFrom)} {wrapperName} From({itemUnderlyingType} value) {{ {Util.GenerateNullCheckAndThrowIfNeeded(item, generateReturnDefault: true)} diff --git a/src/Vogen/Util.cs b/src/Vogen/Util.cs index a2ec6a7a283..bae8788fdb7 100644 --- a/src/Vogen/Util.cs +++ b/src/Vogen/Util.cs @@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; +using System.Collections.Generic; using Vogen.Generators.Conversions; using Vogen.Types; @@ -29,6 +30,37 @@ public static string GenerateNullCheckAndThrowIfNeeded(VoWorkItem voWorkItem, bo """; } + public static string GenerateMethodModifiers( + Accessibility defaultAccessibility, + IEnumerable otherModifers, + UserProvidedPartial? userProvidedPartial + ) + { +#pragma warning disable CS8524 // A switch on enum handles all the values + var accessModifiers = (userProvidedPartial?.DeclaredAccessibility ?? defaultAccessibility) switch +#pragma warning restore CS8524 + { + Accessibility.NotApplicable => string.Empty, + Accessibility.Private => "private", + Accessibility.ProtectedAndInternal => "private protected", + Accessibility.Protected => "protected", + Accessibility.Internal => "internal", + Accessibility.ProtectedOrInternal => "protected internal", + Accessibility.Public => "public", + }; + + var modifiers = new List { accessModifiers }; + + modifiers.AddRange(otherModifers); + + if (userProvidedPartial is not null) + { + modifiers.Add("partial"); + } + + return string.Join(" ", modifiers); + } + public static string EscapeTypeNameForTripleSlashComment(string typeName) => typeName.Replace("<", "{").Replace(">", "}"); diff --git a/src/Vogen/VoWorkItem.cs b/src/Vogen/VoWorkItem.cs index 4f9d05d1202..db6a7abc95a 100644 --- a/src/Vogen/VoWorkItem.cs +++ b/src/Vogen/VoWorkItem.cs @@ -80,6 +80,7 @@ private bool SeeIfAssignableFromString() public string AccessibilityKeyword { get; init; } = "public"; public required UserProvidedOverloads UserProvidedOverloads { get; init; } + public required UserProvidedPartials UserProvidedPartials { get; init; } public required INamedTypeSymbol WrapperType { get; init; } @@ -140,3 +141,14 @@ public class UserProvidedOverloads public required UserProvidedTryFormatMethods TryFormatMethods { get; init; } } +public record UserProvidedPartial( + Accessibility DeclaredAccessibility +); + +public class UserProvidedPartials +{ + public required UserProvidedPartial? PartialValue { get; init; } + public required UserProvidedPartial? PartialFrom { get; init; } + public required UserProvidedPartial? PartialBoolTryFrom { get; init; } + public required UserProvidedPartial? PartialErrorTryFrom { get; init; } +} diff --git a/tests/Shared/ProjectBuilder.cs b/tests/Shared/ProjectBuilder.cs index 3bdf538cef8..f8c037be6d2 100644 --- a/tests/Shared/ProjectBuilder.cs +++ b/tests/Shared/ProjectBuilder.cs @@ -347,7 +347,8 @@ internal static class IsExternalInit {} } else { - initialDiags = compilation.GetDiagnostics(); + initialDiags = compilation.GetDiagnostics() + .RemoveAll(x => x.Id is "CS8795"); // allow partial method implementation in generated code } //var initialDiags = compilation.GetDiagnostics(); diff --git a/tests/SnapshotTests/InternalDiagnostics/snapshots/snap-v8.0/InternalDiagnosticsTests.It_writes_diagnostics_if___ProduceDiagnostics_class_is_present_in_the_Vogen_namespace.verified.txt b/tests/SnapshotTests/InternalDiagnostics/snapshots/snap-v8.0/InternalDiagnosticsTests.It_writes_diagnostics_if___ProduceDiagnostics_class_is_present_in_the_Vogen_namespace.verified.txt index 475642a7c29..eb767b363ba 100644 --- a/tests/SnapshotTests/InternalDiagnostics/snapshots/snap-v8.0/InternalDiagnosticsTests.It_writes_diagnostics_if___ProduceDiagnostics_class_is_present_in_the_Vogen_namespace.verified.txt +++ b/tests/SnapshotTests/InternalDiagnostics/snapshots/snap-v8.0/InternalDiagnosticsTests.It_writes_diagnostics_if___ProduceDiagnostics_class_is_present_in_the_Vogen_namespace.verified.txt @@ -641,7 +641,7 @@ private readonly global::System.Diagnostics.StackTrace _stackTrace = null!; /* Generator count: 1 -LanguageVersion: CSharp12 +LanguageVersion: CSharp13 User provided global config =========== diff --git a/tests/SnapshotTests/PartialMethods/PartialMethodsTests.cs b/tests/SnapshotTests/PartialMethods/PartialMethodsTests.cs new file mode 100644 index 00000000000..14b486bc515 --- /dev/null +++ b/tests/SnapshotTests/PartialMethods/PartialMethodsTests.cs @@ -0,0 +1,52 @@ +using Shared; +using System.Threading.Tasks; +using Vogen; + +namespace SnapshotTests.PartialMethods; + +public sealed class PartialMethodsTests +{ + [Fact] + public Task Uses_method_partial_modifier_to_change_visibility() + { + const string source = """ + namespace Whatever; + + using Vogen; + + [ValueObject] + public partial class MyVo + { + private static partial MyVo From(string value); + internal static partial bool TryFrom(string value, out MyVo result); + private protected static partial ValueObjectOrError TryFrom(string value); + } + """; + + return new SnapshotRunner() + .WithSource(source) + .RunOn(TargetFramework.Net9_0); + } + + [Fact] + public Task Uses_method_partial_modifier_to_add_attribute() + { + const string source = """ + namespace Whatever; + + using System; + using Vogen; + + [ValueObject] + public partial struct MyVo + { + [Obsolete("Let's try an attribute")] + public static partial MyVo From(string value); + } + """; + + return new SnapshotRunner() + .WithSource(source) + .RunOn(TargetFramework.Net9_0); + } +} \ No newline at end of file diff --git a/tests/SnapshotTests/PartialMethods/snapshots/snap-v9.0/PartialMethodsTests.Uses_method_partial_modifier_to_add_attribute.verified.txt b/tests/SnapshotTests/PartialMethods/snapshots/snap-v9.0/PartialMethodsTests.Uses_method_partial_modifier_to_add_attribute.verified.txt new file mode 100644 index 00000000000..058550022ea --- /dev/null +++ b/tests/SnapshotTests/PartialMethods/snapshots/snap-v9.0/PartialMethodsTests.Uses_method_partial_modifier_to_add_attribute.verified.txt @@ -0,0 +1,478 @@ +[ +// ------------------------------------------------------------------------------ +// +// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen) +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +// Suppress warnings about [Obsolete] member usage in generated code. +#pragma warning disable CS0618 +// Suppress warnings for 'Override methods on comparable types'. +#pragma warning disable CA1036 +// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators +#pragma warning disable MA0097 +// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.' +// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations. +#pragma warning disable CS8669, CS8632 +#pragma warning disable CS8604 // Possible null reference argument. + +// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' +#pragma warning disable CS1591 +namespace generator +{ + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")] + public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory + { + public VogenTypesFactory() + { + } + + private static readonly global::System.Collections.Generic.Dictionary> _lookup = new global::System.Collections.Generic.Dictionary> + { + { + typeof(global::Whatever.MyVo), + new global::System.Lazy(() => new global::Whatever.MyVo.MyVoSystemTextJsonConverter()) + } + }; + public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert); + public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) => _lookup[typeToConvert].Value; + } +} + +// ------------------------------------------------------------------------------ +// +// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen) +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +// Suppress warnings about [Obsolete] member usage in generated code. +#pragma warning disable CS0618 +// Suppress warnings for 'Override methods on comparable types'. +#pragma warning disable CA1036 +// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators +#pragma warning disable MA0097 +// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.' +// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations. +#pragma warning disable CS8669, CS8632 +#pragma warning disable CS8604 // Possible null reference argument. + +// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' +#pragma warning disable CS1591 +namespace Whatever +{ + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyVoSystemTextJsonConverter))] + [global::System.ComponentModel.TypeConverter(typeof(MyVoTypeConverter))] + [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(MyVoDebugView))] + [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.String, Value = { _value }")] + // ReSharper disable once UnusedType.Global + public partial struct MyVo : global::System.IEquatable, global::System.IEquatable, global::System.IComparable, global::System.IComparable, global::System.IParsable + { +#if DEBUG +private readonly global::System.Diagnostics.StackTrace _stackTrace = null!; +#endif +#if !VOGEN_NO_VALIDATION + private readonly global::System.Boolean _isInitialized; +#endif + private readonly System.String _value; + /// + /// Gets the underlying value if set, otherwise a is thrown. + /// + public readonly System.String Value + { + [global::System.Diagnostics.DebuggerStepThroughAttribute] + [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] + get + { + EnsureInitialized(); + return _value; + } + } + + [global::System.Diagnostics.DebuggerStepThroughAttribute] + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public MyVo() + { +#if DEBUG + _stackTrace = new global::System.Diagnostics.StackTrace(); +#endif +#if !VOGEN_NO_VALIDATION + _isInitialized = false; +#endif + _value = default; + } + + [global::System.Diagnostics.DebuggerStepThroughAttribute] + private MyVo(System.String value) + { + _value = value; +#if !VOGEN_NO_VALIDATION + _isInitialized = true; +#endif +#if DEBUG + _stackTrace = null; +#endif + } + + /// + /// Builds an instance from the provided underlying type. + /// + /// The underlying type. + /// An instance of this type. + [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] + public static partial MyVo From(System.String value) + { + if (value is null) + { + ThrowHelper.ThrowWhenCreatedWithNull(); + return default !; + } + + return new MyVo(value); + } + + /// + /// Tries to build an instance from the provided underlying type. + /// If a normalization method is provided, it will be called. + /// If validation is provided, and it fails, false will be returned. + /// + /// The underlying type. + /// An instance of the value object. + /// True if the value object can be built, otherwise false. + +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member because of nullability attributes. + + public static bool TryFrom( +#if NETCOREAPP3_0_OR_GREATER +[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + System.String value, +#if NETCOREAPP3_0_OR_GREATER +[global::System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] +#endif + out MyVo vo) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member because of nullability attributes. + + { + if (value is null) + { + vo = default; + return false; + } + + vo = new MyVo(value); + return true; + } + + /// + /// Tries to build an instance from the provided underlying value. + /// If a normalization method is provided, it will be called. + /// If validation is provided, and it fails, an error will be returned. + /// + /// The primitive value. + /// A containing either the value object, or an error. + public static Vogen.ValueObjectOrError TryFrom(System.String value) + { + if (value is null) + { + return new Vogen.ValueObjectOrError(Vogen.Validation.Invalid("The value provided was null")); + } + + return new Vogen.ValueObjectOrError(new MyVo(value)); + } + + [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#if VOGEN_NO_VALIDATION +#pragma warning disable CS8775 + public readonly bool IsInitialized() => true; +#pragma warning restore CS8775 +#else + public readonly bool IsInitialized() => _isInitialized; +#endif + public static explicit operator MyVo(System.String value) => From(value); + public static explicit operator System.String(MyVo value) => value.Value; + // only called internally when something has been deserialized into + // its primitive type. + private static MyVo __Deserialize(System.String value) + { + if (value is null) + { + ThrowHelper.ThrowWhenCreatedWithNull(); + return default !; + } + + return new MyVo(value); + } + + public readonly global::System.Boolean Equals(MyVo other) + { + // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals. + // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type. + if (!IsInitialized() || !other.IsInitialized()) + return false; + return global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value); + } + + public global::System.Boolean Equals(MyVo other, global::System.Collections.Generic.IEqualityComparer comparer) + { + return comparer.Equals(this, other); + } + + public readonly global::System.Boolean Equals(System.String primitive) + { + return Value.Equals(primitive); + } + + public readonly global::System.Boolean Equals(System.String primitive, global::System.StringComparer comparer) + { + return comparer.Equals(Value, primitive); + } + + public readonly override global::System.Boolean Equals(global::System.Object obj) + { + return obj is MyVo && Equals((MyVo)obj); + } + + public static global::System.Boolean operator ==(MyVo left, MyVo right) => left.Equals(right); + public static global::System.Boolean operator !=(MyVo left, MyVo right) => !(left == right); + public static global::System.Boolean operator ==(MyVo left, System.String right) => left.Value.Equals(right); + public static global::System.Boolean operator ==(System.String left, MyVo right) => right.Value.Equals(left); + public static global::System.Boolean operator !=(System.String left, MyVo right) => !(left == right); + public static global::System.Boolean operator !=(MyVo left, System.String right) => !(left == right); + public int CompareTo(MyVo other) => Value.CompareTo(other.Value); + public int CompareTo(object other) + { + if (other is null) + return 1; + if (other is MyVo x) + return CompareTo(x); + ThrowHelper.ThrowArgumentException("Cannot compare to object as it is not of type MyVo", nameof(other)); + return 0; + } + + /// + /// + /// + /// True if the value passes any validation (after running any optional normalization). + /// + public static global::System.Boolean TryParse( +#if NETCOREAPP3_0_OR_GREATER +[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + global::System.String s, global::System.IFormatProvider provider, +#if NETCOREAPP3_0_OR_GREATER +[global::System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] +#endif + out MyVo result) + { + if (s is null) + { + result = default; + return false; + } + + result = new MyVo(s); + return true; + } + + /// + /// + /// + /// The value created via the method. + /// + /// Thrown when the value can be parsed, but is not valid. + public static MyVo Parse(global::System.String s, global::System.IFormatProvider provider) + { + return From(s); + } + +#nullable disable +#nullable restore + public readonly override global::System.Int32 GetHashCode() + { + return global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value); + } + + /// + public override global::System.String ToString() => IsInitialized() ? Value.ToString() ?? "" : "[UNINITIALIZED]"; + /// + public global::System.String ToString(global::System.IFormatProvider provider) => IsInitialized() ? Value.ToString(provider) ?? "" : "[UNINITIALIZED]"; + [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] + private readonly void EnsureInitialized() + { + if (!IsInitialized()) + { +#if DEBUG + ThrowHelper.ThrowWhenNotInitialized(_stackTrace); +#else + ThrowHelper.ThrowWhenNotInitialized(); +#endif + } + } + +#nullable disable + /// + /// Converts a MyVo to or from JSON. + /// + public partial class MyVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override MyVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + { + return DeserializeJson(reader.GetString()); + } + + public override void Write(System.Text.Json.Utf8JsonWriter writer, MyVo value, global::System.Text.Json.JsonSerializerOptions options) + { + writer.WriteStringValue(value.Value); + } + +#if NET6_0_OR_GREATER + public override MyVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + { + return DeserializeJson(reader.GetString()); + } + + public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, MyVo value, global::System.Text.Json.JsonSerializerOptions options) + { + writer.WritePropertyName(value.Value); + } +#endif +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + private static void ThrowJsonExceptionWhenValidationFails(Vogen.Validation validation) + { + var e = ThrowHelper.CreateValidationException(validation); + throw new global::System.Text.Json.JsonException(null, e); + } + + private static void ThrowJsonExceptionWhenNull(System.String value) + { + if (value == null) + { + var e = ThrowHelper.CreateCannotBeNullException(); + throw new global::System.Text.Json.JsonException(null, e); + } + } + + private static MyVo DeserializeJson(System.String value) + { + ThrowJsonExceptionWhenNull(value); + return new MyVo(value); + } + } + +#nullable restore +#nullable disable + class MyVoTypeConverter : global::System.ComponentModel.TypeConverter + { + public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType); + } + + public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value) + { + var stringValue = value as global::System.String; + if (stringValue != null) + { + return MyVo.__Deserialize(stringValue); + } + + return base.ConvertFrom(context, culture, value); + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType); + } + + public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType) + { + if (value is MyVo idValue) + { + if (destinationType == typeof(global::System.String)) + { + return idValue.Value; + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + +#nullable restore +#nullable disable + internal sealed class MyVoDebugView + { + private readonly MyVo _t; + MyVoDebugView(MyVo t) + { + _t = t; + } + + public global::System.Boolean IsInitialized => _t.IsInitialized(); + public global::System.String UnderlyingType => "System.String"; + public global::System.String Value => _t.IsInitialized() ? _t._value.ToString() : "[not initialized]"; +#if DEBUG + public global::System.String CreatedWith => _t._stackTrace.ToString() ?? "the From method"; +#endif + public global::System.String Conversions => @"Default"; + } + +#nullable restore + static class ThrowHelper + { +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowInvalidOperationException(string message) => throw new global::System.InvalidOperationException(message); +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowArgumentException(string message, string arg) => throw new global::System.ArgumentException(message, arg); +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowWhenCreatedWithNull() => throw CreateCannotBeNullException(); +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowWhenNotInitialized() => throw CreateValidationException("Use of uninitialized Value Object."); +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowWhenNotInitialized(global::System.Diagnostics.StackTrace stackTrace) => throw CreateValidationException("Use of uninitialized Value Object at: " + stackTrace ?? ""); +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowWhenValidationFails(Vogen.Validation validation) + { + throw CreateValidationException(validation); + } + + internal static System.Exception CreateValidationException(string message) => new global::Vogen.ValueObjectValidationException(message); + internal static System.Exception CreateCannotBeNullException() => new global::Vogen.ValueObjectValidationException("Cannot create a value object with null."); + internal static System.Exception CreateValidationException(Vogen.Validation validation) + { + var ex = CreateValidationException(validation.ErrorMessage); + if (validation.Data != null) + { + foreach (var kvp in validation.Data) + { + ex.Data[kvp.Key] = kvp.Value; + } + } + + return ex; + } + } + } +} +] \ No newline at end of file diff --git a/tests/SnapshotTests/PartialMethods/snapshots/snap-v9.0/PartialMethodsTests.Uses_method_partial_modifier_to_change_visibility.verified.txt b/tests/SnapshotTests/PartialMethods/snapshots/snap-v9.0/PartialMethodsTests.Uses_method_partial_modifier_to_change_visibility.verified.txt new file mode 100644 index 00000000000..178760cd2fb --- /dev/null +++ b/tests/SnapshotTests/PartialMethods/snapshots/snap-v9.0/PartialMethodsTests.Uses_method_partial_modifier_to_change_visibility.verified.txt @@ -0,0 +1,492 @@ +[ +// ------------------------------------------------------------------------------ +// +// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen) +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +// Suppress warnings about [Obsolete] member usage in generated code. +#pragma warning disable CS0618 +// Suppress warnings for 'Override methods on comparable types'. +#pragma warning disable CA1036 +// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators +#pragma warning disable MA0097 +// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.' +// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations. +#pragma warning disable CS8669, CS8632 +#pragma warning disable CS8604 // Possible null reference argument. + +// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' +#pragma warning disable CS1591 +namespace generator +{ + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")] + public class VogenTypesFactory : global::System.Text.Json.Serialization.JsonConverterFactory + { + public VogenTypesFactory() + { + } + + private static readonly global::System.Collections.Generic.Dictionary> _lookup = new global::System.Collections.Generic.Dictionary> + { + { + typeof(global::Whatever.MyVo), + new global::System.Lazy(() => new global::Whatever.MyVo.MyVoSystemTextJsonConverter()) + } + }; + public override bool CanConvert(global::System.Type typeToConvert) => _lookup.ContainsKey(typeToConvert); + public override global::System.Text.Json.Serialization.JsonConverter CreateConverter(global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) => _lookup[typeToConvert].Value; + } +} + +// ------------------------------------------------------------------------------ +// +// This code was generated by a source generator named Vogen (https://github.com/SteveDunn/Vogen) +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +// Suppress warnings about [Obsolete] member usage in generated code. +#pragma warning disable CS0618 +// Suppress warnings for 'Override methods on comparable types'. +#pragma warning disable CA1036 +// Suppress Error MA0097 : A class that implements IComparable or IComparable should override comparison operators +#pragma warning disable MA0097 +// Suppress warning for 'The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source.' +// The generator copies signatures from the BCL, e.g. for `TryParse`, and some of those have nullable annotations. +#pragma warning disable CS8669, CS8632 +#pragma warning disable CS8604 // Possible null reference argument. + +// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' +#pragma warning disable CS1591 +namespace Whatever +{ + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Vogen", "1.0.0.0")] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyVoSystemTextJsonConverter))] + [global::System.ComponentModel.TypeConverter(typeof(MyVoTypeConverter))] + [global::System.Diagnostics.DebuggerTypeProxyAttribute(typeof(MyVoDebugView))] + [global::System.Diagnostics.DebuggerDisplayAttribute("Underlying type: System.String, Value = { _value }")] + public partial class MyVo : global::System.IEquatable, global::System.IEquatable, global::System.IComparable, global::System.IComparable, global::System.IParsable + { +#if DEBUG +private readonly global::System.Diagnostics.StackTrace _stackTrace = null!; +#endif +#if !VOGEN_NO_VALIDATION + private readonly global::System.Boolean _isInitialized; +#endif + private readonly System.String _value; + /// + /// Gets the underlying value if set, otherwise a is thrown. + /// + public System.String Value + { + [global::System.Diagnostics.DebuggerStepThroughAttribute] + [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] + get + { + EnsureInitialized(); + return _value; + } + } + + [global::System.Diagnostics.DebuggerStepThroughAttribute] + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public MyVo() + { +#if DEBUG + _stackTrace = new global::System.Diagnostics.StackTrace(); +#endif +#if !VOGEN_NO_VALIDATION + _isInitialized = false; +#endif + _value = default; + } + + [global::System.Diagnostics.DebuggerStepThroughAttribute] + private MyVo(System.String value) + { + _value = value; +#if !VOGEN_NO_VALIDATION + _isInitialized = true; +#endif + } + + /// + /// Builds an instance from the provided underlying type. + /// + /// The underlying type. + /// An instance of this type. + [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] + private static partial MyVo From(System.String value) + { + if (value is null) + { + ThrowHelper.ThrowWhenCreatedWithNull(); + return default !; + } + + return new MyVo(value); + } + + /// + /// Tries to build an instance from the provided underlying type. + /// If a normalization method is provided, it will be called. + /// If validation is provided, and it fails, false will be returned. + /// + /// The underlying type. + /// An instance of the value object. + /// True if the value object can be built, otherwise false. + +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member because of nullability attributes. + + internal static partial bool TryFrom( +#if NETCOREAPP3_0_OR_GREATER +[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + System.String value, +#if NETCOREAPP3_0_OR_GREATER +[global::System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] +#endif + out MyVo vo) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member because of nullability attributes. + + { + if (value is null) + { + vo = default; + return false; + } + + vo = new MyVo(value); + return true; + } + + /// + /// Tries to build an instance from the provided underlying value. + /// If a normalization method is provided, it will be called. + /// If validation is provided, and it fails, an error will be returned. + /// + /// The primitive value. + /// A containing either the value object, or an error. + private protected static partial Vogen.ValueObjectOrError TryFrom(System.String value) + { + if (value is null) + { + return new Vogen.ValueObjectOrError(Vogen.Validation.Invalid("The value provided was null")); + } + + return new Vogen.ValueObjectOrError(new MyVo(value)); + } + + [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#if VOGEN_NO_VALIDATION +#pragma warning disable CS8775 + public bool IsInitialized() => true; +#pragma warning restore CS8775 +#else + public bool IsInitialized() => _isInitialized; +#endif + // only called internally when something has been deserialized into + // its primitive type. + private static MyVo __Deserialize(System.String value) + { + if (value is null) + { + ThrowHelper.ThrowWhenCreatedWithNull(); + return default !; + } + + return new MyVo(value); + } + + public global::System.Boolean Equals(MyVo other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + // It's possible to create uninitialized instances via converters such as EfCore (HasDefaultValue), which call Equals. + // We treat anything uninitialized as not equal to anything, even other uninitialized instances of this type. + if (!IsInitialized() || !other.IsInitialized()) + return false; + if (ReferenceEquals(this, other)) + { + return true; + } + + return GetType() == other.GetType() && global::System.Collections.Generic.EqualityComparer.Default.Equals(Value, other.Value); + } + + public global::System.Boolean Equals(MyVo other, global::System.Collections.Generic.IEqualityComparer comparer) + { + return comparer.Equals(this, other); + } + + public global::System.Boolean Equals(System.String primitive) + { + return Value.Equals(primitive); + } + + public global::System.Boolean Equals(System.String primitive, global::System.StringComparer comparer) + { + return comparer.Equals(Value, primitive); + } + + public override global::System.Boolean Equals(global::System.Object obj) + { + return Equals(obj as MyVo); + } + + public static global::System.Boolean operator ==(MyVo left, MyVo right) => Equals(left, right); + public static global::System.Boolean operator !=(MyVo left, MyVo right) => !Equals(left, right); + public static global::System.Boolean operator ==(MyVo left, System.String right) => left.Value.Equals(right); + public static global::System.Boolean operator ==(System.String left, MyVo right) => right.Value.Equals(left); + public static global::System.Boolean operator !=(System.String left, MyVo right) => !(left == right); + public static global::System.Boolean operator !=(MyVo left, System.String right) => !(left == right); + public static explicit operator MyVo(System.String value) => From(value); + public static explicit operator System.String(MyVo value) => value.Value; + public int CompareTo(MyVo other) + { + if (other is null) + return 1; + return Value.CompareTo(other.Value); + } + + public int CompareTo(object other) + { + if (other is null) + return 1; + if (other is MyVo x) + return CompareTo(x); + ThrowHelper.ThrowArgumentException("Cannot compare to object as it is not of type MyVo", nameof(other)); + return 0; + } + + /// + /// + /// + /// True if the value passes any validation (after running any optional normalization). + /// + public static global::System.Boolean TryParse( +#if NETCOREAPP3_0_OR_GREATER +[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + global::System.String s, global::System.IFormatProvider provider, +#if NETCOREAPP3_0_OR_GREATER +[global::System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] +#endif + out MyVo result) + { + if (s is null) + { + result = default; + return false; + } + + result = new MyVo(s); + return true; + } + + /// + /// + /// + /// The value created via the method. + /// + /// Thrown when the value can be parsed, but is not valid. + public static MyVo Parse(global::System.String s, global::System.IFormatProvider provider) + { + return From(s); + } + +#nullable disable +#nullable restore + public override global::System.Int32 GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + global::System.Int32 hash = (global::System.Int32)2166136261; + hash = (hash * 16777619) ^ GetType().GetHashCode(); + hash = (hash * 16777619) ^ global::System.Collections.Generic.EqualityComparer.Default.GetHashCode(Value); + return hash; + } + } + + /// + public override global::System.String ToString() => IsInitialized() ? Value.ToString() ?? "" : "[UNINITIALIZED]"; + /// + public global::System.String ToString(global::System.IFormatProvider provider) => IsInitialized() ? Value.ToString(provider) ?? "" : "[UNINITIALIZED]"; + [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] + private void EnsureInitialized() + { + if (!IsInitialized()) + { +#if DEBUG + ThrowHelper.ThrowWhenNotInitialized(_stackTrace); +#else + ThrowHelper.ThrowWhenNotInitialized(); +#endif + } + } + +#nullable disable + /// + /// Converts a MyVo to or from JSON. + /// + public partial class MyVoSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override MyVo Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + { + return DeserializeJson(reader.GetString()); + } + + public override void Write(System.Text.Json.Utf8JsonWriter writer, MyVo value, global::System.Text.Json.JsonSerializerOptions options) + { + writer.WriteStringValue(value.Value); + } + +#if NET6_0_OR_GREATER + public override MyVo ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + { + return DeserializeJson(reader.GetString()); + } + + public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, MyVo value, global::System.Text.Json.JsonSerializerOptions options) + { + writer.WritePropertyName(value.Value); + } +#endif +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + private static void ThrowJsonExceptionWhenValidationFails(Vogen.Validation validation) + { + var e = ThrowHelper.CreateValidationException(validation); + throw new global::System.Text.Json.JsonException(null, e); + } + + private static void ThrowJsonExceptionWhenNull(System.String value) + { + if (value == null) + { + var e = ThrowHelper.CreateCannotBeNullException(); + throw new global::System.Text.Json.JsonException(null, e); + } + } + + private static MyVo DeserializeJson(System.String value) + { + ThrowJsonExceptionWhenNull(value); + return new MyVo(value); + } + } + +#nullable restore +#nullable disable + class MyVoTypeConverter : global::System.ComponentModel.TypeConverter + { + public override global::System.Boolean CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.String) || base.CanConvertFrom(context, sourceType); + } + + public override global::System.Object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value) + { + var stringValue = value as global::System.String; + if (stringValue != null) + { + return MyVo.__Deserialize(stringValue); + } + + return base.ConvertFrom(context, culture, value); + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.String) || base.CanConvertTo(context, sourceType); + } + + public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, global::System.Object value, global::System.Type destinationType) + { + if (value is MyVo idValue) + { + if (destinationType == typeof(global::System.String)) + { + return idValue.Value; + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + +#nullable restore + internal sealed class MyVoDebugView + { + private readonly MyVo _t; + MyVoDebugView(MyVo t) + { + _t = t; + } + + public global::System.String UnderlyingType => "System.String"; + public System.String Value => _t.Value; + public global::System.String Conversions => @"[global::System.Text.Json.Serialization.JsonConverter(typeof(MyVoSystemTextJsonConverter))] +[global::System.ComponentModel.TypeConverter(typeof(MyVoTypeConverter))] +"; + } + + static class ThrowHelper + { +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowInvalidOperationException(string message) => throw new global::System.InvalidOperationException(message); +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowArgumentException(string message, string arg) => throw new global::System.ArgumentException(message, arg); +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowWhenCreatedWithNull() => throw CreateCannotBeNullException(); +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowWhenNotInitialized() => throw CreateValidationException("Use of uninitialized Value Object."); +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowWhenNotInitialized(global::System.Diagnostics.StackTrace stackTrace) => throw CreateValidationException("Use of uninitialized Value Object at: " + stackTrace ?? ""); +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute] +#endif + internal static void ThrowWhenValidationFails(Vogen.Validation validation) + { + throw CreateValidationException(validation); + } + + internal static System.Exception CreateValidationException(string message) => new global::Vogen.ValueObjectValidationException(message); + internal static System.Exception CreateCannotBeNullException() => new global::Vogen.ValueObjectValidationException("Cannot create a value object with null."); + internal static System.Exception CreateValidationException(Vogen.Validation validation) + { + var ex = CreateValidationException(validation.ErrorMessage); + if (validation.Data != null) + { + foreach (var kvp in validation.Data) + { + ex.Data[kvp.Key] = kvp.Value; + } + } + + return ex; + } + } + } +} +] \ No newline at end of file