Skip to content

Commit 58f80cd

Browse files
Remove the 'force compute' entrypoint for diagnostics
1 parent 940a005 commit 58f80cd

File tree

11 files changed

+35
-80
lines changed

11 files changed

+35
-80
lines changed

src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using Microsoft.CodeAnalysis.Collections;
1515
using Microsoft.CodeAnalysis.Diagnostics;
1616
using Microsoft.CodeAnalysis.Editor.Implementation.Suggestions;
17+
using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions;
1718
using Microsoft.CodeAnalysis.ErrorLogger;
1819
using Microsoft.CodeAnalysis.ErrorReporting;
1920
using Microsoft.CodeAnalysis.Extensions;

src/EditorFeatures/Test/Diagnostics/DiagnosticAnalyzerServiceTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using Microsoft.CodeAnalysis.CSharp.RemoveUnnecessarySuppressions;
1414
using Microsoft.CodeAnalysis.Diagnostics;
1515
using Microsoft.CodeAnalysis.Diagnostics.CSharp;
16+
using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions;
1617
using Microsoft.CodeAnalysis.Options;
1718
using Microsoft.CodeAnalysis.PooledObjects;
1819
using Microsoft.CodeAnalysis.Remote.Diagnostics;

src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Imports Microsoft.CodeAnalysis.CSharp
1313
Imports Microsoft.CodeAnalysis.Diagnostics
1414
Imports Microsoft.CodeAnalysis.Diagnostics.CSharp
1515
Imports Microsoft.CodeAnalysis.Editor.UnitTests
16+
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions
1617
Imports Microsoft.CodeAnalysis.Host.Mef
1718
Imports Microsoft.CodeAnalysis.Serialization
1819
Imports Microsoft.CodeAnalysis.SolutionCrawler
@@ -2141,8 +2142,7 @@ class MyClass
21412142
Assert.Equal(analyzer.Descriptor.Id, descriptors.Single().Id)
21422143

21432144
' Get cached project diagnostics.
2144-
Dim diagnostics = Await diagnosticService.ForceAnalyzeProjectAsync(
2145-
project, CancellationToken.None)
2145+
Dim diagnostics = Await diagnosticService.ForceAnalyzeProjectAsync(project, CancellationToken.None)
21462146

21472147
' in v2, solution crawler never creates non-local hidden diagnostics.
21482148
' v2 still creates those for LB and explicit queries such as FixAll.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Collections.Immutable;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Diagnostics;
9+
10+
namespace Microsoft.CodeAnalysis.Editor.UnitTests.Extensions;
11+
12+
internal static class IDiagnosticServiceExtensions
13+
{
14+
public static async Task<ImmutableArray<DiagnosticData>> ForceAnalyzeProjectAsync(
15+
this IDiagnosticAnalyzerService service, Project project, CancellationToken cancellationToken)
16+
{
17+
var documentDiagnostics = await service.GetDiagnosticsForIdsAsync(project, documentId: null, diagnosticIds: null, shouldIncludeAnalyzer: null, includeLocalDocumentDiagnostics: true, cancellationToken).ConfigureAwait(false);
18+
var projectDiagnostics = await service.GetProjectDiagnosticsForIdsAsync(project, diagnosticIds: null, shouldIncludeAnalyzer: null, cancellationToken).ConfigureAwait(false);
19+
return [.. documentDiagnostics, .. projectDiagnostics];
20+
}
21+
}

src/Features/Core/Portable/Diagnostics/CodeAnalysisDiagnosticAnalyzerService.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,17 @@ public async ValueTask RunAnalysisAsync(Project project, CancellationToken cance
8888

8989
Contract.ThrowIfFalse(project.Solution.Workspace == _workspace);
9090

91-
// Execute force analysis for the project.
92-
var diagnostics = await _diagnosticAnalyzerService.ForceAnalyzeProjectAsync(project, cancellationToken).ConfigureAwait(false);
91+
// Compute all the diagnostics for all the documents in the project.
92+
var documentDiagnostics = await _diagnosticAnalyzerService.GetDiagnosticsForIdsAsync(
93+
project, documentId: null, diagnosticIds: null, shouldIncludeAnalyzer: null, includeLocalDocumentDiagnostics: true, cancellationToken).ConfigureAwait(false);
94+
95+
// Then all the non-document diagnostics for that project as well.
96+
var projectDiagnostics = await _diagnosticAnalyzerService.GetProjectDiagnosticsForIdsAsync(
97+
project, diagnosticIds: null, shouldIncludeAnalyzer: null, cancellationToken).ConfigureAwait(false);
9398

9499
// Add the given project to the analyzed projects list **after** analysis has completed.
95100
// We need this ordering to ensure that 'HasProjectBeenAnalyzed' call above functions correctly.
96-
_analyzedProjectToDiagnostics[project.Id] = diagnostics;
101+
_analyzedProjectToDiagnostics[project.Id] = [.. documentDiagnostics, .. projectDiagnostics];
97102

98103
// Remove from the cleared list now that we've run a more recent "run code analysis" on this project.
99104
_clearedProjectIds.Remove(project.Id);

src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ internal interface IDiagnosticAnalyzerService : IWorkspaceService
2222
/// </remarks>
2323
void RequestDiagnosticRefresh();
2424

25-
/// <inheritdoc cref="IRemoteDiagnosticAnalyzerService.ForceAnalyzeProjectAsync"/>
26-
Task<ImmutableArray<DiagnosticData>> ForceAnalyzeProjectAsync(Project project, CancellationToken cancellationToken);
27-
2825
/// <inheritdoc cref="IRemoteDiagnosticAnalyzerService.GetDeprioritizationCandidatesAsync"/>
2926
Task<ImmutableArray<DiagnosticAnalyzer>> GetDeprioritizationCandidatesAsync(
3027
Project project, ImmutableArray<DiagnosticAnalyzer> analyzers, CancellationToken cancellationToken);

src/Features/Core/Portable/Diagnostics/Service/DiagnosticAnalyzerService_ForceAnalyzeProject.cs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics;
1717

1818
internal sealed partial class DiagnosticAnalyzerService
1919
{
20-
/// <summary>
21-
/// Cached data from a real <see cref="ProjectState"/> instance to the cached diagnostic data produced by
22-
/// <em>all</em> the analyzers for the project. This data can then be used by <see
23-
/// cref="GetDiagnosticsForIdsAsync"/> to speed up subsequent calls through the normal <see
24-
/// cref="IDiagnosticAnalyzerService"/> entry points as long as the project hasn't changed at all.
25-
/// </summary>
26-
/// <remarks>
27-
/// This table is keyed off of <see cref="ProjectState"/> but stores data from <see cref="SolutionState"/> on
28-
/// it. Specifically <see cref="SolutionState.Analyzers"/>. Normally keying off a ProjectState would not be ok
29-
/// as the ProjectState might stay the same while the SolutionState changed. However, that can't happen as
30-
/// SolutionState has the data for Analyzers computed prior to Projects being added, and then never changes.
31-
/// Practically, solution analyzers are the core Roslyn analyzers themselves we distribute, or analyzers shipped
32-
/// by vsix (not nuget). These analyzers do not get loaded after changing *until* VS restarts.
33-
/// </remarks>
34-
private static readonly ConditionalWeakTable<ProjectState, StrongBox<(Checksum checksum, ImmutableArray<DiagnosticAnalyzer> analyzers, ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult> diagnosticAnalysisResults)>> s_projectToForceAnalysisData = new();
35-
20+
#if false
3621
public async Task<ImmutableArray<DiagnosticData>> ForceAnalyzeProjectInProcessAsync(Project project, CancellationToken cancellationToken)
3722
{
3823
var projectState = project.State;
@@ -134,4 +119,5 @@ static bool IsCandidateForFullSolutionAnalysis(
134119
return descriptors.Any(static (d, arg) => d.GetEffectiveSeverity(arg.CompilationOptions, arg.isHostAnalyzer ? arg.analyzerConfigOptions?.ConfigOptionsWithFallback : arg.analyzerConfigOptions?.ConfigOptionsWithoutFallback, arg.analyzerConfigOptions?.TreeOptions) != ReportDiagnostic.Hidden, (project.CompilationOptions, isHostAnalyzer, analyzerConfigOptions));
135120
}
136121
}
122+
#endif
137123
}

src/Features/Core/Portable/Diagnostics/Service/DiagnosticAnalyzerService_ProduceProjectDiagnostics.cs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,6 @@ void AddIncludedDiagnostics(ArrayBuilder<DiagnosticData> builder, ImmutableArray
7070
async Task<ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>> GetOrComputeDiagnosticAnalysisResultsAsync(
7171
ImmutableArray<DiagnosticAnalyzer> analyzers)
7272
{
73-
// If there was a 'ForceAnalyzeProjectAsync' run for this project, we can piggy back off of the
74-
// prior computed/cached results as they will be a superset of the results we want.
75-
//
76-
// Note: the caller will loop over *its* analyzers, grabbing from the full set of data we've cached for
77-
// this project, and filtering down further. So it's ok to return this potentially larger set.
78-
//
79-
// Note: While ForceAnalyzeProjectAsync should always run with a larger set of analyzers than us
80-
// (since it runs all analyzers), we still run a paranoia check that the analyzers we care about are
81-
// a subset of that call so that we don't accidentally reuse results that would not correspond to
82-
// what we are computing ourselves.
83-
if (s_projectToForceAnalysisData.TryGetValue(project.State, out var box) &&
84-
analyzers.IsSubsetOf(box.Value.analyzers))
85-
{
86-
var checksum = await project.GetDiagnosticChecksumAsync(cancellationToken).ConfigureAwait(false);
87-
if (box.Value.checksum == checksum)
88-
return box.Value.diagnosticAnalysisResults;
89-
}
90-
9173
// Otherwise, just compute for the analyzers we care about.
9274
var compilation = await GetOrCreateCompilationWithAnalyzersAsync(
9375
project, analyzers, hostAnalyzerInfo, this.CrashOnAnalyzerException, cancellationToken).ConfigureAwait(false);

src/Features/Core/Portable/Diagnostics/Service/DiagnosticAnalyzerService_RemoteOrLocalDispatcher.cs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,6 @@ namespace Microsoft.CodeAnalysis.Diagnostics;
1919

2020
internal sealed partial class DiagnosticAnalyzerService : IDiagnosticAnalyzerService
2121
{
22-
public async Task<ImmutableArray<DiagnosticData>> ForceAnalyzeProjectAsync(Project project, CancellationToken cancellationToken)
23-
{
24-
var client = await RemoteHostClient.TryGetClientAsync(project, cancellationToken).ConfigureAwait(false);
25-
if (client is not null)
26-
{
27-
var result = await client.TryInvokeAsync<IRemoteDiagnosticAnalyzerService, ImmutableArray<DiagnosticData>>(
28-
project,
29-
(service, solution, cancellationToken) => service.ForceAnalyzeProjectAsync(solution, project.Id, cancellationToken),
30-
cancellationToken).ConfigureAwait(false);
31-
32-
return result.HasValue ? result.Value : [];
33-
}
34-
35-
// No OOP connection. Compute in proc.
36-
return await ForceAnalyzeProjectInProcessAsync(project, cancellationToken).ConfigureAwait(false);
37-
}
38-
3922
public async Task<ImmutableArray<DiagnosticDescriptor>> GetDiagnosticDescriptorsAsync(
4023
Solution solution, ProjectId projectId, AnalyzerReference analyzerReference, string language, CancellationToken cancellationToken)
4124
{

src/Workspaces/Core/Portable/Diagnostics/IRemoteDiagnosticAnalyzerService.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@ namespace Microsoft.CodeAnalysis.Diagnostics;
1414

1515
internal interface IRemoteDiagnosticAnalyzerService
1616
{
17-
/// <summary>
18-
/// Force analyzes the given project by running all applicable analyzers on the project.
19-
/// </summary>
20-
ValueTask<ImmutableArray<DiagnosticData>> ForceAnalyzeProjectAsync(Checksum solutionChecksum, ProjectId projectId, CancellationToken cancellationToken);
21-
2217
/// <summary>
2318
/// Returns the analyzers that are candidates to be de-prioritized to
2419
/// <see cref="CodeActionRequestPriority.Low"/> priority for improvement in analyzer

0 commit comments

Comments
 (0)