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); }
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); }
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)); }