Add diagnostic for missing project files

This commit is contained in:
Michael B. Gale
2023-02-22 11:33:47 +00:00
parent b97c885c8d
commit b2d1cfe3d1
2 changed files with 74 additions and 0 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Semmle.Autobuild.Shared;
@@ -56,6 +57,70 @@ namespace Semmle.Autobuild.CSharp
}
}
public class MissingProjectFileRule : DiagnosticRule
{
private const string runsOnDocsUrl = "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on";
private const string checkoutDocsUrl = "https://github.com/actions/checkout#usage";
public class Result : IDiagnosticsResult
{
/// <summary>
/// A set of missing project files.
/// </summary>
public HashSet<string> MissingProjectFiles { get; }
public Result()
{
this.MissingProjectFiles = new HashSet<string>();
}
public DiagnosticMessage ToDiagnosticMessage<T>(Autobuilder<T> builder) where T : AutobuildOptionsShared
{
var diag = builder.MakeDiagnostic(
$"missing-project-files",
$"Missing project files"
);
diag.MarkdownMessage =
"Some project files were not found when CodeQL built your project:\n\n" +
this.MissingProjectFiles.AsEnumerable().ToMarkdownList(MarkdownUtil.CodeFormatter, 5) +
"\n\nThis may lead to subsequent failures. " +
"You can check for common causes for missing project files:\n\n" +
$"- Ensure that the project is built using the {runsOnDocsUrl.ToMarkdownLink("intended operating system")} and that filenames on case-sensitive platforms are correctly specified.\n" +
$"- If your repository uses Git submodules, ensure that those are {checkoutDocsUrl.ToMarkdownLink("checked out")} before the CodeQL action is run.\n" +
"- If you auto-generate some project files as part of your build process, ensure that these are generated before the CodeQL action is run.";
diag.Severity = DiagnosticMessage.TspSeverity.Warning;
return diag;
}
}
public MissingProjectFileRule() :
base("MSB3202: The project file \"(?<projectFile>[^\"]+)\" was not found. \\[(?<location>[^\\]]+)\\]")
{
}
public override void Fire(DiagnosticClassifier classifier, Match match)
{
if (!match.Groups.TryGetValue("projectFile", out var projectFile))
throw new ArgumentException("Expected regular expression match to contain projectFile");
if (!match.Groups.TryGetValue("location", out var location))
throw new ArgumentException("Expected regular expression match to contain location");
var result = classifier.Results.OfType<Result>().FirstOrDefault();
// if we do not yet have a result for this rule, create one and add it to the list
// of results the classifier knows about
if (result is null)
{
result = new Result();
classifier.Results.Add(result);
}
// then add the missing project file
result.MissingProjectFiles.Add(projectFile.Value);
}
}
/// <summary>
/// Implements a <see cref="DiagnosticClassifier" /> which applies C#-specific rules to
/// the build output.
@@ -66,6 +131,7 @@ namespace Semmle.Autobuild.CSharp
{
// add C#-specific rules to this classifier
this.AddRule(new MissingXamarinSdkRule());
this.AddRule(new MissingProjectFileRule());
}
}
}

View File

@@ -13,6 +13,14 @@ namespace Semmle.Autobuild.Shared
/// <returns>A function which formats items as markdown inline code.</returns>
public static readonly Func<string, string> CodeFormatter = item => $"`{item}`";
/// <summary>
/// Formats the string as a markdown link.
/// </summary>
/// <param name="link">The URL for the link.</param>
/// <param name="title">The text that is displayed.</param>
/// <returns>A string containing a markdown-formatted link.</returns>
public static string ToMarkdownLink(this string link, string title) => $"[{title}]({link})";
/// <summary>
/// Renders <see cref="projects" /> as a markdown list of the project paths.
/// </summary>