internal static IList<ITagSpan<IErrorTag>> GetErrorsFromUpdateSource(TestWorkspace workspace, TestHostDocument document, DiagnosticsUpdatedArgs updateArgs) { var source = new TestDiagnosticUpdateSource(); var listener = new AsynchronousOperationListener(); var listeners = AsynchronousOperationListener.CreateListeners( ValueTuple.Create(FeatureAttribute.DiagnosticService, listener), ValueTuple.Create(FeatureAttribute.ErrorSquiggles, listener)); var optionsService = workspace.Services.GetService<IOptionService>(); var diagnosticService = new DiagnosticService(SpecializedCollections.SingletonEnumerable<IDiagnosticUpdateSource>(source), listeners); var foregroundService = workspace.GetService<IForegroundNotificationService>(); //new TestForegroundNotificationService(); var buffer = document.GetTextBuffer(); var provider = new DiagnosticsSquiggleTaggerProvider(optionsService, diagnosticService, foregroundService, listeners); var tagger = provider.CreateTagger<IErrorTag>(buffer); source.RaiseDiagnosticsUpdated(updateArgs); listener.CreateWaitTask().PumpingWait(); var snapshot = buffer.CurrentSnapshot; var spans = tagger.GetTags(new NormalizedSnapshotSpanCollection(new SnapshotSpan(snapshot, 0, snapshot.Length))).ToImmutableArray(); ((IDisposable)tagger).Dispose(); return spans; }
internal static IList<ITagSpan<IErrorTag>> GetErrorsFromUpdateSource(TestWorkspace workspace, TestHostDocument document, DiagnosticsUpdatedArgs updateArgs) { var source = new TestDiagnosticUpdateSource(); var diagnosticWaiter = new DiagnosticServiceWaiter(); var diagnosticListeners = SpecializedCollections.SingletonEnumerable(new Lazy<IAsynchronousOperationListener, FeatureMetadata>( () => diagnosticWaiter, new FeatureMetadata(new Dictionary<string, object>() { { "FeatureName", FeatureAttribute.DiagnosticService } }))); var optionsService = workspace.Services.GetService<IOptionService>(); var diagnosticService = new DiagnosticService(SpecializedCollections.SingletonEnumerable<IDiagnosticUpdateSource>(source), diagnosticListeners); var squiggleWaiter = new ErrorSquiggleWaiter(); var foregroundService = new TestForegroundNotificationService(); var buffer = document.GetTextBuffer(); var taggerSource = new DiagnosticsSquiggleTaggerProvider.TagSource(buffer, foregroundService, diagnosticService, optionsService, squiggleWaiter); source.RaiseDiagnosticsUpdated(updateArgs); diagnosticWaiter.CreateWaitTask().PumpingWait(); squiggleWaiter.CreateWaitTask().PumpingWait(); var snapshot = buffer.CurrentSnapshot; var intervalTree = taggerSource.GetTagIntervalTreeForBuffer(buffer); var spans = intervalTree.GetIntersectingSpans(new SnapshotSpan(snapshot, 0, snapshot.Length)); taggerSource.TestOnly_Dispose(); return spans; }
protected void RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs args) { var updated = this.DiagnosticsUpdated; if (updated != null) { updated(this, args); } }
internal void RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs state) { var handler = this.DiagnosticsUpdated; if (handler != null) { handler(this, state); } }
internal void RaiseDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs state) { var handler = this.DiagnosticsUpdated; if (handler != null) { handler(sender, state); } }
private void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e) { var document = _subjectBuffer.AsTextContainer().GetOpenDocumentInCurrentContext(); if (document != null && document.Project.Solution.Workspace == e.Workspace && document.Id == e.DocumentId) { this.RaiseChanged(); } }
internal void RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs args) { // all diagnostics events are serialized. var ev = _eventMap.GetEventHandlers<EventHandler<DiagnosticsUpdatedArgs>>(DiagnosticsUpdatedEventName); if (ev.HasHandlers) { var asyncToken = Listener.BeginAsyncOperation(nameof(RaiseDiagnosticsUpdated)); _eventQueue.ScheduleTask(() => ev.RaiseEvent(handler => handler(this, args))).CompletesAsyncOperation(asyncToken); } }
private void RaiseDiagnosticsUpdatedForProject(ProjectId projectId, object key, IEnumerable<DiagnosticData> items) { var args = new DiagnosticsUpdatedArgs( id: Tuple.Create(this, projectId, key), workspace: _workspace, solution: null, projectId: projectId, documentId: null, diagnostics: items.AsImmutableOrEmpty()); RaiseDiagnosticsUpdated(args); }
internal static async Task<IList<ITagSpan<IErrorTag>>> GetErrorsFromUpdateSource(TestWorkspace workspace, TestHostDocument document, DiagnosticsUpdatedArgs updateArgs) { var source = new TestDiagnosticUpdateSource(); using (var wrapper = new DiagnosticTaggerWrapper(workspace, source)) { var tagger = wrapper.TaggerProvider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer()); using (var disposable = tagger as IDisposable) { source.RaiseDiagnosticsUpdated(updateArgs); await wrapper.WaitForTags(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToImmutableArray(); return spans; } } }
public void OnAnalyzerLoadFailed(object?sender, AnalyzerLoadFailureEventArgs e) { if (!(sender is AnalyzerFileReference reference)) { return; } var diagnostic = AnalyzerHelper.CreateAnalyzerLoadFailureDiagnostic(e, reference.FullPath, projectId: null, language: null); // diagnostic from host analyzer can never go away var args = DiagnosticsUpdatedArgs.DiagnosticsCreated( id: Tuple.Create(this, reference.FullPath, e.ErrorCode, e.TypeName), workspace: _primaryWorkspace.Workspace, solution: null, projectId: null, documentId: null, diagnostics: ImmutableArray.Create <DiagnosticData>(diagnostic)); // this can be null in test. but in product code, this should never be null. _hostUpdateSource?.RaiseDiagnosticsUpdated(args); }
public async Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, CancellationToken cancellationToken) { // right now, there is no way to observe diagnostics for closed file. if (!_workspace.IsDocumentOpen(document.Id) || !_workspace.Options.GetOption(InternalRuntimeDiagnosticOptions.Syntax)) { return; } var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var diagnostics = tree.GetDiagnostics(cancellationToken); Contract.Requires(document.Project.Solution.Workspace == _workspace); var diagnosticData = diagnostics == null ? ImmutableArray <DiagnosticData> .Empty : diagnostics.Select(d => DiagnosticData.Create(document, d)).ToImmutableArrayOrEmpty(); _service.RaiseDiagnosticsUpdated( DiagnosticsUpdatedArgs.DiagnosticsCreated(new DefaultUpdateArgsId(_workspace.Kind, Syntax, document.Id), _workspace, document.Project.Solution, document.Project.Id, document.Id, diagnosticData)); }
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 async Task AnalyzeForKind(Document document, AnalysisKind kind, CancellationToken cancellationToken) { var diagnosticData = await _service._analyzerService.GetDiagnosticsAsync(document, GetAnalyzers(), kind, cancellationToken).ConfigureAwait(false); _service.RaiseDiagnosticsUpdated( DiagnosticsUpdatedArgs.DiagnosticsCreated(new DefaultUpdateArgsId(_workspace.Kind, kind, document.Id), _workspace, document.Project.Solution, document.Project.Id, document.Id, diagnosticData.ToImmutableArrayOrEmpty())); IEnumerable <DiagnosticAnalyzer> GetAnalyzers() { // C# or VB document that supports compiler var compilerAnalyzer = _service._analyzerService.GetCompilerDiagnosticAnalyzer(document.Project.Language); if (compilerAnalyzer != null) { return(SpecializedCollections.SingletonEnumerable(compilerAnalyzer)); } // document that doesn't support compiler diagnostics such as fsharp or typescript return(_service._analyzerService.GetDiagnosticAnalyzers(document.Project)); } }
public void OnAnalyzerLoadFailed(object sender, AnalyzerLoadFailureEventArgs e) { var reference = sender as AnalyzerFileReference; if (reference == null) { return; } var diagnostic = AnalyzerHelper.CreateAnalyzerLoadFailureDiagnostic(reference.FullPath, e); // diagnostic from host analyzer can never go away var args = DiagnosticsUpdatedArgs.DiagnosticsCreated( id: Tuple.Create(this, reference.FullPath, e.ErrorCode, e.TypeName), workspace: PrimaryWorkspace.Workspace, solution: null, projectId: null, documentId: null, diagnostics: ImmutableArray.Create <DiagnosticData>(diagnostic)); _hostUpdateSource.RaiseDiagnosticsUpdated(args); }
public async Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken) { // right now, there is no way to observe diagnostics for closed file. if (!_workspace.IsDocumentOpen(document.Id) || !_workspace.Options.GetOption(InternalRuntimeDiagnosticOptions.Semantic)) { return; } var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var diagnostics = model.GetMethodBodyDiagnostics(span: null, cancellationToken: cancellationToken).Concat( model.GetDeclarationDiagnostics(span: null, cancellationToken: cancellationToken)); Debug.Assert(document.Project.Solution.Workspace == _workspace); var diagnosticData = diagnostics == null ? ImmutableArray <DiagnosticData> .Empty : diagnostics.Select(d => DiagnosticData.Create(document, d)).ToImmutableArrayOrEmpty(); _service.RaiseDiagnosticsUpdated( DiagnosticsUpdatedArgs.DiagnosticsCreated(new DefaultUpdateArgsId(_workspace.Kind, Semantic, document.Id), _workspace, document.Project.Solution, document.Project.Id, document.Id, diagnosticData)); }
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); } }
public void RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs args) { this.DiagnosticsUpdated?.Invoke(this, args); }
private void RaiseEmptyDiagnosticUpdated(AnalysisKind kind, DocumentId documentId) { _service.RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs.DiagnosticsRemoved( new DefaultUpdateArgsId(_workspace.Kind, kind, documentId), _workspace, null, documentId.ProjectId, documentId)); }
private DiagnosticsUpdatedArgs MakeCreatedArgs(DiagnosticAnalyzer analyzer, ImmutableHashSet <DiagnosticData> items, Project project) { return(DiagnosticsUpdatedArgs.DiagnosticsCreated( CreateId(analyzer, project), this.Workspace, project?.Solution, project?.Id, documentId: null, diagnostics: items.ToImmutableArray())); }
private DiagnosticsUpdatedArgs MakeRemovedArgs(DiagnosticAnalyzer analyzer, Project project) { return(DiagnosticsUpdatedArgs.DiagnosticsRemoved( CreateId(analyzer, project), this.Workspace, project?.Solution, project?.Id, documentId: null)); }
public void RaiseUpdateEvent(DiagnosticsUpdatedArgs args) { DiagnosticsUpdated?.Invoke(this, args); }
public void LiveErrorZeroLengthSpan() { var workspaceXml = @"<Workspace> <Project Language=""C#"" CommonReferences=""true""> <Document FilePath = ""Test.cs"" > class Test { } </Document> </Project> </Workspace>"; using (var workspace = TestWorkspaceFactory.CreateWorkspace(workspaceXml)) { var document = workspace.Documents.First(); var updateArgs = new DiagnosticsUpdatedArgs( new LiveId(), workspace, workspace.CurrentSolution, document.Project.Id, document.Id, ImmutableArray.Create( CreateDiagnosticData(workspace, document, new TextSpan(0, 0)), CreateDiagnosticData(workspace, document, new TextSpan(0, 1)))); var spans = GetErrorsFromUpdateSource(workspace, document, updateArgs); Assert.Equal(2, spans.Count()); var first = spans.First(); var second = spans.Last(); Assert.Equal(1, first.Span.Span.Length); Assert.Equal(1, second.Span.Span.Length); } }
public void RaiseUpdateEvent(DiagnosticsUpdatedArgs args) { var handler = DiagnosticsUpdated; if (handler != null) { handler(this, args); } }
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 OnAnalyzerLoadFailed(object sender, AnalyzerLoadFailureEventArgs e) { var reference = sender as AnalyzerFileReference; if (reference == null) { return; } var diagnostic = AnalyzerHelper.CreateAnalyzerLoadFailureDiagnostic(reference.FullPath, e); // diagnostic from host analyzer can never go away var args = new DiagnosticsUpdatedArgs( id: Tuple.Create(this, reference.FullPath, e.ErrorCode, e.TypeName), workspace: PrimaryWorkspace.Workspace, solution: null, projectId: null, documentId: null, diagnostics: ImmutableArray.Create<DiagnosticData>(diagnostic)); _hostUpdateSource.RaiseDiagnosticsUpdated(args); }
private void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e) { // document removed case. no reason to raise event if (e.Solution == null) { return; } OnSuggestedActionsChanged(e.Workspace, e.DocumentId, e.Solution.WorkspaceVersion); }
private void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e) { RaiseDiagnosticsUpdated(sender, e); }
private void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e) { AssertIfNull(e.Diagnostics); RaiseDiagnosticsUpdated(sender, e); }
internal void RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs state) => DiagnosticsUpdated?.Invoke(this, state);
internal void RaiseDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs state) { this.DiagnosticsUpdated?.Invoke(sender, state); }
private void OnSuggestedActionsChanged(Workspace currentWorkspace, DocumentId currentDocumentId, int solutionVersion, DiagnosticsUpdatedArgs args = null) { // Explicitly hold onto the _subjectBuffer field in a local and use this local in this function to avoid crashes // if this field happens to be cleared by Dispose() below. This is required since this code path involves code // that can run on background thread. var buffer = _subjectBuffer; if (buffer == null) { return; } var workspace = buffer.GetWorkspace(); // workspace is not ready, nothing to do. if (workspace == null || workspace != currentWorkspace) { return; } if (currentDocumentId != workspace.GetDocumentIdInCurrentContext(buffer.AsTextContainer()) || solutionVersion == Volatile.Read(ref _lastSolutionVersionReported)) { return; } this.SuggestedActionsChanged?.Invoke(this, EventArgs.Empty); Volatile.Write(ref _lastSolutionVersionReported, solutionVersion); }
private void OnSuggestedActionsChanged(Workspace currentWorkspace, DocumentId currentDocumentId, int solutionVersion, DiagnosticsUpdatedArgs args = null) { if (_subjectBuffer == null) { return; } var workspace = _subjectBuffer.GetWorkspace(); // workspace is not ready, nothing to do. if (workspace == null || workspace != currentWorkspace) { return; } if (currentDocumentId != workspace.GetDocumentIdInCurrentContext(_subjectBuffer.AsTextContainer()) || solutionVersion == Volatile.Read(ref _lastSolutionVersionReported)) { return; } // make sure we only raise event once for same solution version. // light bulb controller will call us back to find out new information var changed = this.SuggestedActionsChanged; if (changed != null) { changed(this, EventArgs.Empty); } Volatile.Write(ref _lastSolutionVersionReported, solutionVersion); }