private static Task <ImmutableArray <Diagnostic> > AnalyzeSemanticsImplAsync(
            Document document,
            CancellationToken cancellationToken
            )
        {
            var workspace = document.Project.Solution.Workspace;
            var proxy     = new RemoteEditAndContinueServiceProxy(workspace);

            var activeStatementSpanProvider = new DocumentActiveStatementSpanProvider(
                async cancellationToken =>
            {
                var trackingService =
                    workspace.Services.GetRequiredService <IActiveStatementTrackingService>();
                return(await trackingService
                       .GetSpansAsync(document, cancellationToken)
                       .ConfigureAwait(false));
            }
                );

            return(proxy
                   .GetDocumentDiagnosticsAsync(
                       document,
                       activeStatementSpanProvider,
                       cancellationToken
                       )
                   .AsTask());
        }
        public override Task <ImmutableArray <Diagnostic> > AnalyzeSemanticsAsync(Document document, CancellationToken cancellationToken)
        {
            var services   = document.Project.Solution.Workspace.Services;
            var encService = services.GetService <IEditAndContinueWorkspaceService>();

            if (encService is null)
            {
                return(SpecializedTasks.EmptyImmutableArray <Diagnostic>());
            }

            var activeStatementSpanProvider = new DocumentActiveStatementSpanProvider(async cancellationToken =>
            {
                var trackingService = services.GetRequiredService <IActiveStatementTrackingService>();
                return(await trackingService.GetSpansAsync(document, cancellationToken).ConfigureAwait(false));
            });

            return(encService.GetDocumentDiagnosticsAsync(document, activeStatementSpanProvider, cancellationToken));
        }
示例#3
0
 public DocumentActiveStatementSpanProviderCallback(DocumentActiveStatementSpanProvider documentProvider)
 => _documentProvider = documentProvider;
        public async Task <ImmutableArray <Diagnostic> > GetDocumentDiagnosticsAsync(Document document, DocumentActiveStatementSpanProvider activeStatementSpanProvider, CancellationToken cancellationToken)
        {
            try
            {
                var debuggingSession = _debuggingSession;
                if (debuggingSession == null)
                {
                    return(ImmutableArray <Diagnostic> .Empty);
                }

                // Not a C# or VB project.
                var project = document.Project;
                if (!SupportsEditAndContinue(project))
                {
                    return(ImmutableArray <Diagnostic> .Empty);
                }

                // Document does not compile to the assembly (e.g. cshtml files, .g.cs files generated for completion only)
                if (document.State.Attributes.DesignTimeOnly || !document.SupportsSyntaxTree)
                {
                    return(ImmutableArray <Diagnostic> .Empty);
                }

                // Do not analyze documents (and report diagnostics) of projects that have not been built.
                // Allow user to make any changes in these documents, they won't be applied within the current debugging session.
                // Do not report the file read error - it might be an intermittent issue. The error will be reported when the
                // change is attempted to be applied.
                var(mvid, _) = await debuggingSession.GetProjectModuleIdAsync(project, cancellationToken).ConfigureAwait(false);

                if (mvid == Guid.Empty)
                {
                    return(ImmutableArray <Diagnostic> .Empty);
                }

                var(oldDocument, oldDocumentState) = await debuggingSession.LastCommittedSolution.GetDocumentAndStateAsync(document.Id, cancellationToken).ConfigureAwait(false);

                if (oldDocumentState == CommittedSolution.DocumentState.OutOfSync ||
                    oldDocumentState == CommittedSolution.DocumentState.Indeterminate ||
                    oldDocumentState == CommittedSolution.DocumentState.DesignTimeOnly)
                {
                    // Do not report diagnostics for existing out-of-sync documents or design-time-only documents.
                    return(ImmutableArray <Diagnostic> .Empty);
                }

                // The document has not changed while the application is running since the last changes were committed:
                var editSession = _editSession;

                if (editSession == null)
                {
                    if (document == oldDocument)
                    {
                        return(ImmutableArray <Diagnostic> .Empty);
                    }

                    // Any changes made in loaded, built projects outside of edit session are rude edits (the application is running):
                    var newSyntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                    Contract.ThrowIfNull(newSyntaxTree);

                    var changedSpans = await GetChangedSpansAsync(oldDocument, newSyntaxTree, cancellationToken).ConfigureAwait(false);

                    return(GetRunModeDocumentDiagnostics(document, newSyntaxTree, changedSpans));
                }

                var documentActiveStatementSpans = await activeStatementSpanProvider(cancellationToken).ConfigureAwait(false);

                var analysis = await editSession.GetDocumentAnalysis(oldDocument, document, documentActiveStatementSpans).GetValueAsync(cancellationToken).ConfigureAwait(false);

                if (analysis.HasChanges)
                {
                    // Once we detected a change in a document let the debugger know that the corresponding loaded module
                    // is about to be updated, so that it can start initializing it for EnC update, reducing the amount of time applying
                    // the change blocks the UI when the user "continues".
                    if (debuggingSession.AddModulePreparedForUpdate(mvid))
                    {
                        // fire and forget:
                        _ = Task.Run(() => _debugeeModuleMetadataProvider.PrepareModuleForUpdateAsync(mvid, cancellationToken), cancellationToken);
                    }
                }

                if (analysis.RudeEditErrors.IsEmpty)
                {
                    return(ImmutableArray <Diagnostic> .Empty);
                }

                editSession.Telemetry.LogRudeEditDiagnostics(analysis.RudeEditErrors);

                // track the document, so that we can refresh or clean diagnostics at the end of edit session:
                editSession.TrackDocumentWithReportedDiagnostics(document.Id);

                var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                return(analysis.RudeEditErrors.SelectAsArray((e, t) => e.ToDiagnostic(t), tree));
            }
            catch (Exception e) when(FatalError.ReportWithoutCrashUnlessCanceled(e))
            {
                return(ImmutableArray <Diagnostic> .Empty);
            }
        }