added Try extensions generator
All checks were successful
.NET Test / test (push) Successful in 4m13s
All checks were successful
.NET Test / test (push) Successful in 4m13s
This commit is contained in:
@@ -8,7 +8,7 @@ using Microsoft.CodeAnalysis;
|
|||||||
namespace Just.Railway.SourceGen;
|
namespace Just.Railway.SourceGen;
|
||||||
|
|
||||||
[Generator]
|
[Generator]
|
||||||
public class ResultMethodGenerator : IIncrementalGenerator
|
public class ExtensionsMethodGenerator : IIncrementalGenerator
|
||||||
{
|
{
|
||||||
private readonly IEnumerable<IGeneratorExecutor> _executors = new IGeneratorExecutor[]
|
private readonly IEnumerable<IGeneratorExecutor> _executors = new IGeneratorExecutor[]
|
||||||
{
|
{
|
||||||
@@ -18,6 +18,7 @@ public class ResultMethodGenerator : IIncrementalGenerator
|
|||||||
new ResultBindExecutor(),
|
new ResultBindExecutor(),
|
||||||
new ResultTapExecutor(),
|
new ResultTapExecutor(),
|
||||||
new ResultAppendExecutor(),
|
new ResultAppendExecutor(),
|
||||||
|
new TryExtensionsExecutor(),
|
||||||
};
|
};
|
||||||
|
|
||||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||||
211
Railway.SourceGenerator/TryExtensionsExecutor.cs
Normal file
211
Railway.SourceGenerator/TryExtensionsExecutor.cs
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Just.Railway.SourceGen;
|
||||||
|
|
||||||
|
public sealed class TryExtensionsExecutor : IGeneratorExecutor
|
||||||
|
{
|
||||||
|
public void Execute(SourceProductionContext context, Compilation source)
|
||||||
|
{
|
||||||
|
var methods = GenerateMethods();
|
||||||
|
var code = $$"""
|
||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.Contracts;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
|
namespace Just.Railway;
|
||||||
|
|
||||||
|
public static partial class Try
|
||||||
|
{
|
||||||
|
{{methods}}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
context.AddSource("Try.Run.g.cs", code);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateMethods()
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i <= Constants.MaxResultTupleSize; i++)
|
||||||
|
{
|
||||||
|
GenerateMethodsForArgCount(sb, argCount: i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateMethodsForArgCount(StringBuilder sb, int argCount)
|
||||||
|
{
|
||||||
|
var templateArgNames = Enumerable.Range(1, argCount)
|
||||||
|
.Select(i => $"T{i}")
|
||||||
|
.ToImmutableArray();
|
||||||
|
var argNames = Enumerable.Range(1, argCount)
|
||||||
|
.Select(i => $"arg{i}")
|
||||||
|
.ToImmutableArray();
|
||||||
|
|
||||||
|
string actionTemplateDecl = GenerateTemplateDecl(templateArgNames);
|
||||||
|
string resultActionTemplateDecl = GenerateTemplateDecl(templateArgNames.Add("Result"));
|
||||||
|
string funcTemplateDecl = GenerateTemplateDecl(templateArgNames.Add("TResult"));
|
||||||
|
string resultFuncTemplateDecl = GenerateTemplateDecl(templateArgNames.Add("Result<TResult>"));
|
||||||
|
string argumentsDeclExpansion = string.Join(", ", templateArgNames.Zip(argNames, (t, n) => $"{t} {n}"));
|
||||||
|
string argumentsExpansion = string.Join(", ", argNames);
|
||||||
|
|
||||||
|
sb.AppendLine($"#region <{string.Join(", ", templateArgNames)}>");
|
||||||
|
|
||||||
|
sb.AppendLine($$"""
|
||||||
|
[PureAttribute]
|
||||||
|
[GeneratedCodeAttribute("{{nameof(TryExtensionsExecutor)}}", "1.0.0.0")]
|
||||||
|
public static Result Run{{actionTemplateDecl}}(Action{{actionTemplateDecl}} action{{TrailingArguments(argumentsDeclExpansion)}})
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action({{argumentsExpansion}});
|
||||||
|
return Result.Success();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Error.New(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
sb.AppendLine($$"""
|
||||||
|
[PureAttribute]
|
||||||
|
[GeneratedCodeAttribute("{{nameof(TryExtensionsExecutor)}}", "1.0.0.0")]
|
||||||
|
public static Result Run{{actionTemplateDecl}}(Func{{resultActionTemplateDecl}} action{{TrailingArguments(argumentsDeclExpansion)}})
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return action({{argumentsExpansion}});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Error.New(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
sb.AppendLine($$"""
|
||||||
|
[PureAttribute]
|
||||||
|
[GeneratedCodeAttribute("{{nameof(TryExtensionsExecutor)}}", "1.0.0.0")]
|
||||||
|
public static Result<TResult> Run{{funcTemplateDecl}}(Func{{funcTemplateDecl}} func{{TrailingArguments(argumentsDeclExpansion)}})
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Result.Success(func({{argumentsExpansion}}));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Error.New(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
sb.AppendLine($$"""
|
||||||
|
[PureAttribute]
|
||||||
|
[GeneratedCodeAttribute("{{nameof(TryExtensionsExecutor)}}", "1.0.0.0")]
|
||||||
|
public static Result<TResult> Run{{funcTemplateDecl}}(Func{{resultFuncTemplateDecl}} func{{TrailingArguments(argumentsDeclExpansion)}})
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return func({{argumentsExpansion}});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Error.New(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
GenerateAsyncMethods(sb, templateArgNames, actionTemplateDecl, funcTemplateDecl, argumentsDeclExpansion, argumentsExpansion, "Task");
|
||||||
|
GenerateAsyncMethods(sb, templateArgNames, actionTemplateDecl, funcTemplateDecl, argumentsDeclExpansion, argumentsExpansion, "ValueTask");
|
||||||
|
|
||||||
|
sb.AppendLine("#endregion");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateAsyncMethods(StringBuilder sb, ImmutableArray<string> templateArgNames, string actionTemplateDecl, string funcTemplateDecl, string argumentsDeclExpansion, string argumentsExpansion, string taskType)
|
||||||
|
{
|
||||||
|
string actionTaskTemplateDecl = GenerateTemplateDecl(templateArgNames.Add(taskType));
|
||||||
|
string resultActionTaskTemplateDecl = GenerateTemplateDecl(templateArgNames.Add($"{taskType}<Result>"));
|
||||||
|
string funcTaskTemplateDecl = GenerateTemplateDecl(templateArgNames.Add($"{taskType}<TResult>"));
|
||||||
|
string resultFuncTaskTemplateDecl = GenerateTemplateDecl(templateArgNames.Add($"{taskType}<Result<TResult>>"));
|
||||||
|
sb.AppendLine($$"""
|
||||||
|
[PureAttribute]
|
||||||
|
[GeneratedCodeAttribute("{{nameof(TryExtensionsExecutor)}}", "1.0.0.0")]
|
||||||
|
public static async {{taskType}}<Result> Run{{actionTemplateDecl}}(Func{{actionTaskTemplateDecl}} action{{TrailingArguments(argumentsDeclExpansion)}})
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await action({{argumentsExpansion}}).ConfigureAwait(false);
|
||||||
|
return Result.Success();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Error.New(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
sb.AppendLine($$"""
|
||||||
|
[PureAttribute]
|
||||||
|
[GeneratedCodeAttribute("{{nameof(TryExtensionsExecutor)}}", "1.0.0.0")]
|
||||||
|
public static async {{taskType}}<Result> Run{{actionTemplateDecl}}(Func{{resultActionTaskTemplateDecl}} action{{TrailingArguments(argumentsDeclExpansion)}})
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await action({{argumentsExpansion}}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Error.New(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
sb.AppendLine($$"""
|
||||||
|
[PureAttribute]
|
||||||
|
[GeneratedCodeAttribute("{{nameof(TryExtensionsExecutor)}}", "1.0.0.0")]
|
||||||
|
public static async {{taskType}}<Result<TResult>> Run{{funcTemplateDecl}}(Func{{funcTaskTemplateDecl}} func{{TrailingArguments(argumentsDeclExpansion)}})
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Result.Success(await func({{argumentsExpansion}}).ConfigureAwait(false));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Error.New(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
sb.AppendLine($$"""
|
||||||
|
[PureAttribute]
|
||||||
|
[GeneratedCodeAttribute("{{nameof(TryExtensionsExecutor)}}", "1.0.0.0")]
|
||||||
|
public static async {{taskType}}<Result<TResult>> Run{{funcTemplateDecl}}(Func{{resultFuncTaskTemplateDecl}} func{{TrailingArguments(argumentsDeclExpansion)}})
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await func({{argumentsExpansion}}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Error.New(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string TrailingArguments(string argumentsExpansion) => string.IsNullOrEmpty(argumentsExpansion)
|
||||||
|
? string.Empty
|
||||||
|
: $", {argumentsExpansion}";
|
||||||
|
private static string GenerateTemplateDecl(ImmutableArray<string> templateArgNames) => templateArgNames.Length > 0
|
||||||
|
? $"<{string.Join(", ", templateArgNames)}>"
|
||||||
|
: string.Empty;
|
||||||
|
}
|
||||||
105
Railway/Try.cs
105
Railway/Try.cs
@@ -1,108 +1,5 @@
|
|||||||
namespace Just.Railway;
|
namespace Just.Railway;
|
||||||
|
|
||||||
public static class Try
|
public static partial class Try
|
||||||
{
|
{
|
||||||
public static Result Run(Action action)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
action();
|
|
||||||
return Result.Success();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Result.Failure(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static async Task<Result> Run(Func<Task> action)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await action().ConfigureAwait(false);
|
|
||||||
return Result.Success();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Result.Failure(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static async ValueTask<Result> Run(Func<ValueTask> action)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await action().ConfigureAwait(false);
|
|
||||||
return Result.Success();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Result.Failure(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static Result<T> Run<T>(Func<T> func)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return Result.Success(func());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Result.Failure<T>(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static async Task<Result<T>> Run<T>(Func<Task<T>> func)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return Result.Success(await func().ConfigureAwait(false));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Result.Failure<T>(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static async ValueTask<Result<T>> Run<T>(Func<ValueTask<T>> func)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return Result.Success(await func().ConfigureAwait(false));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Result.Failure<T>(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Result<T> Run<T>(Func<Result<T>> func)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return func();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Result.Failure<T>(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static async Task<Result<T>> Run<T>(Func<Task<Result<T>>> func)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await func().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Result.Failure<T>(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static async ValueTask<Result<T>> Run<T>(Func<ValueTask<Result<T>>> func)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await func().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return Result.Failure<T>(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user