Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ public async Task TestHostAnalyzerErrorNotLeaking()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

view with whitespace off.

var solution = workspace.CurrentSolution;

var analyzerReference = new AnalyzerImageReference([new LeakDocumentAnalyzer(), new LeakProjectAnalyzer()]);
var analyzerReference = new AnalyzerImageReference([new LeakDocumentAnalyzer()]);

var globalOptions = GetGlobalOptions(workspace);
globalOptions.SetGlobalOption(SolutionCrawlerOptionsStorage.BackgroundAnalysisScopeOption, LanguageNames.CSharp, BackgroundAnalysisScope.FullSolution);
Expand Down Expand Up @@ -913,13 +913,6 @@ public override Task<ImmutableArray<Diagnostic>> AnalyzeSemanticsAsync(Document
=> SpecializedTasks.Default<ImmutableArray<Diagnostic>>();
}

private sealed class LeakProjectAnalyzer : ProjectDiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor s_rule = new DiagnosticDescriptor("project", "test", "test", "test", DiagnosticSeverity.Error, isEnabledByDefault: true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [s_rule];
public override Task<ImmutableArray<Diagnostic>> AnalyzeProjectAsync(Project project, CancellationToken cancellationToken) => SpecializedTasks.Default<ImmutableArray<Diagnostic>>();
}

[DiagnosticAnalyzer(LanguageNames.CSharp)]
private sealed class NamedTypeAnalyzer : DiagnosticAnalyzer
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics;
internal static class DiagnosticAnalyzerExtensions
{
public static bool IsWorkspaceDiagnosticAnalyzer(this DiagnosticAnalyzer analyzer)
=> analyzer is DocumentDiagnosticAnalyzer
|| analyzer is ProjectDiagnosticAnalyzer;
=> analyzer is DocumentDiagnosticAnalyzer;

public static bool IsBuiltInAnalyzer(this DiagnosticAnalyzer analyzer)
=> analyzer is IBuiltInAnalyzer || analyzer.IsWorkspaceDiagnosticAnalyzer() || analyzer.IsCompilerAnalyzer();
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -119,39 +119,6 @@ public static async Task<ImmutableArray<Diagnostic>> ComputeDocumentDiagnosticAn
return diagnostics;
}

public static async Task<ImmutableArray<Diagnostic>> ComputeProjectDiagnosticAnalyzerDiagnosticsAsync(
ProjectDiagnosticAnalyzer analyzer,
Project project,
Compilation? compilation,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();

ImmutableArray<Diagnostic> diagnostics;
try
{
diagnostics = (await analyzer.AnalyzeProjectAsync(project, cancellationToken).ConfigureAwait(false)).NullToEmpty();
#if DEBUG
// since all ProjectDiagnosticAnalyzers are from internal users, we only do debug check. also this can be expensive at runtime
// since it requires await. if we find any offender through NFW, we should be able to fix those since all those should
// from intern teams.
await VerifyDiagnosticLocationsAsync(diagnostics, project, cancellationToken).ConfigureAwait(false);
#endif
}
catch (Exception e) when (!IsCanceled(e, cancellationToken))
{
diagnostics = [CreateAnalyzerExceptionDiagnostic(analyzer, e)];
}

// Apply filtering from compilation options (source suppressions, ruleset, etc.)
if (compilation != null)
{
diagnostics = CompilationWithAnalyzers.GetEffectiveDiagnostics(diagnostics, compilation).ToImmutableArrayOrEmpty();
}

return diagnostics;
}

private static bool IsCanceled(Exception ex, CancellationToken cancellationToken)
=> (ex as OperationCanceledException)?.CancellationToken == cancellationToken;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ private sealed partial class DiagnosticIncrementalAnalyzer
private async Task<ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>> ComputeDiagnosticAnalysisResultsAsync(
CompilationWithAnalyzersPair? compilationWithAnalyzers,
Project project,
ImmutableArray<DiagnosticAnalyzer> analyzers,
ImmutableArray<DocumentDiagnosticAnalyzer> analyzers,
CancellationToken cancellationToken)
{
using (Logger.LogBlock(FunctionId.Diagnostics_ProjectDiagnostic, GetProjectLogMessage, project, analyzers, cancellationToken))
{
try
{
var result = await ComputeDiagnosticsForIDEAnalyzersAsync(analyzers).ConfigureAwait(false);
var result = await ComputeDiagnosticsForAnalyzersAsync(analyzers).ConfigureAwait(false);

// If project is not loaded successfully, get rid of any semantic errors from compiler analyzer.
// Note: In the past when project was not loaded successfully we did not run any analyzers on the project.
Expand Down Expand Up @@ -86,7 +86,7 @@ async Task<ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>> Re
// Calculate all diagnostics for a given project using analyzers referenced by the project and specified IDE analyzers.
// </summary>
async Task<ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>> ComputeDiagnosticsForAnalyzersAsync(
ImmutableArray<DiagnosticAnalyzer> ideAnalyzers)
ImmutableArray<DocumentDiagnosticAnalyzer> ideAnalyzers)
{
try
{
Expand All @@ -107,7 +107,6 @@ async Task<ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>> Co
}

// check whether there is IDE specific project diagnostic analyzer
Debug.Assert(ideAnalyzers.All(a => a is ProjectDiagnosticAnalyzer or DocumentDiagnosticAnalyzer));
return await MergeProjectDiagnosticAnalyzerDiagnosticsAsync(ideAnalyzers, result).ConfigureAwait(false);
}
catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken))
Expand All @@ -116,67 +115,42 @@ async Task<ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>> Co
}
}

async Task<ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>> ComputeDiagnosticsForIDEAnalyzersAsync(
ImmutableArray<DiagnosticAnalyzer> analyzers)
{
try
{
var ideAnalyzers = analyzers.WhereAsArray(a => a is ProjectDiagnosticAnalyzer or DocumentDiagnosticAnalyzer);

return await ComputeDiagnosticsForAnalyzersAsync(ideAnalyzers).ConfigureAwait(false);
}
catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken))
{
throw ExceptionUtilities.Unreachable();
}
}

async Task<ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>> MergeProjectDiagnosticAnalyzerDiagnosticsAsync(
ImmutableArray<DiagnosticAnalyzer> ideAnalyzers,
ImmutableArray<DocumentDiagnosticAnalyzer> ideAnalyzers,
ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult> result)
{
try
{
var compilation = compilationWithAnalyzers?.HostCompilation;

foreach (var analyzer in ideAnalyzers)
foreach (var documentAnalyzer in ideAnalyzers)
{
var builder = new DiagnosticAnalysisResultBuilder(project);

switch (analyzer)
foreach (var textDocument in project.AdditionalDocuments.Concat(project.Documents))
{
case DocumentDiagnosticAnalyzer documentAnalyzer:
foreach (var textDocument in project.AdditionalDocuments.Concat(project.Documents))
{
var tree = textDocument is Document document
? await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false)
: null;
var syntaxDiagnostics = await DocumentAnalysisExecutor.ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(documentAnalyzer, textDocument, AnalysisKind.Syntax, compilation, tree, cancellationToken).ConfigureAwait(false);
var semanticDiagnostics = await DocumentAnalysisExecutor.ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(documentAnalyzer, textDocument, AnalysisKind.Semantic, compilation, tree, cancellationToken).ConfigureAwait(false);

if (tree != null)
{
builder.AddSyntaxDiagnostics(tree, syntaxDiagnostics);
builder.AddSemanticDiagnostics(tree, semanticDiagnostics);
}
else
{
builder.AddExternalSyntaxDiagnostics(textDocument.Id, syntaxDiagnostics);
builder.AddExternalSemanticDiagnostics(textDocument.Id, semanticDiagnostics);
}
}

break;

case ProjectDiagnosticAnalyzer projectAnalyzer:
builder.AddCompilationDiagnostics(await DocumentAnalysisExecutor.ComputeProjectDiagnosticAnalyzerDiagnosticsAsync(projectAnalyzer, project, compilation, cancellationToken).ConfigureAwait(false));
break;
var tree = textDocument is Document document
? await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false)
: null;
var syntaxDiagnostics = await DocumentAnalysisExecutor.ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(documentAnalyzer, textDocument, AnalysisKind.Syntax, compilation, tree, cancellationToken).ConfigureAwait(false);
var semanticDiagnostics = await DocumentAnalysisExecutor.ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync(documentAnalyzer, textDocument, AnalysisKind.Semantic, compilation, tree, cancellationToken).ConfigureAwait(false);

if (tree != null)
{
builder.AddSyntaxDiagnostics(tree, syntaxDiagnostics);
builder.AddSemanticDiagnostics(tree, semanticDiagnostics);
}
else
{
builder.AddExternalSyntaxDiagnostics(textDocument.Id, syntaxDiagnostics);
builder.AddExternalSemanticDiagnostics(textDocument.Id, semanticDiagnostics);
}
}

// merge the result to existing one.
// there can be existing one from compiler driver with empty set. overwrite it with
// ide one.
result = result.SetItem(analyzer, DiagnosticAnalysisResult.CreateFromBuilder(builder));
result = result.SetItem(documentAnalyzer, DiagnosticAnalysisResult.CreateFromBuilder(builder));
}

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ private static int GetPriority(DiagnosticAnalyzer state)
return state switch
{
DocumentDiagnosticAnalyzer analyzer => analyzer.Priority,
ProjectDiagnosticAnalyzer analyzer => Math.Max(0, analyzer.Priority),
_ => RegularDiagnosticAnalyzerPriority,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public DiagnosticIncrementalAnalyzer(
public Task<ImmutableArray<DiagnosticAnalyzer>> GetAnalyzersForTestingPurposesOnlyAsync(Project project, CancellationToken cancellationToken)
=> _stateManager.GetOrCreateAnalyzersAsync(project.Solution.SolutionState, project.State, cancellationToken);

private static string GetProjectLogMessage(Project project, ImmutableArray<DiagnosticAnalyzer> analyzers)
private static string GetProjectLogMessage(Project project, ImmutableArray<DocumentDiagnosticAnalyzer> analyzers)
=> $"project: ({project.Id}), ({string.Join(Environment.NewLine, analyzers.Select(a => a.ToString()))})";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ async Task<ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>> Ge
var compilation = await GetOrCreateCompilationWithAnalyzersAsync(
project, analyzers, hostAnalyzerInfo, AnalyzerService.CrashOnAnalyzerException, cancellationToken).ConfigureAwait(false);

var result = await ComputeDiagnosticAnalysisResultsAsync(compilation, project, analyzers, cancellationToken).ConfigureAwait(false);
var result = await ComputeDiagnosticAnalysisResultsAsync(
compilation, project, [.. analyzers.OfType<DocumentDiagnosticAnalyzer>()], cancellationToken).ConfigureAwait(false);
return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ public async Task<ImmutableArray<DiagnosticData>> ForceAnalyzeProjectAsync(Proje
var compilationWithAnalyzers = await GetOrCreateCompilationWithAnalyzersAsync(
project, fullSolutionAnalysisAnalyzers, hostAnalyzerInfo, AnalyzerService.CrashOnAnalyzerException, cancellationToken).ConfigureAwait(false);

var projectAnalysisData = await ComputeDiagnosticAnalysisResultsAsync(compilationWithAnalyzers, project, fullSolutionAnalysisAnalyzers, cancellationToken).ConfigureAwait(false);
var projectAnalysisData = await ComputeDiagnosticAnalysisResultsAsync(
compilationWithAnalyzers, project, [.. fullSolutionAnalysisAnalyzers.OfType<DocumentDiagnosticAnalyzer>()], cancellationToken).ConfigureAwait(false);
return (checksum, fullSolutionAnalysisAnalyzers, projectAnalysisData);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ public static DiagnosticAnalyzerCategory GetDiagnosticAnalyzerCategory(this Diag
{
FileContentLoadAnalyzer => DiagnosticAnalyzerCategory.SyntaxTreeWithoutSemanticsAnalysis,
DocumentDiagnosticAnalyzer => DiagnosticAnalyzerCategory.SyntaxTreeWithoutSemanticsAnalysis | DiagnosticAnalyzerCategory.SemanticDocumentAnalysis,
ProjectDiagnosticAnalyzer => DiagnosticAnalyzerCategory.None,
IBuiltInAnalyzer builtInAnalyzer => builtInAnalyzer.GetAnalyzerCategory(),

// Compiler analyzer supports syntax diagnostics, span-based semantic diagnostics and project level diagnostics.
Expand Down
Loading
Loading