Skip to content

Commit d6374f6

Browse files
authored
Merge pull request #15957 from tamasvajk/feature/limit-message-extraction
C#: Limit extracted compilation and extraction messages
2 parents 45ce988 + 205d6a3 commit d6374f6

File tree

13 files changed

+130
-49
lines changed

13 files changed

+130
-49
lines changed

csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Compilation.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.IO;
34
using System.Linq;
45
using Microsoft.CodeAnalysis;
@@ -8,6 +9,8 @@ namespace Semmle.Extraction.CSharp.Entities
89
{
910
internal class Compilation : CachedEntity<object>
1011
{
12+
internal readonly ConcurrentDictionary<string, int> messageCounts = new();
13+
1114
private static (string Cwd, string[] Args) settings;
1215
private static int hashCode;
1316

@@ -78,10 +81,11 @@ public override void Populate(TextWriter trapFile)
7881
.ForEach((file, index) => trapFile.compilation_referencing_files(this, index, file));
7982

8083
// Diagnostics
81-
Context.Compilation
82-
.GetDiagnostics()
83-
.Select(d => new Diagnostic(Context, d))
84-
.ForEach((diag, index) => trapFile.diagnostic_for(diag, this, 0, index));
84+
var diags = Context.Compilation.GetDiagnostics();
85+
diags.ForEach((diag, index) => new CompilerDiagnostic(Context, diag, this, index));
86+
87+
var diagCounts = diags.GroupBy(diag => diag.Id).ToDictionary(group => group.Key, group => group.Count());
88+
diagCounts.ForEach(pair => trapFile.compilation_info(this, $"Compiler diagnostic count for {pair.Key}", pair.Value.ToString()));
8589
}
8690

8791
public void PopulatePerformance(PerformanceMetrics p)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System.IO;
2+
using Semmle.Util;
3+
4+
namespace Semmle.Extraction.CSharp.Entities
5+
{
6+
internal class CompilerDiagnostic : FreshEntity
7+
{
8+
private static readonly int limit = EnvironmentVariables.TryGetExtractorNumberOption<int>("COMPILER_DIAGNOSTIC_LIMIT") ?? 1000;
9+
10+
private readonly Microsoft.CodeAnalysis.Diagnostic diagnostic;
11+
private readonly Compilation compilation;
12+
private readonly int index;
13+
14+
public CompilerDiagnostic(Context cx, Microsoft.CodeAnalysis.Diagnostic diag, Compilation compilation, int index) : base(cx)
15+
{
16+
diagnostic = diag;
17+
this.compilation = compilation;
18+
this.index = index;
19+
TryPopulate();
20+
}
21+
22+
protected override void Populate(TextWriter trapFile)
23+
{
24+
// The below doesn't limit the extractor messages to the exact limit, but it's good enough.
25+
var key = diagnostic.Id;
26+
var messageCount = compilation.messageCounts.AddOrUpdate(key, 1, (_, c) => c + 1);
27+
if (messageCount > limit)
28+
{
29+
if (messageCount == limit + 1)
30+
{
31+
Context.Extractor.Logger.LogWarning($"Stopped logging {key} compiler diagnostics for the current compilation after reaching {limit}");
32+
}
33+
34+
return;
35+
}
36+
37+
trapFile.diagnostics(this, (int)diagnostic.Severity, key, diagnostic.Descriptor.Title.ToString(),
38+
diagnostic.GetMessage(), Context.CreateLocation(diagnostic.Location));
39+
40+
trapFile.diagnostic_for(this, compilation, 0, index);
41+
}
42+
}
43+
}

csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Diagnostic.cs

Lines changed: 0 additions & 21 deletions
This file was deleted.

csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,10 @@ internal static void destructor_location(this TextWriter trapFile, Destructor de
122122
internal static void destructors(this TextWriter trapFile, Destructor destructor, string name, Type containingType, Destructor original) =>
123123
trapFile.WriteTuple("destructors", destructor, name, containingType, original);
124124

125-
internal static void diagnostic_for(this TextWriter trapFile, Diagnostic diag, Compilation comp, int fileNo, int index) =>
125+
internal static void diagnostic_for(this TextWriter trapFile, CompilerDiagnostic diag, Compilation comp, int fileNo, int index) =>
126126
trapFile.WriteTuple("diagnostic_for", diag, comp, fileNo, index);
127127

128-
internal static void diagnostics(this TextWriter trapFile, Diagnostic diag, int severity, string errorTag, string errorMessage, string fullErrorMessage, Location location) =>
128+
internal static void diagnostics(this TextWriter trapFile, CompilerDiagnostic diag, int severity, string errorTag, string errorMessage, string fullErrorMessage, Location location) =>
129129
trapFile.WriteTuple("diagnostics", diag, severity, errorTag, errorMessage, fullErrorMessage, location);
130130

131131
internal static void dynamic_member_name(this TextWriter trapFile, Expression e, string name) =>

csharp/extractor/Semmle.Extraction/Entities/ExtractionError.cs

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.IO;
2+
using System.Threading;
3+
using Semmle.Util;
4+
5+
namespace Semmle.Extraction.Entities
6+
{
7+
internal class ExtractionMessage : FreshEntity
8+
{
9+
private static readonly int limit = EnvironmentVariables.TryGetExtractorNumberOption<int>("MESSAGE_LIMIT") ?? 10000;
10+
private static int messageCount = 0;
11+
12+
private readonly Message msg;
13+
14+
public ExtractionMessage(Context cx, Message msg) : base(cx)
15+
{
16+
this.msg = msg;
17+
TryPopulate();
18+
}
19+
20+
protected override void Populate(TextWriter trapFile)
21+
{
22+
// The below doesn't limit the extractor messages to the exact limit, but it's good enough.
23+
Interlocked.Increment(ref messageCount);
24+
if (messageCount > limit)
25+
{
26+
if (messageCount == limit + 1)
27+
{
28+
Context.Extractor.Logger.LogWarning($"Stopped logging extractor messages after reaching {limit}");
29+
}
30+
return;
31+
}
32+
33+
trapFile.extractor_messages(this, msg.Severity, "C# extractor", msg.Text, msg.EntityText ?? string.Empty,
34+
msg.Location ?? Context.CreateLocation(), msg.StackTrace ?? string.Empty);
35+
}
36+
}
37+
}

csharp/extractor/Semmle.Util/EnvironmentVariables.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Globalization;
3+
using System.Numerics;
24

35
namespace Semmle.Util
46
{
@@ -7,6 +9,16 @@ public class EnvironmentVariables
79
public static string? GetExtractorOption(string name) =>
810
Environment.GetEnvironmentVariable($"CODEQL_EXTRACTOR_CSHARP_OPTION_{name.ToUpper()}");
911

12+
public static T? TryGetExtractorNumberOption<T>(string name) where T : struct, INumberBase<T>
13+
{
14+
var value = GetExtractorOption(name);
15+
if (T.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out var result))
16+
{
17+
return result;
18+
}
19+
return null;
20+
}
21+
1022
public static int GetDefaultNumberOfThreads()
1123
{
1224
if (!int.TryParse(Environment.GetEnvironmentVariable("CODEQL_THREADS"), out var threads) || threads == -1)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extractorMessages
2+
| 5 |
3+
compilerDiagnostics
4+
| 4 |
5+
compilationInfo
6+
| Compiler diagnostic count for CS0103 | 3.0 |
7+
| Compiler diagnostic count for CS8019 | 7.0 |
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import csharp
2+
import semmle.code.csharp.commons.Diagnostics
3+
4+
query predicate extractorMessages(int c) { c = count(ExtractorMessage msg) }
5+
6+
query predicate compilerDiagnostics(int c) { c = count(Diagnostic diag) }
7+
8+
query predicate compilationInfo(string key, float value) {
9+
exists(Compilation c, string infoValue |
10+
infoValue = c.getInfo(key) and key.matches("Compiler diagnostic count for%")
11+
|
12+
value = infoValue.toFloat()
13+
)
14+
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
var dummy = "dummy";
1+
var dummy = "dummy";
2+
dummy = M() + M() + M();

0 commit comments

Comments
 (0)