This commit is contained in:
melekhin
2026-06-09 16:45:22 +07:00
parent 39ee5bdddf
commit 6765aa23b1
22 changed files with 2493 additions and 1328 deletions

View File

@@ -1,10 +1,4 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Text;
namespace G;
namespace G;
[Generator]
public class UnitGenerator : IIncrementalGenerator
@@ -20,7 +14,7 @@ public class UnitGenerator : IIncrementalGenerator
namespace QWERTYkez.Mensura
{
[System.AttributeUsage(System.AttributeTargets.Struct, AllowMultiple = false)]
public sealed class UnitGeneratorAttribute : System.Attribute { }
internal sealed class UnitGeneratorAttribute : System.Attribute { }
}";
ctx.AddSource(".UnitGeneratorAttribute.g.cs", SourceText.From(attributeSource, Encoding.UTF8));
});
@@ -36,11 +30,44 @@ namespace QWERTYkez.Mensura
context.RegisterSourceOutput(structsProvider, (spc, structs) =>
{
// Сначала генерируем сами структуры (Ваш оригинальный код без изменений)
foreach (var structInfo in structs)
{
string generatedCode = GeneratePartial(structInfo);
spc.AddSource($"{structInfo.TypeName}.g.cs", SourceText.From(generatedCode, Encoding.UTF8));
}
// --- ТОТ САМЫЙ КОД УСЛОВНОЙ ГЕНЕРАЦИИ БИНДЕРА ---
bool isMainAssembly = false;
var firstStruct = structs.FirstOrDefault();
if (firstStruct.TypeName != null)
{
// Если пространство имен содержит "Tests", флаг останется false
if (firstStruct.Namespace.StartsWith("QWERTYkez.Mensura") && !firstStruct.Namespace.Contains("Tests"))
{
isMainAssembly = true;
}
}
// Генерируем файл ТОЛЬКО для основного проекта
if (isMainAssembly)
{
var sb = new StringBuilder();
sb.AppendLine("namespace QWERTYkez.Mensura;");
sb.AppendLine("internal static partial class MensuraBinder");
sb.AppendLine("{");
sb.AppendLine(" [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]");
sb.AppendLine(" static partial void AddGeneratedConverters(System.Collections.IList converters)");
sb.AppendLine(" {");
foreach (var structInfo in structs)
{
sb.AppendLine($" converters.Add(new QWERTYkez.Mensura.MensuraBinder.NewtonsoftRegistrar.NewtonsoftUnitConverter<QWERTYkez.Mensura.Units.{structInfo.TypeName}>());");
}
sb.AppendLine(" }");
sb.AppendLine("}");
spc.AddSource(".Units.MensuraBinder.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
}
});
}
@@ -98,7 +125,7 @@ using System.Runtime.Serialization;
namespace QWERTYkez.Mensura.Units;
[Newtonsoft.Json.JsonConverter(typeof(NewtonsoftUnitConverter<{typeName}>)), JsonConverter(typeof(UnitJsonConverter<{typeName}>))]
[JsonConverter(typeof(UnitJsonConverter<{typeName}>))]
public readonly partial record struct {typeName} : IMensuraUnit<{typeName}>, IEquatable<{typeName}>, IMensuraUnit
{
[JsonInclude, DataMember, JsonPropertyName(""v""), Obsolete] // для JSON / EF на случай сбоев, если пробелма с _Value
@@ -286,7 +313,341 @@ public readonly partial record struct {typeName} : IMensuraUnit<{typeName}>, IEq
public static class {typeName}Extensions
{
public static double Protected(this {typeName}? unit) => unit is null ? 0d : unit.Value._Value;
internal static double Protected(this {typeName}? unit) => unit is null ? 0d : unit.Value._Value;
// === ReadOnlySpan
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan<{typeName}> units,
double divisor, Span<{typeName}> destination) => units.Div<{typeName}>(divisor, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ReadOnlySpan<{typeName}?> units,
double divisor, Span<{typeName}?> destination) => units.Div<{typeName}>(divisor, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend,
ReadOnlySpan<{typeName}> units, Span<{typeName}> destination) => dividend.Div<{typeName}>(units, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend,
ReadOnlySpan<{typeName}?> units, Span<{typeName}?> destination) => dividend.Div<{typeName}>(units, destination);
// === Array ===
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static {typeName}[] Div(
this {typeName}[] units, double divisor) => units.Div<{typeName}>(divisor);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}?[] Div(
this {typeName}?[] units, double divisor) => units.Div<{typeName}>(divisor);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}[] Div(
this double dividend, {typeName}[] units) => dividend.Div<{typeName}>(units);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}?[] Div(
this double dividend, {typeName}?[] units) => dividend.Div<{typeName}>(units);
// === List<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}> Div(
this List<{typeName}> units, double divisor) => units.Div<{typeName}>(divisor);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}?> Div(
this List<{typeName}?> units, double divisor) => units.Div<{typeName}>(divisor);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}> Div(
this double dividend, List<{typeName}> units) => dividend.Div<{typeName}>(units);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}?> Div(
this double dividend, List<{typeName}?> units) => dividend.Div<{typeName}>(units);
// === ICollection<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ICollection<{typeName}> units,
double divisor, Span<{typeName}> destination) => units.Div<{typeName}>(divisor, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this ICollection<{typeName}?> units,
double divisor, Span<{typeName}?> destination) => units.Div<{typeName}>(divisor, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend,
ICollection<{typeName}> units, Span<{typeName}> destination) => dividend.Div<{typeName}>(units, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend,
ICollection<{typeName}?> units, Span<{typeName}?> destination) => dividend.Div<{typeName}>(units, destination);
// === IReadOnlyCollection<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Div(this IReadOnlyCollection<{typeName}> units,
double divisor, Span<{typeName}> destination) => units.Div<{typeName}>(divisor, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Div(this IReadOnlyCollection<{typeName}?> units,
double divisor, Span<{typeName}?> destination) => units.Div<{typeName}>(divisor, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend,
IReadOnlyCollection<{typeName}> units, Span<{typeName}> destination) => dividend.Div<{typeName}>(units, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Div(this double dividend,
IReadOnlyCollection<{typeName}?> units, Span<{typeName}?> destination) => dividend.Div<{typeName}>(units, destination);
// === IEnumerable<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}> Div(
this IEnumerable<{typeName}> units, double divisor) => units.Div<{typeName}>(divisor);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}?> Div(
this IEnumerable<{typeName}?> units, double divisor) => units.Div<{typeName}>(divisor);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}> Div(
this double dividend, IEnumerable<{typeName}> units) => dividend.Div<{typeName}>(units);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}?> Div(
this double dividend, IEnumerable<{typeName}?> units) => dividend.Div<{typeName}>(units);
// === ReadOnlySpan
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ReadOnlySpan<{typeName}> units,
double subtrahend, Span<{typeName}> destination) => units.Minus<{typeName}>(subtrahend, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ReadOnlySpan<{typeName}?> units,
double subtrahend, Span<{typeName}?> destination) => units.Minus<{typeName}>(subtrahend, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend,
ReadOnlySpan<{typeName}> units, Span<{typeName}> destination) => minuend.Minus<{typeName}>(units, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend,
ReadOnlySpan<{typeName}?> units, Span<{typeName}?> destination) => minuend.Minus<{typeName}>(units, destination);
// === Array ===
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static {typeName}[] Minus(
this {typeName}[] units, double subtrahend) => units.Minus<{typeName}>(subtrahend);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}?[] Minus(
this {typeName}?[] units, double subtrahend) => units.Minus<{typeName}>(subtrahend);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}[] Minus(
this double minuend, {typeName}[] units) => minuend.Minus<{typeName}>(units);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}?[] Minus(
this double minuend, {typeName}?[] units) => minuend.Minus<{typeName}>(units);
// === List<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}> Minus(
this List<{typeName}> units, double subtrahend) => units.Minus<{typeName}>(subtrahend);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}?> Minus(
this List<{typeName}?> units, double subtrahend) => units.Minus<{typeName}>(subtrahend);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}> Minus(
this double minuend, List<{typeName}> units) => minuend.Minus<{typeName}>(units);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}?> Minus(
this double minuend, List<{typeName}?> units) => minuend.Minus<{typeName}>(units);
// === ICollection<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ICollection<{typeName}> units,
double subtrahend, Span<{typeName}> destination) => units.Minus<{typeName}>(subtrahend, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this ICollection<{typeName}?> units,
double subtrahend, Span<{typeName}?> destination) => units.Minus<{typeName}>(subtrahend, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend,
ICollection<{typeName}> units, Span<{typeName}> destination) => minuend.Minus<{typeName}>(units, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend,
ICollection<{typeName}?> units, Span<{typeName}?> destination) => minuend.Minus<{typeName}>(units, destination);
// === IReadOnlyCollection<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Minus(this IReadOnlyCollection<{typeName}> units,
double subtrahend, Span<{typeName}> destination) => units.Minus<{typeName}>(subtrahend, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Minus(this IReadOnlyCollection<{typeName}?> units,
double subtrahend, Span<{typeName}?> destination) => units.Minus<{typeName}>(subtrahend, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend,
IReadOnlyCollection<{typeName}> units, Span<{typeName}> destination) => minuend.Minus<{typeName}>(units, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Minus(this double minuend,
IReadOnlyCollection<{typeName}?> units, Span<{typeName}?> destination) => minuend.Minus<{typeName}>(units, destination);
// === IEnumerable<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}> Minus(
this IEnumerable<{typeName}> units, double subtrahend) => units.Minus<{typeName}>(subtrahend);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}?> Minus(
this IEnumerable<{typeName}?> units, double subtrahend) => units.Minus<{typeName}>(subtrahend);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}> Minus(
this double minuend, IEnumerable<{typeName}> units) => minuend.Minus<{typeName}>(units);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}?> Minus(
this double minuend, IEnumerable<{typeName}?> units) => minuend.Minus<{typeName}>(units);
// === ReadOnlySpan
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ReadOnlySpan<{typeName}> units,
double multiplicator, Span<{typeName}> destination) => units.Mul<{typeName}>(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ReadOnlySpan<{typeName}?> units,
double multiplicator, Span<{typeName}?> destination) => units.Mul<{typeName}>(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator,
ReadOnlySpan<{typeName}> units, Span<{typeName}> destination) => units.Mul<{typeName}>(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator,
ReadOnlySpan<{typeName}?> units, Span<{typeName}?> destination) => units.Mul<{typeName}>(multiplicator, destination);
// === Array ===
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static {typeName}[] Mul(
this {typeName}[] units, double multiplicator) => units.Mul<{typeName}>(multiplicator);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}?[] Mul(
this {typeName}?[] units, double multiplicator) => units.Mul<{typeName}>(multiplicator);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}[] Mul(
this double multiplicator, {typeName}[] units) => units.Mul<{typeName}>(multiplicator);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}?[] Mul(
this double multiplicator, {typeName}?[] units) => units.Mul<{typeName}>(multiplicator);
// === List<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}> Mul(
this List<{typeName}> units, double multiplicator) => units.Mul<{typeName}>(multiplicator);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}?> Mul(
this List<{typeName}?> units, double multiplicator) => units.Mul<{typeName}>(multiplicator);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}> Mul(
this double multiplicator, List<{typeName}> units) => units.Mul<{typeName}>(multiplicator);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}?> Mul(
this double multiplicator, List<{typeName}?> units) => units.Mul<{typeName}>(multiplicator);
// === ICollection<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ICollection<{typeName}> units,
double multiplicator, Span<{typeName}> destination) => units.Mul<{typeName}>(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this ICollection<{typeName}?> units,
double multiplicator, Span<{typeName}?> destination) => units.Mul<{typeName}>(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator,
ICollection<{typeName}> units, Span<{typeName}> destination) => units.Mul<{typeName}>(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator,
ICollection<{typeName}?> units, Span<{typeName}?> destination) => units.Mul<{typeName}>(multiplicator, destination);
// === IReadOnlyCollection<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Mul(this IReadOnlyCollection<{typeName}> units,
double multiplicator, Span<{typeName}> destination) => units.Mul<{typeName}>(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Mul(this IReadOnlyCollection<{typeName}?> units,
double multiplicator, Span<{typeName}?> destination) => units.Mul<{typeName}>(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator,
IReadOnlyCollection<{typeName}> units, Span<{typeName}> destination) => units.Mul<{typeName}>(multiplicator, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Mul(this double multiplicator,
IReadOnlyCollection<{typeName}?> units, Span<{typeName}?> destination) => units.Mul<{typeName}>(multiplicator, destination);
// === IEnumerable<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}> Mul(
this IEnumerable<{typeName}> units, double multiplicator) => units.Mul<{typeName}>(multiplicator);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}?> Mul(
this IEnumerable<{typeName}?> units, double multiplicator) => units.Mul<{typeName}>(multiplicator);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}> Mul(
this double multiplicator, IEnumerable<{typeName}> units) => units.Mul<{typeName}>(multiplicator);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}?> Mul(
this double multiplicator, IEnumerable<{typeName}?> units) => units.Mul<{typeName}>(multiplicator);
// === ReadOnlySpan
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ReadOnlySpan<{typeName}> units,
double summand, Span<{typeName}> destination) => units.Plus<{typeName}>(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ReadOnlySpan<{typeName}?> units,
double summand, Span<{typeName}?> destination) => units.Plus<{typeName}>(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand,
ReadOnlySpan<{typeName}> units, Span<{typeName}> destination) => units.Plus<{typeName}>(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand,
ReadOnlySpan<{typeName}?> units, Span<{typeName}?> destination) => units.Plus<{typeName}>(summand, destination);
// === Array ===
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static {typeName}[] Plus(
this {typeName}[] units, double summand) => units.Plus<{typeName}>(summand);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}?[] Plus(
this {typeName}?[] units, double summand) => units.Plus<{typeName}>(summand);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}[] Plus(
this double summand, {typeName}[] units) => units.Plus<{typeName}>(summand);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName}?[] Plus(
this double summand, {typeName}?[] units) => units.Plus<{typeName}>(summand);
// === List<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}> Plus(
this List<{typeName}> units, double summand) => units.Plus<{typeName}>(summand);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}?> Plus(
this List<{typeName}?> units, double summand) => units.Plus<{typeName}>(summand);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}> Plus(
this double summand, List<{typeName}> units) => units.Plus<{typeName}>(summand);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static List<{typeName}?> Plus(
this double summand, List<{typeName}?> units) => units.Plus<{typeName}>(summand);
// === ICollection<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ICollection<{typeName}> units,
double summand, Span<{typeName}> destination) => units.Plus<{typeName}>(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this ICollection<{typeName}?> units,
double summand, Span<{typeName}?> destination) => units.Plus<{typeName}>(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand,
ICollection<{typeName}> units, Span<{typeName}> destination) => units.Plus<{typeName}>(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand,
ICollection<{typeName}?> units, Span<{typeName}?> destination) => units.Plus<{typeName}>(summand, destination);
// === IReadOnlyCollection<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Plus(this IReadOnlyCollection<{typeName}> units,
double summand, Span<{typeName}> destination) => units.Plus<{typeName}>(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)]public static void Plus(this IReadOnlyCollection<{typeName}?> units,
double summand, Span<{typeName}?> destination) => units.Plus<{typeName}>(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand,
IReadOnlyCollection<{typeName}> units, Span<{typeName}> destination) => units.Plus<{typeName}>(summand, destination);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Plus(this double summand,
IReadOnlyCollection<{typeName}?> units, Span<{typeName}?> destination) => units.Plus<{typeName}>(summand, destination);
// === IEnumerable<T> ===
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}> Plus(
this IEnumerable<{typeName}> units, double summand) => units.Plus<{typeName}>(summand);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}?> Plus(
this IEnumerable<{typeName}?> units, double summand) => units.Plus<{typeName}>(summand);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}> Plus(
this double summand, IEnumerable<{typeName}> units) => units.Plus<{typeName}>(summand);
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable<{typeName}?> Plus(
this double summand, IEnumerable<{typeName}?> units) => units.Plus<{typeName}>(summand);
// Sum Average Max Min (не nullable) ==========================================
// === ReadOnlySpan === SIMD
public static {typeName} Sum(this ReadOnlySpan<{typeName}> units) => AggregateUnitExtensions.Sum(units);
public static {typeName} Average(this ReadOnlySpan<{typeName}> units) => AggregateUnitExtensions.Average(units);
public static {typeName} Max(this ReadOnlySpan<{typeName}> units) => AggregateUnitExtensions.Max(units);
public static {typeName} Min(this ReadOnlySpan<{typeName}> units) => AggregateUnitExtensions.Min(units);
// === List<T> ===
public static {typeName} Sum(this List<{typeName}> list) => AggregateUnitExtensions.Sum(list);
public static {typeName} Average(this List<{typeName}> list) => AggregateUnitExtensions.Average(list);
public static {typeName} Max(this List<{typeName}> list) => AggregateUnitExtensions.Max(list);
public static {typeName} Min(this List<{typeName}> list) => AggregateUnitExtensions.Min(list);
// === ICollection<T> ===
public static {typeName} Sum(this ICollection<{typeName}> collection) => AggregateUnitExtensions.Sum(collection);
public static {typeName} Average(this ICollection<{typeName}> collection) => AggregateUnitExtensions.Average(collection);
public static {typeName} Max(this ICollection<{typeName}> collection) => AggregateUnitExtensions.Max(collection);
public static {typeName} Min(this ICollection<{typeName}> collection) => AggregateUnitExtensions.Min(collection);
// === IReadOnlyCollection<T> ===
public static {typeName} Sum(this IReadOnlyCollection<{typeName}> collection) => AggregateUnitExtensions.Sum(collection);
public static {typeName} Average(this IReadOnlyCollection<{typeName}> collection) => AggregateUnitExtensions.Average(collection);
public static {typeName} Max(this IReadOnlyCollection<{typeName}> collection) => AggregateUnitExtensions.Max(collection);
public static {typeName} Min(this IReadOnlyCollection<{typeName}> collection) => AggregateUnitExtensions.Min(collection);
// === IEnumerable<T> ===
public static {typeName} Sum(this IEnumerable<{typeName}> collection) => AggregateUnitExtensions.Sum(collection);
public static {typeName} Average(this IEnumerable<{typeName}> collection) => AggregateUnitExtensions.Average(collection);
public static {typeName} Max(this IEnumerable<{typeName}> collection) => AggregateUnitExtensions.Max(collection);
public static {typeName} Min(this IEnumerable<{typeName}> collection) => AggregateUnitExtensions.Min(collection);
// Sum Average Max Min (nullable) ==========================================
// === ReadOnlySpan ===
public static {typeName} Sum(this ReadOnlySpan<{typeName}?> units) => AggregateUnitExtensions.Sum(units);
public static {typeName} Average(this ReadOnlySpan<{typeName}?> units) => AggregateUnitExtensions.Average(units);
public static {typeName} Max(this ReadOnlySpan<{typeName}?> units) => AggregateUnitExtensions.Max(units);
public static {typeName} Min(this ReadOnlySpan<{typeName}?> units) => AggregateUnitExtensions.Min(units);
// === List<T> ===
public static {typeName} Sum(this List<{typeName}?> list) => AggregateUnitExtensions.Sum(list);
public static {typeName} Average(this List<{typeName}?> list) => AggregateUnitExtensions.Average(list);
public static {typeName} Max(this List<{typeName}?> list) => AggregateUnitExtensions.Max(list);
public static {typeName} Min(this List<{typeName}?> list) => AggregateUnitExtensions.Min(list);
// === ICollection<T> ===
public static {typeName} Sum(this ICollection<{typeName}?> collection) => AggregateUnitExtensions.Sum(collection);
public static {typeName} Average(this ICollection<{typeName}?> collection) => AggregateUnitExtensions.Average(collection);
public static {typeName} Max(this ICollection<{typeName}?> collection) => AggregateUnitExtensions.Max(collection);
public static {typeName} Min(this ICollection<{typeName}?> collection) => AggregateUnitExtensions.Min(collection);
// === IReadOnlyCollection<T> ===
public static {typeName} Sum(this IReadOnlyCollection<{typeName}?> collection) => AggregateUnitExtensions.Sum(collection);
public static {typeName} Average(this IReadOnlyCollection<{typeName}?> collection) => AggregateUnitExtensions.Average(collection);
public static {typeName} Max(this IReadOnlyCollection<{typeName}?> collection) => AggregateUnitExtensions.Max(collection);
public static {typeName} Min(this IReadOnlyCollection<{typeName}?> collection) => AggregateUnitExtensions.Min(collection);
// === IEnumerable<T> ===
public static {typeName} Sum(this IEnumerable<{typeName}?> collection) => AggregateUnitExtensions.Sum(collection);
public static {typeName} Average(this IEnumerable<{typeName}?> collection) => AggregateUnitExtensions.Average(collection);
public static {typeName} Max(this IEnumerable<{typeName}?> collection) => AggregateUnitExtensions.Max(collection);
public static {typeName} Min(this IEnumerable<{typeName}?> collection) => AggregateUnitExtensions.Min(collection);
}
";
return skeleton.Replace("{typeName}", typeName).Replace("{ns}", ns);