コード例 #1
0
        private void RaiseDocumentDiagnosticsIfNeeded(
            Document document, StateSet stateSet, AnalysisKind kind,
            AnalysisResult oldResult, AnalysisResult 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 ImmutableArray <DiagnosticData> GetDiagnostics(AnalysisResult 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());
        }
コード例 #3
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.Solution.Workspace, project.Language);

                // 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 AnalysisResult(_lastResult.ProjectId, version, _lastResult.DocumentIdsOrEmpty.Add(state.DocumentId), isEmpty: false, fromBuild: fromBuild);
            }
コード例 #4
0
        private static ImmutableArray <DiagnosticData> GetResult(AnalysisResult 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"));
            }
        }
コード例 #5
0
            public async Task SaveAsync(Project project, AnalysisResult 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);
                    Contract.ThrowIfNull(document);

                    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);
            }
コード例 #6
0
        private void RaiseProjectDiagnosticsCreated(Project project, StateSet stateSet, AnalysisResult oldAnalysisResult, AnalysisResult newAnalysisResult, Action <DiagnosticsUpdatedArgs> raiseEvents)
        {
            foreach (var documentId in newAnalysisResult.DocumentIds)
            {
                var document = project.GetDocument(documentId);
                Contract.ThrowIfNull(document);

                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 async Task FireAndForgetReportAnalyzerPerformanceAsync(Project project, RemoteHostClient?client, AnalysisResult analysisResult, CancellationToken cancellationToken)
            {
                if (client == null)
                {
                    return;
                }

                try
                {
                    _ = await client.TryRunRemoteAsync(
                        WellKnownServiceHubServices.CodeAnalysisService,
                        nameof(IRemoteDiagnosticAnalyzerService.ReportAnalyzerPerformance),
                        solution : null,
                        new object[]
                    {
                        analysisResult.AnalyzerTelemetryInfo.ToAnalyzerPerformanceInfo(_analyzerInfoCache),
                        // +1 for project itself
                        project.DocumentIds.Count + 1
                    },
                        callbackTarget : null,
                        cancellationToken).ConfigureAwait(false);
                }
                catch (Exception ex) when(FatalError.ReportWithoutCrashUnlessCanceled(ex))
                {
                    // ignore all, this is fire and forget method
                }
            }
        private void RaiseProjectDiagnosticsCreated(Project project, StateSet stateSet, AnalysisResult oldAnalysisResult, AnalysisResult 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);
        }
コード例 #9
0
 private bool IsEmpty(AnalysisResult result, DocumentId documentId)
 {
     return(!result.DocumentIdsOrEmpty.Contains(documentId));
 }
コード例 #10
0
 public ProjectState(StateSet owner, ProjectId projectId)
 {
     _owner      = owner;
     _lastResult = new AnalysisResult(projectId, VersionStamp.Default, documentIds: null, isEmpty: true);
 }
コード例 #11
0
 public void ResetVersion()
 {
     // reset version of cached data so that we can recalculate new data (ex, OnDocumentReset)
     _lastResult = new AnalysisResult(_lastResult.ProjectId, VersionStamp.Default, _lastResult.DocumentIds, _lastResult.IsEmpty, _lastResult.FromBuild);
 }