private async Task AddSubscriptionsAsync(AggregateWorkspaceProjectContext newProjectContext) { Requires.NotNull(newProjectContext, nameof(newProjectContext)); await _commonServices.ThreadingService.SwitchToUIThread(); await _tasksService.LoadedProjectAsync(() => { IEnumerable <string> watchedEvaluationRules = _languageServiceHandlerManager.GetWatchedRules(RuleHandlerType.Evaluation); IEnumerable <string> watchedDesignTimeBuildRules = _languageServiceHandlerManager.GetWatchedRules(RuleHandlerType.DesignTimeBuild); foreach (ConfiguredProject configuredProject in newProjectContext.InnerConfiguredProjects) { if (_projectConfigurationsWithSubscriptions.Contains(configuredProject.ProjectConfiguration)) { continue; } _designTimeBuildSubscriptionLinks.Add(configuredProject.Services.ProjectSubscription.JointRuleSource.SourceBlock.LinkTo( new ActionBlock <IProjectVersionedValue <IProjectSubscriptionUpdate> >(e => OnProjectChangedCoreAsync(e, RuleHandlerType.DesignTimeBuild)), ruleNames: watchedDesignTimeBuildRules, suppressVersionOnlyUpdates: true)); _evaluationSubscriptionLinks.Add(configuredProject.Services.ProjectSubscription.ProjectRuleSource.SourceBlock.LinkTo( new ActionBlock <IProjectVersionedValue <IProjectSubscriptionUpdate> >(e => OnProjectChangedCoreAsync(e, RuleHandlerType.Evaluation)), ruleNames: watchedEvaluationRules, suppressVersionOnlyUpdates: true)); _projectConfigurationsWithSubscriptions.Add(configuredProject.ProjectConfiguration); } return(Task.CompletedTask); }); }
private async Task AddSubscriptionsAsync(AggregateWorkspaceProjectContext newProjectContext) { Requires.NotNull(newProjectContext, nameof(newProjectContext)); await _commonServices.ThreadingService.SwitchToUIThread(); using (_tasksService.LoadedProject()) { var watchedEvaluationRules = GetWatchedRules(RuleHandlerType.Evaluation); var watchedDesignTimeBuildRules = GetWatchedRules(RuleHandlerType.DesignTimeBuild); foreach (var configuredProject in newProjectContext.InnerConfiguredProjects) { if (_projectConfigurationsWithSubscriptions.Contains(configuredProject.ProjectConfiguration)) { continue; } _designTimeBuildSubscriptionLinks.Add(configuredProject.Services.ProjectSubscription.JointRuleSource.SourceBlock.LinkTo( new ActionBlock <IProjectVersionedValue <IProjectSubscriptionUpdate> >(e => OnProjectChangedCoreAsync(e, RuleHandlerType.DesignTimeBuild)), ruleNames: watchedDesignTimeBuildRules.Union(watchedEvaluationRules), suppressVersionOnlyUpdates: true)); _evaluationSubscriptionLinks.Add(configuredProject.Services.ProjectSubscription.ProjectRuleSource.SourceBlock.LinkTo( new ActionBlock <IProjectVersionedValue <IProjectSubscriptionUpdate> >(e => OnProjectChangedCoreAsync(e, RuleHandlerType.Evaluation)), ruleNames: watchedEvaluationRules, suppressVersionOnlyUpdates: true)); _projectConfigurationsWithSubscriptions.Add(configuredProject.ProjectConfiguration); } } }
private async Task DisposeAggregateProjectContextAsync(AggregateWorkspaceProjectContext projectContext) { await _contextProvider.Value.ReleaseProjectContextAsync(projectContext).ConfigureAwait(false); foreach (IWorkspaceProjectContext innerContext in projectContext.DisposedInnerProjectContexts) { _languageServiceHandlerManager.OnContextReleased(innerContext); } }
/// <summary> /// Ensures that <see cref="_currentAggregateProjectContext"/> is updated for the latest TargetFrameworks from the project properties /// and returns this value. /// </summary> private async Task <AggregateWorkspaceProjectContext> UpdateProjectContextAsync() { // Ensure that only single thread is attempting to create a project context. AggregateWorkspaceProjectContext previousContextToDispose = null; using (await _gate.DisposableWaitAsync().ConfigureAwait(false)) { // Check if we have already computed the project context. if (_currentAggregateProjectContext != null) { // For non-cross targeting projects, we can use the current project context. // For cross-targeting projects, we need to verify that the TargetFrameworks for the current project context matches latest TargetFrameworks project property value. // If not, we create a new one and dispose the current one. if (!_currentAggregateProjectContext.IsCrossTargeting) { return(_currentAggregateProjectContext); } var projectProperties = await _commonServices.ActiveConfiguredProjectProperties.GetConfigurationGeneralPropertiesAsync().ConfigureAwait(false); var targetFrameworks = (string)await projectProperties.TargetFrameworks.GetValueAsync().ConfigureAwait(false); if (_currentAggregateProjectContext.HasMatchingTargetFrameworks(targetFrameworks)) { return(_currentAggregateProjectContext); } previousContextToDispose = _currentAggregateProjectContext; } // Force refresh the CPS active project configuration (needs UI thread). await _commonServices.ThreadingService.SwitchToUIThread(); await _activeProjectConfigurationRefreshService.RefreshActiveProjectConfigurationAsync().ConfigureAwait(false); // Create new project context. _currentAggregateProjectContext = await _contextProvider.Value.CreateProjectContextAsync().ConfigureAwait(false); // Dispose the old project context, if one exists. if (previousContextToDispose != null) { await _contextProvider.Value.ReleaseProjectContextAsync(previousContextToDispose).ConfigureAwait(false); foreach (var innerContext in previousContextToDispose.DisposedInnerProjectContexts) { foreach (var handler in Handlers) { await handler.Value.OnContextReleasedAsync(innerContext).ConfigureAwait(false); } } } return(_currentAggregateProjectContext); } }
private async Task UpdateProjectContextAndSubscriptionsAsync() { AggregateWorkspaceProjectContext previousProjectContext = _currentAggregateProjectContext; AggregateWorkspaceProjectContext newProjectContext = await UpdateProjectContextAsync().ConfigureAwait(false); if (previousProjectContext != newProjectContext) { // Add subscriptions for the new configured projects in the new project context. await AddSubscriptionsAsync(newProjectContext).ConfigureAwait(false); } }
private async Task DisposeAggregateProjectContextAsync(AggregateWorkspaceProjectContext projectContext) { await _contextProvider.Value.ReleaseProjectContextAsync(projectContext).ConfigureAwait(false); foreach (var innerContext in projectContext.DisposedInnerProjectContexts) { foreach (var handler in Handlers) { await handler.Value.OnContextReleasedAsync(innerContext).ConfigureAwait(false); } } }
/// <summary> /// Ensures that <see cref="_currentAggregateProjectContext"/> is updated for the latest target frameworks from the project properties /// and returns this value. /// </summary> private async Task <AggregateWorkspaceProjectContext> UpdateProjectContextAsync() { // Ensure that only single thread is attempting to create a project context. AggregateWorkspaceProjectContext previousContextToDispose = null; return(await ExecuteWithinLockAsync(async() => { await _commonServices.ThreadingService.SwitchToUIThread(); string newTargetFramework = null; var projectProperties = await _commonServices.ActiveConfiguredProjectProperties.GetConfigurationGeneralPropertiesAsync().ConfigureAwait(false); // Check if we have already computed the project context. if (_currentAggregateProjectContext != null) { // For non-cross targeting projects, we can use the current project context if the TargetFramework hasn't changed. // For cross-targeting projects, we need to verify that the current project context matches latest frameworks targeted by the project. // If not, we create a new one and dispose the current one. if (!_currentAggregateProjectContext.IsCrossTargeting) { newTargetFramework = (string)await projectProperties.TargetFramework.GetValueAsync().ConfigureAwait(false); if (StringComparers.PropertyValues.Equals(_currentTargetFramework, newTargetFramework)) { return _currentAggregateProjectContext; } // Dispose the old workspace project context for the previous target framework. await DisposeAggregateProjectContextAsync(_currentAggregateProjectContext).ConfigureAwait(false); } else { // Check if the current project context is up-to-date for the current active and known project configurations. var activeProjectConfiguration = _commonServices.ActiveConfiguredProject.ProjectConfiguration; var knownProjectConfigurations = await _commonServices.Project.Services.ProjectConfigurationsService.GetKnownProjectConfigurationsAsync().ConfigureAwait(false); if (knownProjectConfigurations.All(c => c.IsCrossTargeting()) && _currentAggregateProjectContext.HasMatchingTargetFrameworks(activeProjectConfiguration, knownProjectConfigurations)) { return _currentAggregateProjectContext; } previousContextToDispose = _currentAggregateProjectContext; } } else { newTargetFramework = (string)await projectProperties.TargetFramework.GetValueAsync().ConfigureAwait(false); } // Force refresh the CPS active project configuration (needs UI thread). await _commonServices.ThreadingService.SwitchToUIThread(); await _activeProjectConfigurationRefreshService.RefreshActiveProjectConfigurationAsync().ConfigureAwait(false); // Create new project context. _currentAggregateProjectContext = await _contextProvider.Value.CreateProjectContextAsync().ConfigureAwait(false); _currentTargetFramework = newTargetFramework; // Dispose the old project context, if one exists. if (previousContextToDispose != null) { await DisposeAggregateProjectContextAsync(previousContextToDispose).ConfigureAwait(false); } return _currentAggregateProjectContext; })); }