Ejemplo n.º 1
0
            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, 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));
            }
Ejemplo n.º 3
0
        private void RaiseDiagnosticsCreated(
            TextDocument document,
            StateSet stateSet,
            AnalysisKind kind,
            ImmutableArray <DiagnosticData> items,
            Action <DiagnosticsUpdatedArgs> raiseEvents
            )
        {
            Contract.ThrowIfFalse(document.Project.Solution.Workspace == Workspace);

            raiseEvents(
                DiagnosticsUpdatedArgs.DiagnosticsCreated(
                    CreateId(stateSet, document.Id, kind),
                    document.Project.Solution.Workspace,
                    document.Project.Solution,
                    document.Project.Id,
                    document.Id,
                    items
                    )
                );
        }
            public async Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, 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));

                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, Semantic, document.Id),
                                                              _workspace, document.Project.Solution, document.Project.Id, document.Id, diagnosticData));
            }
Ejemplo n.º 5
0
        private void RaiseEvents(Project project, ImmutableArray <DiagnosticData> diagnostics)
        {
            var groups = diagnostics.GroupBy(d => d.DocumentId);

            var solution  = project.Solution;
            var workspace = solution.Workspace;

            foreach (var kv in groups)
            {
                if (kv.Key == null)
                {
                    Owner.RaiseDiagnosticsUpdated(
                        this, DiagnosticsUpdatedArgs.DiagnosticsCreated(
                            ValueTuple.Create(this, project.Id), workspace, solution, project.Id, null, kv.ToImmutableArrayOrEmpty()));
                    continue;
                }

                Owner.RaiseDiagnosticsUpdated(
                    this, DiagnosticsUpdatedArgs.DiagnosticsCreated(
                        ValueTuple.Create(this, kv.Key), workspace, solution, project.Id, kv.Key, kv.ToImmutableArrayOrEmpty()));
            }
        }
            private void OnDiagnosticsUpdatedOnForeground(
                DiagnosticsUpdatedArgs e, SourceText sourceText, ITextSnapshot editorSnapshot)
            {
                this.AssertIsForeground();
                Debug.Assert(!_disposed);

                // Find the appropriate async tagger for this diagnostics id, and let it know that
                // there were new diagnostics produced for it.
                var id = e.Id;
                ValueTuple <TaggerProvider, IAccurateTagger <TTag> > providerAndTagger;

                if (!_idToProviderAndTagger.TryGetValue(id, out providerAndTagger))
                {
                    // We didn't have an existing tagger for this diagnostic id.  If there are no actual
                    // diagnostics being reported, then don't bother actually doing anything.  This saves
                    // us from creating a lot of objects, and subscribing to tons of events that we don't
                    // actually need (since we don't even have any diagnostics to show!).
                    if (e.Diagnostics.Length == 0)
                    {
                        return;
                    }

                    // Didn't have an existing tagger for this diagnostic id.  Make a new one
                    // and cache it so we can use it in the future.
                    var taggerProvider = new TaggerProvider(_owner);
                    var tagger         = taggerProvider.CreateTagger <TTag>(_subjectBuffer);
                    providerAndTagger = ValueTuple.Create(taggerProvider, tagger);

                    _idToProviderAndTagger[id] = providerAndTagger;

                    // Register for changes from the underlying tagger.  When it tells us about
                    // changes, we'll let anyone know who is registered with us.
                    tagger.TagsChanged += OnUnderlyingTaggerTagsChanged;
                }

                // Let the provider know that there are new diagnostics.  It will then
                // handle all the async processing of those diagnostics.
                providerAndTagger.Item1.OnDiagnosticsUpdated(e, sourceText, editorSnapshot);
            }
Ejemplo n.º 7
0
        async void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e)
        {
            if (!enabled)
            {
                return;
            }

            var doc = DocumentContext.ParsedDocument;

            if (doc == null || DocumentContext.IsAdHocProject)
            {
                return;
            }

            var cad = DocumentContext.AnalysisDocument;

            if (cad == null || cad.Project == null)
            {
                return;
            }

            if (e.DocumentId != cad.Id || e.ProjectId != cad.Project.Id)
            {
                return;
            }
            var token = CancelUpdateTimeout(e.Id);
            var ad    = new AnalysisDocument(Editor, DocumentContext);

            try {
                var result = await CodeDiagnosticRunner.Check(ad, token, e.Diagnostics).ConfigureAwait(false);

                if (result is IReadOnlyList <Result> resultList)
                {
                    var updater = new ResultsUpdater(this, resultList, e.Id, token);
                    updater.Update();
                }
            } catch (Exception) {
            }
        }
Ejemplo n.º 8
0
        private void DiagnosticService_DiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e)
        {
            // LSP doesnt support diagnostics without a document. So if we get project level diagnostics without a document, ignore them.
            if (e.DocumentId != null && e.Solution != null)
            {
                var document = e.Solution.GetDocument(e.DocumentId);
                if (document == null || document.FilePath == null)
                {
                    return;
                }

                // Only publish document diagnostics for the languages this provider supports.
                if (document.Project.Language != CodeAnalysis.LanguageNames.CSharp && document.Project.Language != CodeAnalysis.LanguageNames.VisualBasic)
                {
                    return;
                }

                // LSP does not currently support publishing diagnostics incrememntally, so we re-publish all diagnostics.
                var asyncToken = _listener.BeginAsyncOperation(nameof(PublishDiagnosticsAsync));
                Task.Run(() => PublishDiagnosticsAsync(document))
                .CompletesAsyncOperation(asyncToken);
            }
        }
Ejemplo n.º 9
0
        private void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs diagnosticsUpdatedArgs)
        {
            var documentId = diagnosticsUpdatedArgs?.DocumentId;

            if (documentId == null)
            {
                return;
            }

            if (_diagnosticsUpdatedNotifiers.TryGetValue(documentId, out var notifier))
            {
                if (diagnosticsUpdatedArgs.Kind == DiagnosticsUpdatedKind.DiagnosticsCreated)
                {
                    var remove = diagnosticsUpdatedArgs.Diagnostics.RemoveAll(d => DisabledDiagnostics.Contains(d.Id));
                    if (remove.Length != diagnosticsUpdatedArgs.Diagnostics.Length)
                    {
                        diagnosticsUpdatedArgs = diagnosticsUpdatedArgs.WithDiagnostics(remove);
                    }
                }

                notifier(diagnosticsUpdatedArgs);
            }
        }
Ejemplo n.º 10
0
            private void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e)
            {
                if (_workspace != e.Workspace)
                {
                    return;
                }

                if (e.Diagnostics.Length == 0)
                {
                    OnDataRemoved(e);
                    return;
                }

                var count = e.Diagnostics.Where(ShouldInclude).Count();

                if (count <= 0)
                {
                    OnDataRemoved(e);
                    return;
                }

                OnDataAddedOrChanged(e);
            }
Ejemplo n.º 11
0
        void UpdateInitialDiagnostics()
        {
            if (!AnalysisOptions.EnableFancyFeatures)
            {
                return;
            }

            var doc = DocumentContext.ParsedDocument;

            if (doc == null || DocumentContext.IsAdHocProject)
            {
                return;
            }

            var ad = new AnalysisDocument(Editor, DocumentContext);

            Task.Run(() => {
                var ws       = DocumentContext.RoslynWorkspace;
                var project  = DocumentContext.AnalysisDocument.Project.Id;
                var document = DocumentContext.AnalysisDocument.Id;

                // Force an initial diagnostic update from the engine.
                foreach (var updateArgs in diagService.GetDiagnosticsUpdatedEventArgs(ws, project, document, src.Token))
                {
                    var diagnostics = AdjustInitialDiagnostics(DocumentContext.AnalysisDocument.Project.Solution, updateArgs, src.Token);
                    if (diagnostics.Length == 0)
                    {
                        continue;
                    }

                    var e = DiagnosticsUpdatedArgs.DiagnosticsCreated(
                        updateArgs.Id, updateArgs.Workspace, DocumentContext.AnalysisDocument.Project.Solution, updateArgs.ProjectId, updateArgs.DocumentId, diagnostics);

                    OnDiagnosticsUpdated(this, e);
                }
            });
        }
            private void GetInitialDiagnosticsInBackground(
                Document document, CancellationToken cancellationToken)
            {
                this.AssertIsBackground();
                cancellationToken.ThrowIfCancellationRequested();

                if (document != null)
                {
                    var project   = document.Project;
                    var workspace = project.Solution.Workspace;
                    foreach (var updateArgs in _owner._diagnosticService.GetDiagnosticsUpdatedEventArgs(workspace, project.Id, document.Id, cancellationToken))
                    {
                        var diagnostics = AdjustInitialDiagnostics(project.Solution, updateArgs, cancellationToken);
                        if (diagnostics.Length == 0)
                        {
                            continue;
                        }

                        OnDiagnosticsUpdatedOnBackground(
                            DiagnosticsUpdatedArgs.DiagnosticsCreated(
                                updateArgs.Id, updateArgs.Workspace, project.Solution, updateArgs.ProjectId, updateArgs.DocumentId, diagnostics));
                    }
                }
            }
Ejemplo n.º 13
0
 public void RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs args)
 {
     _diagnostics = args.GetPushDiagnostics(_globalOptions, InternalDiagnosticsOptions.NormalDiagnosticMode);
     DiagnosticsUpdated?.Invoke(this, args);
 }
Ejemplo n.º 14
0
        internal static async Task <IList <ITagSpan <TTag> > > GetErrorsFromUpdateSource(TestWorkspace workspace, DiagnosticsUpdatedArgs updateArgs)
        {
            var globalOptions = workspace.GetService <IGlobalOptionService>();
            var source        = new TestDiagnosticUpdateSource(globalOptions);

            using var wrapper = new DiagnosticTaggerWrapper <TProvider, TTag>(workspace, updateSource: source);

            var tagger = wrapper.TaggerProvider.CreateTagger <TTag>(workspace.Documents.First().GetTextBuffer());

            using var disposable = (IDisposable)tagger;

            source.RaiseDiagnosticsUpdated(updateArgs);

            await wrapper.WaitForTags();

            var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot;
            var spans    = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToImmutableArray();

            return(spans);
        }
Ejemplo n.º 15
0
 private void RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs args)
 {
     this.DiagnosticsUpdated?.Invoke(this, args);
 }
Ejemplo n.º 16
0
 public void RaiseDiagnosticsUpdated(DiagnosticsUpdatedArgs args)
 {
     this.diagnostics = args.Diagnostics;
     DiagnosticsUpdated?.Invoke(this, args);
 }
 private void DiagnosticService_DiagnosticsUpdated(object?_, DiagnosticsUpdatedArgs e)
 => DiagnosticService_DiagnosticsUpdated(e.Solution, e.DocumentId);
            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;
                }

                // 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);
            }
 private void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e)
 {
     OnDataAddedOrChanged(this, _buildErrorSource.GetBuildErrors().Length);
 }
Ejemplo n.º 20
0
 /// <summary>
 /// Called from the roslyn host when diagnostics was updated.
 /// </summary>
 /// <param name="a">a.</param>
 public void EhDiagnosticsUpdated(DiagnosticsUpdatedArgs a)
 {
     DiagnosticsUpdated?.Invoke(a);
 }
            /// <summary>
            /// We do all mutation work on the UI thread.  That ensures that all mutation
            /// is processed serially *and* it means we can safely examine things like
            /// subject buffers and open documents without any threat of race conditions.
            /// Note that we do not do any expensive work here.  We just store (or remove)
            /// the data we were given in appropriate buckets.
            ///
            /// For example, we create a TaggerProvider per unique DiagnosticUpdatedArgs.Id
            /// we get.  So if we see a new id we simply create a tagger for it and pass it
            /// these args to store.  Otherwise we pass these args to the existing tagger.
            ///
            /// Similarly, clearing out data is just a matter of us clearing our reference
            /// to the data.
            /// </summary>
            private void OnDiagnosticsUpdatedOnForeground(DiagnosticsUpdatedArgs e)
            {
                this.AssertIsForeground();

                if (_disposed)
                {
                    return;
                }

                // Do some quick checks to avoid doing any further work for diagnostics  we don't
                // care about.
                var ourDocument   = _subjectBuffer.AsTextContainer().GetOpenDocumentInCurrentContext();
                var ourDocumentId = ourDocument?.Id;

                if (ourDocumentId != _currentDocumentId)
                {
                    // Our buffer has started tracking some other document entirely.
                    // We have to clear out all of the diagnostics we have currently stored.
                    RemoveAllCachedDiagnostics();
                }

                _currentDocumentId = ourDocumentId;

                // Now see if the document we're tracking corresponds to the diagnostics
                // we're hearing about.  If not, just ignore them.
                if (ourDocument == null ||
                    ourDocument.Project.Solution.Workspace != e.Workspace ||
                    ourDocument.Id != e.DocumentId)
                {
                    return;
                }

                // We're hearing about diagnostics for our document.  We may be hearing
                // about new diagnostics coming, or existing diagnostics being cleared
                // out.

                // First see if this is a document/project removal.  If so, clear out any state we
                // have associated with any analyzers we have for that document/project.
                ProcessRemovedDiagnostics(e);

                // Make sure we can find an editor snapshot for these errors.  Otherwise we won't
                // be able to make ITagSpans for them.  If we can't, just bail out.  This happens
                // when the solution crawler is very far behind.  However, it will have a more
                // up to date document within it that it will eventually process.  Until then
                // we just keep around the stale tags we have.
                //
                // Note: if the Solution or Document is null here, then that means the document
                // was removed.  In that case, we do want to proceed so that we'll produce 0
                // tags and we'll update the editor appropriately.
                SourceText    sourceText     = null;
                ITextSnapshot editorSnapshot = null;

                if (e.Solution != null)
                {
                    var diagnosticDocument = e.Solution.GetDocument(e.DocumentId);
                    if (diagnosticDocument != null)
                    {
                        if (!diagnosticDocument.TryGetText(out sourceText))
                        {
                            return;
                        }

                        editorSnapshot = sourceText.FindCorrespondingEditorTextSnapshot();
                        if (editorSnapshot == null)
                        {
                            return;
                        }

                        // Make sure the editor we've got associated with these diagnostics is the
                        // same one we're a tagger for.  It is possible for us to hear about diagnostics
                        // for the *same* Document that are not from the *same* buffer.  For example,
                        // say we have the following chain of events:
                        //
                        //      Document is opened.
                        //      Diagnostics start analyzing.
                        //      Document is closed.
                        //      Document is opened.
                        //      Diagnostics finish and report for document.
                        //
                        // We'll hear about diagnostics for the original Document/Buffer that was
                        // opened.  But we'll be trying to apply them to this current Document/Buffer.
                        // That won't work since these will be different buffers (and thus, we won't
                        // be able to map the diagnostic spans appropriately).
                        //
                        // Note: returning here is safe.  Because the file is closed/opened, The
                        // Diagnostics Service will reanalyze it.  It will then report the new results
                        // which we will hear about and use.
                        if (editorSnapshot.TextBuffer != _subjectBuffer)
                        {
                            return;
                        }
                    }
                }

                OnDiagnosticsUpdatedOnForeground(e, sourceText, editorSnapshot);
            }
 private void OnDiagnosticsUpdatedOnBackground(DiagnosticsUpdatedArgs e)
 {
     this.AssertIsBackground();
     RegisterNotification(() => OnDiagnosticsUpdatedOnForeground(e));
 }
Ejemplo n.º 23
0
 public void RaiseUpdateEvent(DiagnosticsUpdatedArgs args)
 {
     DiagnosticsUpdated?.Invoke(this, args);
 }
Ejemplo n.º 24
0
 private void RaiseDiagnosticsCreated(object id, Solution solution, ProjectId projectId, DocumentId documentId, ImmutableArray <DiagnosticData> items)
 {
     DiagnosticsUpdated?.Invoke(this, DiagnosticsUpdatedArgs.DiagnosticsCreated(
                                    CreateArgumentKey(id), _workspace, solution, projectId, documentId, items));
 }
Ejemplo n.º 25
0
 private void RaiseDiagnosticsRemoved(object id, Solution solution, ProjectId projectId, DocumentId documentId)
 {
     DiagnosticsUpdated?.Invoke(this, DiagnosticsUpdatedArgs.DiagnosticsRemoved(
                                    CreateArgumentKey(id), _workspace, solution, projectId, documentId));
 }
Ejemplo n.º 26
0
 private DiagnosticsUpdatedArgs MakeCreatedArgs(
     DebuggingSession session, object errorId, Workspace workspace, Solution solution, ProjectId projectId, DocumentId documentId, ImmutableArray <DiagnosticData> items)
 {
     return(DiagnosticsUpdatedArgs.DiagnosticsCreated(
                CreateId(session, errorId), workspace, solution, projectId, documentId, items));
 }
Ejemplo n.º 27
0
 public void RaiseDiagnosticsUpdatedEvent(DiagnosticsUpdatedArgs args)
 => DiagnosticsUpdated?.Invoke(this, args);
Ejemplo n.º 28
0
 private DiagnosticsUpdatedArgs MakeRemovedArgs(
     DebuggingSession session, object errorId, Workspace workspace, Solution solution, ProjectId projectId, DocumentId documentId)
 {
     return(DiagnosticsUpdatedArgs.DiagnosticsRemoved(
                CreateId(session, errorId), workspace, solution, projectId, documentId));
 }
Ejemplo n.º 29
0
 private void Editor_ProcessDiagnostics(object sender, DiagnosticsUpdatedArgs e)
 {
     CodeEditor.ProcessDiagnostics(e);
 }
Ejemplo n.º 30
0
        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);
                }
            }
        }