Make improvements based on PR feedback

This commit is contained in:
Michael B. Gale
2023-02-22 12:29:10 +00:00
parent 8e83fd00b7
commit 0f320996cf
10 changed files with 60 additions and 69 deletions

View File

@@ -1,5 +1,6 @@
using Xunit; using Xunit;
using Semmle.Autobuild.Shared; using Semmle.Autobuild.Shared;
using Semmle.Util;
using System.Collections.Generic; using System.Collections.Generic;
using System; using System;
using System.Linq; using System.Linq;
@@ -79,10 +80,7 @@ namespace Semmle.Autobuild.Cpp.Tests
{ {
var ret = (this as IBuildActions).RunProcess(cmd, args, workingDirectory, env, out var stdout); var ret = (this as IBuildActions).RunProcess(cmd, args, workingDirectory, env, out var stdout);
foreach (var line in stdout) stdout.ForEach(line => onOutput(line));
{
onOutput(line);
}
return ret; return ret;
} }

View File

@@ -21,12 +21,10 @@ namespace Semmle.Autobuild.Cpp
public class CppAutobuilder : Autobuilder<CppAutobuildOptions> public class CppAutobuilder : Autobuilder<CppAutobuildOptions>
{ {
private DiagnosticClassifier classifier; private readonly DiagnosticClassifier classifier;
public CppAutobuilder(IBuildActions actions, CppAutobuildOptions options) : base(actions, options) public CppAutobuilder(IBuildActions actions, CppAutobuildOptions options) : base(actions, options) =>
{
classifier = new DiagnosticClassifier(); classifier = new DiagnosticClassifier();
}
protected override DiagnosticClassifier DiagnosticClassifier => classifier; protected override DiagnosticClassifier DiagnosticClassifier => classifier;

View File

@@ -1,5 +1,6 @@
using Xunit; using Xunit;
using Semmle.Autobuild.Shared; using Semmle.Autobuild.Shared;
using Semmle.Util;
using System.Collections.Generic; using System.Collections.Generic;
using System; using System;
using System.Linq; using System.Linq;
@@ -89,10 +90,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{ {
var ret = (this as IBuildActions).RunProcess(cmd, args, workingDirectory, env, out var stdout); var ret = (this as IBuildActions).RunProcess(cmd, args, workingDirectory, env, out var stdout);
foreach (var line in stdout) stdout.ForEach(line => onOutput(line));
{
onOutput(line);
}
return ret; return ret;
} }

View File

@@ -41,10 +41,8 @@ namespace Semmle.Autobuild.CSharp
protected override DiagnosticClassifier DiagnosticClassifier => diagnosticClassifier; protected override DiagnosticClassifier DiagnosticClassifier => diagnosticClassifier;
public CSharpAutobuilder(IBuildActions actions, CSharpAutobuildOptions options) : base(actions, options) public CSharpAutobuilder(IBuildActions actions, CSharpAutobuildOptions options) : base(actions, options) =>
{
diagnosticClassifier = new CSharpDiagnosticClassifier(); diagnosticClassifier = new CSharpDiagnosticClassifier();
}
public override BuildScript GetBuildScript() public override BuildScript GetBuildScript()
{ {
@@ -164,7 +162,7 @@ namespace Semmle.Autobuild.CSharp
} }
message.Severity = DiagnosticMessage.TspSeverity.Error; message.Severity = DiagnosticMessage.TspSeverity.Error;
Diagnostic(message); AddDiagnostic(message);
} }
// both dotnet and msbuild builds require project or solution files; if we haven't found any // both dotnet and msbuild builds require project or solution files; if we haven't found any
@@ -177,7 +175,7 @@ namespace Semmle.Autobuild.CSharp
"You can manually specify a suitable build command for your project."; "You can manually specify a suitable build command for your project.";
message.Severity = DiagnosticMessage.TspSeverity.Error; message.Severity = DiagnosticMessage.TspSeverity.Error;
Diagnostic(message); AddDiagnostic(message);
} }
else if (dotNetRule is not null && dotNetRule.NotDotNetProjects.Any()) else if (dotNetRule is not null && dotNetRule.NotDotNetProjects.Any())
{ {
@@ -187,7 +185,7 @@ namespace Semmle.Autobuild.CSharp
string.Join('\n', dotNetRule.NotDotNetProjects.Select(p => $"- `{p.FullPath}`")); string.Join('\n', dotNetRule.NotDotNetProjects.Select(p => $"- `{p.FullPath}`"));
message.Severity = DiagnosticMessage.TspSeverity.Warning; message.Severity = DiagnosticMessage.TspSeverity.Warning;
Diagnostic(message); AddDiagnostic(message);
} }
// report any projects that failed to build with .NET Core // report any projects that failed to build with .NET Core
@@ -201,7 +199,7 @@ namespace Semmle.Autobuild.CSharp
"or to ensure that they can be built successfully."; "or to ensure that they can be built successfully.";
message.Severity = DiagnosticMessage.TspSeverity.Error; message.Severity = DiagnosticMessage.TspSeverity.Error;
Diagnostic(message); AddDiagnostic(message);
} }
// report any projects that failed to build with MSBuild // report any projects that failed to build with MSBuild
@@ -215,7 +213,7 @@ namespace Semmle.Autobuild.CSharp
"or to ensure that they can be built successfully.";; "or to ensure that they can be built successfully.";;
message.Severity = DiagnosticMessage.TspSeverity.Error; message.Severity = DiagnosticMessage.TspSeverity.Error;
Diagnostic(message); AddDiagnostic(message);
} }
} }

View File

@@ -15,22 +15,14 @@ namespace Semmle.Autobuild.CSharp
/// </summary> /// </summary>
internal class DotNetRule : IBuildRule<CSharpAutobuildOptions> internal class DotNetRule : IBuildRule<CSharpAutobuildOptions>
{ {
private IEnumerable<Project<CSharpAutobuildOptions>> notDotNetProjects;
public readonly List<IProjectOrSolution> FailedProjectsOrSolutions = new(); public readonly List<IProjectOrSolution> FailedProjectsOrSolutions = new();
/// <summary> /// <summary>
/// A list of projects which are incompatible with DotNet. /// A list of projects which are incompatible with DotNet.
/// </summary> /// </summary>
public IEnumerable<Project<CSharpAutobuildOptions>> NotDotNetProjects public IEnumerable<Project<CSharpAutobuildOptions>> NotDotNetProjects { get; private set; }
{
get { return this.notDotNetProjects; }
}
public DotNetRule() public DotNetRule() => NotDotNetProjects = new List<Project<CSharpAutobuildOptions>>();
{
this.notDotNetProjects = new List<Project<CSharpAutobuildOptions>>();
}
public BuildScript Analyse(IAutobuilder<CSharpAutobuildOptions> builder, bool auto) public BuildScript Analyse(IAutobuilder<CSharpAutobuildOptions> builder, bool auto)
{ {
@@ -39,11 +31,11 @@ namespace Semmle.Autobuild.CSharp
if (auto) if (auto)
{ {
notDotNetProjects = builder.ProjectsOrSolutionsToBuild NotDotNetProjects = builder.ProjectsOrSolutionsToBuild
.SelectMany(p => Enumerators.Singleton(p).Concat(p.IncludedProjects)) .SelectMany(p => Enumerators.Singleton(p).Concat(p.IncludedProjects))
.OfType<Project<CSharpAutobuildOptions>>() .OfType<Project<CSharpAutobuildOptions>>()
.Where(p => !p.DotNetProject); .Where(p => !p.DotNetProject);
var notDotNetProject = notDotNetProjects.FirstOrDefault(); var notDotNetProject = NotDotNetProjects.FirstOrDefault();
if (notDotNetProject is not null) if (notDotNetProject is not null)
{ {

View File

@@ -284,7 +284,7 @@ namespace Semmle.Autobuild.Shared
/// Write <paramref name="diagnostic"/> to the diagnostics file. /// Write <paramref name="diagnostic"/> to the diagnostics file.
/// </summary> /// </summary>
/// <param name="diagnostic">The diagnostics entry to write.</param> /// <param name="diagnostic">The diagnostics entry to write.</param>
public void Diagnostic(DiagnosticMessage diagnostic) public void AddDiagnostic(DiagnosticMessage diagnostic)
{ {
diagnostics.AddEntry(diagnostic); diagnostics.AddEntry(diagnostic);
} }
@@ -320,13 +320,11 @@ namespace Semmle.Autobuild.Shared
// if the build succeeded, all diagnostics we captured from the build output should be warnings; // if the build succeeded, all diagnostics we captured from the build output should be warnings;
// otherwise they should all be errors // otherwise they should all be errors
var diagSeverity = buildResult == 0 ? DiagnosticMessage.TspSeverity.Warning : DiagnosticMessage.TspSeverity.Error; var diagSeverity = buildResult == 0 ? DiagnosticMessage.TspSeverity.Warning : DiagnosticMessage.TspSeverity.Error;
foreach (var diagResult in this.DiagnosticClassifier.Results) this.DiagnosticClassifier.Results.Select(result => result.ToDiagnosticMessage(this)).ForEach(result =>
{ {
var diag = diagResult.ToDiagnosticMessage(this); result.Severity = diagSeverity;
diag.Severity = diagSeverity; AddDiagnostic(result);
});
Diagnostic(diag);
}
return buildResult; return buildResult;
} }
@@ -345,8 +343,11 @@ namespace Semmle.Autobuild.Shared
/// <returns>The resulting <see cref="DiagnosticMessage" />.</returns> /// <returns>The resulting <see cref="DiagnosticMessage" />.</returns>
public DiagnosticMessage MakeDiagnostic(string id, string name) public DiagnosticMessage MakeDiagnostic(string id, string name)
{ {
DiagnosticMessage diag = new(new($"{this.Options.Language.UpperCaseName.ToLower()}/autobuilder/{id}", name)); DiagnosticMessage diag = new(new(
diag.Source.ExtractorName = Options.Language.UpperCaseName.ToLower(); $"{this.Options.Language.UpperCaseName.ToLower()}/autobuilder/{id}",
name,
Options.Language.UpperCaseName.ToLower()
));
diag.Visibility.StatusPage = true; diag.Visibility.StatusPage = true;
return diag; return diag;
@@ -367,7 +368,7 @@ namespace Semmle.Autobuild.Shared
"You can manually specify a suitable build command for your project."; "You can manually specify a suitable build command for your project.";
message.Severity = DiagnosticMessage.TspSeverity.Error; message.Severity = DiagnosticMessage.TspSeverity.Error;
Diagnostic(message); AddDiagnostic(message);
} }
/// <summary> /// <summary>

View File

@@ -10,29 +10,21 @@ namespace Semmle.Autobuild.Shared
public class BuildCommandAutoRule : IBuildRule<AutobuildOptionsShared> public class BuildCommandAutoRule : IBuildRule<AutobuildOptionsShared>
{ {
private readonly WithDotNet<AutobuildOptionsShared> withDotNet; private readonly WithDotNet<AutobuildOptionsShared> withDotNet;
private IEnumerable<string> candidatePaths;
private string? scriptPath;
/// <summary> /// <summary>
/// A list of paths to files in the project directory which we classified as scripts. /// A list of paths to files in the project directory which we classified as scripts.
/// </summary> /// </summary>
public IEnumerable<string> CandidatePaths public IEnumerable<string> CandidatePaths { get; private set; }
{
get { return this.candidatePaths; }
}
/// <summary> /// <summary>
/// The path of the script we decided to run, if any. /// The path of the script we decided to run, if any.
/// </summary> /// </summary>
public string? ScriptPath public string? ScriptPath { get; private set; }
{
get { return this.scriptPath; }
}
public BuildCommandAutoRule(WithDotNet<AutobuildOptionsShared> withDotNet) public BuildCommandAutoRule(WithDotNet<AutobuildOptionsShared> withDotNet)
{ {
this.withDotNet = withDotNet; this.withDotNet = withDotNet;
this.candidatePaths = new List<string>(); this.CandidatePaths = new List<string>();
} }
/// <summary> /// <summary>
@@ -70,18 +62,18 @@ namespace Semmle.Autobuild.Shared
var scripts = buildScripts.SelectMany(s => extensions.Select(e => s + e)); var scripts = buildScripts.SelectMany(s => extensions.Select(e => s + e));
// search through the files in the project directory for paths which end in one of // search through the files in the project directory for paths which end in one of
// the names given by `scripts`, then order them by their distance from the root // the names given by `scripts`, then order them by their distance from the root
this.candidatePaths = builder.Paths.Where(p => scripts.Any(p.Item1.ToLower().EndsWith)).OrderBy(p => p.Item2).Select(p => p.Item1); this.CandidatePaths = builder.Paths.Where(p => scripts.Any(p.Item1.ToLower().EndsWith)).OrderBy(p => p.Item2).Select(p => p.Item1);
// pick the first matching path, if there is one // pick the first matching path, if there is one
this.scriptPath = candidatePaths.FirstOrDefault(); this.ScriptPath = this.CandidatePaths.FirstOrDefault();
if (scriptPath is null) if (this.ScriptPath is null)
return BuildScript.Failure; return BuildScript.Failure;
var chmod = new CommandBuilder(builder.Actions); var chmod = new CommandBuilder(builder.Actions);
chmod.RunCommand("/bin/chmod", $"u+x {scriptPath}"); chmod.RunCommand("/bin/chmod", $"u+x {this.ScriptPath}");
var chmodScript = builder.Actions.IsWindows() ? BuildScript.Success : BuildScript.Try(chmod.Script); var chmodScript = builder.Actions.IsWindows() ? BuildScript.Success : BuildScript.Try(chmod.Script);
var dir = builder.Actions.GetDirectoryName(scriptPath); var dir = builder.Actions.GetDirectoryName(this.ScriptPath);
// A specific .NET Core version may be required // A specific .NET Core version may be required
return chmodScript & withDotNet(builder, environment => return chmodScript & withDotNet(builder, environment =>
@@ -93,7 +85,7 @@ namespace Semmle.Autobuild.Shared
if (vsTools is not null) if (vsTools is not null)
command.CallBatFile(vsTools.Path); command.CallBatFile(vsTools.Path);
command.RunCommand(scriptPath); command.RunCommand(this.ScriptPath);
return command.Script; return command.Script;
}); });
} }

View File

@@ -80,15 +80,14 @@ namespace Semmle.Autobuild.Shared
/// <param name="line">The line to which the rules should be applied to.</param> /// <param name="line">The line to which the rules should be applied to.</param>
public void ClassifyLine(string line) public void ClassifyLine(string line)
{ {
foreach (var rule in this.rules) this.rules.ForEach(rule =>
{ {
var match = rule.Pattern.Match(line); var match = rule.Pattern.Match(line);
if (match.Success) if (match.Success)
{ {
rule.Fire(this, match); rule.Fire(this, match);
} }
} });
} }
} }
} }

View File

@@ -15,7 +15,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" /> <PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -31,12 +31,13 @@ namespace Semmle.Util
/// <summary> /// <summary>
/// Name of the CodeQL extractor. This is used to identify which tool component the reporting descriptor object should be nested under in SARIF. /// Name of the CodeQL extractor. This is used to identify which tool component the reporting descriptor object should be nested under in SARIF.
/// </summary> /// </summary>
public string? ExtractorName { get; set; } public string? ExtractorName { get; }
public TspSource(string id, string name) public TspSource(string id, string name, string? extractorName = null)
{ {
Id = id; Id = id;
Name = name; Name = name;
ExtractorName = extractorName;
} }
} }
@@ -66,6 +67,13 @@ namespace Semmle.Util
/// True if the message should be sent to telemetry (defaults to false). /// True if the message should be sent to telemetry (defaults to false).
/// </summary> /// </summary>
public bool? Telemetry { get; set; } public bool? Telemetry { get; set; }
public TspVisibility(bool? statusPage = null, bool? cliSummaryTable = null, bool? telemetry = null)
{
this.StatusPage = statusPage;
this.CLISummaryTable = cliSummaryTable;
this.Telemetry = telemetry;
}
} }
public class TspLocation public class TspLocation
@@ -78,6 +86,15 @@ namespace Semmle.Util
public int? StartColumn { get; set; } public int? StartColumn { get; set; }
public int? EndLine { get; set; } public int? EndLine { get; set; }
public int? EndColumn { get; set; } public int? EndColumn { get; set; }
public TspLocation(string? file = null, int? startLine = null, int? startColumn = null, int? endLine = null, int? endColumn = null)
{
this.File = file;
this.StartLine = startLine;
this.StartColumn = startColumn;
this.EndLine = endLine;
this.EndColumn = endColumn;
}
} }
/// <summary> /// <summary>
@@ -109,9 +126,6 @@ namespace Semmle.Util
/// If true, then this message won't be presented to users. /// If true, then this message won't be presented to users.
/// </summary> /// </summary>
public bool Internal { get; set; } public bool Internal { get; set; }
/// <summary>
///
/// </summary>
public TspVisibility Visibility { get; } public TspVisibility Visibility { get; }
public TspLocation Location { get; } public TspLocation Location { get; }
/// <summary> /// <summary>
@@ -162,7 +176,8 @@ namespace Semmle.Util
serializer = new JsonSerializer serializer = new JsonSerializer
{ {
ContractResolver = contractResolver ContractResolver = contractResolver,
NullValueHandling = NullValueHandling.Ignore
}; };
writer = streamWriter; writer = streamWriter;