提交 4af2693b 编写于 作者: T Tomáš Matoušek

Add exception filters to incremental analyzer (#11783)

上级 87a01262
...@@ -147,44 +147,58 @@ public IEnumerable<DiagnosticData> ConvertToLocalDiagnostics(Document targetDocu ...@@ -147,44 +147,58 @@ public IEnumerable<DiagnosticData> ConvertToLocalDiagnostics(Document targetDocu
public async Task<ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult>> ComputeDiagnosticsAsync( public async Task<ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult>> ComputeDiagnosticsAsync(
CompilationWithAnalyzers analyzerDriverOpt, Project project, IEnumerable<StateSet> stateSets, CancellationToken cancellationToken) CompilationWithAnalyzers analyzerDriverOpt, Project project, IEnumerable<StateSet> stateSets, CancellationToken cancellationToken)
{ {
var result = ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult>.Empty; try
// analyzerDriver can be null if given project doesn't support compilation.
if (analyzerDriverOpt != null)
{ {
// calculate regular diagnostic analyzers diagnostics var result = ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult>.Empty;
var compilerResult = await analyzerDriverOpt.AnalyzeAsync(project, cancellationToken).ConfigureAwait(false);
result = compilerResult.AnalysisResult;
// record telemetry data // analyzerDriver can be null if given project doesn't support compilation.
UpdateAnalyzerTelemetryData(compilerResult, project, cancellationToken); if (analyzerDriverOpt != null)
} {
// calculate regular diagnostic analyzers diagnostics
var compilerResult = await analyzerDriverOpt.AnalyzeAsync(project, cancellationToken).ConfigureAwait(false);
result = compilerResult.AnalysisResult;
// check whether there is IDE specific project diagnostic analyzer // record telemetry data
return await MergeProjectDiagnosticAnalyzerDiagnosticsAsync(project, stateSets, analyzerDriverOpt?.Compilation, result, cancellationToken).ConfigureAwait(false); UpdateAnalyzerTelemetryData(compilerResult, project, cancellationToken);
}
// check whether there is IDE specific project diagnostic analyzer
return await MergeProjectDiagnosticAnalyzerDiagnosticsAsync(project, stateSets, analyzerDriverOpt?.Compilation, result, cancellationToken).ConfigureAwait(false);
}
catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
{
throw ExceptionUtilities.Unreachable;
}
} }
private async Task<ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult>> ComputeDiagnosticsAsync( private async Task<ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult>> ComputeDiagnosticsAsync(
CompilationWithAnalyzers analyzerDriverOpt, Project project, IEnumerable<StateSet> stateSets, CompilationWithAnalyzers analyzerDriverOpt, Project project, IEnumerable<StateSet> stateSets,
ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult> existing, CancellationToken cancellationToken) ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult> existing, CancellationToken cancellationToken)
{ {
// PERF: check whether we can reduce number of analyzers we need to run. try
// this can happen since caller could have created the driver with different set of analyzers that are different
// than what we used to create the cache.
var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);
ImmutableArray<DiagnosticAnalyzer> analyzersToRun;
if (TryReduceAnalyzersToRun(analyzerDriverOpt, version, existing, out analyzersToRun))
{ {
// it looks like we can reduce the set. create new CompilationWithAnalyzer. // PERF: check whether we can reduce number of analyzers we need to run.
var analyzerDriverWithReducedSet = await _owner._compilationManager.CreateAnalyzerDriverAsync( // this can happen since caller could have created the driver with different set of analyzers that are different
project, analyzersToRun, analyzerDriverOpt.AnalysisOptions.ReportSuppressedDiagnostics, cancellationToken).ConfigureAwait(false); // than what we used to create the cache.
var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);
ImmutableArray<DiagnosticAnalyzer> analyzersToRun;
if (TryReduceAnalyzersToRun(analyzerDriverOpt, version, existing, out analyzersToRun))
{
// it looks like we can reduce the set. create new CompilationWithAnalyzer.
var analyzerDriverWithReducedSet = await _owner._compilationManager.CreateAnalyzerDriverAsync(
project, analyzersToRun, analyzerDriverOpt.AnalysisOptions.ReportSuppressedDiagnostics, cancellationToken).ConfigureAwait(false);
var result = await ComputeDiagnosticsAsync(analyzerDriverWithReducedSet, project, stateSets, cancellationToken).ConfigureAwait(false); var result = await ComputeDiagnosticsAsync(analyzerDriverWithReducedSet, project, stateSets, cancellationToken).ConfigureAwait(false);
return MergeExistingDiagnostics(version, existing, result); return MergeExistingDiagnostics(version, existing, result);
} }
// we couldn't reduce the set. // we couldn't reduce the set.
return await ComputeDiagnosticsAsync(analyzerDriverOpt, project, stateSets, cancellationToken).ConfigureAwait(false); return await ComputeDiagnosticsAsync(analyzerDriverOpt, project, stateSets, cancellationToken).ConfigureAwait(false);
}
catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
{
throw ExceptionUtilities.Unreachable;
}
} }
private ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult> MergeExistingDiagnostics( private ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult> MergeExistingDiagnostics(
...@@ -254,49 +268,56 @@ public IEnumerable<DiagnosticData> ConvertToLocalDiagnostics(Document targetDocu ...@@ -254,49 +268,56 @@ public IEnumerable<DiagnosticData> ConvertToLocalDiagnostics(Document targetDocu
private async Task<ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult>> MergeProjectDiagnosticAnalyzerDiagnosticsAsync( private async Task<ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult>> MergeProjectDiagnosticAnalyzerDiagnosticsAsync(
Project project, IEnumerable<StateSet> stateSets, Compilation compilationOpt, ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult> result, CancellationToken cancellationToken) Project project, IEnumerable<StateSet> stateSets, Compilation compilationOpt, ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult> result, CancellationToken cancellationToken)
{ {
// check whether there is IDE specific project diagnostic analyzer try
var ideAnalyzers = stateSets.Select(s => s.Analyzer).Where(a => a is ProjectDiagnosticAnalyzer || a is DocumentDiagnosticAnalyzer).ToImmutableArrayOrEmpty();
if (ideAnalyzers.Length <= 0)
{ {
return result; // check whether there is IDE specific project diagnostic analyzer
} var ideAnalyzers = stateSets.Select(s => s.Analyzer).Where(a => a is ProjectDiagnosticAnalyzer || a is DocumentDiagnosticAnalyzer).ToImmutableArrayOrEmpty();
if (ideAnalyzers.Length <= 0)
{
return result;
}
// create result map // create result map
var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false); var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);
var builder = new CompilerDiagnosticExecutor.Builder(project, version); var builder = new CompilerDiagnosticExecutor.Builder(project, version);
foreach (var analyzer in ideAnalyzers) foreach (var analyzer in ideAnalyzers)
{
var documentAnalyzer = analyzer as DocumentDiagnosticAnalyzer;
if (documentAnalyzer != null)
{ {
foreach (var document in project.Documents) var documentAnalyzer = analyzer as DocumentDiagnosticAnalyzer;
if (documentAnalyzer != null)
{ {
if (document.SupportsSyntaxTree) foreach (var document in project.Documents)
{ {
var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (document.SupportsSyntaxTree)
builder.AddSyntaxDiagnostics(tree, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Syntax, compilationOpt, cancellationToken).ConfigureAwait(false)); {
builder.AddSemanticDiagnostics(tree, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Semantic, compilationOpt, cancellationToken).ConfigureAwait(false)); var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
} builder.AddSyntaxDiagnostics(tree, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Syntax, compilationOpt, cancellationToken).ConfigureAwait(false));
else builder.AddSemanticDiagnostics(tree, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Semantic, compilationOpt, cancellationToken).ConfigureAwait(false));
{ }
builder.AddExternalSyntaxDiagnostics(document.Id, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Syntax, compilationOpt, cancellationToken).ConfigureAwait(false)); else
builder.AddExternalSemanticDiagnostics(document.Id, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Semantic, compilationOpt, cancellationToken).ConfigureAwait(false)); {
builder.AddExternalSyntaxDiagnostics(document.Id, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Syntax, compilationOpt, cancellationToken).ConfigureAwait(false));
builder.AddExternalSemanticDiagnostics(document.Id, await ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(document, documentAnalyzer, AnalysisKind.Semantic, compilationOpt, cancellationToken).ConfigureAwait(false));
}
} }
} }
}
var projectAnalyzer = analyzer as ProjectDiagnosticAnalyzer; var projectAnalyzer = analyzer as ProjectDiagnosticAnalyzer;
if (projectAnalyzer != null) if (projectAnalyzer != null)
{ {
builder.AddCompilationDiagnostics(await ComputeProjectDiagnosticAnalyzerDiagnosticsAsync(project, projectAnalyzer, compilationOpt, cancellationToken).ConfigureAwait(false)); builder.AddCompilationDiagnostics(await ComputeProjectDiagnosticAnalyzerDiagnosticsAsync(project, projectAnalyzer, compilationOpt, cancellationToken).ConfigureAwait(false));
}
// merge the result to existing one.
result = result.Add(analyzer, builder.ToResult());
} }
// merge the result to existing one. return result;
result = result.Add(analyzer, builder.ToResult()); }
catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
{
throw ExceptionUtilities.Unreachable;
} }
return result;
} }
private async Task<IEnumerable<Diagnostic>> ComputeProjectDiagnosticAnalyzerDiagnosticsAsync( private async Task<IEnumerable<Diagnostic>> ComputeProjectDiagnosticAnalyzerDiagnosticsAsync(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册