From fb44ad24562c3ed2b24bc9dee8a919e71998d7ba Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 1 Aug 2026 21:29:41 +0200 Subject: [PATCH] Describe Modular numeric format strings --- .../QuantityEmitter.cs | 13 +++++++++++-- .../GeneratedQuantityTests.cs | 19 +++++++++++++++++++ .../Metadata/QuantityDescriptor.cs | 1 + 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/UnitsNet.Modular/UnitsNet.Modular.Generator/QuantityEmitter.cs b/UnitsNet.Modular/UnitsNet.Modular.Generator/QuantityEmitter.cs index 01e0b7083b..809c7428f0 100644 --- a/UnitsNet.Modular/UnitsNet.Modular.Generator/QuantityEmitter.cs +++ b/UnitsNet.Modular/UnitsNet.Modular.Generator/QuantityEmitter.cs @@ -10,6 +10,10 @@ namespace UnitsNet.Modular.Generator; internal static class QuantityEmitter { + private const string NumericFormatStringSyntaxAttribute = + "global::System.Diagnostics.CodeAnalysis.StringSyntax(" + + "global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.NumericFormat)"; + public static string Emit( QuantitySelection selection, IReadOnlyList relationships, @@ -222,8 +226,13 @@ public static string Emit( writer.AppendLine(" public override int GetHashCode() => BaseValue.GetHashCode();"); writer.AppendLine(" public override string ToString() => ToString(null, null);"); writer.AppendLine(" public string ToString(global::System.IFormatProvider? formatProvider) => ToString(null, formatProvider);"); - writer.AppendLine(" public string ToString(string? format) => ToString(format, null);"); - writer.AppendLine(" public string ToString(string? format, global::System.IFormatProvider? formatProvider) =>"); + writer.AppendLine(" public string ToString("); + writer.Append(" [").Append(NumericFormatStringSyntaxAttribute).AppendLine("]"); + writer.AppendLine(" string? format) => ToString(format, null);"); + writer.AppendLine(" public string ToString("); + writer.Append(" [").Append(NumericFormatStringSyntaxAttribute).AppendLine("]"); + writer.AppendLine(" string? format,"); + writer.AppendLine(" global::System.IFormatProvider? formatProvider) =>"); writer.AppendLine(" global::UnitsNet.Modular.SourceGen.QuantityOperations.Format(_value, Unit, format, formatProvider, Metadata);"); writer.AppendLine(); if (quantity.IsLogarithmic) diff --git a/UnitsNet.Modular/UnitsNet.Modular.Tests/GeneratedQuantityTests.cs b/UnitsNet.Modular/UnitsNet.Modular.Tests/GeneratedQuantityTests.cs index 2b46c2ecfc..bece36f27e 100644 --- a/UnitsNet.Modular/UnitsNet.Modular.Tests/GeneratedQuantityTests.cs +++ b/UnitsNet.Modular/UnitsNet.Modular.Tests/GeneratedQuantityTests.cs @@ -1,5 +1,7 @@ // Licensed under MIT No Attribution, see LICENSE file at the root. +using System.Diagnostics.CodeAnalysis; +using System.Reflection; using System.Text.Json; using Fictional.Measurements; using UnitsNet; @@ -10,6 +12,23 @@ namespace UnitsNet.Modular.Tests; public sealed class GeneratedQuantityTests { + [Fact] + public void FormattingApis_IdentifyNumericFormatSyntax() + { + MethodInfo quantityToString = typeof(Length).GetMethod(nameof(Length.ToString), [typeof(string)])!; + StringSyntaxAttribute? quantitySyntax = quantityToString + .GetParameters()[0] + .GetCustomAttribute(); + + MethodInfo descriptorFormat = typeof(IQuantityDescriptor).GetMethod(nameof(IQuantityDescriptor.Format))!; + StringSyntaxAttribute? descriptorSyntax = descriptorFormat + .GetParameters()[1] + .GetCustomAttribute(); + + Assert.Equal(StringSyntaxAttribute.NumericFormat, quantitySyntax?.Syntax); + Assert.Equal(StringSyntaxAttribute.NumericFormat, descriptorSyntax?.Syntax); + } + [Fact] public void GeneratedRegistry_SystemTextJsonRoundTripsBuiltInAndCustomQuantities() { diff --git a/UnitsNet.Modular/UnitsNet.Modular/Metadata/QuantityDescriptor.cs b/UnitsNet.Modular/UnitsNet.Modular/Metadata/QuantityDescriptor.cs index b8e45d38a1..88c24ad51b 100644 --- a/UnitsNet.Modular/UnitsNet.Modular/Metadata/QuantityDescriptor.cs +++ b/UnitsNet.Modular/UnitsNet.Modular/Metadata/QuantityDescriptor.cs @@ -89,6 +89,7 @@ bool TryParse( /// Formats a generated quantity after validating its concrete type. string Format( IQuantity quantity, + [System.Diagnostics.CodeAnalysis.StringSyntax(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.NumericFormat)] string? format = null, IFormatProvider? formatProvider = null); }