예제 #1
0
 private void RemoveInMemoryCache(DiagnosticAnalysisResult lastResult)
 {
     // remove old cache
     foreach (var documentId in lastResult.DocumentIdsOrEmpty)
     {
         RemoveInMemoryCacheEntries(documentId);
     }
 }
예제 #2
0
        public static DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> Deserialize(
            ObjectReader reader, IDictionary <string, DiagnosticAnalyzer> analyzerMap, Project project, VersionStamp version, CancellationToken cancellationToken)
        {
            var diagnosticDataSerializer = new DiagnosticDataSerializer(VersionStamp.Default, VersionStamp.Default);

            var analysisMap = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, DiagnosticAnalysisResult>();

            var analysisCount = reader.ReadInt32();

            for (var i = 0; i < analysisCount; i++)
            {
                var analyzer = analyzerMap[reader.ReadString()];

                var syntaxLocalMap   = Deserialize(reader, diagnosticDataSerializer, project, cancellationToken);
                var semanticLocalMap = Deserialize(reader, diagnosticDataSerializer, project, cancellationToken);
                var nonLocalMap      = Deserialize(reader, diagnosticDataSerializer, project, cancellationToken);

                var others = diagnosticDataSerializer.ReadFrom(reader, project, cancellationToken);

                var analysisResult = DiagnosticAnalysisResult.CreateFromSerialization(
                    project,
                    version,
                    syntaxLocalMap,
                    semanticLocalMap,
                    nonLocalMap,
                    GetOrDefault(others),
                    documentIds: null);

                analysisMap.Add(analyzer, analysisResult);
            }

            var telemetryMap = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, AnalyzerTelemetryInfo>();

            var telemetryCount = reader.ReadInt32();

            for (var i = 0; i < telemetryCount; i++)
            {
                var analyzer      = analyzerMap[reader.ReadString()];
                var telemetryInfo = Deserialize(reader, cancellationToken);

                telemetryMap.Add(analyzer, telemetryInfo);
            }

            var exceptionMap = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, ImmutableArray <DiagnosticData> >();

            var exceptionCount = reader.ReadInt32();

            for (var i = 0; i < exceptionCount; i++)
            {
                var analyzer   = analyzerMap[reader.ReadString()];
                var exceptions = diagnosticDataSerializer.ReadFrom(reader, project, cancellationToken);

                exceptionMap.Add(analyzer, GetOrDefault(exceptions));
            }

            return(DiagnosticAnalysisResultMap.Create(analysisMap.ToImmutable(), telemetryMap.ToImmutable(), exceptionMap.ToImmutable()));
        }
예제 #3
0
        private static DiagnosticAnalysisResult GetResultOrEmpty(ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> map, DiagnosticAnalyzer analyzer, ProjectId projectId, VersionStamp version)
        {
            if (map.TryGetValue(analyzer, out var result))
            {
                return(result);
            }

            return(DiagnosticAnalysisResult.CreateEmpty(projectId, version));
        }
 public DiagnosticAnalysisResult ToResult()
 {
     return(DiagnosticAnalysisResult.Create(_project, _version,
                                            _syntaxLocals?.ToImmutable() ?? ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty,
                                            _semanticLocals?.ToImmutable() ?? ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty,
                                            _nonLocals?.ToImmutable() ?? ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty,
                                            _others.NullToEmpty(),
                                            _documentIds));
 }
예제 #5
0
            private async Task <ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> > MergeProjectDiagnosticAnalyzerDiagnosticsAsync(
                Project project, IEnumerable <StateSet> stateSets, Compilation compilationOpt, ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> result, CancellationToken cancellationToken)
            {
                try
                {
                    // check whether there is IDE specific project diagnostic analyzer
                    var ideAnalyzers = stateSets.Select(s => s.Analyzer).Where(a => a is ProjectDiagnosticAnalyzer || a is DocumentDiagnosticAnalyzer).ToImmutableArrayOrEmpty();
                    if (ideAnalyzers.Length <= 0)
                    {
                        return(result);
                    }

                    // create result map
                    var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

                    foreach (var analyzer in ideAnalyzers)
                    {
                        var builder = new DiagnosticAnalysisResultBuilder(project, version);

                        if (analyzer is DocumentDiagnosticAnalyzer documentAnalyzer)
                        {
                            foreach (var document in project.Documents)
                            {
                                if (document.SupportsSyntaxTree)
                                {
                                    var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                                    builder.AddSyntaxDiagnostics(tree, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Syntax, compilationOpt, cancellationToken).ConfigureAwait(false));
                                    builder.AddSemanticDiagnostics(tree, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Semantic, compilationOpt, cancellationToken).ConfigureAwait(false));
                                }
                                else
                                {
                                    builder.AddExternalSyntaxDiagnostics(document.Id, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Syntax, compilationOpt, cancellationToken).ConfigureAwait(false));
                                    builder.AddExternalSemanticDiagnostics(document.Id, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Semantic, compilationOpt, cancellationToken).ConfigureAwait(false));
                                }
                            }
                        }

                        if (analyzer is ProjectDiagnosticAnalyzer projectAnalyzer)
                        {
                            builder.AddCompilationDiagnostics(await ComputeProjectDiagnosticAnalyzerDiagnosticsAsync(project, projectAnalyzer, compilationOpt, cancellationToken).ConfigureAwait(false));
                        }

                        // merge the result to existing one.
                        // there can be existing one from compiler driver with empty set. overwrite it with
                        // ide one.
                        result = result.SetItem(analyzer, DiagnosticAnalysisResult.CreateFromBuilder(builder));
                    }

                    return(result);
                }
                catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
        private void RaiseDocumentDiagnosticsIfNeeded(
            Document document, StateSet stateSet, AnalysisKind kind,
            DiagnosticAnalysisResult oldResult, DiagnosticAnalysisResult newResult,
            Action <DiagnosticsUpdatedArgs> raiseEvents)
        {
            var oldItems = GetResult(oldResult, kind, document.Id);
            var newItems = GetResult(newResult, kind, document.Id);

            RaiseDocumentDiagnosticsIfNeeded(document, stateSet, kind, oldItems, newItems, raiseEvents);
        }
        private async Task <ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> > MergeProjectDiagnosticAnalyzerDiagnosticsAsync(
            Project project,
            ImmutableArray <DiagnosticAnalyzer> ideAnalyzers,
            Compilation?compilation,
            ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> result,
            CancellationToken cancellationToken)
        {
            try
            {
                // create result map
                var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

                foreach (var analyzer in ideAnalyzers)
                {
                    var builder = new DiagnosticAnalysisResultBuilder(project, version);

                    if (analyzer is DocumentDiagnosticAnalyzer documentAnalyzer)
                    {
                        foreach (var document in project.Documents)
                        {
                            var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                            if (tree != null)
                            {
                                builder.AddSyntaxDiagnostics(tree, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Syntax, compilation, cancellationToken).ConfigureAwait(false));
                                builder.AddSemanticDiagnostics(tree, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Semantic, compilation, cancellationToken).ConfigureAwait(false));
                            }
                            else
                            {
                                builder.AddExternalSyntaxDiagnostics(document.Id, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Syntax, compilation, cancellationToken).ConfigureAwait(false));
                                builder.AddExternalSemanticDiagnostics(document.Id, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Semantic, compilation, cancellationToken).ConfigureAwait(false));
                            }
                        }
                    }

                    if (analyzer is ProjectDiagnosticAnalyzer projectAnalyzer)
                    {
                        builder.AddCompilationDiagnostics(await ComputeProjectDiagnosticAnalyzerDiagnosticsAsync(project, projectAnalyzer, compilation, cancellationToken).ConfigureAwait(false));
                    }

                    // merge the result to existing one.
                    // there can be existing one from compiler driver with empty set. overwrite it with
                    // ide one.
                    result = result.SetItem(analyzer, DiagnosticAnalysisResult.CreateFromBuilder(builder));
                }

                return(result);
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
        private ImmutableArray <DiagnosticData> GetDiagnostics(DiagnosticAnalysisResult result)
        {
            // PERF: don't allocation anything if not needed
            if (result.IsAggregatedForm || result.IsEmpty)
            {
                return(ImmutableArray <DiagnosticData> .Empty);
            }

            return(result.SyntaxLocals.Values.SelectMany(v => v).Concat(
                       result.SemanticLocals.Values.SelectMany(v => v)).Concat(
                       result.NonLocals.Values.SelectMany(v => v)).Concat(
                       result.Others).ToImmutableArray());
        }
예제 #9
0
        private static ImmutableArray <DiagnosticData> GetResult(DiagnosticAnalysisResult result, AnalysisKind kind, DocumentId id)
        {
            if (result.IsEmpty || !result.DocumentIds.Contains(id) || result.IsAggregatedForm)
            {
                return(ImmutableArray <DiagnosticData> .Empty);
            }

            return(kind switch
            {
                AnalysisKind.Syntax => result.GetResultOrEmpty(result.SyntaxLocals, id),
                AnalysisKind.Semantic => result.GetResultOrEmpty(result.SemanticLocals, id),
                AnalysisKind.NonLocal => result.GetResultOrEmpty(result.NonLocals, id),
                _ => Contract.FailWithReturn <ImmutableArray <DiagnosticData> >("shouldn't reach here"),
            });
예제 #10
0
        public static DiagnosticAnalysisResultMap<DiagnosticAnalyzer, DiagnosticAnalysisResult> Deserialize(
            ObjectReader reader, IDictionary<string, DiagnosticAnalyzer> analyzerMap, Project project, VersionStamp version, CancellationToken cancellationToken)
        {
            var diagnosticDataSerializer = new DiagnosticDataSerializer(VersionStamp.Default, VersionStamp.Default);

            var analysisMap = ImmutableDictionary.CreateBuilder<DiagnosticAnalyzer, DiagnosticAnalysisResult>();

            var analysisCount = reader.ReadInt32();
            for (var i = 0; i < analysisCount; i++)
            {
                var analyzer = analyzerMap[reader.ReadString()];

                var syntaxLocalMap = Deserialize(reader, diagnosticDataSerializer, project, cancellationToken);
                var semanticLocalMap = Deserialize(reader, diagnosticDataSerializer, project, cancellationToken);
                var nonLocalMap = Deserialize(reader, diagnosticDataSerializer, project, cancellationToken);

                var others = diagnosticDataSerializer.ReadFrom(reader, project, cancellationToken);

                var analysisResult = new DiagnosticAnalysisResult(
                    project.Id, version,
                    syntaxLocalMap, semanticLocalMap, nonLocalMap, others,
                    documentIds: null, fromBuild: false);

                analysisMap.Add(analyzer, analysisResult);
            }

            var telemetryMap = ImmutableDictionary.CreateBuilder<DiagnosticAnalyzer, AnalyzerTelemetryInfo>();

            var telemetryCount = reader.ReadInt32();
            for (var i = 0; i < telemetryCount; i++)
            {
                var analyzer = analyzerMap[reader.ReadString()];
                var telemetryInfo = Deserialize(reader, cancellationToken);

                telemetryMap.Add(analyzer, telemetryInfo);
            }

            var exceptionMap = ImmutableDictionary.CreateBuilder<DiagnosticAnalyzer, ImmutableArray<DiagnosticData>>();

            var exceptionCount = reader.ReadInt32();
            for (var i = 0; i < exceptionCount; i++)
            {
                var analyzer = analyzerMap[reader.ReadString()];
                var exceptions = diagnosticDataSerializer.ReadFrom(reader, project, cancellationToken);

                exceptionMap.Add(analyzer, exceptions);
            }

            return DiagnosticAnalysisResultMap.Create(analysisMap.ToImmutable(), telemetryMap.ToImmutable(), exceptionMap.ToImmutable());
        }
예제 #11
0
        private static async Task <(DiagnosticAnalysisResult loadDiagnostics, ImmutableHashSet <Document>?failedDocuments)> GetDocumentLoadFailuresAsync(
            Project project,
            VersionStamp version,
            CancellationToken cancellationToken
            )
        {
            ImmutableHashSet <Document> .Builder?failedDocuments = null;
            ImmutableDictionary <
                DocumentId,
                ImmutableArray <DiagnosticData>
                > .Builder?lazyLoadDiagnostics = null;

            foreach (var document in project.Documents)
            {
                var loadDiagnostic = await document.State
                                     .GetLoadDiagnosticAsync(cancellationToken)
                                     .ConfigureAwait(false);

                if (loadDiagnostic != null)
                {
                    lazyLoadDiagnostics ??= ImmutableDictionary.CreateBuilder <
                        DocumentId,
                        ImmutableArray <DiagnosticData>
                        >();
                    lazyLoadDiagnostics.Add(
                        document.Id,
                        ImmutableArray.Create(DiagnosticData.Create(loadDiagnostic, document))
                        );

                    failedDocuments ??= ImmutableHashSet.CreateBuilder <Document>();
                    failedDocuments.Add(document);
                }
            }

            var result = DiagnosticAnalysisResult.Create(
                project,
                version,
                syntaxLocalMap: lazyLoadDiagnostics?.ToImmutable()
                ?? ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty,
                semanticLocalMap: ImmutableDictionary <
                    DocumentId,
                    ImmutableArray <DiagnosticData>
                    > .Empty,
                nonLocalMap: ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty,
                others: ImmutableArray <DiagnosticData> .Empty,
                documentIds: null
                );

            return(result, failedDocuments?.ToImmutable());
        }
            private async Task <DiagnosticAnalysisResult> LoadInitialProjectAnalysisDataAsync(IPersistentStorageService persistentService, Project project, CancellationToken cancellationToken)
            {
                // loading data can be cancelled any time.
                var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

                var serializer = new DiagnosticDataSerializer(_owner.AnalyzerVersion, version);
                var builder    = new Builder(project, version);

                if (!await TryDeserializeProjectDiagnosticsAsync(persistentService, serializer, project, builder, cancellationToken).ConfigureAwait(false))
                {
                    return(DiagnosticAnalysisResult.CreateEmpty(project.Id, VersionStamp.Default));
                }

                return(builder.ToResult());
            }
            private async Task <DiagnosticAnalysisResult> LoadInitialProjectAnalysisDataAsync(Project project, CancellationToken cancellationToken)
            {
                // loading data can be canceled any time.
                var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

                var serializerVersion = version;
                var builder           = new Builder(project, version);

                if (!await TryGetProjectDiagnosticsFromInMemoryStorageAsync(serializerVersion, project, builder, cancellationToken).ConfigureAwait(false))
                {
                    return(DiagnosticAnalysisResult.CreateEmpty(project.Id, VersionStamp.Default));
                }

                return(builder.ToResult());
            }
예제 #14
0
            public async Task MergeAsync(ActiveFileState state, Document document)
            {
                Contract.ThrowIfFalse(state.DocumentId == document.Id);

                // merge active file state to project state
                var lastResult = _lastResult;

                var syntax   = state.GetAnalysisData(AnalysisKind.Syntax);
                var semantic = state.GetAnalysisData(AnalysisKind.Semantic);

                AnalyzerABTestLogger.LogDocumentDiagnostics(document, _owner.StateName, syntax.Items, semantic.Items);

                var project = document.Project;

                // if project didn't successfully loaded, then it is same as FSA off
                var fullAnalysis = ServiceFeatureOnOffOptions.IsClosedFileDiagnosticsEnabled(project) &&
                                   await project.HasSuccessfullyLoadedAsync(CancellationToken.None).ConfigureAwait(false);

                // keep from build flag if full analysis is off
                var fromBuild = fullAnalysis ? false : lastResult.FromBuild;

                var openFileOnlyAnalyzer = _owner.Analyzer.IsOpenFileOnly(document.Project.Solution.Workspace);

                // if it is allowed to keep project state, check versions and if they are same, bail out.
                // if full solution analysis is off or we are asked to reset document state, we always merge.
                if (fullAnalysis && !openFileOnlyAnalyzer &&
                    syntax.Version != VersionStamp.Default &&
                    syntax.Version == semantic.Version &&
                    syntax.Version == lastResult.Version)
                {
                    // all data is in sync already.
                    return;
                }

                // we have mixed versions or full analysis is off, set it to default so that it can be re-calculated next time so data can be in sync.
                var version = VersionStamp.Default;

                // serialization can't be cancelled.
                var serializer = new DiagnosticDataSerializer(_owner.AnalyzerVersion, version);

                // save active file diagnostics back to project state
                await SerializeAsync(serializer, document, document.Id, _owner.SyntaxStateName, syntax.Items).ConfigureAwait(false);
                await SerializeAsync(serializer, document, document.Id, _owner.SemanticStateName, semantic.Items).ConfigureAwait(false);

                // save last aggregated form of analysis result
                _lastResult = _lastResult.UpdateAggregatedResult(version, state.DocumentId, fromBuild);
            }
            public async ValueTask MergeAsync(ActiveFileState state, TextDocument document, IGlobalOptionService globalOptions)
            {
                Contract.ThrowIfFalse(state.DocumentId == document.Id);

                // merge active file state to project state
                var lastResult = _lastResult;

                var syntax   = state.GetAnalysisData(AnalysisKind.Syntax);
                var semantic = state.GetAnalysisData(AnalysisKind.Semantic);

                var project = document.Project;

                // if project didn't successfully loaded, then it is same as FSA off
                var fullAnalysis = globalOptions.GetBackgroundAnalysisScope(project.Language) == BackgroundAnalysisScope.FullSolution &&
                                   await project.HasSuccessfullyLoadedAsync(CancellationToken.None).ConfigureAwait(false);

                // keep from build flag if full analysis is off
                var fromBuild = fullAnalysis ? false : lastResult.FromBuild;

                var languageServices     = document.Project.LanguageServices;
                var simplifierOptions    = (languageServices.GetService <ISimplifierOptionsStorage>() != null) ? globalOptions.GetSimplifierOptions(languageServices) : null;
                var openFileOnlyAnalyzer = _owner.Analyzer.IsOpenFileOnly(simplifierOptions);

                // if it is allowed to keep project state, check versions and if they are same, bail out.
                // if full solution analysis is off or we are asked to reset document state, we always merge.
                if (fullAnalysis && !openFileOnlyAnalyzer &&
                    syntax.Version != VersionStamp.Default &&
                    syntax.Version == semantic.Version &&
                    syntax.Version == lastResult.Version)
                {
                    // all data is in sync already.
                    return;
                }

                // we have mixed versions or full analysis is off, set it to default so that it can be re-calculated next time so data can be in sync.
                var version = VersionStamp.Default;

                // serialization can't be canceled.
                var serializerVersion = version;

                // save active file diagnostics back to project state
                await AddToInMemoryStorageAsync(serializerVersion, project, document, document.Id, _owner.SyntaxStateName, syntax.Items).ConfigureAwait(false);
                await AddToInMemoryStorageAsync(serializerVersion, project, document, document.Id, _owner.SemanticStateName, semantic.Items).ConfigureAwait(false);

                // save last aggregated form of analysis result
                _lastResult = _lastResult.UpdateAggregatedResult(version, state.DocumentId, fromBuild);
            }
예제 #16
0
            > CreateAnalysisResults(
            Project project,
            ImmutableArray <StateSet> stateSets,
            ImmutableArray <DiagnosticData> diagnostics
            )
        {
            using var poolObject = SharedPools.Default <HashSet <string> >().GetPooledObject();

            var lookup = diagnostics.ToLookup(d => d.Id);

            var builder = ImmutableDictionary.CreateBuilder <
                DiagnosticAnalyzer,
                DiagnosticAnalysisResult
                >();

            using var _ = PooledHashSet <DocumentId> .GetInstance(
                      out var existingDocumentsInStateSet
                      );

            foreach (var stateSet in stateSets)
            {
                var descriptors = DiagnosticAnalyzerInfoCache.GetDiagnosticDescriptors(
                    stateSet.Analyzer
                    );
                var liveDiagnostics = ConvertToLiveDiagnostics(
                    lookup,
                    descriptors,
                    poolObject.Object
                    );

                // Ensure that all documents with diagnostics in the previous state set are added to the result.
                existingDocumentsInStateSet.Clear();
                stateSet.CollectDocumentsWithDiagnostics(project.Id, existingDocumentsInStateSet);

                builder.Add(
                    stateSet.Analyzer,
                    DiagnosticAnalysisResult.CreateFromBuild(
                        project,
                        liveDiagnostics,
                        existingDocumentsInStateSet
                        )
                    );
            }

            return(builder.ToImmutable());
        }
예제 #17
0
            private async Task <DiagnosticAnalysisResult> LoadInitialAnalysisDataAsync(Document document, CancellationToken cancellationToken)
            {
                // loading data can be cancelled any time.
                var project = document.Project;

                var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

                var serializer = new DiagnosticDataSerializer(_owner.AnalyzerVersion, version);
                var builder    = new Builder(project, version);

                if (!await TryDeserializeDocumentAsync(serializer, document, builder, cancellationToken).ConfigureAwait(false))
                {
                    return(DiagnosticAnalysisResult.CreateEmpty(project.Id, VersionStamp.Default));
                }

                return(builder.ToResult());
            }
예제 #18
0
        public static DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> ReadDiagnosticAnalysisResults(
            ObjectReader reader, IDictionary <string, DiagnosticAnalyzer> analyzerMap, Project project, VersionStamp version, CancellationToken cancellationToken)
        {
            var diagnosticDataSerializer = new DiagnosticDataSerializer(VersionStamp.Default, VersionStamp.Default);

            var analysisMap = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, DiagnosticAnalysisResult>();

            var analysisCount = reader.ReadInt32();

            for (var i = 0; i < analysisCount; i++)
            {
                var analyzer = analyzerMap[reader.ReadString()];

                var syntaxLocalMap   = ReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken);
                var semanticLocalMap = ReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken);
                var nonLocalMap      = ReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken);

                var others = diagnosticDataSerializer.ReadDiagnosticData(reader, project, document: null, cancellationToken);

                var analysisResult = DiagnosticAnalysisResult.Create(
                    project,
                    version,
                    syntaxLocalMap,
                    semanticLocalMap,
                    nonLocalMap,
                    others.NullToEmpty(),
                    documentIds: null);

                analysisMap.Add(analyzer, analysisResult);
            }

            var telemetryMap = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, AnalyzerTelemetryInfo>();

            var telemetryCount = reader.ReadInt32();

            for (var i = 0; i < telemetryCount; i++)
            {
                var analyzer      = analyzerMap[reader.ReadString()];
                var telemetryInfo = ReadTelemetry(reader, cancellationToken);

                telemetryMap.Add(analyzer, telemetryInfo);
            }

            return(DiagnosticAnalysisResultMap.Create(analysisMap.ToImmutable(), telemetryMap.ToImmutable()));
        }
            public async ValueTask SaveToInMemoryStorageAsync(Project project, DiagnosticAnalysisResult result)
            {
                Contract.ThrowIfTrue(result.IsAggregatedForm);
                Contract.ThrowIfNull(result.DocumentIds);

                RemoveInMemoryCache(_lastResult);

                // save last aggregated form of analysis result
                _lastResult = result.ToAggregatedForm();

                // serialization can't be canceled.
                var serializerVersion = result.Version;

                foreach (var documentId in result.DocumentIds)
                {
                    var document = project.GetTextDocument(documentId);

                    // If we couldn't find a normal document, and all features are enabled for source generated
                    // documents, attempt to locate a matching source generated document in the project.
                    if (document is null &&
                        project.Solution.Workspace.Services.GetService <IWorkspaceConfigurationService>()?.Options.EnableOpeningSourceGeneratedFiles == true)
                    {
                        document = await project.GetSourceGeneratedDocumentAsync(documentId, CancellationToken.None).ConfigureAwait(false);
                    }

                    if (document == null)
                    {
                        // it can happen with build synchronization since, in build case,
                        // we don't have actual snapshot (we have no idea what sources out of proc build has picked up)
                        // so we might be out of sync.
                        // example of such cases will be changing anything about solution while building is going on.
                        // it can be user explicit actions such as unloading project, deleting a file, but also it can be
                        // something project system or roslyn workspace does such as populating workspace right after
                        // solution is loaded.
                        continue;
                    }

                    await AddToInMemoryStorageAsync(serializerVersion, project, document, document.Id, _owner.SyntaxStateName, result.GetDocumentDiagnostics(document.Id, AnalysisKind.Syntax)).ConfigureAwait(false);
                    await AddToInMemoryStorageAsync(serializerVersion, project, document, document.Id, _owner.SemanticStateName, result.GetDocumentDiagnostics(document.Id, AnalysisKind.Semantic)).ConfigureAwait(false);
                    await AddToInMemoryStorageAsync(serializerVersion, project, document, document.Id, _owner.NonLocalStateName, result.GetDocumentDiagnostics(document.Id, AnalysisKind.NonLocal)).ConfigureAwait(false);
                }

                await AddToInMemoryStorageAsync(serializerVersion, project, document : null, result.ProjectId, _owner.NonLocalStateName, result.GetOtherDiagnostics()).ConfigureAwait(false);
            }
        private void RaiseDocumentDiagnosticsIfNeeded(
            Document document, StateSet stateSet, AnalysisKind kind,
            DiagnosticAnalysisResult oldResult, DiagnosticAnalysisResult newResult,
            Action <DiagnosticsUpdatedArgs> raiseEvents)
        {
            // if our old result is from build and we don't have actual data, don't try micro-optimize and always refresh diagnostics.
            // most of time, we don't actually load or hold the old data in memory from persistent storage due to perf reasons.
            //
            // we need this special behavior for errors from build since unlike live errors, we don't know whether errors
            // from build is for syntax, semantic or others. due to that, we blindly mark them as semantic errors (most common type of errors from build)
            //
            // that can sometime cause issues. for example, if the error turns out to be syntax error (live) then we at the end fail to de-dup.
            // but since this optimization saves us a lot of refresh between live errors analysis we want to disable this only in this condition.
            var forceUpdate = oldResult.FromBuild && oldResult.IsAggregatedForm;

            var oldItems = oldResult.GetDocumentDiagnostics(document.Id, kind);
            var newItems = newResult.GetDocumentDiagnostics(document.Id, kind);

            RaiseDocumentDiagnosticsIfNeeded(document, stateSet, kind, oldItems, newItems, raiseEvents, forceUpdate);
        }
            private async Task <ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> > FilterOutCompilerSemanticErrorsIfNeccessaryAsync(
                Project project, ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> result, CancellationToken cancellationToken)
            {
                // see whether solution is loaded successfully
                var projectLoadedSuccessfully = await project.HasSuccessfullyLoadedAsync(cancellationToken).ConfigureAwait(false);

                if (projectLoadedSuccessfully)
                {
                    return(result);
                }

                var compilerAnalyzer = _owner.HostAnalyzerManager.GetCompilerDiagnosticAnalyzer(project.Language);

                if (compilerAnalyzer == null)
                {
                    // this language doesn't support compiler analyzer
                    return(result);
                }

                if (!result.TryGetValue(compilerAnalyzer, out var analysisResult))
                {
                    // no result from compiler analyzer
                    return(result);
                }

                Logger.Log(FunctionId.Diagnostics_ProjectDiagnostic, p => $"Failed to Load Successfully ({p.FilePath ?? p.Name})", project);

                // get rid of any result except syntax from compiler analyzer result
                var newCompilerAnalysisResult = new DiagnosticAnalysisResult(
                    analysisResult.ProjectId,
                    analysisResult.Version,
                    analysisResult.SyntaxLocals,
                    semanticLocals: ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty,
                    nonLocals: ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty,
                    others: ImmutableArray <DiagnosticData> .Empty,
                    documentIds: null,
                    fromBuild: false);

                // return new result
                return(result.SetItem(compilerAnalyzer, newCompilerAnalysisResult));
            }
            public async ValueTask SaveToInMemoryStorageAsync(Project project, DiagnosticAnalysisResult result)
            {
                Contract.ThrowIfTrue(result.IsAggregatedForm);
                Contract.ThrowIfNull(result.DocumentIds);

                RemoveInMemoryCache(_lastResult);

                // save last aggregated form of analysis result
                _lastResult = result.ToAggregatedForm();

                // serialization can't be canceled.
                var serializerVersion = result.Version;

                foreach (var documentId in result.DocumentIds)
                {
                    var document = project.GetTextDocument(documentId);

                    // If we couldn't find a normal document, and all features are enabled for source generated
                    // documents, attempt to locate a matching source generated document in the project.
                    if (document is null &&
                        project.Solution.Workspace.Services.GetService <ISyntaxTreeConfigurationService>() is { EnableOpeningSourceGeneratedFilesInWorkspace: true })
예제 #23
0
            private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeInProcAsync(
                CompilationWithAnalyzers compilation, Project project, RemoteHostClient?client, CancellationToken cancellationToken)
            {
                Debug.Assert(compilation.Analyzers.Length != 0);

                var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

                // PERF: Run all analyzers at once using the new GetAnalysisResultAsync API.
                var analysisResult = await compilation.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false);

                // if remote host is there, report performance data
                var asyncToken = _asyncOperationListener.BeginAsyncOperation(nameof(AnalyzeInProcAsync));
                var _          = FireAndForgetReportAnalyzerPerformanceAsync(project, client, analysisResult, cancellationToken).CompletesAsyncOperation(asyncToken);

                // get compiler result builder map
                var builderMap = analysisResult.ToResultBuilderMap(project, version, compilation.Compilation, compilation.Analyzers, cancellationToken);

                return(DiagnosticAnalysisResultMap.Create(
                           builderMap.ToImmutableDictionary(kv => kv.Key, kv => DiagnosticAnalysisResult.CreateFromBuilder(kv.Value)),
                           analysisResult.AnalyzerTelemetryInfo));
            }
        private ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> CreateAnalysisResults(
            Project project, ImmutableArray <StateSet> stateSets, ProjectAnalysisData oldAnalysisData, ImmutableArray <DiagnosticData> diagnostics)
        {
            using var poolObject = SharedPools.Default <HashSet <string> >().GetPooledObject();

            var lookup = diagnostics.ToLookup(d => d.Id);

            var builder = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, DiagnosticAnalysisResult>();

            foreach (var stateSet in stateSets)
            {
                var descriptors     = HostAnalyzerManager.GetDiagnosticDescriptors(stateSet.Analyzer);
                var liveDiagnostics = MergeDiagnostics(ConvertToLiveDiagnostics(lookup, descriptors, poolObject.Object), GetDiagnostics(oldAnalysisData.GetResult(stateSet.Analyzer)));

                var result = DiagnosticAnalysisResult.CreateFromBuild(project, liveDiagnostics);

                builder.Add(stateSet.Analyzer, result);
            }

            return(builder.ToImmutable());
        }
예제 #25
0
            public async Task MergeAsync(ActiveFileState state, Document document)
            {
                Contract.ThrowIfFalse(state.DocumentId == document.Id);

                // merge active file state to project state
                var lastResult = _lastResult;

                var syntax   = state.GetAnalysisData(AnalysisKind.Syntax);
                var semantic = state.GetAnalysisData(AnalysisKind.Semantic);

                var project      = document.Project;
                var fullAnalysis = ServiceFeatureOnOffOptions.IsClosedFileDiagnosticsEnabled(project);

                // keep from build flag if full analysis is off
                var fromBuild = fullAnalysis ? false : lastResult.FromBuild;

                // if it is allowed to keep project state, check versions and if they are same, bail out
                // if full solution analysis is off or we are asked to reset document state, we always merge.
                if (fullAnalysis &&
                    syntax.Version != VersionStamp.Default &&
                    syntax.Version == semantic.Version &&
                    syntax.Version == lastResult.Version)
                {
                    // all data is in sync already.
                    return;
                }

                // we have mixed versions or full analysis is off, set it to default so that it can be re-calculated next time so data can be in sync.
                var version = VersionStamp.Default;

                // serialization can't be cancelled.
                var serializer = new DiagnosticDataSerializer(_owner.AnalyzerVersion, version);

                // save active file diagnostics back to project state
                await SerializeAsync(serializer, document, document.Id, _owner.SyntaxStateName, syntax.Items).ConfigureAwait(false);
                await SerializeAsync(serializer, document, document.Id, _owner.SemanticStateName, semantic.Items).ConfigureAwait(false);

                // save last aggregated form of analysis result
                _lastResult = new DiagnosticAnalysisResult(_lastResult.ProjectId, version, _lastResult.DocumentIdsOrEmpty.Add(state.DocumentId), isEmpty: false, fromBuild: fromBuild);
            }
        private static ImmutableArray <DiagnosticData> GetResult(DiagnosticAnalysisResult result, AnalysisKind kind, DocumentId id)
        {
            if (result.IsEmpty || !result.DocumentIds.Contains(id) || result.IsAggregatedForm)
            {
                return(ImmutableArray <DiagnosticData> .Empty);
            }

            switch (kind)
            {
            case AnalysisKind.Syntax:
                return(result.GetResultOrEmpty(result.SyntaxLocals, id));

            case AnalysisKind.Semantic:
                return(result.GetResultOrEmpty(result.SemanticLocals, id));

            case AnalysisKind.NonLocal:
                return(result.GetResultOrEmpty(result.NonLocals, id));

            default:
                return(Contract.FailWithReturn <ImmutableArray <DiagnosticData> >("shouldn't reach here"));
            }
        }
            public async Task <DiagnosticAnalysisResult> GetAnalysisDataAsync(IPersistentStorageService persistentService, TextDocument document, bool avoidLoadingData, CancellationToken cancellationToken)
            {
                // make a copy of last result.
                var lastResult = _lastResult;

                Contract.ThrowIfFalse(lastResult.ProjectId == document.Project.Id);

                if (lastResult.IsDefault)
                {
                    return(await LoadInitialAnalysisDataAsync(persistentService, document, cancellationToken).ConfigureAwait(false));
                }

                var version = await GetDiagnosticVersionAsync(document.Project, cancellationToken).ConfigureAwait(false);

                if (avoidLoadingData && lastResult.Version != version)
                {
                    return(lastResult);
                }

                // if given document doesnt have any diagnostics, return empty.
                if (IsEmpty(lastResult, document.Id))
                {
                    return(DiagnosticAnalysisResult.CreateEmpty(lastResult.ProjectId, lastResult.Version));
                }

                // loading data can be cancelled any time.
                var serializer = new DiagnosticDataSerializer(_owner.AnalyzerVersion, lastResult.Version);
                var builder    = new Builder(document.Project, lastResult.Version);

                if (!await TryDeserializeDocumentDiagnosticsAsync(persistentService, serializer, document, builder, cancellationToken).ConfigureAwait(false))
                {
                    Debug.Assert(lastResult.Version == VersionStamp.Default);

                    // this can happen if we merged back active file diagnostics back to project state but
                    // project state didn't have diagnostics for the file yet. (since project state was staled)
                }

                return(builder.ToResult());
            }
예제 #28
0
        public static void LogProjectDiagnostics(Project project, DiagnosticAnalysisResult result)
        {
            if (!s_reportErrors || !s_reported.TryAdd(project.Id, null))
            {
                // doesn't meet the bar to report the issue.
                return;
            }

            // logs count of errors for this project. this won't log anything if FSA off since
            // we don't collect any diagnostics for a project if FSA is off.
            var map = new Dictionary <string, int>();

            foreach (var documentId in result.DocumentIdsOrEmpty)
            {
                CountErrors(map, result.GetResultOrEmpty(result.SyntaxLocals, documentId));
                CountErrors(map, result.GetResultOrEmpty(result.SemanticLocals, documentId));
                CountErrors(map, result.GetResultOrEmpty(result.NonLocals, documentId));
            }

            CountErrors(map, result.Others);

            LogErrors(project, "ProjectDignostics", project.Id.Id, map);
        }
            public async Task <DiagnosticAnalysisResult> GetProjectAnalysisDataAsync(IPersistentStorageService persistentService, Project project, bool avoidLoadingData, CancellationToken cancellationToken)
            {
                // make a copy of last result.
                var lastResult = _lastResult;

                Contract.ThrowIfFalse(lastResult.ProjectId == project.Id);

                if (lastResult.IsDefault)
                {
                    return(await LoadInitialProjectAnalysisDataAsync(persistentService, project, cancellationToken).ConfigureAwait(false));
                }

                var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

                if (avoidLoadingData && lastResult.Version != version)
                {
                    return(lastResult);
                }

                // if given document doesnt have any diagnostics, return empty.
                if (lastResult.IsEmpty)
                {
                    return(DiagnosticAnalysisResult.CreateEmpty(lastResult.ProjectId, lastResult.Version));
                }

                // loading data can be cancelled any time.
                var serializer = new DiagnosticDataSerializer(_owner.AnalyzerVersion, lastResult.Version);
                var builder    = new Builder(project, lastResult.Version);

                if (!await TryDeserializeProjectDiagnosticsAsync(persistentService, serializer, project, builder, cancellationToken).ConfigureAwait(false))
                {
                    // this can happen if SaveAsync is not yet called but active file merge happened. one of case is if user did build before the very first
                    // analysis happened.
                }

                return(builder.ToResult());
            }
예제 #30
0
        private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeInProcAsync(
            DocumentAnalysisScope?documentAnalysisScope,
            Project project,
            CompilationWithAnalyzers compilationWithAnalyzers,
            RemoteHostClient?client,
            bool logPerformanceInfo,
            bool getTelemetryInfo,
            CancellationToken cancellationToken)
        {
            var version = await DiagnosticIncrementalAnalyzer.GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

            var(analysisResult, additionalPragmaSuppressionDiagnostics) = await compilationWithAnalyzers.GetAnalysisResultAsync(
                documentAnalysisScope, project, AnalyzerInfoCache, cancellationToken).ConfigureAwait(false);

            if (logPerformanceInfo)
            {
                // if remote host is there, report performance data
                var asyncToken = _asyncOperationListener.BeginAsyncOperation(nameof(AnalyzeInProcAsync));
                var _          = FireAndForgetReportAnalyzerPerformanceAsync(documentAnalysisScope, project, client, analysisResult, cancellationToken).CompletesAsyncOperation(asyncToken);
            }

            var analyzers            = documentAnalysisScope?.Analyzers ?? compilationWithAnalyzers.Analyzers;
            var skippedAnalyzersInfo = project.GetSkippedAnalyzersInfo(AnalyzerInfoCache);

            // get compiler result builder map
            var builderMap = await analysisResult.ToResultBuilderMapAsync(
                additionalPragmaSuppressionDiagnostics, documentAnalysisScope, project, version,
                compilationWithAnalyzers.Compilation, analyzers, skippedAnalyzersInfo,
                compilationWithAnalyzers.AnalysisOptions.ReportSuppressedDiagnostics, cancellationToken).ConfigureAwait(false);

            var result    = builderMap.ToImmutableDictionary(kv => kv.Key, kv => DiagnosticAnalysisResult.CreateFromBuilder(kv.Value));
            var telemetry = getTelemetryInfo
                ? analysisResult.AnalyzerTelemetryInfo
                : ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty;

            return(DiagnosticAnalysisResultMap.Create(result, telemetry));
        }
예제 #31
0
            public async Task SaveAsync(Project project, DiagnosticAnalysisResult result)
            {
                Contract.ThrowIfTrue(result.IsAggregatedForm);

                RemoveInMemoryCache(_lastResult);

                // save last aggregated form of analysis result
                _lastResult = result.ToAggregatedForm();

                // serialization can't be cancelled.
                var serializer = new DiagnosticDataSerializer(_owner.AnalyzerVersion, result.Version);

                foreach (var documentId in result.DocumentIds)
                {
                    var document = project.GetDocument(documentId);
                    if (document == null)
                    {
                        // it can happen with build synchronization since, in build case,
                        // we don't have actual snapshot (we have no idea what sources out of proc build has picked up)
                        // so we might be out of sync.
                        // example of such cases will be changing anything about solution while building is going on.
                        // it can be user explict actions such as unloading project, deleting a file, but also it can be
                        // something project system or roslyn workspace does such as populating workspace right after
                        // solution is loaded.
                        continue;
                    }

                    await SerializeAsync(serializer, document, document.Id, _owner.SyntaxStateName, GetResult(result, AnalysisKind.Syntax, document.Id)).ConfigureAwait(false);
                    await SerializeAsync(serializer, document, document.Id, _owner.SemanticStateName, GetResult(result, AnalysisKind.Semantic, document.Id)).ConfigureAwait(false);
                    await SerializeAsync(serializer, document, document.Id, _owner.NonLocalStateName, GetResult(result, AnalysisKind.NonLocal, document.Id)).ConfigureAwait(false);
                }

                await SerializeAsync(serializer, project, result.ProjectId, _owner.NonLocalStateName, result.Others).ConfigureAwait(false);

                AnalyzerABTestLogger.LogProjectDiagnostics(project, _owner.StateName, result);
            }
        private ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult> CreateAnalysisResults(
            Project project, ImmutableArray<StateSet> stateSets, ProjectAnalysisData oldAnalysisData, ImmutableArray<DiagnosticData> diagnostics)
        {
            using (var poolObject = SharedPools.Default<HashSet<string>>().GetPooledObject())
            {
                // we can't distinguish locals and non locals from build diagnostics nor determine right snapshot version for the build.
                // so we put everything in as semantic local with default version. this lets us to replace those to live diagnostics when needed easily.
                var version = VersionStamp.Default;
                var lookup = diagnostics.ToLookup(d => d.Id);

                var builder = ImmutableDictionary.CreateBuilder<DiagnosticAnalyzer, DiagnosticAnalysisResult>();
                foreach (var stateSet in stateSets)
                {
                    var descriptors = HostAnalyzerManager.GetDiagnosticDescriptors(stateSet.Analyzer);
                    var liveDiagnostics = MergeDiagnostics(ConvertToLiveDiagnostics(lookup, descriptors, poolObject.Object), GetDiagnostics(oldAnalysisData.GetResult(stateSet.Analyzer)));

                    var group = liveDiagnostics.GroupBy(d => d.DocumentId);
                    var result = new DiagnosticAnalysisResult(
                        project.Id,
                        version,
                        documentIds: group.Where(g => g.Key != null).Select(g => g.Key).ToImmutableHashSet(),
                        syntaxLocals: ImmutableDictionary<DocumentId, ImmutableArray<DiagnosticData>>.Empty,
                        semanticLocals: group.Where(g => g.Key != null).ToImmutableDictionary(g => g.Key, g => g.ToImmutableArray()),
                        nonLocals: ImmutableDictionary<DocumentId, ImmutableArray<DiagnosticData>>.Empty,
                        others: group.Where(g => g.Key == null).SelectMany(g => g).ToImmutableArrayOrEmpty(),
                        fromBuild: true);

                    builder.Add(stateSet.Analyzer, result);
                }

                return builder.ToImmutable();
            }
        }
        private static ImmutableArray<DiagnosticData> GetResult(DiagnosticAnalysisResult result, AnalysisKind kind, DocumentId id)
        {
            if (result.IsEmpty || !result.DocumentIds.Contains(id) || result.IsAggregatedForm)
            {
                return ImmutableArray<DiagnosticData>.Empty;
            }

            switch (kind)
            {
                case AnalysisKind.Syntax:
                    return result.GetResultOrEmpty(result.SyntaxLocals, id);
                case AnalysisKind.Semantic:
                    return result.GetResultOrEmpty(result.SemanticLocals, id);
                case AnalysisKind.NonLocal:
                    return result.GetResultOrEmpty(result.NonLocals, id);
                default:
                    return Contract.FailWithReturn<ImmutableArray<DiagnosticData>>("shouldn't reach here");
            }
        }
        private ImmutableArray<DiagnosticData> GetDiagnostics(DiagnosticAnalysisResult result)
        {
            // PERF: don't allocation anything if not needed
            if (result.IsAggregatedForm || result.IsEmpty)
            {
                return ImmutableArray<DiagnosticData>.Empty;
            }

            return result.SyntaxLocals.Values.SelectMany(v => v).Concat(
                   result.SemanticLocals.Values.SelectMany(v => v)).Concat(
                   result.NonLocals.Values.SelectMany(v => v)).Concat(
                   result.Others).ToImmutableArray();
        }
        private void RaiseProjectDiagnosticsCreated(Project project, StateSet stateSet, DiagnosticAnalysisResult oldAnalysisResult, DiagnosticAnalysisResult newAnalysisResult, Action<DiagnosticsUpdatedArgs> raiseEvents)
        {
            foreach (var documentId in newAnalysisResult.DocumentIds)
            {
                var document = project.GetDocument(documentId);
                if (document == null)
                {
                    // it can happen with build synchronization since, in build case, 
                    // we don't have actual snapshot (we have no idea what sources out of proc build has picked up)
                    // so we might be out of sync.
                    // example of such cases will be changing anything about solution while building is going on.
                    // it can be user explict actions such as unloading project, deleting a file, but also it can be 
                    // something project system or roslyn workspace does such as populating workspace right after
                    // solution is loaded.
                    continue;
                }

                RaiseDocumentDiagnosticsIfNeeded(document, stateSet, AnalysisKind.NonLocal, oldAnalysisResult, newAnalysisResult, raiseEvents);

                // we don't raise events for active file. it will be taken cared by active file analysis
                if (stateSet.IsActiveFile(documentId))
                {
                    continue;
                }

                RaiseDocumentDiagnosticsIfNeeded(document, stateSet, AnalysisKind.Syntax, oldAnalysisResult, newAnalysisResult, raiseEvents);
                RaiseDocumentDiagnosticsIfNeeded(document, stateSet, AnalysisKind.Semantic, oldAnalysisResult, newAnalysisResult, raiseEvents);
            }

            RaiseDiagnosticsCreated(project, stateSet, newAnalysisResult.Others, raiseEvents);
        }
        private void RaiseDocumentDiagnosticsIfNeeded(
            Document document, StateSet stateSet, AnalysisKind kind,
            DiagnosticAnalysisResult oldResult, DiagnosticAnalysisResult newResult,
            Action<DiagnosticsUpdatedArgs> raiseEvents)
        {
            var oldItems = GetResult(oldResult, kind, document.Id);
            var newItems = GetResult(newResult, kind, document.Id);

            RaiseDocumentDiagnosticsIfNeeded(document, stateSet, kind, oldItems, newItems, raiseEvents);
        }