Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,118 changes: 594 additions & 524 deletions Source/FunicularSwitch.Generators.Templates/ResultType.cs

Large diffs are not rendered by default.

94 changes: 55 additions & 39 deletions Source/FunicularSwitch.Generators.Templates/ResultTypeWithMerge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,28 @@ public abstract partial class MyResult

public static partial class MyResultExtension
{
public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T1>> Map<T, T1>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> results,
[global::JetBrains.Annotations.MustUseReturnValue]
public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T1>> Map<T, T1>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> results,
[global::JetBrains.Annotations.InstantHandle]global::System.Func<T, T1> map) =>
results.Select(r => r.Map(map)).Aggregate();
results.Select(r => r.Map(map)).Aggregate();

public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T1>> Bind<T, T1>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> results,
[global::JetBrains.Annotations.MustUseReturnValue]
public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T1>> Bind<T, T1>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> results,
[global::JetBrains.Annotations.InstantHandle]global::System.Func<T, MyResult<T1>> bind) =>
results.Select(r => r.Bind(bind)).Aggregate();

public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T1>> Bind<T, T1>(this MyResult<T> result,
results.Select(r => r.Bind(bind)).Aggregate();

[global::JetBrains.Annotations.MustUseReturnValue]
public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T1>> Bind<T, T1>(this MyResult<T> result,
[global::JetBrains.Annotations.InstantHandle]global::System.Func<T, global::System.Collections.Generic.IEnumerable<MyResult<T1>>> bindMany) =>
result.Map(ok => bindMany(ok).Aggregate()).Flatten();

public static MyResult<T1> Bind<T, T1>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> results,
result.Map(ok => bindMany(ok).Aggregate()).Flatten();

[global::JetBrains.Annotations.MustUseReturnValue]
public static MyResult<T1> Bind<T, T1>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> results,
[global::JetBrains.Annotations.InstantHandle]global::System.Func<global::System.Collections.Generic.IEnumerable<T>, MyResult<T1>> bind) =>
results.Aggregate().Bind(bind);

public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>> Aggregate<T>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> results)
results.Aggregate().Bind(bind);

[global::JetBrains.Annotations.MustUseReturnValue]
public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>> Aggregate<T>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> results)
{
var isError = false;
MyError aggregated = default!;
Expand All @@ -48,27 +53,31 @@ public static MyResult<T1> Bind<T, T1>(this global::System.Collections.Generic.I
return isError
? MyResult.Error<global::System.Collections.Generic.IReadOnlyCollection<T>>(aggregated)
: MyResult.Ok<global::System.Collections.Generic.IReadOnlyCollection<T>>(oks);
}
}

public static async global::System.Threading.Tasks.Task<MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>>> Aggregate<T>(
[global::JetBrains.Annotations.MustUseReturnValue]
public static async global::System.Threading.Tasks.Task<MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>>> Aggregate<T>(
this global::System.Threading.Tasks.Task<global::System.Collections.Generic.IEnumerable<MyResult<T>>> results)
=> (await results.ConfigureAwait(false))
.Aggregate();
.Aggregate();

public static async global::System.Threading.Tasks.Task<MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>>> Aggregate<T>(
[global::JetBrains.Annotations.MustUseReturnValue]
public static async global::System.Threading.Tasks.Task<MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>>> Aggregate<T>(
this global::System.Collections.Generic.IEnumerable<global::System.Threading.Tasks.Task<MyResult<T>>> results)
=> (await global::System.Threading.Tasks.Task.WhenAll(results.Select(e => e)).ConfigureAwait(false))
.Aggregate();
.Aggregate();

public static async global::System.Threading.Tasks.Task<MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>>> AggregateMany<T>(
[global::JetBrains.Annotations.MustUseReturnValue]
public static async global::System.Threading.Tasks.Task<MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>>> AggregateMany<T>(
this global::System.Collections.Generic.IEnumerable<global::System.Threading.Tasks.Task<global::System.Collections.Generic.IEnumerable<MyResult<T>>>> results)
=> (await global::System.Threading.Tasks.Task.WhenAll(results.Select(e => e)).ConfigureAwait(false))
.SelectMany(e => e)
.Aggregate();

//generated aggregate extension methods

public static MyResult<T> FirstOk<T>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> results, [global::JetBrains.Annotations.InstantHandle]global::System.Func<MyError> onEmpty)
.Aggregate();

//generated aggregate extension methods

[global::JetBrains.Annotations.MustUseReturnValue]
public static MyResult<T> FirstOk<T>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> results, [global::JetBrains.Annotations.InstantHandle]global::System.Func<MyError> onEmpty)
{
var errors = new global::System.Collections.Generic.List<MyError>();
foreach (var result in results)
Expand All @@ -83,15 +92,17 @@ public static MyResult<T> FirstOk<T>(this global::System.Collections.Generic.IEn
errors.Add(onEmpty());

return MyResult.Error<T>(MergeErrors(errors));
}
}

public static async global::System.Threading.Tasks.Task<MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>>> Aggregate<T>(
[global::JetBrains.Annotations.MustUseReturnValue]
public static async global::System.Threading.Tasks.Task<MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>>> Aggregate<T>(
this global::System.Collections.Generic.IEnumerable<global::System.Threading.Tasks.Task<MyResult<T>>> results,
int maxDegreeOfParallelism)
=> (await results.SelectAsync(e => e, maxDegreeOfParallelism).ConfigureAwait(false))
.Aggregate();

public static async global::System.Threading.Tasks.Task<MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>>> AggregateMany<T>(
.Aggregate();

[global::JetBrains.Annotations.MustUseReturnValue]
public static async global::System.Threading.Tasks.Task<MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>>> AggregateMany<T>(
this global::System.Collections.Generic.IEnumerable<global::System.Threading.Tasks.Task<global::System.Collections.Generic.IEnumerable<MyResult<T>>>> results,
int maxDegreeOfParallelism)
=> (await results.SelectAsync(e => e, maxDegreeOfParallelism).ConfigureAwait(false))
Expand All @@ -117,21 +128,25 @@ public static MyResult<T> FirstOk<T>(this global::System.Collections.Generic.IEn
}
})).ConfigureAwait(false);
}
}
}

public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>> AllOk<T>(this global::System.Collections.Generic.IEnumerable<T> candidates, [global::JetBrains.Annotations.InstantHandle]global::System.Func<T, global::System.Collections.Generic.IEnumerable<MyError>> validate) =>
[global::JetBrains.Annotations.MustUseReturnValue]
public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>> AllOk<T>(this global::System.Collections.Generic.IEnumerable<T> candidates, [global::JetBrains.Annotations.InstantHandle]global::System.Func<T, global::System.Collections.Generic.IEnumerable<MyError>> validate) =>
candidates
.Select(c => c.Validate(validate))
.Aggregate();

public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>> AllOk<T>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> candidates,
.Aggregate();

[global::JetBrains.Annotations.MustUseReturnValue]
public static MyResult<global::System.Collections.Generic.IReadOnlyCollection<T>> AllOk<T>(this global::System.Collections.Generic.IEnumerable<MyResult<T>> candidates,
[global::JetBrains.Annotations.InstantHandle]global::System.Func<T, global::System.Collections.Generic.IEnumerable<MyError>> validate) =>
candidates
.Bind(items => items.AllOk(validate));
.Bind(items => items.AllOk(validate));

public static MyResult<T> Validate<T>(this MyResult<T> item, [global::JetBrains.Annotations.InstantHandle]global::System.Func<T, global::System.Collections.Generic.IEnumerable<MyError>> validate) => item.Bind(i => i.Validate(validate));

public static MyResult<T> Validate<T>(this T item, [global::JetBrains.Annotations.InstantHandle]global::System.Func<T, global::System.Collections.Generic.IEnumerable<MyError>> validate)
[global::JetBrains.Annotations.MustUseReturnValue]
public static MyResult<T> Validate<T>(this MyResult<T> item, [global::JetBrains.Annotations.InstantHandle]global::System.Func<T, global::System.Collections.Generic.IEnumerable<MyError>> validate) => item.Bind(i => i.Validate(validate));

[global::JetBrains.Annotations.MustUseReturnValue]
public static MyResult<T> Validate<T>(this T item, [global::JetBrains.Annotations.InstantHandle]global::System.Func<T, global::System.Collections.Generic.IEnumerable<MyError>> validate)
{
try
{
Expand All @@ -145,9 +160,10 @@ public static MyResult<T> Validate<T>(this T item, [global::JetBrains.Annotation
{
throw; //createGenericErrorResult
}
}
}

public static MyResult<T> FirstOk<T>(this global::System.Collections.Generic.IEnumerable<T> candidates, [global::JetBrains.Annotations.InstantHandle]global::System.Func<T, global::System.Collections.Generic.IEnumerable<MyError>> validate, [global::JetBrains.Annotations.InstantHandle]global::System.Func<MyError> onEmpty) =>
[global::JetBrains.Annotations.MustUseReturnValue]
public static MyResult<T> FirstOk<T>(this global::System.Collections.Generic.IEnumerable<T> candidates, [global::JetBrains.Annotations.InstantHandle]global::System.Func<T, global::System.Collections.Generic.IEnumerable<MyError>> validate, [global::JetBrains.Annotations.InstantHandle]global::System.Func<MyError> onEmpty) =>
candidates
.Select(r => r.Validate(validate))
.FirstOk(onEmpty);
Expand Down
2 changes: 2 additions & 0 deletions Source/FunicularSwitch.Generators/Attributes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
namespace FunicularSwitch.Generators;

11 changes: 4 additions & 7 deletions Source/FunicularSwitch.Generators/EnumType/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ static class Generator
{
private const string VoidMatchMethodName = "Switch";
private const string MatchMethodName = "Match";
private const string InstantHandleAttribute = "[global::JetBrains.Annotations.InstantHandle]";
private const string InstantHandleRequireAwaitAttribute = "[global::JetBrains.Annotations.InstantHandle(RequireAwait = true)]";
private const string DebuggerStepThroughAttribute = "global::System.Diagnostics.DebuggerStepThrough";

public static (string filename, string source) Emit(
EnumTypeSchema enumTypeSchema,
Expand Down Expand Up @@ -134,7 +131,7 @@ static void WriteMatchSignature(
string? handlerReturnType = null)
{
var instantHandle = hasJetBrainsAnnotationsReference ?
isAsync ? InstantHandleRequireAwaitAttribute : InstantHandleAttribute
isAsync ? Constants.Attributes.InstantHandleRequireAwait : Constants.Attributes.InstantHandle
: "";
var modifiers = "public static";
if (isAsync)
Expand All @@ -146,7 +143,7 @@ static void WriteMatchSignature(
var handlerParameters = enumTypeSchema.Cases
.Select(c => new Parameter($"{instantHandle}global::System.Func<{handlerReturnType}>", c.ParameterName));

builder.WriteAttribute(DebuggerStepThroughAttribute);
builder.WriteLine(Constants.Attributes.DebuggerStepThrough);
builder.WriteMethodSignature(
modifiers: modifiers,
returnType: returnType,
Expand All @@ -165,13 +162,13 @@ static void WriteSwitchSignature(
bool lambda = false)
{
var instantHandle = hasJetBrainsAnnotationsReference ?
isAsync ? InstantHandleRequireAwaitAttribute : InstantHandleAttribute
isAsync ? Constants.Attributes.InstantHandleRequireAwait : Constants.Attributes.InstantHandle
: "";
var returnType = asyncReturn ?? isAsync ? "async global::System.Threading.Tasks.Task" : "void";
var handlerParameters = enumTypeSchema.Cases
.Select(c => new Parameter(isAsync ? $"{instantHandle}global::System.Func<global::System.Threading.Tasks.Task>" : $"{instantHandle}global::System.Action", c.ParameterName));

builder.WriteAttribute(DebuggerStepThroughAttribute);
builder.WriteLine(Constants.Attributes.DebuggerStepThrough);
builder.WriteMethodSignature(
modifiers: "public static",
returnType: returnType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<!--#region adapt versions here-->
<MajorVersion>4</MajorVersion>
<MinorAndPatchVersion>5.2</MinorAndPatchVersion>
<MinorAndPatchVersion>6.0</MinorAndPatchVersion>
<!--#endregion-->

<VersionSuffixLocal />
Expand Down
15 changes: 11 additions & 4 deletions Source/FunicularSwitch.Generators/Generation/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@ namespace FunicularSwitch.Generators.Generation;

internal static class Constants
{
public const string DebuggerStepThroughAttribute = "global::System.Diagnostics.DebuggerStepThroughAttribute";

public const string ExperimentalGeneratorDocs = """
public const string ExperimentalGeneratorDocs = """
<summary>
This generator is still considered experimental and might break.
Please open any issues you may find in <see href=""https://github.com/bluehands/Funicular-Switch/issues"">the GitHub repo</see>.
</summary>
""";
""";

public static class Attributes
{
public const string InstantHandle = "[global::JetBrains.Annotations.InstantHandle]";
public const string InstantHandleRequireAwait = "[global::JetBrains.Annotations.InstantHandle(RequireAwait = true)]";
public const string MustUseReturnValue = "[global::JetBrains.Annotations.MustUseReturnValue]";
public const string DebuggerStepThrough = "[global::System.Diagnostics.DebuggerStepThrough]";
public const string Pure = "[global::System.Diagnostics.Contracts.PureAttribute]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ internal static class GeneralGenerator
{
public static void BlankLine(CSharpBuilder cs) => cs.Content.AppendLine();

public static void WriteCommonMethodAttributes(CSharpBuilder cs) =>
cs.WriteLine($"[global::System.Diagnostics.Contracts.PureAttribute, {Constants.DebuggerStepThroughAttribute}]");
public static void WriteCommonMethodAttributes(CSharpBuilder cs)
{
cs.WriteLine(Constants.Attributes.Pure);
cs.WriteLine(Constants.Attributes.DebuggerStepThrough);
}

public static void WriteStaticMonad(StaticMonadGenerationInfo data, CSharpBuilder cs, CancellationToken cancellationToken)
{
Expand Down
4 changes: 0 additions & 4 deletions Source/FunicularSwitch.Generators/Generation/Indent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,6 @@ public static void WriteUsings(this CSharpBuilder tt, params string[] usings)
}
tt.NewLine();
}
public static void WriteAttribute(this CSharpBuilder tt, string attributeName)
{
tt.WriteLine("[{0}]", attributeName);
}

public static void WriteAutoProperty(this CSharpBuilder tt, string returnType, string propertyName)
{
Expand Down
8 changes: 4 additions & 4 deletions Source/FunicularSwitch.Generators/Generation/MonadMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ IEnumerable<MethodGenerationInfo> ForFnType(Func<IReadOnlyList<TypeInfo>, TypeIn
new ParameterGenerationInfo(Types.Func("A", fnReturnType(t)), "fn"),
],
name,
t => $"{chainedMonad.BindMethod.Invoke([..t, "A", "B"], [$"(({chainedMonad.GenericTypeName([..t, "A"])}){p})", $"[{Constants.DebuggerStepThroughAttribute}](a) => fn(a)"])}"
t => $"{chainedMonad.BindMethod.Invoke([..t, "A", "B"], [$"(({chainedMonad.GenericTypeName([..t, "A"])}){p})", $"{Constants.Attributes.DebuggerStepThrough}(a) => fn(a)"])}"
));
}

Expand All @@ -142,7 +142,7 @@ IEnumerable<MethodGenerationInfo> ForFnType(Func<IReadOnlyList<TypeInfo>, TypeIn
new ParameterGenerationInfo(Types.Func("A", "B", "C"), "selector"),
],
name,
t => $"{p}.SelectMany([{Constants.DebuggerStepThroughAttribute}](a) => (({genericTypeName([..t, "B"])})fn(a)).Map([{Constants.DebuggerStepThroughAttribute}](b) => selector(a, b)))"
t => $"{p}.SelectMany({Constants.Attributes.DebuggerStepThrough}(a) => (({genericTypeName([..t, "B"])})fn(a)).Map({Constants.Attributes.DebuggerStepThrough}(b) => selector(a, b)))"
));
}

Expand All @@ -152,7 +152,7 @@ private static IEnumerable<MethodGenerationInfo> Lift(ConstructType genericTypeN
["A"],
[new ParameterGenerationInfo(outerMonad.GenericTypeName(["A"]), "ma")],
"Lift",
$"{outerMonad.BindMethod.Invoke(["A", $"{innerMonad.GenericTypeName(["A"])}"], [p, $"[{Constants.DebuggerStepThroughAttribute}](a) => {chainedMonad.ReturnMethod.Invoke(["A"], ["a"])}"])}"
$"{outerMonad.BindMethod.Invoke(["A", $"{innerMonad.GenericTypeName(["A"])}"], [p, $"{Constants.Attributes.DebuggerStepThrough}(a) => {chainedMonad.ReturnMethod.Invoke(["A"], ["a"])}"])}"
));

private static IEnumerable<MethodGenerationInfo> Map(string name, ConstructType genericTypeName, MonadInfo monad) =>
Expand All @@ -167,7 +167,7 @@ private static IEnumerable<MethodGenerationInfo> Map(string name, ConstructType
new ParameterGenerationInfo(Types.Func("A", "B"), "fn"),
],
name,
t => $"{p}.{monad.BindMethod.Name}([{Constants.DebuggerStepThroughAttribute}](a) => {monad.ReturnMethod.Invoke([..t, "B"], ["fn(a)"])})"
t => $"{p}.{monad.BindMethod.Name}({Constants.Attributes.DebuggerStepThrough}(a) => {monad.ReturnMethod.Invoke([..t, "B"], ["fn(a)"])})"
));

private static IEnumerable<MethodGenerationInfo> Return(ConstructType genericTypeName, MonadInfo chainedMonad) =>
Expand Down
Loading
Loading