예제 #1
0
        public void ExportedPropertyValueDoesNotGetDisposed(IContainer container)
        {
            DisposableValue actual = container.GetExportedValue <DisposableValue>(nameof(ExportingMembersClass.PropertyReturningNewDisposableValue));

            container.Dispose();
            Assert.Equal(0, actual.DisposalCount);
        }
예제 #2
0
 public void Fail_DefaultMessage()
 {
     using (DisposableValue <Mock <TraceListener> > listener = Listen())
     {
         Report.Fail();
     }
 }
예제 #3
0
        protected override IDisposable LinkExternalInput(ITargetBlock <RestoreInfo> targetBlock)
        {
            // At a high-level, we want to combine all implicitly active configurations (ie the active config of each TFM) restore data
            // (via ProjectRestoreUpdate) and combine it into a single IVsProjectRestoreInfo2 instance and publish that. When a change is
            // made to a configuration, such as adding a PackageReference, we should react to it and push a new version of our output. If the
            // active configuration changes, we should react to it, and publish data from the new set of implicitly active configurations.

            var joinBlock = new ConfiguredProjectDataSourceJoinBlock <PackageRestoreConfiguredInput>(
                project => project.Services.ExportProvider.GetExportedValueOrDefault <IPackageRestoreConfiguredInputDataSource>(),
                JoinableFactory,
                _project);

            // Transform all restore data -> combined restore data
            DisposableValue <ISourceBlock <RestoreInfo> > mergeBlock = joinBlock.TransformWithNoDelta(update => update.Derive(MergeRestoreInputs));

            JoinUpstreamDataSources(_activeConfigurationGroupService.ActiveConfiguredProjectGroupSource);

            // Set the link up so that we publish changes to target block
            mergeBlock.Value.LinkTo(targetBlock, DataflowOption.PropagateCompletion);

            return(new DisposableBag
            {
                joinBlock,

                // Link the active configured projects to our join block
                _activeConfigurationGroupService.ActiveConfiguredProjectGroupSource.SourceBlock.LinkTo(joinBlock, DataflowOption.PropagateCompletion),
            });
        }
예제 #4
0
 public void Fail()
 {
     using (DisposableValue <Mock <TraceListener> > listener = Listen())
     {
         Report.Fail(FailureMessage);
     }
 }
        protected override IDisposable LinkExternalInput(ITargetBlock <RestoreInfo> targetBlock)
        {
            // At a high-level, we want to combine all implicitly active configurations (ie the active config of each TFM) restore data
            // (via ProjectRestoreUpdate) and combine it into a single IVsProjectRestoreInfo2 instance and publish that. When a change is
            // made to a configuration, such as adding a PackageReference, we should react to it and push a new version of our output. If the
            // active configuration changes, we should react to it, and publish data from the new set of implicitly active configurations.
            var disposables = new DisposableBag();

            var packageRestoreConfiguredSource = new UnwrapCollectionChainedProjectValueDataSource <IReadOnlyCollection <ConfiguredProject>, ProjectRestoreUpdate>(
                _project.Services,
                projects => projects.Select(project => GetProjectRestoreDataSource(project)),
                includeSourceVersions: true);

            disposables.AddDisposable(packageRestoreConfiguredSource);

            IProjectValueDataSource <IConfigurationGroup <ConfiguredProject> > activeConfiguredProjectsSource = _activeConfigurationGroupService.ActiveConfiguredProjectGroupSource;

            disposables.AddDisposable(activeConfiguredProjectsSource.SourceBlock.LinkTo(packageRestoreConfiguredSource, DataflowOption.PropagateCompletion));

            // Transform all restore data -> combined restore data
            DisposableValue <ISourceBlock <RestoreInfo> > mergeBlock = packageRestoreConfiguredSource.SourceBlock
                                                                       .TransformWithNoDelta(update => update.Derive(MergeRestoreData));

            disposables.AddDisposable(mergeBlock);

            // Set the link up so that we publish changes to target block
            mergeBlock.Value.LinkTo(targetBlock, DataflowOption.PropagateCompletion);

            // Join the source blocks, so if they need to switch to UI thread to complete
            // and someone is blocked on us on the same thread, the call proceeds
            JoinUpstreamDataSources(packageRestoreConfiguredSource, activeConfiguredProjectsSource);

            return(disposables);
        }
예제 #6
0
        public static DisposableValue <Assembly> Load(string assemblyPath)
        {
            var context      = new CollectibleAssemblyLoadContext();
            var assemblyFile = new FileInfo(assemblyPath);
            var assembly     = context.LoadFromAssemblyPath(assemblyFile.FullName);

            return(DisposableValue.Create(assembly, _ => context.Unload()));
        }
예제 #7
0
 public void IfNot()
 {
     using (DisposableValue <Mock <TraceListener> > listener = Listen())
     {
         Report.IfNot(true, FailureMessage);
         Report.IfNot(false, FailureMessage);
     }
 }
예제 #8
0
 public void IfNot_FormatNArg()
 {
     using (DisposableValue <Mock <TraceListener> > listener = Listen())
     {
         Report.IfNot(true, "a{0}{1}{2}e", "b", "c", "d");
         Report.IfNot(false, "a{0}{1}{2}e", "b", "c", "d");
     }
 }
예제 #9
0
 public void Fail_DefaultMessage()
 {
     using (DisposableValue <Mock <TraceListener> > listener = Listen())
     {
         listener.Value.Setup(l => l.WriteLine(DefaultFailureMessage)).Verifiable();
         listener.Value.Setup(l => l.Fail(DefaultFailureMessage)).Verifiable();
         Report.Fail();
     }
 }
        protected override IDisposable LinkExternalInput(ITargetBlock <IProjectVersionedValue <T> > targetBlock)
        {
            JoinUpstreamDataSources(_dataSource);

            DisposableValue <ISourceBlock <IProjectVersionedValue <T> > > block = _dataSource.SourceBlock.Transform(DropConfiguredProjectVersion);

            block.Value.LinkTo(targetBlock, DataflowOption.PropagateCompletion);

            return(block);
        }
예제 #11
0
 public void IfNot_FormatNArg()
 {
     using (DisposableValue <Mock <TraceListener> > listener = Listen())
     {
         Report.IfNot(true, "a{0}{1}{2}e", "b", "c", "d");
         listener.Value.Setup(l => l.WriteLine("abcde")).Verifiable();
         listener.Value.Setup(l => l.Fail("abcde")).Verifiable();
         Report.IfNot(false, "a{0}{1}{2}e", "b", "c", "d");
     }
 }
예제 #12
0
 public void IfNot()
 {
     using (DisposableValue <Mock <TraceListener> > listener = Listen())
     {
         Report.IfNot(true, FailureMessage);
         listener.Value.Setup(l => l.WriteLine(FailureMessage)).Verifiable();
         listener.Value.Setup(l => l.Fail(FailureMessage)).Verifiable();
         Report.IfNot(false, FailureMessage);
     }
 }
        private static async Task OnReceived(Socket socket, DisposableValue <ArraySegment <byte> > arrSeg,
                                             CancellationToken ctsToken)
        {
            var buffer = arrSeg.Value;
            var buf    = buffer.Array;
            var count  = buffer.Count;

            if (count > 0 && buf != null)
            {
                var funcId = (DevCommandFuncId)buf[buffer.Offset];
                AppLogger.Debug($"func:{funcId},{buffer.Show()}");
                switch (funcId)
                {
                case DevCommandFuncId.StartStop:
                    HandlerStartStop(socket, buffer, ctsToken);
                    return;

                case DevCommandFuncId.SetSampleRate:
                    await SetSampleRate(socket, buffer, ctsToken);

                    return;

                case DevCommandFuncId.SetTrap:
                    await SetTrap(socket, buffer, ctsToken);

                    return;

                case DevCommandFuncId.SetFilter:
                    await SetFilter(socket, buffer, ctsToken);

                    return;

                case DevCommandFuncId.QueryParam:
                    await QueryParam(socket, buffer, ctsToken);

                    return;

                case DevCommandFuncId.QueryFaultState:
                    await QueryFaultState(socket, buffer, ctsToken);

                    return;

                case DevCommandFuncId.TestSingleImpedance:
                    await TestSingleImpedance(socket, buffer, ctsToken);

                    return;

                case DevCommandFuncId.TestMultiImpedance:
                    await TestMultiImpedance(socket, buffer, ctsToken);

                    return;
                }
            }
            await SimpleSend(socket, buffer);
        }
예제 #14
0
 public void IfNotPresent()
 {
     using (DisposableValue <Mock <TraceListener> > listener = Listen())
     {
         string?possiblyPresent = "not missing";
         var    missingTypeName = possiblyPresent.GetType().FullName;
         Report.IfNotPresent(possiblyPresent);
         possiblyPresent = null;
         Report.IfNotPresent(possiblyPresent);
     }
 }
예제 #15
0
        public static IObservable <DisposableValue <ArraySegment <byte> > > ToFrameClientObservable(this Socket socket, SocketFlags socketFlags, BufferManager bufferManager, Selector selector)
        {
            return(Observable.Create <DisposableValue <ArraySegment <byte> > >(observer =>
            {
                var headerState = new BufferState(new byte[sizeof(int)], 0, sizeof(int));
                var contentState = new BufferState(null, 0, -1);

                var selectMode = socketFlags.HasFlag(SocketFlags.OutOfBand) ? SelectMode.SelectError : SelectMode.SelectRead;

                selector.AddCallback(selectMode, socket, _ =>
                {
                    try
                    {
                        if (headerState.Length > 0)
                        {
                            headerState.Advance(socket.Receive(headerState.Bytes, headerState.Offset, headerState.Length, socketFlags));

                            if (headerState.Length == 0)
                            {
                                contentState.Length = BitConverter.ToInt32(headerState.Bytes, 0);
                                contentState.Offset = 0;
                                contentState.Bytes = bufferManager.TakeBuffer(contentState.Length);
                            }
                        }

                        if (contentState.Bytes != null)
                        {
                            contentState.Advance(socket.Receive(contentState.Bytes, contentState.Offset, contentState.Length, socketFlags));

                            if (contentState.Length == 0)
                            {
                                var managedBuffer = contentState.Bytes;
                                var length = contentState.Offset;
                                observer.OnNext(DisposableValue.Create(new ArraySegment <byte>(managedBuffer, 0, length), Disposable.Create(() => bufferManager.ReturnBuffer(managedBuffer))));

                                contentState.Bytes = null;

                                headerState.Length = headerState.Offset;
                                headerState.Offset = 0;
                            }
                        }
                    }
                    catch (Exception exception)
                    {
                        if (!exception.IsWouldBlock())
                        {
                            observer.OnError(exception);
                        }
                    }
                });

                return Disposable.Create(() => selector.RemoveCallback(SelectMode.SelectRead, socket));
            }));
        }
        protected override IDisposable?LinkExternalInput(ITargetBlock <IProjectVersionedValue <RestoreData> > targetBlock)
        {
            JoinUpstreamDataSources(_dataSource);

            // Take the unconfigured "restore inputs", send them to NuGet, and then return the result of that restore
            // We make use of TransformMany so that we can opt out of returning
            DisposableValue <ISourceBlock <IProjectVersionedValue <RestoreData> > > transformBlock = _dataSource.SourceBlock.TransformManyWithNoDelta(RestoreAsync);

            transformBlock.Value.LinkTo(targetBlock, DataflowOption.PropagateCompletion);

            return(transformBlock);
        }
예제 #17
0
 public void IfNotPresent()
 {
     using (DisposableValue <Mock <TraceListener> > listener = Listen())
     {
         string?possiblyPresent = "not missing";
         string missingTypeName = possiblyPresent.GetType().FullName !;
         Report.IfNotPresent(possiblyPresent);
         listener.Value.Setup(l => l.WriteLine(It.Is <string>(v => v.Contains(missingTypeName)))).Verifiable();
         listener.Value.Setup(l => l.Fail(It.Is <string>(v => v.Contains(missingTypeName)))).Verifiable();
         possiblyPresent = null;
         Report.IfNotPresent(possiblyPresent);
     }
 }
예제 #18
0
        public DisposableValue <T[]> Resize(DisposableValue <T[]> source, int size)
        {
            if (size < 0)
            {
                throw new ArgumentOutOfRangeException("size", "Must be positive.");
            }

            var dest = AllocateDisposable(size);

            Array.Copy(source.Value, dest.Value, size < source.Value.Length ? size : source.Value.Length);
            source.Dispose();
            return(dest);
        }
예제 #19
0
        public static void Main(string[] args)
        {
            var endpoint = ProgramArgs.Parse(args, new[] { "127.0.0.1:9211" }).EndPoint;

            var cts           = new CancellationTokenSource();
            var bufferManager = BufferManager.CreateBufferManager(2 << 16, 2 << 8);

            endpoint.ToConnectObservable()
            .ObserveOn(TaskPoolScheduler.Default)
            .Subscribe(socket =>
            {
                var frameClientSubject = socket.ToFrameClientSubject(SocketFlags.None, bufferManager, cts.Token);

                var observerDisposable =
                    frameClientSubject
                    .ObserveOn(TaskPoolScheduler.Default)
                    .Subscribe(
                        managedBuffer =>
                {
                    var buf = managedBuffer.Value;
                    if (buf.Array != null)
                    {
                        Console.WriteLine("Read: " + Encoding.UTF8.GetString(buf.Array, buf.Offset, buf.Count));
                    }
                    managedBuffer.Dispose();
                },
                        error => Console.WriteLine("Error: " + error.Message),
                        () => Console.WriteLine("OnCompleted: FrameReceiver"));

                Console.In.ToLineObservable()
                .Subscribe(
                    line =>
                {
                    var writeBuffer = Encoding.UTF8.GetBytes(line);
                    frameClientSubject.OnNext(DisposableValue.Create(new ArraySegment <byte>(writeBuffer), Disposable.Empty));
                },
                    error => Console.WriteLine("Error: " + error.Message),
                    () => Console.WriteLine("OnCompleted: LineReader"));
                cts.Token.WaitHandle.WaitOne();
                //Thread.Sleep(10*1000);
                observerDisposable.Dispose();

                cts.Cancel();
            },
                       error => Console.WriteLine("Failed to connect: " + error.Message),
                       cts.Token);

            cts.Token.WaitHandle.WaitOne();
        }
예제 #20
0
        private static async Task <DisposableValue <ArraySegment <byte> > > ReadBody(this Stream stream, int length, BufferManager bufferManager, CancellationToken token)
        {
            if (length <= 0)
            {
                return(DisposableValue <ArraySegment <byte> > .Empty);
            }

            var buffer = bufferManager.TakeBuffer(length);

            if (await stream.ReadBytesCompletelyAsync(buffer, length, token) != length)
            {
                return(DisposableValue <ArraySegment <byte> > .Empty);
            }

            return(DisposableValue.Create(new ArraySegment <byte>(buffer, 0, length), Disposable.Create(() => bufferManager.ReturnBuffer(buffer))));
        }
예제 #21
0
        static void Main(string[] args)
        {
            var endpoint = ProgramArgs.Parse(args, new[] { "127.0.0.1:9211" }).EndPoint;

            var cts           = new CancellationTokenSource();
            var bufferManager = BufferManager.CreateBufferManager(2 << 16, 2 << 8);

            endpoint.ToConnectObservable()
            .Subscribe(client =>
            {
                var frameClientSubject = client.ToFrameClientSubject(bufferManager, cts.Token);

                var observerDisposable =
                    frameClientSubject
                    .ObserveOn(TaskPoolScheduler.Default)
                    .Subscribe(
                        disposableBuffer =>
                {
                    Console.WriteLine("Read: " + Encoding.UTF8.GetString(disposableBuffer.Value.Array, 0, disposableBuffer.Value.Count));
                    disposableBuffer.Dispose();
                },
                        error => Console.WriteLine("Error: " + error.Message),
                        () => Console.WriteLine("OnCompleted: FrameReceiver"));

                Console.In.ToLineObservable()
                .Subscribe(
                    line =>
                {
                    var writeBuffer = Encoding.UTF8.GetBytes(line);
                    frameClientSubject.OnNext(DisposableValue.Create(new ArraySegment <byte>(writeBuffer), Disposable.Empty));
                },
                    error => Console.WriteLine("Error: " + error.Message),
                    () => Console.WriteLine("OnCompleted: LineReader"));

                observerDisposable.Dispose();

                cts.Cancel();
            },
                       error =>
            {
                Console.WriteLine("Failed to connect: " + error.Message);
                Environment.Exit(-1);
            });

            cts.Token.WaitHandle.WaitOne();
        }
예제 #22
0
        static void Main(string[] args)
        {
            var endpoint = ProgramArgs.Parse(args, new[] { "127.0.0.1:9211" }).EndPoint;

            var cts           = new CancellationTokenSource();
            var bufferManager = BufferManager.CreateBufferManager(2 << 16, 2 << 8);

            var selector = new Selector();

            Task.Factory.StartNew(() => selector.Dispatch(60000000, cts.Token), cts.Token);

            endpoint.ToConnectObservable(selector, cts.Token)
            .Subscribe(socket =>
            {
                var frameClientSubject = socket.ToFrameClientSubject(SocketFlags.None, bufferManager, selector, cts.Token);

                var observerDisposable =
                    frameClientSubject
                    .ObserveOn(TaskPoolScheduler.Default)
                    .Subscribe(
                        disposableBuffer =>
                {
                    Console.WriteLine("Read: " + Encoding.UTF8.GetString(disposableBuffer.Value.Array, 0, disposableBuffer.Value.Count));
                    disposableBuffer.Dispose();
                },
                        error => Console.WriteLine("Error: " + error.Message),
                        () => Console.WriteLine("OnCompleted: FrameReceiver"));

                Console.In.ToLineObservable()
                .Subscribe(
                    line =>
                {
                    var writeBuffer = Encoding.UTF8.GetBytes(line);
                    frameClientSubject.OnNext(DisposableValue.Create(new ArraySegment <byte>(writeBuffer, 0, writeBuffer.Length), Disposable.Empty));
                },
                    error => Console.WriteLine("Error: " + error.Message),
                    () => Console.WriteLine("OnCompleted: LineReader"));

                observerDisposable.Dispose();

                cts.Cancel();
            });

            cts.Token.WaitHandle.WaitOne();
        }
예제 #23
0
        protected override IDisposable LinkExternalInput(ITargetBlock <RestoreUpdate> targetBlock)
        {
            IProjectValueDataSource <IProjectSubscriptionUpdate> source = _projectSubscriptionService.JointRuleSource;

            // Transform the changes from evaluation/design-time build -> restore data
            DisposableValue <ISourceBlock <RestoreUpdate> > transformBlock = source.SourceBlock.TransformWithNoDelta(update => update.Derive(u => CreateRestoreInput(u.ProjectConfiguration, u.CurrentState)),
                                                                                                                     suppressVersionOnlyUpdates: false, // We need to coordinate these at the unconfigured-level
                                                                                                                     ruleNames: s_rules);

            // Set the link up so that we publish changes to target block
            transformBlock.Value.LinkTo(targetBlock, DataflowOption.PropagateCompletion);

            // Join the source blocks, so if they need to switch to UI thread to complete
            // and someone is blocked on us on the same thread, the call proceeds
            JoinUpstreamDataSources(source);

            return(transformBlock);
        }
예제 #24
0
        /// <summary>
        /// Starts the worker process, and returns a disposable pipe connection. Disposing the connection will also destroy the worker process.
        /// </summary>
        /// <returns>A pipe connection to the worker process.</returns>
        public async Task <DisposableValue <PipeServer> > ExecuteAsync()
        {
            myWorkerProcess = StartWorkerProcess();
            myPipeServer    = await StartPipeServerAsync();

            if (myConfig.IsDebug)
            {
                Console.WriteLine("Waiting for debugger to attach to child process. Press enter to continue.");
                Console.ReadLine();
            }

            return(DisposableValue.Create(myPipeServer, pipeServer =>
            {
                StopWorkerProcess();
                myPipeServer?.Dispose();
                myWorkerProcess?.Dispose();
            }));
        }
예제 #25
0
        protected override IDisposable?LinkExternalInput(ITargetBlock <EnumCollectionProjectValue> targetBlock)
        {
            IProjectValueDataSource <IProjectSubscriptionUpdate> source = SubscriptionService.ProjectRuleSource;

            // Transform the values from evaluation to structure from the rule schema.
            DisposableValue <ISourceBlock <EnumCollectionProjectValue> > transformBlock = source.SourceBlock.TransformWithNoDelta(
                update => update.Derive(Transform),
                suppressVersionOnlyUpdates: false,
                ruleNames: RuleNames);

            // Set the link up so that we publish changes to target block.
            transformBlock.Value.LinkTo(targetBlock, DataflowOption.PropagateCompletion);

            // Join the source blocks, so if they need to switch to UI thread to complete
            // and someone is blocked on us on the same thread, the call proceeds.
            JoinUpstreamDataSources(source);

            return(transformBlock);
        }
예제 #26
0
        protected override IDisposable LinkExternalInput(ITargetBlock <RestoreInfo> targetBlock)
        {
            // At a high-level, we want to combine all implicitly active configurations (ie the active config of each TFM) restore data
            // (via ProjectRestoreUpdate) and combine it into a single IVsProjectRestoreInfo2 instance and publish that. When a change is
            // made to a configuration, such as adding a PackageReference, we should react to it and push a new version of our output. If the
            // active configuration changes, we should react to it, and publish data from the new set of implicitly active configurations.
            var disposables = new DisposableBag();

            var restoreConfiguredInputSource = new UnwrapCollectionChainedProjectValueDataSource <IReadOnlyCollection <ConfiguredProject>, PackageRestoreConfiguredInput>(
                _project,
                projects => projects.Select(project => project.Services.ExportProvider.GetExportedValueOrDefault <IPackageRestoreConfiguredInputDataSource>())
                .WhereNotNull()                     // Filter out those without PackageReference
                .Select(DropConfiguredProjectVersions),
                includeSourceVersions: true);

            disposables.Add(restoreConfiguredInputSource);

            IProjectValueDataSource <IConfigurationGroup <ConfiguredProject> > activeConfiguredProjectsSource = _activeConfigurationGroupService.ActiveConfiguredProjectGroupSource;

            disposables.Add(activeConfiguredProjectsSource.SourceBlock.LinkTo(restoreConfiguredInputSource, DataflowOption.PropagateCompletion));

            // Dataflow from two configurations can depend on a same unconfigured level data source, and processes it at a different speed.
            // Introduce a forward-only block to prevent regressions in versions.
            var forwardOnlyBlock = ProjectDataSources.CreateDataSourceVersionForwardOnlyFilteringBlock <IReadOnlyCollection <PackageRestoreConfiguredInput> >();

            disposables.Add(restoreConfiguredInputSource.SourceBlock.LinkTo(forwardOnlyBlock, DataflowOption.PropagateCompletion));

            // Transform all restore data -> combined restore data
            DisposableValue <ISourceBlock <RestoreInfo> > mergeBlock = forwardOnlyBlock.TransformWithNoDelta(update => update.Derive(MergeRestoreInputs));

            disposables.Add(mergeBlock);

            // Set the link up so that we publish changes to target block
            mergeBlock.Value.LinkTo(targetBlock, DataflowOption.PropagateCompletion);

            // Join the source blocks, so if they need to switch to UI thread to complete
            // and someone is blocked on us on the same thread, the call proceeds
            JoinUpstreamDataSources(restoreConfiguredInputSource, activeConfiguredProjectsSource);

            _packageReferenceTelemetryService.PostPackageRestoreEvent(PackageRestoreOperationNames.PackageRestoreUnconfiguredInputDataSourceLinkedToExternalInput);

            return(disposables);
        }
예제 #27
0
        public static void Example_Dispose()
        {
            var d = new DisposableValue();

            Console.WriteLine("Passing value variable:");
            CallDispose(d);
            CallDispose(d);
            CallDispose(d);

            IDisposable i = d;

            Console.WriteLine("Passing interface variable:");
            CallDispose(i);
            CallDispose(i);
            CallDispose(i);

            Console.WriteLine("Call Dispose on value variable:");
            d.Dispose();
            d.Dispose();
            d.Dispose();
        }
예제 #28
0
        protected override IDisposable LinkExternalInput(ITargetBlock <IProjectVersionedValue <UpToDateCheckConfiguredInput> > targetBlock)
        {
            // Provides the set of implicitly active configured projects
            IProjectValueDataSource <IConfigurationGroup <ConfiguredProject> > activeConfiguredProjectsSource = _activeConfigurationGroupService.ActiveConfiguredProjectGroupSource;

            // Aggregates implicitly active UpToDateCheckImplicitConfiguredInput inputs from their sources
            var restoreConfiguredInputSource = new UnwrapCollectionChainedProjectValueDataSource <IReadOnlyCollection <ConfiguredProject>, UpToDateCheckImplicitConfiguredInput>(
                _configuredProject,
                projects => projects.Select(project => project.Services.ExportProvider.GetExportedValueOrDefault <IUpToDateCheckImplicitConfiguredInputDataSource>())
                .WhereNotNull()     // Filter out any configurations which don't have this export
                .Select(DropConfiguredProjectVersions),
                includeSourceVersions: true);

            // Dataflow from two configurations can depend on a same unconfigured level data source, and processes it at a different speed.
            // Introduce a forward-only block to prevent regressions in versions.
            var forwardOnlyBlock = ProjectDataSources.CreateDataSourceVersionForwardOnlyFilteringBlock <IReadOnlyCollection <UpToDateCheckImplicitConfiguredInput> >();

            DisposableValue <ISourceBlock <IProjectVersionedValue <UpToDateCheckConfiguredInput> > >
            mergeBlock = forwardOnlyBlock.TransformWithNoDelta(update => update.Derive(MergeInputs));

            JoinUpstreamDataSources(restoreConfiguredInputSource, activeConfiguredProjectsSource);

            return(new DisposableBag
            {
                restoreConfiguredInputSource,
                activeConfiguredProjectsSource.SourceBlock.LinkTo(restoreConfiguredInputSource, DataflowOption.PropagateCompletion),
                restoreConfiguredInputSource.SourceBlock.LinkTo(forwardOnlyBlock, DataflowOption.PropagateCompletion),
                mergeBlock,
                mergeBlock.Value.LinkTo(targetBlock, DataflowOption.PropagateCompletion)
            });

            IProjectValueDataSource <UpToDateCheckImplicitConfiguredInput> DropConfiguredProjectVersions(IUpToDateCheckImplicitConfiguredInputDataSource dataSource)
            {
                // Wrap it in a data source that will drop project version and identity versions so as they will never agree
                // on these versions as they are unique to each configuration. They'll be consistent by all other versions.
                return(new DropConfiguredProjectVersionDataSource <UpToDateCheckImplicitConfiguredInput>(_configuredProject.UnconfiguredProject, dataSource));
            }
        protected override IDisposable LinkExternalInput(ITargetBlock <IProjectVersionedValue <UpToDateCheckConfiguredInput> > targetBlock)
        {
            // Aggregates implicitly active UpToDateCheckImplicitConfiguredInput inputs from their sources
            var joinBlock = new ConfiguredProjectDataSourceJoinBlock <UpToDateCheckImplicitConfiguredInput>(
                project => project.Services.ExportProvider.GetExportedValueOrDefault <IUpToDateCheckImplicitConfiguredInputDataSource>(),
                JoinableFactory,
                _configuredProject.UnconfiguredProject);

            // Merges UpToDateCheckImplicitConfiguredInputs into a UpToDateCheckConfiguredInput
            DisposableValue <ISourceBlock <IProjectVersionedValue <UpToDateCheckConfiguredInput> > >
            mergeBlock = joinBlock.TransformWithNoDelta(update => update.Derive(MergeInputs));

            JoinUpstreamDataSources(_activeConfigurationGroupService.ActiveConfiguredProjectGroupSource);

            // Set the link up so that we publish changes to target block
            mergeBlock.Value.LinkTo(targetBlock, DataflowOption.PropagateCompletion);

            return(new DisposableBag
            {
                joinBlock,

                // Link the active configured projects to our join block
                _activeConfigurationGroupService.ActiveConfiguredProjectGroupSource.SourceBlock.LinkTo(joinBlock, DataflowOption.PropagateCompletion),
            });
        protected override IDisposable?LinkExternalInput(ITargetBlock <IProjectVersionedValue <ISet <WorkloadDescriptor> > > targetBlock)
        {
            IProjectValueDataSource <IProjectSubscriptionUpdate> source = _projectSubscriptionService.ProjectBuildRuleSource;

            // Transform the changes from design-time build -> workload data
            DisposableValue <ISourceBlock <IProjectVersionedValue <ISet <WorkloadDescriptor> > > > transformBlock =
                source.SourceBlock.TransformWithNoDelta(update => update.Derive(u => CreateWorkloadDescriptor(u.CurrentState)),
                                                        suppressVersionOnlyUpdates: false,
                                                        ruleNames: s_rules);

            // Set the link up so that we publish changes to target block
            transformBlock.Value.LinkTo(targetBlock, DataflowOption.PropagateCompletion);

            // Join the source blocks, so if they need to switch to UI thread to complete
            // and someone is blocked on us on the same thread, the call proceeds
            JoinUpstreamDataSources(source);

            return(transformBlock);
        }