Skip to content

Commit 3bf6b6f

Browse files
committed
Add helper for markdown lists of projects
1 parent b034b2f commit 3bf6b6f

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpAutobuilder.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Semmle.Autobuild.Shared;
44
using Semmle.Util;
55
using System.Linq;
6+
using System.Collections.Generic;
67

78
namespace Semmle.Autobuild.CSharp
89
{
@@ -141,7 +142,7 @@ protected override void AutobuildFailureDiagnostic()
141142
var message = MakeDiagnostic("dotnet-incompatible-projects", "Some projects are incompatible with .NET Core");
142143
message.MarkdownMessage =
143144
"CodeQL found some projects which cannot be built with .NET Core:\n" +
144-
string.Join('\n', autoBuildRule.DotNetRule.NotDotNetProjects.Select(p => $"- `{p.FullPath}`"));
145+
autoBuildRule.DotNetRule.NotDotNetProjects.ToMarkdownList(5);
145146
message.Severity = DiagnosticMessage.TspSeverity.Warning;
146147

147148
AddDiagnostic(message);
@@ -153,7 +154,7 @@ protected override void AutobuildFailureDiagnostic()
153154
var message = MakeDiagnostic("dotnet-build-failure", "Some projects or solutions failed to build using .NET Core");
154155
message.MarkdownMessage =
155156
"CodeQL was unable to build the following projects using .NET Core:\n" +
156-
string.Join('\n', autoBuildRule.DotNetRule.FailedProjectsOrSolutions.Select(p => $"- `{p.FullPath}`")) +
157+
autoBuildRule.DotNetRule.FailedProjectsOrSolutions.ToMarkdownList(10) +
157158
$"\nSet up a [manual build command]({buildCommandDocsUrl}).";
158159
message.Severity = DiagnosticMessage.TspSeverity.Error;
159160

@@ -166,7 +167,7 @@ protected override void AutobuildFailureDiagnostic()
166167
var message = MakeDiagnostic("msbuild-build-failure", "Some projects or solutions failed to build using MSBuild");
167168
message.MarkdownMessage =
168169
"CodeQL was unable to build the following projects using MSBuild:\n" +
169-
string.Join('\n', autoBuildRule.MsBuildRule.FailedProjectsOrSolutions.Select(p => $"- `{p.FullPath}`")) +
170+
autoBuildRule.MsBuildRule.FailedProjectsOrSolutions.ToMarkdownList(10) +
170171
$"\nSet up a [manual build command]({buildCommandDocsUrl}).";
171172
message.Severity = DiagnosticMessage.TspSeverity.Error;
172173

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace Semmle.Autobuild.Shared
7+
{
8+
public static class MarkdownUtil
9+
{
10+
/// <summary>
11+
/// Formats items as markdown inline code.
12+
/// </summary>
13+
/// <returns>A function which formats items as markdown inline code.</returns>
14+
public static readonly Func<string, string> CodeFormatter = item => $"`{item}`";
15+
16+
/// <summary>
17+
/// Renders <see cref="projects" /> as a markdown list of the project paths.
18+
/// </summary>
19+
/// <param name="projects">
20+
/// The list of projects whose paths should be rendered as a markdown list.
21+
/// </param>
22+
/// <param name="limit">The maximum number of items to include in the list.</param>
23+
/// <returns>Returns the markdown list as a string.</returns>
24+
public static string ToMarkdownList(this IEnumerable<IProjectOrSolution> projects, int? limit = null)
25+
{
26+
return projects.ToMarkdownList(p => $"`{p.FullPath}`", limit);
27+
}
28+
29+
/// <summary>
30+
/// Renders <see cref="items" /> as a markdown list.
31+
/// </summary>
32+
/// <typeparam name="T">The item type.</typeparam>
33+
/// <param name="items">The list that should be formatted as a markdown list.</param>
34+
/// <param name="formatter">A function which converts individual items into a string representation.</param>
35+
/// <param name="limit">The maximum number of items to include in the list.</param>
36+
/// <returns>Returns the markdown list as a string.</returns>
37+
public static string ToMarkdownList<T>(this IEnumerable<T> items, Func<T, string> formatter, int? limit = null)
38+
{
39+
var sb = new StringBuilder();
40+
41+
// if there is a limit, take at most that many items from the start of the list
42+
var list = limit is not null ? items.Take(limit.Value) : items;
43+
sb.Append(string.Join('\n', list.Select(item => $"- {formatter(item)}")));
44+
45+
// if there were more items than allowed in the list, add an extra item indicating
46+
// how many more items there were
47+
var length = items.Count();
48+
49+
if (limit is not null && length > limit)
50+
{
51+
sb.Append($"\n- and {length - limit} more. View the CodeQL logs for a full list.");
52+
}
53+
54+
return sb.ToString();
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)