From 0b2cb02cdf40dc816223310b0e72887710720123 Mon Sep 17 00:00:00 2001 From: glopesdev Date: Fri, 19 Jul 2024 10:36:06 +0100 Subject: [PATCH 1/4] Regression test for defer visualizer propagation --- Bonsai.Core.Tests/InspectBuilderTests.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Bonsai.Core.Tests/InspectBuilderTests.cs b/Bonsai.Core.Tests/InspectBuilderTests.cs index 4c6f3aad..7c40640f 100644 --- a/Bonsai.Core.Tests/InspectBuilderTests.cs +++ b/Bonsai.Core.Tests/InspectBuilderTests.cs @@ -100,6 +100,27 @@ public void Build_GroupInspectBuilder_ReturnNestedVisualizerElement() Assert.AreSame(target, visualizerElement.Builder); } + [TestMethod] + public void Build_DeferInspectBuilder_ReturnNestedVisualizerElement() + { + // related to https://github.com/bonsai-rx/bonsai/issues/1896 + ExpressionBuilder target = null; + var workflow = new TestWorkflow() + .AppendUnit() + .AppendNested( + input => input + .AppendUnit() + .Capture(out target) + .AppendOutput(), + workflow => new Reactive.Defer(workflow)) + .ToInspectableGraph(); + workflow.Build(); + + var output = workflow[workflow.Count - 1].Value; + var visualizerElement = ExpressionBuilder.GetVisualizerElement(output); + Assert.AreSame(target, visualizerElement.Builder); + } + [TestMethod] public void Build_PropertyMappedInspectBuilderToWorkflowOutput_ReturnVisualizerElement() { From 642ba8cae6e857349fac731f12622009635da89b Mon Sep 17 00:00:00 2001 From: glopesdev Date: Fri, 19 Jul 2024 13:36:50 +0100 Subject: [PATCH 2/4] Allow propagation of Defer nested visualizer --- Bonsai.Core/Expressions/InspectBuilder.cs | 7 +++++++ Bonsai.Core/Reactive/Defer.cs | 15 ++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Bonsai.Core/Expressions/InspectBuilder.cs b/Bonsai.Core/Expressions/InspectBuilder.cs index 9820d365..b0ec68de 100644 --- a/Bonsai.Core/Expressions/InspectBuilder.cs +++ b/Bonsai.Core/Expressions/InspectBuilder.cs @@ -217,6 +217,13 @@ methodCall.Arguments[0] is MethodCallExpression lazy && { source = methodCall.Arguments[0]; } + // If multicasting into a defer combinator, recurse on the main output + else if (methodCall.Method.DeclaringType == typeof(Reactive.Defer) && + methodCall.Arguments.Count == 1 && + methodCall.Arguments[0] is LambdaExpression lambda) + { + source = lambda.Body; + } else break; } else if (methodCall.Object.Type == typeof(InspectBuilder)) diff --git a/Bonsai.Core/Reactive/Defer.cs b/Bonsai.Core/Reactive/Defer.cs index 9c43de2c..1f125e2c 100644 --- a/Bonsai.Core/Reactive/Defer.cs +++ b/Bonsai.Core/Reactive/Defer.cs @@ -1,9 +1,7 @@ using System.Collections.Generic; -using System.Linq; using System.ComponentModel; using System.Xml.Serialization; using System.Linq.Expressions; -using System.Reflection; using System.Reactive.Linq; using System; using Bonsai.Expressions; @@ -18,12 +16,6 @@ namespace Bonsai.Reactive [Description("Creates a new observable sequence for each subscription using the encapsulated workflow.")] public class Defer : WorkflowExpressionBuilder { - static readonly MethodInfo deferMethod = typeof(Observable).GetMethods() - .Single(m => m.Name == "Defer" && - m.GetParameters()[0].ParameterType - .GetGenericArguments()[0] - .GetGenericTypeDefinition() == typeof(IObservable<>)); - /// /// Initializes a new instance of the class. /// @@ -59,8 +51,13 @@ public override Expression Build(IEnumerable arguments) { var factory = Expression.Lambda(selectorBody); var resultType = selectorBody.Type.GetGenericArguments()[0]; - return Expression.Call(deferMethod.MakeGenericMethod(resultType), factory); + return Expression.Call(typeof(Defer), nameof(Process), new[] { resultType }, factory); }); } + + static IObservable Process(Func> factory) + { + return Observable.Defer(factory); + } } } From 297552e897776859ae5f5b40d7da6e8e21e45406 Mon Sep 17 00:00:00 2001 From: glopesdev Date: Fri, 19 Jul 2024 13:37:02 +0100 Subject: [PATCH 3/4] Regression test for defer with nested visualizer --- Bonsai.Core.Tests/InspectBuilderTests.cs | 27 ++++++++++++++++++++++++ Bonsai.Core.Tests/TestWorkflow.cs | 7 ++++++ 2 files changed, 34 insertions(+) diff --git a/Bonsai.Core.Tests/InspectBuilderTests.cs b/Bonsai.Core.Tests/InspectBuilderTests.cs index 7c40640f..4a0cc06b 100644 --- a/Bonsai.Core.Tests/InspectBuilderTests.cs +++ b/Bonsai.Core.Tests/InspectBuilderTests.cs @@ -121,6 +121,33 @@ public void Build_DeferInspectBuilder_ReturnNestedVisualizerElement() Assert.AreSame(target, visualizerElement.Builder); } + [TestMethod] + public void Build_DeferWithNestedVisualizerInspectBuilder_ReturnNestedVisualizerElement() + { + // related to https://github.com/bonsai-rx/bonsai/issues/1896 + ExpressionBuilder target = null; + var workflow = new TestWorkflow() + .AppendUnit() + .AppendNested( + input => input + .AppendUnit() + .AppendSubject(nameof(System.Reactive.Unit)) + .AppendNested( + input => input + .AppendUnit() + .Capture(out target) + .AppendOutput(), + workflow => new Reactive.Visualizer(workflow)) + .AppendOutput(), + workflow => new Reactive.Defer(workflow)) + .ToInspectableGraph(); + workflow.Build(); + + var output = workflow[workflow.Count - 1].Value; + var visualizerElement = ExpressionBuilder.GetVisualizerElement(output); + Assert.AreSame(target, visualizerElement.Builder); + } + [TestMethod] public void Build_PropertyMappedInspectBuilderToWorkflowOutput_ReturnVisualizerElement() { diff --git a/Bonsai.Core.Tests/TestWorkflow.cs b/Bonsai.Core.Tests/TestWorkflow.cs index a81ec258..e973c7ed 100644 --- a/Bonsai.Core.Tests/TestWorkflow.cs +++ b/Bonsai.Core.Tests/TestWorkflow.cs @@ -94,6 +94,13 @@ public TestWorkflow AppendNested( return Append(workflowBuilder); } + public TestWorkflow AppendSubject(string name) + where TSubjectBuilder : SubjectExpressionBuilder, new() + { + var subjectBuilder = new TSubjectBuilder { Name = name }; + return Append(subjectBuilder); + } + public ExpressionBuilderGraph ToInspectableGraph() { return Workflow.ToInspectableGraph(); From 9f6565675c7a956a370724f1022102862a05eb1d Mon Sep 17 00:00:00 2001 From: glopesdev Date: Fri, 19 Jul 2024 13:38:36 +0100 Subject: [PATCH 4/4] Allow for recursive subject scope declarations --- Bonsai.Core/Expressions/InspectBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bonsai.Core/Expressions/InspectBuilder.cs b/Bonsai.Core/Expressions/InspectBuilder.cs index b0ec68de..460fe7db 100644 --- a/Bonsai.Core/Expressions/InspectBuilder.cs +++ b/Bonsai.Core/Expressions/InspectBuilder.cs @@ -222,7 +222,7 @@ methodCall.Arguments[0] is MethodCallExpression lazy && methodCall.Arguments.Count == 1 && methodCall.Arguments[0] is LambdaExpression lambda) { - source = lambda.Body; + return GetInspectBuilder(lambda.Body); } else break; }