Skip to content

Commit

Permalink
Refactor domain primitives and update validation methods
Browse files Browse the repository at this point in the history
This commit includes a major refactoring of domain primitives and updates to validation methods.

- The `Validate` method now returns a `PrimitiveValidationResult` instead of throwing an `InvalidDomainValueException`.
- New `TryCreate` methods have been added to all domain primitive classes, which attempt to create an instance and return a boolean indicating success or failure.
- The `InvalidDomainValueException` now includes a reference to the instance that caused the exception.
- A new type `PrimitiveValidationResult` has been introduced, which includes `IsValid` and `ErrorMessage` properties.
- NuGet packages in all projects have been updated to the latest versions.
- Tests have been modified to support the new signatures.
  • Loading branch information
Temo Nikolaishvili committed Jun 3, 2024
1 parent 58006f0 commit 4c77528
Show file tree
Hide file tree
Showing 57 changed files with 1,909 additions and 591 deletions.
2 changes: 2 additions & 0 deletions AltaSoft.DomainPrimitives.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="s_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=15b5b1f1_002D457c_002D4ca6_002Db278_002D5615aedc07d3/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="s_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;&lt;/Policy&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Altasoft/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Browsable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Formattable/@EntryIndexedValue">True</s:Boolean>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using AltaSoft.DomainPrimitives.Generator.Extensions;
using System;
using System.Linq;
using System.Threading;
using AltaSoft.DomainPrimitives.Generator.Extensions;
using AltaSoft.DomainPrimitives.Generator.Models;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System;
using System.Linq;
using System.Threading;

namespace AltaSoft.DomainPrimitives.Generator;

Expand Down
39 changes: 27 additions & 12 deletions src/AltaSoft.DomainPrimitives.Generator/Executor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,6 @@ private static bool ProcessType(GeneratorData data, DomainPrimitiveGlobalOptions
return false;
}

var validateMethod = data.TypeSymbol.GetMembersOfType<IMethodSymbol>().FirstOrDefault(x => string.Equals(x.Name, "Validate", StringComparison.Ordinal));
if (validateMethod is not null)
ExceptionHelper.VerifyException(validateMethod, context);

Process(data, builder.ToString(), options, context);
return true;
}
Expand Down Expand Up @@ -474,6 +470,9 @@ private static void Process(GeneratorData data, string ctorCode, DomainPrimitive
.NewLine();
}

MethodGeneratorHelper.GenerateMandatoryMethods(data, builder);
builder.NewLine();

MethodGeneratorHelper.GenerateEquatableOperators(data.ClassName, data.TypeSymbol.IsValueType, builder);
builder.NewLine();

Expand Down Expand Up @@ -755,7 +754,7 @@ private static bool ProcessConstructor(GeneratorData data, SourceCodeBuilder bui

var underlyingTypeName = interfaceGenericType.GetFriendlyName();

builder.AppendLine($"private {underlyingTypeName} _valueOrThrow => _isInitialized ? _value : throw new InvalidDomainValueException(\"The domain value has not been initialized\");");
builder.AppendLine($"private {underlyingTypeName} _valueOrThrow => _isInitialized ? _value : throw new InvalidDomainValueException(\"The domain value has not been initialized\", this);");

builder.AppendLine("[DebuggerBrowsable(DebuggerBrowsableState.Never)]");
builder.AppendLine($"private readonly {underlyingTypeName} _value;");
Expand All @@ -767,13 +766,23 @@ private static bool ProcessConstructor(GeneratorData data, SourceCodeBuilder bui
builder.AppendSummary($"Initializes a new instance of the <see cref=\"{type.Name}\"/> class by validating the specified <see cref=\"{underlyingTypeName}\"/> value using <see cref=\"Validate\"/> static method.");
builder.AppendParamDescription("value", "The value to be validated.");

builder.AppendLine($"public {type.Name}({underlyingTypeName} value)")
builder.AppendLine($"public {type.Name}({underlyingTypeName} value) : this(value, true)")
.OpenBracket()
.CloseBracket()
.NewLine();

builder.AppendLine($"private {type.Name}({underlyingTypeName} value, bool validate) ")
.OpenBracket();

builder.AppendLine("if (validate)")
.OpenBracket();

if (data.UnderlyingType == DomainPrimitiveUnderlyingType.String)
AddStringLengthAttributeValidation(type, builder);
AddStringLengthAttributeValidation(type, data, builder);

builder.AppendLine("ValidateOrThrow(value);");
builder.CloseBracket()

builder.AppendLine("Validate(value);")
.AppendLine("_value = value;")
.AppendLine("_isInitialized = true;")
.CloseBracket();
Expand All @@ -784,7 +793,7 @@ private static bool ProcessConstructor(GeneratorData data, SourceCodeBuilder bui

builder.NewLine()
.AppendInheritDoc()
.AppendLine("[Obsolete(\"Domain primitive cannot be created using empty Ctor\", true)]");
.AppendLine("[Obsolete(\"Domain primitive cannot be created using empty Constructor\", true)]");

builder.Append("public ").Append(type.Name).AppendLine("()")
.OpenBracket()
Expand All @@ -796,7 +805,7 @@ private static bool ProcessConstructor(GeneratorData data, SourceCodeBuilder bui
return true;
}

private static void AddStringLengthAttributeValidation(ISymbol domainPrimitiveType, SourceCodeBuilder sb)
private static void AddStringLengthAttributeValidation(ISymbol domainPrimitiveType, GeneratorData data, SourceCodeBuilder sb)
{
var attr = domainPrimitiveType.GetAttributes()
.FirstOrDefault(x => string.Equals(x.AttributeClass?.ToDisplayString(), Constants.StringLengthAttributeFullName, StringComparison.Ordinal));
Expand All @@ -806,17 +815,23 @@ private static void AddStringLengthAttributeValidation(ISymbol domainPrimitiveTy

var minValue = (int)attr.ConstructorArguments[0].Value!;
var maxValue = (int)attr.ConstructorArguments[1].Value!;
var validate = (bool)attr.ConstructorArguments[2].Value!;

if (!validate)
return;

var hasMinValue = minValue >= 0;
var hasMaxValue = maxValue != int.MaxValue;
if (!hasMinValue && !hasMaxValue)
return;

data.StringLengthAttributeValidation = (minValue, maxValue);

sb.Append("if (value.Length is ")
.AppendIf(hasMinValue, $"< {minValue}")
.AppendIf(hasMinValue && hasMaxValue, " or")
.AppendIf(hasMinValue && hasMaxValue, " or ")
.AppendIf(hasMaxValue, $"> {maxValue}").AppendLine(")")
.AppendLine($"\tthrow new InvalidDomainValueException(\"String length is out of range {minValue}..{maxValue}\");")
.AppendLine($"\tthrow new InvalidDomainValueException(\"String length is out of range {minValue}..{maxValue}\", this);")
.NewLine();
}
}
78 changes: 0 additions & 78 deletions src/AltaSoft.DomainPrimitives.Generator/Helpers/ExceptionHelper.cs

This file was deleted.

Loading

0 comments on commit 4c77528

Please sign in to comment.