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)); }
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); } }