Skip to content

Commit

Permalink
Report external build errors using the platform's diagnostic brokered
Browse files Browse the repository at this point in the history
service instead of via Roslyn
  • Loading branch information
dibarbet committed May 15, 2024
1 parent 6a0e23e commit 9c076e0
Show file tree
Hide file tree
Showing 8 changed files with 322 additions and 1,333 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal static class FSharpProjectExternalErrorReporterFactory
public static IVsLanguageServiceBuildErrorReporter2 Create(ProjectId projectId, string errorCodePrefix, IServiceProvider serviceProvider)
{
var workspace = (VisualStudioWorkspaceImpl)serviceProvider.GetMefService<VisualStudioWorkspace>();
return new ProjectExternalErrorReporter(projectId, errorCodePrefix, LanguageNames.FSharp, workspace);
return new ProjectExternalErrorReporter(projectId, projectId.Id, errorCodePrefix, LanguageNames.FSharp, workspace);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ public AbstractLegacyProject(
ConnectHierarchyEvents();
RefreshBinOutputPath();

_externalErrorReporter = new ProjectExternalErrorReporter(ProjectSystemProject.Id, externalErrorReportingPrefix, language, workspaceImpl);
var projectHierarchyGuid = GetProjectIDGuid(hierarchy);

_externalErrorReporter = new ProjectExternalErrorReporter(ProjectSystemProject.Id, projectHierarchyGuid, externalErrorReportingPrefix, language, workspaceImpl);
_batchScopeCreator = componentModel.GetService<SolutionEventsBatchScopeCreator>();
_batchScopeCreator.StartTrackingProject(ProjectSystemProject, Hierarchy);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
using Microsoft.CodeAnalysis.Telemetry;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Workspaces.ProjectSystem;
using Microsoft.ServiceHub.Framework;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Composition;
using Microsoft.VisualStudio.Editor;
Expand All @@ -40,6 +41,7 @@
using Microsoft.VisualStudio.LanguageServices.Utilities;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Shell.ServiceBroker;
using Microsoft.VisualStudio.Telemetry;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Projection;
Expand Down Expand Up @@ -132,12 +134,7 @@ public VisualStudioWorkspaceImpl(ExportProvider exportProvider, IAsyncServicePro
_ = Task.Run(() => InitializeUIAffinitizedServicesAsync(asyncServiceProvider));

_lazyExternalErrorDiagnosticUpdateSource = new Lazy<ExternalErrorDiagnosticUpdateSource>(() =>
new ExternalErrorDiagnosticUpdateSource(
this,
exportProvider.GetExportedValue<IDiagnosticAnalyzerService>(),
exportProvider.GetExportedValue<IGlobalOperationNotificationService>(),
exportProvider.GetExportedValue<IAsynchronousOperationListenerProvider>(),
_threadingContext),
exportProvider.GetExportedValue<ExternalErrorDiagnosticUpdateSource>(),
isThreadSafe: true);

_workspaceListener = Services.GetRequiredService<IWorkspaceAsynchronousOperationListenerProvider>().GetListener();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,56 +152,6 @@ private static Func<Project, bool> GetShouldFixInProjectDelegate(IVsHierarchyIte
return p => projectHierarchy == null || p.Id == projectIdToMatch;
}

private async Task<ImmutableArray<DiagnosticData>> GetAllBuildDiagnosticsAsync(Func<Project, bool> shouldFixInProject, CancellationToken cancellationToken)
{
using var _ = CodeAnalysis.PooledObjects.ArrayBuilder<DiagnosticData>.GetInstance(out var builder);

var buildDiagnostics = _buildErrorDiagnosticService.GetBuildErrors().Where(d => d.ProjectId != null && d.Severity != DiagnosticSeverity.Hidden);
var solution = _workspace.CurrentSolution;
foreach (var diagnosticsByProject in buildDiagnostics.GroupBy(d => d.ProjectId))
{
cancellationToken.ThrowIfCancellationRequested();

if (diagnosticsByProject.Key == null)
{
// Diagnostics with no projectId cannot be suppressed.
continue;
}

var project = solution.GetProject(diagnosticsByProject.Key);
if (project != null && shouldFixInProject(project))
{
var diagnosticsByDocument = diagnosticsByProject.GroupBy(d => d.DocumentId);
foreach (var group in diagnosticsByDocument)
{
var documentId = group.Key;
if (documentId == null)
{
// Project diagnostics, just add all of them.
builder.AddRange(group);
continue;
}

// For document diagnostics ensure that whatever was reported is placed at a valid location for
// the state the document is currently in.
var document = project.GetDocument(documentId);
if (document != null)
{
var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
var text = await tree.GetTextAsync(cancellationToken).ConfigureAwait(false);
foreach (var diagnostic in group)
{
var span = diagnostic.DataLocation.UnmappedFileSpan.GetClampedTextSpan(text);
builder.Add(diagnostic.WithLocations(diagnostic.DataLocation.WithSpan(span, tree), additionalLocations: default));
}
}
}
}
}

return builder.ToImmutable();
}

private static string GetFixTitle(bool isAddSuppression)
=> isAddSuppression ? ServicesVSResources.Suppress_diagnostics : ServicesVSResources.Remove_suppressions;

Expand All @@ -219,7 +169,7 @@ void computeDiagnosticsToFix(IUIThreadOperationContext context)
// snapshots. Otherwise, get all diagnostics from the diagnostic service.
var diagnosticsToFixTask = selectedEntriesOnly
? _suppressionStateService.GetSelectedItemsAsync(isAddSuppression, cancellationToken)
: GetAllBuildDiagnosticsAsync(shouldFixInProject, cancellationToken);
: Task.FromResult<ImmutableArray<DiagnosticData>>([]);

diagnosticsToFix = diagnosticsToFixTask.WaitAndGetResult(cancellationToken).ToImmutableHashSet();
}
Expand Down
Loading

0 comments on commit 9c076e0

Please sign in to comment.