private void RaiseDiagnosticsUpdated( IDiagnosticUpdateSource source, DiagnosticsUpdatedArgs args ) { _eventListenerTracker.EnsureEventListener(args.Workspace, this); var ev = _eventMap.GetEventHandlers <EventHandler <DiagnosticsUpdatedArgs> >( DiagnosticsUpdatedEventName ); _eventQueue.ScheduleTask( DiagnosticsUpdatedEventName, () => { if (!UpdateDataMap(source, args)) { // there is no change, nothing to raise events for. return; } ev.RaiseEvent(handler => handler(source, args)); }, CancellationToken.None ); }
public DiagnosticTaggerWrapper( TestWorkspace workspace, IDiagnosticUpdateSource updateSource, bool createTaggerProvider = true) : this(workspace, null, updateSource, createTaggerProvider) { }
private bool ClearDiagnosticsReportedBySource(IDiagnosticUpdateSource source, List <DiagnosticsUpdatedArgs> removed) { // we expect source who uses this ability to have small number of diagnostics. lock (_gate) { Debug.Assert(_updateSources.Contains(source)); // 2 different workspaces (ex, PreviewWorkspaces) can return same Args.Id, we need to // distinguish them. so we separate diagnostics per workspace map. if (!_map.TryGetValue(source, out var workspaceMap)) { return(false); } foreach (var(workspace, map) in workspaceMap) { foreach (var(id, data) in map) { removed.Add(DiagnosticsUpdatedArgs.DiagnosticsRemoved(id, data.Workspace, solution: null, data.ProjectId, data.DocumentId)); } } // all diagnostics from the source is cleared _map.Remove(source); return(true); } }
private void AppendMatchingData( IDiagnosticUpdateSource source, Workspace workspace, ProjectId projectId, DocumentId documentId, object id, List <Data> list) { lock (_gate) { Dictionary <object, Data> current; if (!_map.TryGetValue(source, out current)) { return; } if (id != null) { Data data; if (current.TryGetValue(id, out data)) { list.Add(data); } return; } foreach (var data in current.Values) { if (TryAddData(documentId, data, d => d.DocumentId, list) || TryAddData(projectId, data, d => d.ProjectId, list) || TryAddData(workspace, data, d => d.Workspace, list)) { continue; } } } }
private bool UpdateDataMap(IDiagnosticUpdateSource source, DiagnosticsUpdatedArgs args) { // we expect source who uses this ability to have small number of diagnostics. lock (_gate) { Contract.Requires(_updateSources.Contains(source)); // check cheap early bail out if (args.Diagnostics.Length == 0 && !_map.ContainsKey(source)) { // no new diagnostic, and we don't have update source for it. return(false); } var diagnosticDataMap = _map.GetOrAdd(source, _ => new Dictionary <object, Data>()); diagnosticDataMap.Remove(args.Id); if (diagnosticDataMap.Count == 0 && args.Diagnostics.Length == 0) { _map.Remove(source); return(true); } var data = source.SupportGetDiagnostics ? new Data(args) : new Data(args, args.Diagnostics); diagnosticDataMap.Add(args.Id, data); return(true); } }
private void AppendMatchingData( IDiagnosticUpdateSource source, Workspace workspace, ProjectId projectId, DocumentId documentId, object id, ArrayBuilder <Data> list) { Contract.ThrowIfNull(workspace); lock (_gate) { if (!_map.TryGetValue(source, out var workspaceMap) || !workspaceMap.TryGetValue(workspace, out var current)) { return; } if (id != null) { if (current.TryGetValue(id, out var data)) { list.Add(data); } return; } foreach (var data in current.Values) { if (TryAddData(workspace, documentId, data, d => d.DocumentId, list) || TryAddData(workspace, projectId, data, d => d.ProjectId, list) || TryAddData(workspace, workspace, data, d => d.Workspace, list)) { continue; } } } }
private DiagnosticTaggerWrapper(TestWorkspace workspace, DiagnosticAnalyzerService analyzerService, IDiagnosticUpdateSource updateSource) { if (updateSource == null) { updateSource = analyzerService; } this.workspace = workspace; this.registrationService = workspace.Services.GetService<ISolutionCrawlerRegistrationService>(); registrationService.Register(workspace); this.asyncListener = new AsynchronousOperationListener(); var listeners = AsynchronousOperationListener.CreateListeners( ValueTuple.Create(FeatureAttribute.DiagnosticService, asyncListener), ValueTuple.Create(FeatureAttribute.ErrorSquiggles, asyncListener)); this.analyzerService = analyzerService; var diagnosticService = new DiagnosticService(SpecializedCollections.SingletonEnumerable(updateSource), listeners); this.TaggerProvider = new DiagnosticsSquiggleTaggerProvider( workspace.Services.GetService<IOptionService>(), diagnosticService, workspace.GetService<IForegroundNotificationService>(), listeners); if (analyzerService != null) { this.incrementalAnalyzers = ImmutableArray.Create(analyzerService.CreateIncrementalAnalyzer(workspace)); this.solutionCrawlerService = workspace.Services.GetService<ISolutionCrawlerRegistrationService>() as SolutionCrawlerRegistrationService; } }
private void RaiseDiagnosticsCleared(IDiagnosticUpdateSource source) { var ev = _eventMap.GetEventHandlers <EventHandler <DiagnosticsUpdatedArgs> >(DiagnosticsUpdatedEventName); var eventToken = _listener.BeginAsyncOperation(DiagnosticsUpdatedEventName); _eventQueue.ScheduleTask(() => { using var pooledObject = SharedPools.Default <List <DiagnosticsUpdatedArgs> >().GetPooledObject(); var removed = pooledObject.Object; if (!ClearDiagnosticsReportedBySource(source, removed)) { // there is no change, nothing to raise events for. return; } // don't create event listener if it haven't created yet. if there is a diagnostic to remove // listener should have already created since all events are done in the serialized queue foreach (var args in removed) { ev.RaiseEvent(handler => handler(source, args)); } }).CompletesAsyncOperation(eventToken); }
private void RaiseDiagnosticsCleared(IDiagnosticUpdateSource source) { var ev = _eventMap.GetEventHandlers <EventHandler <DiagnosticsUpdatedArgs> >(DiagnosticsUpdatedEventName); if (!RequireRunningEventTasks(source, ev)) { return; } var eventToken = _listener.BeginAsyncOperation(DiagnosticsUpdatedEventName); _eventQueue.ScheduleTask(() => { using (var pooledObject = SharedPools.Default <List <DiagnosticsUpdatedArgs> >().GetPooledObject()) { var removed = pooledObject.Object; if (!ClearDiagnosticsReportedBySource(source, removed)) { // there is no change, nothing to raise events for. return; } foreach (var args in removed) { ev.RaiseEvent(handler => handler(source, args)); } } }).CompletesAsyncOperation(eventToken); }
private bool UpdateDataMap(IDiagnosticUpdateSource source, DiagnosticsUpdatedArgs args) { // we expect source who uses this ability to have small number of diagnostics. lock (_gate) { Debug.Assert(_updateSources.Contains(source)); // The diagnostic service itself caches all diagnostics produced by the IDiagnosticUpdateSource's. As // such, we want to grab all the diagnostics (regardless of push/pull setting) and cache inside // ourselves. Later, when anyone calls GetDiagnostics or GetDiagnosticBuckets we will check if their // push/pull request matches the current user setting and return these if appropriate. var diagnostics = args.GetAllDiagnosticsRegardlessOfPushPullSetting(); // check cheap early bail out if (diagnostics.Length == 0 && !_map.ContainsKey(source)) { // no new diagnostic, and we don't have update source for it. return(false); } // 2 different workspaces (ex, PreviewWorkspaces) can return same Args.Id, we need to // distinguish them. so we separate diagnostics per workspace map. var workspaceMap = _map.GetOrAdd(source, _ => new Dictionary <Workspace, Dictionary <object, Data> >()); if (diagnostics.Length == 0 && !workspaceMap.ContainsKey(args.Workspace)) { // no new diagnostic, and we don't have workspace for it. return(false); } var diagnosticDataMap = workspaceMap.GetOrAdd(args.Workspace, _ => new Dictionary <object, Data>()); diagnosticDataMap.Remove(args.Id); if (diagnosticDataMap.Count == 0 && diagnostics.Length == 0) { workspaceMap.Remove(args.Workspace); if (workspaceMap.Count == 0) { _map.Remove(source); } return(true); } if (diagnostics.Length > 0) { // save data only if there is a diagnostic var data = source.SupportGetDiagnostics ? new Data(args) : new Data(args, diagnostics); diagnosticDataMap.Add(args.Id, data); } return(true); } }
public void Register(IDiagnosticUpdateSource source) { lock (_gate) { if (_updateSources.Contains(source)) { return; } _updateSources = _updateSources.Add(source); source.DiagnosticsUpdated += OnDiagnosticsUpdated; } }
private bool UpdateDataMap(IDiagnosticUpdateSource source, DiagnosticsUpdatedArgs args) { // we expect source who uses this ability to have small number of diagnostics. lock (_gate) { Debug.Assert(_updateSources.Contains(source)); // check cheap early bail out if (args.Diagnostics.Length == 0 && !_map.ContainsKey(source)) { // no new diagnostic, and we don't have update source for it. return(false); } // 2 different workspaces (ex, PreviewWorkspaces) can return same Args.Id, we need to // distinguish them. so we separate diagnostics per workspace map. var workspaceMap = _map.GetOrAdd(source, _ => new Dictionary <Workspace, Dictionary <object, Data> >()); if (args.Diagnostics.Length == 0 && !workspaceMap.ContainsKey(args.Workspace)) { // no new diagnostic, and we don't have workspace for it. return(false); } var diagnosticDataMap = workspaceMap.GetOrAdd(args.Workspace, _ => new Dictionary <object, Data>()); diagnosticDataMap.Remove(args.Id); if (diagnosticDataMap.Count == 0 && args.Diagnostics.Length == 0) { workspaceMap.Remove(args.Workspace); if (workspaceMap.Count == 0) { _map.Remove(source); } return(true); } if (args.Diagnostics.Length > 0) { // save data only if there is a diagnostic var data = source.SupportGetDiagnostics ? new Data(args) : new Data(args, args.Diagnostics); diagnosticDataMap.Add(args.Id, data); } return(true); } }
/// <summary> /// Test Only /// </summary> public ExternalErrorDiagnosticUpdateSource( Workspace workspace, IDiagnosticAnalyzerService diagnosticService, IAsynchronousOperationListener listener) { // use queue to serialize work. no lock needed _taskQueue = new SimpleTaskQueue(TaskScheduler.Default); _listener = listener; _workspace = workspace; _workspace.WorkspaceChanged += OnWorkspaceChanged; _diagnosticService = (IDiagnosticUpdateSource)diagnosticService; _diagnosticService.DiagnosticsUpdated += OnDiagnosticUpdated; }
private void RaiseDiagnosticsUpdated(IDiagnosticUpdateSource source, DiagnosticsUpdatedArgs args) { _eventListenerTracker.EnsureEventListener(args.Workspace, this); var ev = _eventMap.GetEventHandlers <EventHandler <DiagnosticsUpdatedArgs> >(DiagnosticsUpdatedEventName); var eventToken = _listener.BeginAsyncOperation(DiagnosticsUpdatedEventName); _eventQueue.ScheduleTask(() => { if (!UpdateDataMap(source, args)) { // there is no change, nothing to raise events for. return; } ev.RaiseEvent(handler => handler(source, args)); }).CompletesAsyncOperation(eventToken); }
private bool RequireRunningEventTasks( IDiagnosticUpdateSource source, EventMap.EventHandlerSet <EventHandler <DiagnosticsUpdatedArgs> > ev) { // basically there are 2 cases when there is no event handler registered. // first case is when diagnostic update source itself provide GetDiagnostics functionality. // in that case, DiagnosticService doesn't need to track diagnostics reported. so, it bail out right away. // second case is when diagnostic source doesn't provide GetDiagnostics functionality. // in that case, DiagnosticService needs to track diagnostics reported. so it need to enqueue background // work to process given data regardless whether there is event handler registered or not. // this could be separated in 2 tasks, but we already saw cases where there are too many tasks enqueued, // so I merged it to one. // if it doesn't SupportGetDiagnostics, we need to process reported data, so enqueue task. if (!source.SupportGetDiagnostics) { return(true); } return(ev.HasHandlers); }
private DiagnosticTaggerWrapper( TestWorkspace workspace, Dictionary<string, DiagnosticAnalyzer[]> analyzerMap, IDiagnosticUpdateSource updateSource, bool createTaggerProvider) { _asyncListener = new AsynchronousOperationListener(); _listeners = AsynchronousOperationListener.CreateListeners( ValueTuple.Create(FeatureAttribute.DiagnosticService, _asyncListener), ValueTuple.Create(FeatureAttribute.ErrorSquiggles, _asyncListener)); if (analyzerMap != null || updateSource == null) { AnalyzerService = CreateDiagnosticAnalyzerService(analyzerMap, _asyncListener); } if (updateSource == null) { updateSource = AnalyzerService; } _workspace = workspace; _registrationService = workspace.Services.GetService<ISolutionCrawlerRegistrationService>(); _registrationService.Register(workspace); DiagnosticService = new DiagnosticService(_listeners); DiagnosticService.Register(updateSource); if (createTaggerProvider) { var taggerProvider = this.TaggerProvider; } if (AnalyzerService != null) { _incrementalAnalyzers = ImmutableArray.Create(AnalyzerService.CreateIncrementalAnalyzer(workspace)); _solutionCrawlerService = workspace.Services.GetService<ISolutionCrawlerRegistrationService>() as SolutionCrawlerRegistrationService; } }
private DiagnosticTaggerWrapper( TestWorkspace workspace, Dictionary <string, DiagnosticAnalyzer[]> analyzerMap, IDiagnosticUpdateSource updateSource, bool createTaggerProvider) { _asyncListener = new AsynchronousOperationListener(); _listeners = AsynchronousOperationListener.CreateListeners( ValueTuple.Create(FeatureAttribute.DiagnosticService, _asyncListener), ValueTuple.Create(FeatureAttribute.ErrorSquiggles, _asyncListener)); if (analyzerMap != null || updateSource == null) { AnalyzerService = CreateDiagnosticAnalyzerService(analyzerMap, _asyncListener); } if (updateSource == null) { updateSource = AnalyzerService; } _workspace = workspace; _registrationService = workspace.Services.GetService <ISolutionCrawlerRegistrationService>(); _registrationService.Register(workspace); DiagnosticService = new DiagnosticService(_listeners); DiagnosticService.Register(updateSource); if (createTaggerProvider) { var taggerProvider = this.TaggerProvider; } if (AnalyzerService != null) { _incrementalAnalyzers = ImmutableArray.Create(AnalyzerService.CreateIncrementalAnalyzer(workspace)); _solutionCrawlerService = workspace.Services.GetService <ISolutionCrawlerRegistrationService>() as SolutionCrawlerRegistrationService; } }
private void RaiseDiagnosticsUpdated(IDiagnosticUpdateSource source, DiagnosticsUpdatedArgs args) { var ev = _eventMap.GetEventHandlers <EventHandler <DiagnosticsUpdatedArgs> >(DiagnosticsUpdatedEventName); if (!RequireRunningEventTasks(source, ev)) { return; } var eventToken = _listener.BeginAsyncOperation(DiagnosticsUpdatedEventName); _eventQueue.ScheduleTask(() => { if (!UpdateDataMap(source, args)) { // there is no change, nothing to raise events for. return; } ev.RaiseEvent(handler => handler(source, args)); }).CompletesAsyncOperation(eventToken); }
private DiagnosticTaggerWrapper( TestWorkspace workspace, Dictionary <string, DiagnosticAnalyzer[]> analyzerMap, IDiagnosticUpdateSource updateSource, bool createTaggerProvider) { _threadingContext = workspace.GetService <IThreadingContext>(); _listenerProvider = workspace.GetService <IAsynchronousOperationListenerProvider>(); if (analyzerMap != null || updateSource == null) { AnalyzerService = CreateDiagnosticAnalyzerService(analyzerMap, _listenerProvider.GetListener(FeatureAttribute.DiagnosticService)); } if (updateSource == null) { updateSource = AnalyzerService; } _workspace = workspace; _registrationService = workspace.Services.GetService <ISolutionCrawlerRegistrationService>(); _registrationService.Register(workspace); DiagnosticService = new DiagnosticService(_listenerProvider, Array.Empty <Lazy <IEventListener, EventListenerMetadata> >()); DiagnosticService.Register(updateSource); if (createTaggerProvider) { var taggerProvider = this.TaggerProvider; } if (AnalyzerService != null) { _incrementalAnalyzers = ImmutableArray.Create(AnalyzerService.CreateIncrementalAnalyzer(workspace)); _solutionCrawlerService = workspace.Services.GetService <ISolutionCrawlerRegistrationService>() as SolutionCrawlerRegistrationService; } }
public DiagnosticTaggerWrapper( TestWorkspace workspace, IReadOnlyDictionary <string, ImmutableArray <DiagnosticAnalyzer> > analyzerMap = null, IDiagnosticUpdateSource updateSource = null, bool createTaggerProvider = true) { _threadingContext = workspace.GetService <IThreadingContext>(); _listenerProvider = workspace.GetService <IAsynchronousOperationListenerProvider>(); if (updateSource == null) { updateSource = AnalyzerService = new MyDiagnosticAnalyzerService(_listenerProvider.GetListener(FeatureAttribute.DiagnosticService)); } var analyzerReference = new TestAnalyzerReferenceByLanguage(analyzerMap ?? DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap()); workspace.TryApplyChanges(workspace.CurrentSolution.WithAnalyzerReferences(new[] { analyzerReference })); _workspace = workspace; _registrationService = workspace.Services.GetService <ISolutionCrawlerRegistrationService>(); _registrationService.Register(workspace); DiagnosticService = new DiagnosticService(_listenerProvider, Array.Empty <Lazy <IEventListener, EventListenerMetadata> >()); DiagnosticService.Register(updateSource); if (createTaggerProvider) { _ = TaggerProvider; } if (AnalyzerService != null) { _incrementalAnalyzers = ImmutableArray.Create(AnalyzerService.CreateIncrementalAnalyzer(workspace)); _solutionCrawlerService = workspace.Services.GetService <ISolutionCrawlerRegistrationService>() as SolutionCrawlerRegistrationService; } }
private DiagnosticTaggerWrapper( TestWorkspace workspace, DiagnosticAnalyzerService analyzerService, IDiagnosticUpdateSource updateSource, bool createTaggerProvider) { if (updateSource == null) { updateSource = analyzerService; } this.workspace = workspace; this.registrationService = workspace.Services.GetService <ISolutionCrawlerRegistrationService>(); registrationService.Register(workspace); this.asyncListener = new AsynchronousOperationListener(); this.listeners = AsynchronousOperationListener.CreateListeners( ValueTuple.Create(FeatureAttribute.DiagnosticService, asyncListener), ValueTuple.Create(FeatureAttribute.ErrorSquiggles, asyncListener)); this.analyzerService = analyzerService; this.diagnosticService = new DiagnosticService(listeners); diagnosticService.Register(updateSource); if (createTaggerProvider) { var taggerProvider = this.TaggerProvider; } if (analyzerService != null) { this.incrementalAnalyzers = ImmutableArray.Create(analyzerService.CreateIncrementalAnalyzer(workspace)); this.solutionCrawlerService = workspace.Services.GetService <ISolutionCrawlerRegistrationService>() as SolutionCrawlerRegistrationService; } }
private DiagnosticTaggerWrapper( TestWorkspace workspace, DiagnosticAnalyzerService analyzerService, IDiagnosticUpdateSource updateSource, bool createTaggerProvider) { if (updateSource == null) { updateSource = analyzerService; } this.workspace = workspace; this.registrationService = workspace.Services.GetService<ISolutionCrawlerRegistrationService>(); registrationService.Register(workspace); this.asyncListener = new AsynchronousOperationListener(); this.listeners = AsynchronousOperationListener.CreateListeners( ValueTuple.Create(FeatureAttribute.DiagnosticService, asyncListener), ValueTuple.Create(FeatureAttribute.ErrorSquiggles, asyncListener)); this.analyzerService = analyzerService; this.diagnosticService = new DiagnosticService(listeners); diagnosticService.Register(updateSource); if (createTaggerProvider) { var taggerProvider = this.TaggerProvider; } if (analyzerService != null) { this.incrementalAnalyzers = ImmutableArray.Create(analyzerService.CreateIncrementalAnalyzer(workspace)); this.solutionCrawlerService = workspace.Services.GetService<ISolutionCrawlerRegistrationService>() as SolutionCrawlerRegistrationService; } }
private DiagnosticTaggerWrapper(TestWorkspace workspace, DiagnosticAnalyzerService analyzerService, IDiagnosticUpdateSource updateSource) { if (updateSource == null) { updateSource = analyzerService; } this.workspace = workspace; this.registrationService = workspace.Services.GetService <ISolutionCrawlerRegistrationService>(); registrationService.Register(workspace); this.asyncListener = new AsynchronousOperationListener(); var listeners = AsynchronousOperationListener.CreateListeners( ValueTuple.Create(FeatureAttribute.DiagnosticService, asyncListener), ValueTuple.Create(FeatureAttribute.ErrorSquiggles, asyncListener)); this.analyzerService = analyzerService; var diagnosticService = new DiagnosticService(SpecializedCollections.SingletonEnumerable(updateSource), listeners); this.TaggerProvider = new DiagnosticsSquiggleTaggerProvider( workspace.Services.GetService <IOptionService>(), diagnosticService, workspace.GetService <IForegroundNotificationService>(), listeners); if (analyzerService != null) { this.incrementalAnalyzers = ImmutableArray.Create(analyzerService.CreateIncrementalAnalyzer(workspace)); this.solutionCrawlerService = workspace.Services.GetService <ISolutionCrawlerRegistrationService>() as SolutionCrawlerRegistrationService; } }
public DiagnosticTaggerWrapper(TestWorkspace workspace, IDiagnosticUpdateSource updateSource) : this(workspace, null, updateSource) { }
public void Register(IDiagnosticUpdateSource source) { // do nothing }