Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 38a3a5e

Browse files
committed
Add initial code for diagnostic messages
1 parent e029b1f commit 38a3a5e

2 files changed

Lines changed: 190 additions & 0 deletions

File tree

csharp/extractor/Semmle.Util/Semmle.Util.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
<ItemGroup>
1717
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
18+
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
1819
</ItemGroup>
1920

2021
</Project>
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Globalization;
5+
using System.IO;
6+
using Newtonsoft.Json;
7+
using Newtonsoft.Json.Converters;
8+
using Newtonsoft.Json.Serialization;
9+
10+
namespace Semmle.Util
11+
{
12+
/// <summary>
13+
/// Represents diagnostic messages for the tool status page.
14+
/// </summary>
15+
public class DiagnosticMessage
16+
{
17+
/// <summary>
18+
/// Represents sources of diagnostic messages.
19+
/// </summary>
20+
public class TspSource
21+
{
22+
/// <summary>
23+
/// An identifier under which it makes sense to group this diagnostic message.
24+
/// This is used to build the SARIF reporting descriptor object.
25+
/// </summary>
26+
public string Id { get; }
27+
/// <summary>
28+
/// Display name for the ID. This is used to build the SARIF reporting descriptor object.
29+
/// </summary>
30+
public string Name { get; }
31+
/// <summary>
32+
/// Name of the CodeQL extractor. This is used to identify which tool component the reporting descriptor object should be nested under in SARIF.
33+
/// </summary>
34+
public string? ExtractorName { get; set; }
35+
36+
public TspSource(string id, string name)
37+
{
38+
Id = id;
39+
Name = name;
40+
}
41+
}
42+
43+
/// <summary>
44+
/// Enumerates severity levels for diagnostics.
45+
/// </summary>
46+
[JsonConverter(typeof(StringEnumConverter), typeof(CamelCaseNamingStrategy))]
47+
public enum TspSeverity
48+
{
49+
Note,
50+
Warning,
51+
Error
52+
}
53+
54+
public class TspVisibility
55+
{
56+
/// <summary>
57+
/// True if the message should be displayed on the status page (defaults to false).
58+
/// </summary>
59+
public bool? StatusPage { get; set; }
60+
/// <summary>
61+
/// True if the message should be counted in the diagnostics summary table printed by
62+
/// <c>codeql database analyze</c> (defaults to false).
63+
/// </summary>
64+
public bool? CLISummaryTable { get; set; }
65+
/// <summary>
66+
/// True if the message should be sent to telemetry (defaults to false).
67+
/// </summary>
68+
public bool? Telemetry { get; set; }
69+
}
70+
71+
public class TspLocation
72+
{
73+
/// <summary>
74+
/// Path to the affected file if appropriate, relative to the source root.
75+
/// </summary>
76+
public string? File { get; set; }
77+
public int? StartLine { get; set; }
78+
public int? StartColumn { get; set; }
79+
public int? EndLine { get; set; }
80+
public int? EndColumn { get; set; }
81+
}
82+
83+
/// <summary>
84+
/// ISO 8601 timestamp.
85+
/// </summary>
86+
public string Timestamp { get; set; }
87+
/// <summary>
88+
/// The source of the diagnostic message.
89+
/// </summary>
90+
public TspSource Source { get; set; }
91+
/// <summary>
92+
/// GitHub flavored Markdown formatted message. Should include inline links to any help pages.
93+
/// </summary>
94+
public string? MarkdownMessage { get; set; }
95+
/// <summary>
96+
/// Plain text message. Used by components where the string processing needed to support
97+
/// Markdown is cumbersome.
98+
/// </summary>
99+
public string? PlaintextMessage { get; set; }
100+
/// <summary>
101+
/// List of help links intended to supplement <see cref="PlaintextMessage" />.
102+
/// </summary>
103+
public List<string> HelpLinks { get; }
104+
/// <summary>
105+
/// SARIF severity.
106+
/// </summary>
107+
public TspSeverity? Severity { get; set; }
108+
/// <summary>
109+
/// If true, then this message won't be presented to users.
110+
/// </summary>
111+
public bool Internal { get; set; }
112+
/// <summary>
113+
///
114+
/// </summary>
115+
public TspVisibility Visibility { get; }
116+
public TspLocation Location { get; }
117+
/// <summary>
118+
/// Structured metadata about the diagnostic message.
119+
/// </summary>
120+
public Dictionary<string, object> Attributes { get; }
121+
122+
public DiagnosticMessage(TspSource source)
123+
{
124+
Timestamp = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture);
125+
Source = source;
126+
HelpLinks = new List<string>();
127+
Visibility = new TspVisibility();
128+
Location = new TspLocation();
129+
Attributes = new Dictionary<string, object>();
130+
}
131+
}
132+
133+
/// <summary>
134+
/// A wrapper around an underlying <see cref="StreamWriter" /> which allows
135+
/// <see cref="DiagnosticMessage" /> objects to be serialized to it.
136+
/// </summary>
137+
public sealed class DiagnosticsStream : IDisposable
138+
{
139+
private readonly JsonSerializer serializer;
140+
private readonly StreamWriter writer;
141+
142+
/// <summary>
143+
/// Initialises a new <see cref="DiagnosticsStream" /> for a file at <paramref name="path" />.
144+
/// </summary>
145+
/// <param name="path">The path to the file that should be created.</param>
146+
/// <returns>
147+
/// A <see cref="DiagnosticsStream" /> object which allows diagnostics to be
148+
/// written to a file at <paramname name="path" />.
149+
/// </returns>
150+
public static DiagnosticsStream ForFile(string path)
151+
{
152+
var stream = File.CreateText(path);
153+
return new DiagnosticsStream(stream);
154+
}
155+
156+
public DiagnosticsStream(StreamWriter streamWriter)
157+
{
158+
var contractResolver = new DefaultContractResolver
159+
{
160+
NamingStrategy = new CamelCaseNamingStrategy()
161+
};
162+
163+
serializer = new JsonSerializer
164+
{
165+
ContractResolver = contractResolver
166+
};
167+
168+
writer = streamWriter;
169+
}
170+
171+
/// <summary>
172+
/// Adds <paramref name="message" /> as a new diagnostics entry.
173+
/// </summary>
174+
/// <param name="message">The diagnostics entry to add.</param>
175+
public void AddEntry(DiagnosticMessage message)
176+
{
177+
serializer.Serialize(writer, message);
178+
writer.Flush();
179+
}
180+
181+
/// <summary>
182+
/// Releases all resources used by the <see cref="DiagnosticsStream" /> object.
183+
/// </summary>
184+
public void Dispose()
185+
{
186+
writer.Dispose();
187+
}
188+
}
189+
}

0 commit comments

Comments
 (0)