-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: Ensure we always cache diag results. #73199
Changes from 7 commits
7ce7b8a
6e7fe04
c98306b
9a848f2
e8ac74f
44e5853
01bc98b
511935a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,35 +22,27 @@ public async Task<ImmutableArray<DiagnosticData>> ForceAnalyzeProjectAsync(Proje | |
{ | ||
try | ||
{ | ||
var stateSets = GetStateSetsForFullSolutionAnalysis(_stateManager.GetOrUpdateStateSets(project), project); | ||
|
||
// get driver only with active analyzers. | ||
var ideOptions = AnalyzerService.GlobalOptions.GetIdeAnalyzerOptions(project); | ||
|
||
// PERF: get analyzers that are not suppressed and marked as open file only | ||
// this is perf optimization. we cache these result since we know the result. (no diagnostics) | ||
var activeAnalyzers = stateSets | ||
.Select(s => s.Analyzer) | ||
.Where(a => !a.IsOpenFileOnly(ideOptions.CleanupOptions?.SimplifierOptions)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mavasani this part seems very weird to me. We would get the statesets... but then extract out the analyzers that we'd actually want to run. I tried to change this to just filter down teh statesets in the first place, makign it so that we have a 1:1 mapping from stateset to the analyzers we run, and so we wouldn't have a case where we were looking at statesets taht were actually running/computing/caching data because we filtered out their analyzer. |
||
|
||
CompilationWithAnalyzers? compilationWithAnalyzers = null; | ||
var stateSets = GetStateSetsForFullSolutionAnalysis(_stateManager.GetOrUpdateStateSets(project), project, ideOptions); | ||
|
||
compilationWithAnalyzers = await DocumentAnalysisExecutor.CreateCompilationWithAnalyzersAsync(project, ideOptions, activeAnalyzers, includeSuppressedDiagnostics: true, cancellationToken).ConfigureAwait(false); | ||
var compilationWithAnalyzers = await CreateCompilationWithAnalyzersAsync( | ||
project, ideOptions, stateSets, includeSuppressedDiagnostics: true, cancellationToken).ConfigureAwait(false); | ||
|
||
var result = await GetProjectAnalysisDataAsync(compilationWithAnalyzers, project, ideOptions, stateSets, cancellationToken).ConfigureAwait(false); | ||
|
||
using var _ = ArrayBuilder<DiagnosticData>.GetInstance(out var diagnostics); | ||
|
||
// no cancellation after this point. | ||
cancellationToken = CancellationToken.None; | ||
|
||
foreach (var stateSet in stateSets) | ||
{ | ||
var state = stateSet.GetOrCreateProjectState(project.Id); | ||
|
||
if (result.TryGetResult(stateSet.Analyzer, out var analyzerResult)) | ||
{ | ||
diagnostics.AddRange(analyzerResult.GetAllDiagnostics()); | ||
await state.SaveToInMemoryStorageAsync(project, analyzerResult).ConfigureAwait(false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this was removed because it happens within the call to GetProjectAnalysisDataAsync above now. |
||
} | ||
} | ||
|
||
return diagnostics.ToImmutableAndClear(); | ||
|
@@ -76,7 +68,8 @@ private async Task TextDocumentOpenAsync(TextDocument document, CancellationToke | |
/// <summary> | ||
/// Return list of <see cref="StateSet"/> to be used for full solution analysis. | ||
/// </summary> | ||
private ImmutableArray<StateSet> GetStateSetsForFullSolutionAnalysis(ImmutableArray<StateSet> stateSets, Project project) | ||
private ImmutableArray<StateSet> GetStateSetsForFullSolutionAnalysis( | ||
ImmutableArray<StateSet> stateSets, Project project, IdeAnalyzerOptions ideOptions) | ||
{ | ||
// If full analysis is off, remove state that is created from build. | ||
// this will make sure diagnostics from build (converted from build to live) will never be cleared | ||
|
@@ -104,10 +97,11 @@ private ImmutableArray<StateSet> GetStateSetsForFullSolutionAnalysis(ImmutableAr | |
|
||
// Include only analyzers we want to run for full solution analysis. | ||
// Analyzers not included here will never be saved because result is unknown. | ||
return stateSets.WhereAsArray(s => IsCandidateForFullSolutionAnalysis(s.Analyzer, project)); | ||
return stateSets.WhereAsArray(s => IsCandidateForFullSolutionAnalysis(s.Analyzer, project, ideOptions)); | ||
} | ||
|
||
private bool IsCandidateForFullSolutionAnalysis(DiagnosticAnalyzer analyzer, Project project) | ||
private bool IsCandidateForFullSolutionAnalysis( | ||
DiagnosticAnalyzer analyzer, Project project, IdeAnalyzerOptions ideOptions) | ||
{ | ||
// PERF: Don't query descriptors for compiler analyzer or workspace load analyzer, always execute them. | ||
if (analyzer == FileContentLoadAnalyzer.Instance || | ||
|
@@ -117,17 +111,18 @@ private bool IsCandidateForFullSolutionAnalysis(DiagnosticAnalyzer analyzer, Pro | |
return true; | ||
} | ||
|
||
// Open-file-only analyzers are never candidates for full solution analysis, as they have explicitly marked | ||
// themselves as only being reportable for open files. | ||
if (analyzer.IsOpenFileOnly(ideOptions.CleanupOptions?.SimplifierOptions)) | ||
return false; | ||
|
||
if (analyzer.IsBuiltInAnalyzer()) | ||
{ | ||
// always return true for builtin analyzer. we can't use | ||
// descriptor check since many builtin analyzer always return | ||
// hidden descriptor regardless what descriptor it actually | ||
// return on runtime. they do this so that they can control | ||
// severity through option page rather than rule set editor. | ||
// this is special behavior only ide analyzer can do. we hope | ||
// once we support editorconfig fully, third party can use this | ||
// ability as well and we can remove this kind special treatment on builtin | ||
// analyzer. | ||
// always return true for builtin analyzer. we can't use descriptor check since many builtin analyzer | ||
// always return hidden descriptor regardless what descriptor it actually return on runtime. they do | ||
// this so that they can control severity through option page rather than rule set editor. this is | ||
// special behavior only ide analyzer can do. we hope once we support editorconfig fully, third party | ||
// can use this ability as well and we can remove this kind special treatment on builtin analyzer. | ||
return true; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mavasani i was hoping this would help. By making it so that we always save for any caller of
GetProjectAnalysisDataAsync
(currently there are two of htem).However, it looks like this doesn't help because the code that attempts to load from teh cache seems to bail out for any number of reasons i can't make heads or tails of.