コード例 #1
0
        protected override void Initialize()
        {
            // Create our broadcast block for subscribers to get new ILaunchProfiles Information
            _broadcastBlock     = DataflowBlockSlim.CreateBroadcastBlock <ILaunchSettings>();
            _changedSourceBlock = _broadcastBlock.SafePublicize();


            // Subscribe to changes to the broadcast block using the idle scheduler. This should filter out a lot of the intermediates
            // states that files can be in.
            if (_projectSubscriptionService != null)
            {
                // The use of AsyncLazy with dataflow can allow state stored in the execution context to leak through. The downstream affect is
                // calls to say, get properties, may fail. To avoid this, we capture the execution context here, and it will be reapplied when
                // we get new subscription data from the dataflow.
                ITargetBlock <IProjectVersionedValue <Tuple <IProjectSubscriptionUpdate, IProjectCapabilitiesSnapshot> > > projectChangesBlock = DataflowBlockSlim.CreateActionBlock(
                    DataflowUtilities.CaptureAndApplyExecutionContext <IProjectVersionedValue <Tuple <IProjectSubscriptionUpdate, IProjectCapabilitiesSnapshot> > >(ProjectRuleBlock_ChangedAsync));
                StandardRuleDataflowLinkOptions evaluationLinkOptions = DataflowOption.WithRuleNames(ProjectDebugger.SchemaName);

                _projectRuleSubscriptionLink = ProjectDataSources.SyncLinkTo(
                    _projectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(evaluationLinkOptions),
                    _commonProjectServices.Project.Capabilities.SourceBlock.SyncLinkOptions(),
                    projectChangesBlock,
                    linkOptions: DataflowOption.PropagateCompletion);
            }

            // Make sure we are watching the file at this point
            WatchLaunchSettingsFile();
        }
コード例 #2
0
        protected override void Initialize()
        {
            base.Initialize();

            // Create an action block to process the design time inputs and configuration general changes
            ITargetBlock <IProjectVersionedValue <ValueTuple <DesignTimeInputs, IProjectSubscriptionUpdate> > > inputsAction = DataflowBlockSlim.CreateActionBlock <IProjectVersionedValue <ValueTuple <DesignTimeInputs, IProjectSubscriptionUpdate> > >(ProcessDataflowChanges);

            _broadcastBlock = DataflowBlockSlim.CreateBroadcastBlock <IProjectVersionedValue <DesignTimeInputsDelta> >(nameFormat: nameof(DesignTimeInputsChangeTracker) + "Broadcast {1}");
            _publicBlock    = AllowSourceBlockCompletion ? _broadcastBlock : _broadcastBlock.SafePublicize();

            Assumes.Present(_project.Services.ProjectAsynchronousTasks);

            IDisposable projectLink = ProjectDataSources.SyncLinkTo(
                _inputsDataSource.SourceBlock.SyncLinkOptions(
                    linkOptions: DataflowOption.PropagateCompletion),
                _projectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(
                    linkOptions: DataflowOption.WithRuleNames(ConfigurationGeneral.SchemaName)),
                inputsAction,
                DataflowOption.PropagateCompletion,
                cancellationToken: _project.Services.ProjectAsynchronousTasks.UnloadCancellationToken);

            // Create an action block to process file change notifications
            ITargetBlock <IProjectVersionedValue <string[]> > fileWatcherAction = DataflowBlockSlim.CreateActionBlock <IProjectVersionedValue <string[]> >(ProcessFileChangeNotification);
            IDisposable watcherLink = _fileWatcher.SourceBlock.LinkTo(fileWatcherAction, DataflowOption.PropagateCompletion);

            _disposables.Add(projectLink);
            _disposables.Add(watcherLink);

            JoinUpstreamDataSources(_inputsDataSource, _projectSubscriptionService.ProjectRuleSource, _fileWatcher);
        }
        protected override IDisposable LinkExternalInput(ITargetBlock <IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> > targetBlock)
        {
            Assumes.Present(_configuredProject.Services.ProjectSubscription);

            // Initial state is empty. We will evolve this reference over time, updating it iteratively
            // on each new data update.
            UpToDateCheckImplicitConfiguredInput state = UpToDateCheckImplicitConfiguredInput.Empty;

            IPropagatorBlock <IProjectVersionedValue <UpdateValues>, IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> > transformBlock
                = DataflowBlockSlim.CreateTransformBlock <IProjectVersionedValue <UpdateValues>, IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> >(Transform);

            IProjectValueDataSource <IProjectSubscriptionUpdate> source1 = _configuredProject.Services.ProjectSubscription.JointRuleSource;
            IProjectValueDataSource <IProjectSubscriptionUpdate> source2 = _configuredProject.Services.ProjectSubscription.SourceItemsRuleSource;
            IProjectValueDataSource <IProjectSnapshot>           source3 = _configuredProject.Services.ProjectSubscription.ProjectSource;
            IProjectItemSchemaService source4 = _projectItemSchemaService;
            IProjectValueDataSource <IProjectCatalogSnapshot> source5 = _configuredProject.Services.ProjectSubscription.ProjectCatalogSource;

            return(new DisposableBag
            {
                // Sync-link various sources to our transform block
                ProjectDataSources.SyncLinkTo(
                    source1.SourceBlock.SyncLinkOptions(DataflowOption.WithRuleNames(ProjectPropertiesSchemas)),
                    source2.SourceBlock.SyncLinkOptions(),
                    source3.SourceBlock.SyncLinkOptions(),
                    source4.SourceBlock.SyncLinkOptions(),
                    source5.SourceBlock.SyncLinkOptions(),
                    target: transformBlock,
                    linkOptions: DataflowOption.PropagateCompletion,
                    CancellationToken.None),

                // Link the transform block to our target block
                transformBlock.LinkTo(targetBlock, DataflowOption.PropagateCompletion),

                JoinUpstreamDataSources(source1, source2, source3, source4, source5)
            });

            IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> Transform(IProjectVersionedValue <UpdateValues> e)
            {
                var snapshot = e.Value.Item3 as IProjectSnapshot2;

                Assumes.NotNull(snapshot);

                state = state.Update(
                    jointRuleUpdate: e.Value.Item1,
                    sourceItemsUpdate: e.Value.Item2,
                    projectSnapshot: snapshot,
                    projectItemSchema: e.Value.Item4,
                    projectCatalogSnapshot: e.Value.Item5,
                    configuredProjectVersion: e.DataSourceVersions[ProjectDataSources.ConfiguredProjectVersion]);

                return(new ProjectVersionedValue <UpToDateCheckImplicitConfiguredInput>(state, e.DataSourceVersions));
            }
        }
コード例 #4
0
            /// <summary>
            /// Initialize the watcher.
            /// </summary>
            protected override Task InitializeCoreAsync(CancellationToken cancellationToken)
            {
                return(_projectTasksService.LoadedProjectAsync(() =>
                {
                    // The tree source to get changes to the tree so that we can identify when the assets file changes.
                    ProjectDataSources.SourceBlockAndLink <IProjectVersionedValue <IProjectTreeSnapshot> > treeSource = _fileSystemTreeProvider.Tree.SyncLinkOptions();

                    // The property source used to get the value of the $ProjectAssetsFile property so that we can identify the location of the assets file.
                    StandardRuleDataflowLinkOptions sourceLinkOptions = DataflowOption.WithRuleNames(ConfigurationGeneral.SchemaName);

                    ProjectDataSources.SourceBlockAndLink <IProjectVersionedValue <IProjectSubscriptionUpdate> > propertySource = _activeConfiguredProjectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(sourceLinkOptions);
                    ITargetBlock <IProjectVersionedValue <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > > target = DataflowBlockSlim.CreateActionBlock <IProjectVersionedValue <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > >(DataFlow_ChangedAsync);

                    // Join the two sources so that we get synchronized versions of the data.
                    _treeWatcher = ProjectDataSources.SyncLinkTo(treeSource, propertySource, target);

                    return Task.CompletedTask;
                }));
            }
            private void OnActiveConfigurationsChanged(IProjectVersionedValue <IConfigurationGroup <ConfiguredProject> > e)
            {
                if (IsDisposing || IsDisposed)
                {
                    return;
                }

                // Clean up past subscriptions
                _designTimeBuildSubscriptionLink?.Dispose();

                if (e.Value.Count > 0)
                {
                    StandardRuleDataflowLinkOptions sourceLinkOptions = DataflowOption.WithRuleNames(s_designTimeBuildWatchedRules);

                    var disposableBag = new DisposableBag(CancellationToken.None);
                    // We are taking source blocks from multiple configured projects and creating a SyncLink to combine the sources.
                    // The SyncLink will only publish data when the versions of the sources match. There is a problem with that.
                    // The sources have some version components that will make this impossible to match across TFMs. We introduce a
                    // intermediate block here that will remove those version components so that the synclink can actually sync versions.
                    IEnumerable <ProjectDataSources.SourceBlockAndLink <IProjectValueVersions> > sourceBlocks = e.Value.Select(
                        cp =>
                    {
                        IReceivableSourceBlock <IProjectVersionedValue <IProjectSubscriptionUpdate> > sourceBlock = cp.Services.ProjectSubscription.JointRuleSource.SourceBlock;
                        IPropagatorBlock <IProjectVersionedValue <IProjectSubscriptionUpdate>, IProjectVersionedValue <IProjectSubscriptionUpdate> > versionDropper = CreateVersionDropperBlock();
                        disposableBag.AddDisposable(sourceBlock.LinkTo(versionDropper, sourceLinkOptions));
                        return(versionDropper.SyncLinkOptions <IProjectValueVersions>(sourceLinkOptions));
                    });

                    Action <Tuple <ImmutableList <IProjectValueVersions>, TIdentityDictionary> > action = ProjectPropertyChanged;
                    var target = DataflowBlockSlim.CreateActionBlock(action);

                    DataflowLinkOptions targetLinkOptions = DataflowOption.PropagateCompletion;

                    ImmutableList <ProjectDataSources.SourceBlockAndLink <IProjectValueVersions> > sourceBlocksAndCapabilitiesOptions = sourceBlocks.ToImmutableList()
                                                                                                                                        .Insert(0, _projectVsServices.Project.Capabilities.SourceBlock.SyncLinkOptions <IProjectValueVersions>());

                    disposableBag.AddDisposable(ProjectDataSources.SyncLinkTo(sourceBlocksAndCapabilitiesOptions, target, targetLinkOptions));

                    _designTimeBuildSubscriptionLink = disposableBag;
                }
            }
コード例 #6
0
        /// <summary>
        /// Initialize the watcher.
        /// </summary>
        protected override async Task InitializeCoreAsync(CancellationToken cancellationToken)
        {
            // Explicitly get back to the thread pool for the rest of this method so we don't tie up the UI thread;
            await TaskScheduler.Default;

            await _projectTasksService.LoadedProjectAsync(() =>
            {
                // The tree source to get changes to the tree so that we can identify when the assets file changes.
                ProjectDataSources.SourceBlockAndLink <IProjectVersionedValue <IProjectTreeSnapshot> > treeSource = _fileSystemTreeProvider.Tree.SyncLinkOptions();

                // The property source used to get the value of the $ProjectAssetsFile property so that we can identify the location of the assets file.
                StandardRuleDataflowLinkOptions sourceLinkOptions = DataflowOption.WithRuleNames(ConfigurationGeneral.SchemaName);

                ProjectDataSources.SourceBlockAndLink <IProjectVersionedValue <IProjectSubscriptionUpdate> > propertySource = _activeConfiguredProjectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(sourceLinkOptions);
                var target = new ActionBlock <IProjectVersionedValue <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > >(DataFlow_ChangedAsync);

                // Join the two sources so that we get synchronized versions of the data.
                _treeWatcher = ProjectDataSources.SyncLinkTo(treeSource, propertySource, target);

                return(Task.CompletedTask);
            });
        }
コード例 #7
0
        protected override Task InitializeCoreAsync(CancellationToken cancellationToken)
        {
            _link = ProjectDataSources.SyncLinkTo(
                _configuredProject.Services.ProjectSubscription.JointRuleSource.SourceBlock.SyncLinkOptions(DataflowOption.WithRuleNames(ProjectPropertiesSchemas)),
                _configuredProject.Services.ProjectSubscription.SourceItemsRuleSource.SourceBlock.SyncLinkOptions(),
                _projectItemSchemaService.SourceBlock.SyncLinkOptions(),
                target: DataflowBlockSlim.CreateActionBlock <IProjectVersionedValue <Tuple <IProjectSubscriptionUpdate, IProjectSubscriptionUpdate, IProjectItemSchema> > >(OnChanged),
                linkOptions: DataflowOption.PropagateCompletion);

            return(Task.CompletedTask);
        }
コード例 #8
0
        protected override IDisposable LinkExternalInput(ITargetBlock <IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> > targetBlock)
        {
            Assumes.Present(_configuredProject.Services.ProjectSubscription);

            bool attemptedStateRestore = false;

            // Initial state is empty. We will evolve this reference over time, updating it iteratively
            // on each new data update.
            UpToDateCheckImplicitConfiguredInput state = UpToDateCheckImplicitConfiguredInput.CreateEmpty(_configuredProject.ProjectConfiguration);

            IPropagatorBlock <IProjectVersionedValue <UpdateValues>, IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> > transformBlock
                = DataflowBlockSlim.CreateTransformBlock <IProjectVersionedValue <UpdateValues>, IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> >(TransformAsync);

            IProjectValueDataSource <IProjectSubscriptionUpdate> source1 = _configuredProject.Services.ProjectSubscription.JointRuleSource;
            IProjectValueDataSource <IProjectSubscriptionUpdate> source2 = _configuredProject.Services.ProjectSubscription.SourceItemsRuleSource;
            IProjectItemSchemaService source3 = _projectItemSchemaService;
            IProjectValueDataSource <IProjectCatalogSnapshot> source4 = _configuredProject.Services.ProjectSubscription.ProjectCatalogSource;

            return(new DisposableBag
            {
                // Sync-link various sources to our transform block
                ProjectDataSources.SyncLinkTo(
                    source1.SourceBlock.SyncLinkOptions(DataflowOption.WithRuleNames(ProjectPropertiesSchemas)),
                    source2.SourceBlock.SyncLinkOptions(),
                    source3.SourceBlock.SyncLinkOptions(),
                    source4.SourceBlock.SyncLinkOptions(),
                    target: transformBlock,
                    linkOptions: DataflowOption.PropagateCompletion,
                    CancellationToken.None),

                // Link the transform block to our target block
                transformBlock.LinkTo(targetBlock, DataflowOption.PropagateCompletion),

                JoinUpstreamDataSources(source1, source2, source3, source4)
            });

            async Task <IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> > TransformAsync(IProjectVersionedValue <UpdateValues> e)
            {
                if (!attemptedStateRestore)
                {
                    attemptedStateRestore = true;

                    if (_persistentState is not null)
                    {
                        // Restoring state requires the UI thread. We must use JTF.RunAsync here to ensure the UI
                        // thread is shared between related work and prevent deadlocks.
                        (int ItemHash, DateTime InputsChangedAtUtc)? restoredState =
                            await JoinableFactory.RunAsync(() => _persistentState.RestoreStateAsync(_configuredProject.UnconfiguredProject.FullPath, _configuredProject.ProjectConfiguration.Dimensions, _projectAsynchronousTasksService.UnloadCancellationToken));

                        if (restoredState is not null)
                        {
                            state = state.WithRestoredState(restoredState.Value.ItemHash, restoredState.Value.InputsChangedAtUtc);
                        }
                    }
                }

                int?     priorItemHash = state.ItemHash;
                DateTime priorLastItemsChangedAtUtc = state.LastItemsChangedAtUtc;

                state = state.Update(
                    jointRuleUpdate: e.Value.Item1,
                    sourceItemsUpdate: e.Value.Item2,
                    projectItemSchema: e.Value.Item3,
                    projectCatalogSnapshot: e.Value.Item4);

                if (state.ItemHash is not null && _persistentState is not null && (priorItemHash != state.ItemHash || priorLastItemsChangedAtUtc != state.LastItemsChangedAtUtc))
                {
                    await _persistentState.StoreStateAsync(_configuredProject.UnconfiguredProject.FullPath, _configuredProject.ProjectConfiguration.Dimensions, state.ItemHash.Value, state.LastItemsChangedAtUtc, _projectAsynchronousTasksService.UnloadCancellationToken);
                }

                return(new ProjectVersionedValue <UpToDateCheckImplicitConfiguredInput>(state, e.DataSourceVersions));
            }
        }
コード例 #9
0
            protected override async Task InitializeCoreAsync(CancellationToken cancellationToken)
            {
                _contextAccessor = await _workspaceProjectContextProvider.CreateProjectContextAsync(_project);

                if (_contextAccessor == null)
                {
                    return;
                }

                _activeWorkspaceProjectContextTracker.RegisterContext(_contextAccessor.ContextId);

                _applyChangesToWorkspaceContext = _applyChangesToWorkspaceContextFactory.CreateExport();
                _applyChangesToWorkspaceContext.Value.Initialize(_contextAccessor.Context);

                _evaluationProgressRegistration   = _dataProgressTrackerService.RegisterForIntelliSense(this, _project, nameof(WorkspaceProjectContextHostInstance) + ".Evaluation");
                _projectBuildProgressRegistration = _dataProgressTrackerService.RegisterForIntelliSense(this, _project, nameof(WorkspaceProjectContextHostInstance) + ".ProjectBuild");

                _disposables = new DisposableBag
                {
                    _applyChangesToWorkspaceContext,
                    _evaluationProgressRegistration,
                    _projectBuildProgressRegistration,

                    ProjectDataSources.SyncLinkTo(
                        _activeConfiguredProjectProvider.ActiveConfiguredProjectBlock.SyncLinkOptions(),
                        _projectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(GetProjectEvaluationOptions()),
                        _projectSubscriptionService.SourceItemsRuleSource.SourceBlock.SyncLinkOptions(),
                        target: DataflowBlockFactory.CreateActionBlock <IProjectVersionedValue <(ConfiguredProject, IProjectSubscriptionUpdate, IProjectSubscriptionUpdate)> >(
                            OnEvaluationUpdateAsync,
                            _project.UnconfiguredProject,
                            ProjectFaultSeverity.LimitedFunctionality),
                        linkOptions: DataflowOption.PropagateCompletion,
                        cancellationToken: cancellationToken),

                    ProjectDataSources.SyncLinkTo(
                        _activeConfiguredProjectProvider.ActiveConfiguredProjectBlock.SyncLinkOptions(),
                        _projectSubscriptionService.ProjectBuildRuleSource.SourceBlock.SyncLinkOptions(GetProjectBuildOptions()),
                        _commandLineArgumentsProvider.SourceBlock.SyncLinkOptions(),
                        target: DataflowBlockFactory.CreateActionBlock <IProjectVersionedValue <(ConfiguredProject, IProjectSubscriptionUpdate, CommandLineArgumentsSnapshot)> >(
                            OnBuildUpdateAsync,
                            _project.UnconfiguredProject,
                            ProjectFaultSeverity.LimitedFunctionality),
                        linkOptions: DataflowOption.PropagateCompletion,
                        cancellationToken: cancellationToken)
                };

                return;

                StandardRuleDataflowLinkOptions GetProjectEvaluationOptions()
                {
                    return(DataflowOption.WithRuleNames(_applyChangesToWorkspaceContext.Value.GetProjectEvaluationRules()));
                }

                StandardRuleDataflowLinkOptions GetProjectBuildOptions()
                {
                    return(DataflowOption.WithRuleNames(_applyChangesToWorkspaceContext.Value.GetProjectBuildRules()));
                }

                Task OnEvaluationUpdateAsync(IProjectVersionedValue <(ConfiguredProject ActiveConfiguredProject, IProjectSubscriptionUpdate ProjectUpdate, IProjectSubscriptionUpdate SourceItemsUpdate)> e)
                {
                    return(OnProjectChangedAsync(
                               _evaluationProgressRegistration,
                               e.Value.ActiveConfiguredProject,
                               e,
                               hasChange: static e => e.Value.ProjectUpdate.ProjectChanges.HasChange() || e.Value.SourceItemsUpdate.ProjectChanges.HasChange(),
                               applyFunc: static (e, applyChangesToWorkspaceContext, contextState, token) => applyChangesToWorkspaceContext.ApplyProjectEvaluation(e.Derive(v => (v.ProjectUpdate, v.SourceItemsUpdate)), contextState, token)));
                }

                Task OnBuildUpdateAsync(IProjectVersionedValue <(ConfiguredProject ActiveConfiguredProject, IProjectSubscriptionUpdate BuildUpdate, CommandLineArgumentsSnapshot CommandLineArgumentsUpdate)> e)
                {
                    return(OnProjectChangedAsync(
                               _projectBuildProgressRegistration,
                               e.Value.ActiveConfiguredProject,
                               e,
                               hasChange: static e => e.Value.BuildUpdate.ProjectChanges.HasChange() || e.Value.CommandLineArgumentsUpdate.IsChanged,
                               applyFunc: static (e, applyChangesToWorkspaceContext, contextState, token) => applyChangesToWorkspaceContext.ApplyProjectBuild(e.Derive(v => (v.BuildUpdate, v.CommandLineArgumentsUpdate)), contextState, token)));
                }
            }
コード例 #10
0
        protected override Task InitializeCoreAsync(CancellationToken cancellationToken)
        {
            Assumes.Present(_configuredProject.Services.ProjectSubscription);

            _link = ProjectDataSources.SyncLinkTo(
                _configuredProject.Services.ProjectSubscription.JointRuleSource.SourceBlock.SyncLinkOptions(DataflowOption.WithRuleNames(ProjectPropertiesSchemas)),
                _configuredProject.Services.ProjectSubscription.SourceItemsRuleSource.SourceBlock.SyncLinkOptions(),
                _configuredProject.Services.ProjectSubscription.ProjectSource.SourceBlock.SyncLinkOptions(),
                _projectItemSchemaService.SourceBlock.SyncLinkOptions(),
                _configuredProject.Services.ProjectSubscription.ProjectCatalogSource.SourceBlock.SyncLinkOptions(),
                target: DataflowBlockFactory.CreateActionBlock <IProjectVersionedValue <ValueTuple <IProjectSubscriptionUpdate, IProjectSubscriptionUpdate, IProjectSnapshot, IProjectItemSchema, IProjectCatalogSnapshot> > >(OnChanged, _configuredProject.UnconfiguredProject),
                linkOptions: DataflowOption.PropagateCompletion,
                cancellationToken: cancellationToken);

            return(Task.CompletedTask);
        }