Merge pull request #15957 from tamasvajk/feature/limit-message-extraction

C#: Limit extracted compilation and extraction messages
This commit is contained in:
Tamás Vajk
2024-03-25 10:30:10 +01:00
committed by GitHub
13 changed files with 130 additions and 49 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
@@ -8,6 +9,8 @@ namespace Semmle.Extraction.CSharp.Entities
{
internal class Compilation : CachedEntity<object>
{
internal readonly ConcurrentDictionary<string, int> messageCounts = new();
private static (string Cwd, string[] Args) settings;
private static int hashCode;
@@ -78,10 +81,11 @@ namespace Semmle.Extraction.CSharp.Entities
.ForEach((file, index) => trapFile.compilation_referencing_files(this, index, file));
// Diagnostics
Context.Compilation
.GetDiagnostics()
.Select(d => new Diagnostic(Context, d))
.ForEach((diag, index) => trapFile.diagnostic_for(diag, this, 0, index));
var diags = Context.Compilation.GetDiagnostics();
diags.ForEach((diag, index) => new CompilerDiagnostic(Context, diag, this, index));
var diagCounts = diags.GroupBy(diag => diag.Id).ToDictionary(group => group.Key, group => group.Count());
diagCounts.ForEach(pair => trapFile.compilation_info(this, $"Compiler diagnostic count for {pair.Key}", pair.Value.ToString()));
}
public void PopulatePerformance(PerformanceMetrics p)

View File

@@ -0,0 +1,43 @@
using System.IO;
using Semmle.Util;
namespace Semmle.Extraction.CSharp.Entities
{
internal class CompilerDiagnostic : FreshEntity
{
private static readonly int limit = EnvironmentVariables.TryGetExtractorNumberOption<int>("COMPILER_DIAGNOSTIC_LIMIT") ?? 1000;
private readonly Microsoft.CodeAnalysis.Diagnostic diagnostic;
private readonly Compilation compilation;
private readonly int index;
public CompilerDiagnostic(Context cx, Microsoft.CodeAnalysis.Diagnostic diag, Compilation compilation, int index) : base(cx)
{
diagnostic = diag;
this.compilation = compilation;
this.index = index;
TryPopulate();
}
protected override void Populate(TextWriter trapFile)
{
// The below doesn't limit the extractor messages to the exact limit, but it's good enough.
var key = diagnostic.Id;
var messageCount = compilation.messageCounts.AddOrUpdate(key, 1, (_, c) => c + 1);
if (messageCount > limit)
{
if (messageCount == limit + 1)
{
Context.Extractor.Logger.LogWarning($"Stopped logging {key} compiler diagnostics for the current compilation after reaching {limit}");
}
return;
}
trapFile.diagnostics(this, (int)diagnostic.Severity, key, diagnostic.Descriptor.Title.ToString(),
diagnostic.GetMessage(), Context.CreateLocation(diagnostic.Location));
trapFile.diagnostic_for(this, compilation, 0, index);
}
}
}

View File

@@ -1,21 +0,0 @@
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
internal class Diagnostic : FreshEntity
{
private readonly Microsoft.CodeAnalysis.Diagnostic diagnostic;
public Diagnostic(Context cx, Microsoft.CodeAnalysis.Diagnostic diag) : base(cx)
{
diagnostic = diag;
TryPopulate();
}
protected override void Populate(TextWriter trapFile)
{
trapFile.diagnostics(this, (int)diagnostic.Severity, diagnostic.Id, diagnostic.Descriptor.Title.ToString(),
diagnostic.GetMessage(), Context.CreateLocation(diagnostic.Location));
}
}
}

View File

@@ -122,10 +122,10 @@ namespace Semmle.Extraction.CSharp
internal static void destructors(this TextWriter trapFile, Destructor destructor, string name, Type containingType, Destructor original) =>
trapFile.WriteTuple("destructors", destructor, name, containingType, original);
internal static void diagnostic_for(this TextWriter trapFile, Diagnostic diag, Compilation comp, int fileNo, int index) =>
internal static void diagnostic_for(this TextWriter trapFile, CompilerDiagnostic diag, Compilation comp, int fileNo, int index) =>
trapFile.WriteTuple("diagnostic_for", diag, comp, fileNo, index);
internal static void diagnostics(this TextWriter trapFile, Diagnostic diag, int severity, string errorTag, string errorMessage, string fullErrorMessage, Location location) =>
internal static void diagnostics(this TextWriter trapFile, CompilerDiagnostic diag, int severity, string errorTag, string errorMessage, string fullErrorMessage, Location location) =>
trapFile.WriteTuple("diagnostics", diag, severity, errorTag, errorMessage, fullErrorMessage, location);
internal static void dynamic_member_name(this TextWriter trapFile, Expression e, string name) =>