diff --git a/Directory.Build.props b/Directory.Build.props index 88a2b30..a5739df 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,7 +9,7 @@ Choice generator ALTA Software llc. Copyright © 2024 ALTA Software llc. - 1.3.1 + 1.3.2 diff --git a/src/AltaSoft.Choice.Generator/Executor.cs b/src/AltaSoft.Choice.Generator/Executor.cs index 6c60c25..38a6f92 100644 --- a/src/AltaSoft.Choice.Generator/Executor.cs +++ b/src/AltaSoft.Choice.Generator/Executor.cs @@ -104,8 +104,6 @@ private static SourceCodeBuilder Process(INamedTypeSymbol typeSymbol, List to an ."); sb.AppendParamDescription("value", $"The to convert."); - sb.AppendBlock("returns", $" instance representing the code."); + sb.AppendBlock("returns", $" instance representing the code.").NewLine(); + sb.AppendLine("[return: NotNullIfNotNull(parameterName: nameof(value))]"); + + sb.Append("public static implicit operator ").Append(typeName).Append("? (") + .Append(property.TypeName).AppendLine("? value) ") + .OpenBracket() + .Append("return value is null ? null : CreateAs").Append(property.Name).Append("(value").AppendIf(property.TypeSymbol.IsValueType, ".Value").AppendLine(");") + .CloseBracket(); - sb.Append("public static implicit operator ").Append(typeName).Append("(") - .Append(property.TypeName).Append(" value) => CreateAs").Append(property.Name).AppendLine("(value);"); sb.NewLine(); } diff --git a/src/AltaSoft.Choice.Generator/Extensions/CompilationExt.cs b/src/AltaSoft.Choice.Generator/Extensions/CompilationExt.cs index 1b79546..dd19b24 100644 --- a/src/AltaSoft.Choice.Generator/Extensions/CompilationExt.cs +++ b/src/AltaSoft.Choice.Generator/Extensions/CompilationExt.cs @@ -143,7 +143,7 @@ public static string GetClassNameWithArguments(this INamedTypeSymbol? type) return builder.ToString(); } - +#pragma warning disable S1643 public static string GetFullName(this ITypeSymbol type) { var ns = type.ContainingNamespace?.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat.WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.OmittedAsContaining))!; @@ -175,12 +175,14 @@ public static string GetFullName(this ITypeSymbol type) for (var i = 0; i < typeParameters.Length; ++i) { var typeParamName = typeParameters[i].ToString(); + friendlyName += i == 0 ? typeParamName : "," + typeParamName; + } friendlyName += ">"; return ns + '.' + friendlyName; } - +#pragma warning restore S1643 /// /// Determines whether the specified type symbol is a Nullable<T> value type and, if so, provides the underlying value type symbol. /// diff --git a/src/AltaSoft.Choice.Generator/Extensions/RoslynExt.cs b/src/AltaSoft.Choice.Generator/Extensions/RoslynExt.cs index 7926ea9..ad2dc85 100644 --- a/src/AltaSoft.Choice.Generator/Extensions/RoslynExt.cs +++ b/src/AltaSoft.Choice.Generator/Extensions/RoslynExt.cs @@ -9,62 +9,6 @@ namespace AltaSoft.Choice.Generator.Extensions; /// internal static class RoslynExt { - ///// - ///// Gets the location of the attribute data within the source code. - ///// - ///// The attribute data to retrieve the location for. - ///// The location of the attribute data in the source code, or null if not found. - //public static Location? GetAttributeLocation(this AttributeData self) - //{ - // var syntaxReference = self.ApplicationSyntaxReference; - - // var syntax = (AttributeSyntax?)syntaxReference?.GetSyntax(); - - // return syntax?.GetLocation(); - //} - - ///// - ///// Checks if the symbol has a default constructor (parameterless constructor) defined and retrieves its location. - ///// - ///// The symbol to check for a default constructor. - ///// When this method returns, contains the location of the default constructor, if found; otherwise, null. - ///// True if a default constructor is found; otherwise, false. - //public static bool HasDefaultConstructor(this ISymbol? self, out Location? location) - //{ - // var constructors = self.GetConstructorsFromSyntaxTree(); - - // var ctor = constructors?.Find(x => x.ParameterList.Parameters.Count == 0); - // location = ctor?.GetLocation(); - // return ctor is not null; - //} - - ///// - ///// Retrieves a list of constructor declarations associated with the symbol from the syntax tree. - ///// - ///// The symbol for which to retrieve constructor declarations. - ///// A list of constructor declarations or null if none are found. - //public static List? GetConstructorsFromSyntaxTree(this ISymbol? self) - //{ - // var declaringSyntaxReferences = self?.DeclaringSyntaxReferences; - - // if (self is null || declaringSyntaxReferences is null or { Length: 0 }) - // return null; - - // List? result = null; - - // foreach (var syntax in declaringSyntaxReferences) - // { - // if (syntax.GetSyntax() is TypeDeclarationSyntax classDeclaration && string.Equals(classDeclaration.GetClassFullName(), self.ToString(), System.StringComparison.Ordinal)) - // { - // var constructors = classDeclaration.Members.OfType(); - - // result ??= []; - // result.AddRange(constructors); - // } - // } - // return result; - //} - /// /// Gets the namespace of the specified type declaration syntax. /// diff --git a/src/AltaSoft.Choice.Generator/Helpers/SourceCodeBuilder.cs b/src/AltaSoft.Choice.Generator/Helpers/SourceCodeBuilder.cs index adf8ab5..434a38c 100644 --- a/src/AltaSoft.Choice.Generator/Helpers/SourceCodeBuilder.cs +++ b/src/AltaSoft.Choice.Generator/Helpers/SourceCodeBuilder.cs @@ -367,8 +367,7 @@ public SourceCodeBuilder AppendLines(IEnumerable lines) { _sb.AppendLine(); } - else - if (line[0] == '#') + else if (line[0] == '#') { _sb.AppendLine(line); } diff --git a/tests/AltaSoft.Choice.Generator.SnapshotTests/Snapshots/ChoiceGeneratorTest.ChoiceTypeShouldGenerateAllMethodsAndCompileCorrectly#Authorisation1Choice.g.verified.cs b/tests/AltaSoft.Choice.Generator.SnapshotTests/Snapshots/ChoiceGeneratorTest.ChoiceTypeShouldGenerateAllMethodsAndCompileCorrectly#Authorisation1Choice.g.verified.cs index 17187d4..bb31efb 100644 --- a/tests/AltaSoft.Choice.Generator.SnapshotTests/Snapshots/ChoiceGeneratorTest.ChoiceTypeShouldGenerateAllMethodsAndCompileCorrectly#Authorisation1Choice.g.verified.cs +++ b/tests/AltaSoft.Choice.Generator.SnapshotTests/Snapshots/ChoiceGeneratorTest.ChoiceTypeShouldGenerateAllMethodsAndCompileCorrectly#Authorisation1Choice.g.verified.cs @@ -143,7 +143,12 @@ public void Switch( /// /// instance representing the code. /// - public static implicit operator Authorisation1Choice(TestNamespace.OtherNamespace.Authorisation1Code value) => CreateAsCode(value); + + [return: NotNullIfNotNull(parameterName: nameof(value))] + public static implicit operator Authorisation1Choice? (TestNamespace.OtherNamespace.Authorisation1Code? value) + { + return value is null ? null : CreateAsCode(value.Value); + } /// /// Implicitly converts an to an . @@ -152,7 +157,12 @@ public void Switch( /// /// instance representing the code. /// - public static implicit operator Authorisation1Choice(string value) => CreateAsProprietary(value); + + [return: NotNullIfNotNull(parameterName: nameof(value))] + public static implicit operator Authorisation1Choice? (string? value) + { + return value is null ? null : CreateAsProprietary(value); + } /// /// Determines whether the property should be serialized. diff --git a/tests/AltaSoft.Choice.Generator.SnapshotTests/Snapshots/ChoiceGeneratorTest.ChoiceTypeShouldNotGenerateImplicitMethodsAndCompileCorrectly#Authorisation1Choice.g.verified.cs b/tests/AltaSoft.Choice.Generator.SnapshotTests/Snapshots/ChoiceGeneratorTest.ChoiceTypeShouldNotGenerateImplicitMethodsAndCompileCorrectly#Authorisation1Choice.g.verified.cs index 0e1b9af..4ed06af 100644 --- a/tests/AltaSoft.Choice.Generator.SnapshotTests/Snapshots/ChoiceGeneratorTest.ChoiceTypeShouldNotGenerateImplicitMethodsAndCompileCorrectly#Authorisation1Choice.g.verified.cs +++ b/tests/AltaSoft.Choice.Generator.SnapshotTests/Snapshots/ChoiceGeneratorTest.ChoiceTypeShouldNotGenerateImplicitMethodsAndCompileCorrectly#Authorisation1Choice.g.verified.cs @@ -143,7 +143,12 @@ public void Switch( /// /// instance representing the code. /// - public static implicit operator Authorisation1Choice(string value) => CreateAsCode(value); + + [return: NotNullIfNotNull(parameterName: nameof(value))] + public static implicit operator Authorisation1Choice? (string? value) + { + return value is null ? null : CreateAsCode(value); + } /// /// Implicitly converts an to an . @@ -152,7 +157,12 @@ public void Switch( /// /// instance representing the code. /// - public static implicit operator Authorisation1Choice(TestNamespace.OtherNamespace.Authorisation1Code value) => CreateAsProprietary(value); + + [return: NotNullIfNotNull(parameterName: nameof(value))] + public static implicit operator Authorisation1Choice? (TestNamespace.OtherNamespace.Authorisation1Code? value) + { + return value is null ? null : CreateAsProprietary(value.Value); + } /// /// Determines whether the property should be serialized. diff --git a/tests/AltaSoft.ChoiceGenerator.Tests/ChoiceGeneratorTests.cs b/tests/AltaSoft.ChoiceGenerator.Tests/ChoiceGeneratorTests.cs index d1e9c26..aa09a64 100644 --- a/tests/AltaSoft.ChoiceGenerator.Tests/ChoiceGeneratorTests.cs +++ b/tests/AltaSoft.ChoiceGenerator.Tests/ChoiceGeneratorTests.cs @@ -300,3 +300,4 @@ public void ImplicitConversions_ShouldConvertCorrectly() } } +