protected override async Task ApplyAsync(IProjectVersionedValue <ImmutableList <string> > value) { await JoinableFactory.SwitchToMainThreadAsync(); IProjectVersionedValue <ImmutableList <string> >?previous = AppliedValue; AppliedValue = value; // To avoid callers seeing an inconsistent state where there are no Imports, // we use BlockInitializeOnFirstAppliedValue to block on the first value // being applied. // // Due to that, and to avoid a deadlock when event handlers call back into us // while we're still initializing, we avoid firing the events the first time // a value is applied. if (previous != null) { VisualBasicVSImports imports = VSImports.Value; ImmutableList <string> currentValue = value.Value; ImmutableList <string> previousValue = previous.Value; foreach (string import in previousValue.Except(currentValue)) { imports.OnImportRemoved(import); } foreach (string import in currentValue.Except(previousValue)) { imports.OnImportAdded(import); } } }
private void StartupAnalyzerEventSink_MiddlewareAnalysisCompleted(object sender, MiddlewareAnalysis e) { // Fire-and-forget. We need to get to the UI thread for DTE/IVsHierarchy. JoinableCollection.Add(JoinableFactory.RunAsync(async() => { await JoinableFactory.SwitchToMainThreadAsync(); var solution = _workspace.Value.CurrentSolution; var syntaxTrees = new HashSet <SyntaxTree>(); foreach (var syntax in e.ConfigureMethod.DeclaringSyntaxReferences) { syntaxTrees.Add(syntax.SyntaxTree); } var documentIds = syntaxTrees.Select(s => solution.GetDocumentId(s)); var hierarchies = documentIds.Select(d => _workspace.Value.GetHierarchy(d.ProjectId)).Where(h => h != null); foreach (var hierarchy in hierarchies) { if (hierarchy is IVsBrowseObjectContext context && context.UnconfiguredProject == ConfiguredProject.UnconfiguredProject) { var capabilities = ImmutableHashSet <string> .Empty; if (e.Middleware.Any(m => m.UseMethod.Name == "UseSignalR")) { capabilities = ImmutableHashSet.Create("_PublishSignalRService"); } await UpdateCapabilitiesAsync(capabilities, CancellationToken.None).ConfigureAwait(false); } } })); }
/// <summary> /// ApplyAsync is called on the UI thread and its job is to update AppliedValue to be correct based on the changes that have come through data flow after being processed /// </summary> protected override async Task ApplyAsync(IProjectVersionedValue <DesignTimeInputSnapshot> value) { // Not using use the ThreadingService property because unit tests await JoinableFactory.SwitchToMainThreadAsync(); IProjectVersionedValue <DesignTimeInputSnapshot>?previous = AppliedValue; AppliedValue = value; // To avoid callers seeing an inconsistent state where there are no monikers, // we use BlockInitializeOnFirstAppliedValue to block on the first value // being applied. // // Due to that, and to avoid a deadlock when event handlers call back into us // while we're still initializing, we avoid firing the events the first time // a value is applied. if (previous != null) { DesignTimeInputSnapshot currentValue = value.Value; DesignTimeInputSnapshot previousValue = previous.Value; foreach (DesignTimeInputFileChange change in currentValue.ChangedInputs) { _buildManager.OnDesignTimeOutputDirty(_project.MakeRelative(change.File)); } foreach (string item in previousValue.Inputs.Except(currentValue.Inputs)) { _buildManager.OnDesignTimeOutputDeleted(_project.MakeRelative(item)); } } }
protected override async Task ApplyAsync(IProjectVersionedValue <ImmutableList <string> > value) { await JoinableFactory.SwitchToMainThreadAsync(); ImmutableList <string> current = AppliedValue?.Value ?? ImmutableList <string> .Empty; ImmutableList <string> input = value.Value; IEnumerable <string> removed = current.Except(input); IEnumerable <string> added = input.Except(current); AppliedValue = value; VisualBasicVSImports?imports = VSImports?.Value; if (imports != null) { foreach (string import in removed) { imports.OnImportRemoved(import); } foreach (string import in added) { imports.OnImportAdded(import); } } }
/// <summary> /// ApplyAsync is called on the UI thread and its job is to update AppliedValue to be correct based on the changes that have come through data flow after being processed /// </summary> protected override async Task ApplyAsync(IProjectVersionedValue <DesignTimeInputsDelta> value) { // Not using use the ThreadingService property because unit tests await JoinableFactory.SwitchToMainThreadAsync(); DesignTimeInputsDelta delta = value.Value; ImmutableHashSet <string>?removedFiles = AppliedValue?.Value.Inputs.Except(delta.Inputs); // As it happens the DesignTimeInputsDelta contains all of the state we need AppliedValue = value; foreach (DesignTimeInputFileChange change in delta.ChangedInputs) { _buildManager.OnDesignTimeOutputDirty(_project.MakeRelative(change.File)); } if (removedFiles != null) { foreach (string item in removedFiles) { _buildManager.OnDesignTimeOutputDeleted(_project.MakeRelative(item)); } } }
protected override async Task InitializeCoreAsync(CancellationToken cancellationToken) { // AdviseUpdateSolutionEvents call needs UI thread. await JoinableFactory.SwitchToMainThreadAsync(cancellationToken); _solutionBuildManager = await _solutionBuildManagerService.GetValueAsync(cancellationToken); (_solutionBuildManager as IVsSolutionBuildManager2)?.AdviseUpdateSolutionEvents(this, out _cookie); ErrorHandler.ThrowOnFailure(_solutionBuildManager.AdviseUpdateSolutionEvents3(this, out _cookie3)); _skipAnalyzersForImplicitlyTriggeredBuild = await _options.GetSkipAnalyzersForImplicitlyTriggeredBuildAsync(cancellationToken); _options.RegisterOptionChangedEventHandler(OnOptionChangedAsync); }
protected override async Task DisposeCoreAsync(bool initialized) { if (initialized) { if (_cookie != VSConstants.VSCOOKIE_NIL) { await JoinableFactory.SwitchToMainThreadAsync(); Verify.HResult(_solution.Value.UnadviseSolutionEvents(_cookie)); _loadedInHost.TrySetCanceled(); _cookie = VSConstants.VSCOOKIE_NIL; } } }
protected override async Task InitializeCoreAsync(CancellationToken cancellationToken) { await JoinableFactory.SwitchToMainThreadAsync(cancellationToken); Verify.HResult(_solution.Value.AdviseSolutionEvents(this, out _cookie)); // In the situation where the solution has already been loaded by the time we're // initialized, we need to make sure we set LoadedInHost as we will have missed the // event. This can occur when the first CPS project is loaded due to reload of // an unloaded project or the first CPS project is loaded in the Add New/Existing Project // case. Verify.HResult(_solution.Value.GetProperty((int)__VSPROPID4.VSPROPID_IsSolutionFullyLoaded, out object isFullyLoaded)); if ((bool)isFullyLoaded) { _loadedInHost.SetResult(); } }