diff --git a/src/Vogen/GenerateCodeForBsonSerializers.cs b/src/Vogen/GenerateCodeForBsonSerializers.cs index 4849e76df4..f9d309e60b 100644 --- a/src/Vogen/GenerateCodeForBsonSerializers.cs +++ b/src/Vogen/GenerateCodeForBsonSerializers.cs @@ -18,6 +18,7 @@ internal class GenerateCodeForBsonSerializers /// /// /// + /// public static void GenerateForApplicableValueObjects(SourceProductionContext context, Compilation compilation, List workItems, diff --git a/src/Vogen/GenerateCodeForINumber.cs b/src/Vogen/GenerateCodeForINumber.cs index 2f32a2b653..413757e00f 100644 --- a/src/Vogen/GenerateCodeForINumber.cs +++ b/src/Vogen/GenerateCodeForINumber.cs @@ -7,6 +7,7 @@ namespace Vogen; +#if NET10_0_OR_GREATER /// /// Generates the or /// implementation for value objects whose underlying primitive type implements the corresponding interface. @@ -18,6 +19,19 @@ namespace Vogen; /// /// Requires C# 11 or later. /// +#elif NETSTANDARD +/// +/// Generates the System.Numerics.INumberBase of T or System.Numerics.INumberBase of T +/// implementation for value objects whose underlying primitive type implements the corresponding interface. +/// +/// Static abstract interface members (e.g. double.One) cannot be called on concrete +/// types in ordinary code — they require a constrained type parameter. So the generated code +/// includes private generic helper methods that forward every call through a type parameter, +/// which the C# compiler can then resolve to the concrete type's implementation. +/// +/// Requires C# 11 or later. +/// +#endif public static class GenerateCodeForINumber { private enum NumericMode { None, INumber, INumberBase } @@ -214,7 +228,7 @@ private static void GenerateStaticProperties(StringBuilder sb, string wrapperNam // - If an [Instance] with that name exists: the instance generates a readonly field, which does NOT // satisfy a static abstract property. Generate an explicit interface impl that delegates to the field. // - Otherwise: generate the normal public property. - GenerateNumberProperty(sb, wrapperName, primitiveType, wrapperSymbol, item, + GenerateNumberProperty(sb, wrapperName, wrapperSymbol, item, name: "One", iface: $"global::System.Numerics.INumberBase<{wrapperName}>", body: $"From(__GetOne<{primitiveType}>())"); @@ -225,17 +239,17 @@ private static void GenerateStaticProperties(StringBuilder sb, string wrapperNam sb.AppendLine($" public static global::System.Int32 Radix => __GetRadix<{primitiveType}>();"); } - GenerateNumberProperty(sb, wrapperName, primitiveType, wrapperSymbol, item, + GenerateNumberProperty(sb, wrapperName, wrapperSymbol, item, name: "Zero", iface: $"global::System.Numerics.INumberBase<{wrapperName}>", body: $"From(__GetZero<{primitiveType}>())"); - GenerateNumberProperty(sb, wrapperName, primitiveType, wrapperSymbol, item, + GenerateNumberProperty(sb, wrapperName, wrapperSymbol, item, name: "AdditiveIdentity", iface: $"global::System.Numerics.IAdditiveIdentity<{wrapperName}, {wrapperName}>", body: $"From(__GetAdditiveIdentity<{primitiveType}>())"); - GenerateNumberProperty(sb, wrapperName, primitiveType, wrapperSymbol, item, + GenerateNumberProperty(sb, wrapperName, wrapperSymbol, item, name: "MultiplicativeIdentity", iface: $"global::System.Numerics.IMultiplicativeIdentity<{wrapperName}, {wrapperName}>", body: $"From(__GetMultiplicativeIdentity<{primitiveType}>())"); @@ -246,7 +260,6 @@ private static void GenerateStaticProperties(StringBuilder sb, string wrapperNam private static void GenerateNumberProperty( StringBuilder sb, string wrapperName, - string primitiveType, INamedTypeSymbol wrapperSymbol, VoWorkItem item, string name, diff --git a/src/Vogen/Types/ProjectName.cs b/src/Vogen/Types/ProjectName.cs index 7235f7c183..c1d216d564 100644 --- a/src/Vogen/Types/ProjectName.cs +++ b/src/Vogen/Types/ProjectName.cs @@ -9,7 +9,7 @@ internal class ProjectName /// otherwise falls back to . Either value is normalised. /// public static ProjectName FromRootNamespaceOrAssemblyName(string? rootNamespace, string assemblyName) => - !string.IsNullOrWhiteSpace(rootNamespace) ? new(Normalise(rootNamespace!)) : FromAssemblyName(assemblyName); + !string.IsNullOrWhiteSpace(rootNamespace) ? new(Normalise(rootNamespace)) : FromAssemblyName(assemblyName); /// /// Replaces [., ,, space, -] with [_] for use as type names etc., and ensures the result diff --git a/tests/AnalyzerTests/DoNotUseNewAnalyzerTests.cs b/tests/AnalyzerTests/DoNotUseNewAnalyzerTests.cs index 39cbb37b15..807fa3ac76 100644 --- a/tests/AnalyzerTests/DoNotUseNewAnalyzerTests.cs +++ b/tests/AnalyzerTests/DoNotUseNewAnalyzerTests.cs @@ -474,7 +474,7 @@ private async Task Run(string[] sources, IEnumerable expected) /// /// Like but each source may optionally carry - /// an explicit file name. A null name means auto-assign (same as the plain overload). + /// an explicit file name. A null name means auto-assign (same as the plain overload). /// Named files are used to test path-sensitive filtering (e.g. .razor.g.cs vs .g.cs). /// private async Task RunWithNamedSources(