Skip to content

Commit 69041bc

Browse files
committed
C#: Enable nullability in Autobuilder.
1 parent 8a968da commit 69041bc

18 files changed

+171
-105
lines changed

csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ Autobuilder CreateAutoBuilder(string lgtmLanguage, bool isWindows,
341341
string cwd = @"C:\Project")
342342
{
343343
Actions.GetEnvironmentVariable["CODEQL_AUTOBUILDER_CSHARP_NO_INDEXING"] = "false";
344+
Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
345+
Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
344346
Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_ROOT"] = @"C:\codeql\csharp";
345347
Actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java";
346348
Actions.GetEnvironmentVariable["SEMMLE_DIST"] = @"C:\odasa";
@@ -364,8 +366,7 @@ Autobuilder CreateAutoBuilder(string lgtmLanguage, bool isWindows,
364366
Actions.GetCurrentDirectory = cwd;
365367
Actions.IsWindows = isWindows;
366368

367-
var options = new AutobuildOptions();
368-
options.ReadEnvironment(Actions);
369+
var options = new AutobuildOptions(Actions);
369370
return new Autobuilder(Actions, options);
370371
}
371372

csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ class AspBuildRule : IBuildRule
77
{
88
public BuildScript Analyse(Autobuilder builder, bool auto)
99
{
10-
(var javaHome, var dist) =
11-
builder.CodeQLJavaHome != null ?
12-
(builder.CodeQLJavaHome, builder.CodeQLExtractorCSharpRoot) :
13-
(builder.SemmleJavaHome, builder.SemmleDist);
10+
var javaHome = builder.JavaHome;
11+
var dist = builder.Distribution;
12+
1413
var command = new CommandBuilder(builder.Actions).
1514
RunCommand(builder.Actions.PathCombine(javaHome, "bin", "java")).
1615
Argument("-jar").

csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,40 +10,40 @@ namespace Semmle.Autobuild
1010
public class AutobuildOptions
1111
{
1212
public readonly int SearchDepth = 3;
13-
public string RootDirectory = null;
14-
static readonly string prefix = "LGTM_INDEX_";
15-
16-
public string VsToolsVersion;
17-
public string MsBuildArguments;
18-
public string MsBuildPlatform;
19-
public string MsBuildConfiguration;
20-
public string MsBuildTarget;
21-
public string DotNetArguments;
22-
public string DotNetVersion;
23-
public string BuildCommand;
24-
public string[] Solution;
25-
26-
public bool IgnoreErrors;
27-
public bool Buildless;
28-
public bool AllSolutions;
29-
public bool NugetRestore;
30-
31-
public Language Language;
32-
public bool Indexing;
13+
public readonly string RootDirectory;
14+
private const string prefix = "LGTM_INDEX_";
15+
16+
public readonly string? VsToolsVersion;
17+
public readonly string? MsBuildArguments;
18+
public readonly string? MsBuildPlatform;
19+
public readonly string? MsBuildConfiguration;
20+
public readonly string? MsBuildTarget;
21+
public readonly string? DotNetArguments;
22+
public readonly string? DotNetVersion;
23+
public readonly string? BuildCommand;
24+
public readonly string[] Solution;
25+
26+
public readonly bool IgnoreErrors;
27+
public readonly bool Buildless;
28+
public readonly bool AllSolutions;
29+
public readonly bool NugetRestore;
30+
31+
public readonly Language Language;
32+
public readonly bool Indexing;
3333

3434
/// <summary>
3535
/// Reads options from environment variables.
3636
/// Throws ArgumentOutOfRangeException for invalid arguments.
3737
/// </summary>
38-
public void ReadEnvironment(IBuildActions actions)
38+
public AutobuildOptions(IBuildActions actions)
3939
{
4040
RootDirectory = actions.GetCurrentDirectory();
4141
VsToolsVersion = actions.GetEnvironmentVariable(prefix + "VSTOOLS_VERSION");
42-
MsBuildArguments = actions.GetEnvironmentVariable(prefix + "MSBUILD_ARGUMENTS").AsStringWithExpandedEnvVars(actions);
42+
MsBuildArguments = actions.GetEnvironmentVariable(prefix + "MSBUILD_ARGUMENTS").AsStringWithExpandedEnvVarsMaybeNull(actions);
4343
MsBuildPlatform = actions.GetEnvironmentVariable(prefix + "MSBUILD_PLATFORM");
4444
MsBuildConfiguration = actions.GetEnvironmentVariable(prefix + "MSBUILD_CONFIGURATION");
4545
MsBuildTarget = actions.GetEnvironmentVariable(prefix + "MSBUILD_TARGET");
46-
DotNetArguments = actions.GetEnvironmentVariable(prefix + "DOTNET_ARGUMENTS").AsStringWithExpandedEnvVars(actions);
46+
DotNetArguments = actions.GetEnvironmentVariable(prefix + "DOTNET_ARGUMENTS").AsStringWithExpandedEnvVarsMaybeNull(actions);
4747
DotNetVersion = actions.GetEnvironmentVariable(prefix + "DOTNET_VERSION");
4848
BuildCommand = actions.GetEnvironmentVariable(prefix + "BUILD_COMMAND");
4949
Solution = actions.GetEnvironmentVariable(prefix + "SOLUTION").AsListWithExpandedEnvVars(actions, new string[0]);
@@ -60,7 +60,7 @@ public void ReadEnvironment(IBuildActions actions)
6060

6161
public static class OptionsExtensions
6262
{
63-
public static bool AsBool(this string value, string param, bool defaultValue)
63+
public static bool AsBool(this string? value, string param, bool defaultValue)
6464
{
6565
if (value == null) return defaultValue;
6666
switch (value.ToLower())
@@ -80,7 +80,7 @@ public static bool AsBool(this string value, string param, bool defaultValue)
8080
}
8181
}
8282

83-
public static Language AsLanguage(this string key)
83+
public static Language AsLanguage(this string? key)
8484
{
8585
switch (key)
8686
{
@@ -95,7 +95,7 @@ public static Language AsLanguage(this string key)
9595
}
9696
}
9797

98-
public static string[] AsListWithExpandedEnvVars(this string value, IBuildActions actions, string[] defaultValue)
98+
public static string[] AsListWithExpandedEnvVars(this string? value, IBuildActions actions, string[] defaultValue)
9999
{
100100
if (value == null)
101101
return defaultValue;
@@ -107,6 +107,14 @@ public static string[] AsListWithExpandedEnvVars(this string value, IBuildAction
107107

108108
static readonly Regex linuxEnvRegEx = new Regex(@"\$([a-zA-Z_][a-zA-Z_0-9]*)", RegexOptions.Compiled);
109109

110+
public static string? AsStringWithExpandedEnvVarsMaybeNull(this string? value, IBuildActions actions)
111+
{
112+
if (string.IsNullOrEmpty(value))
113+
return value;
114+
115+
return value.AsStringWithExpandedEnvVars(actions);
116+
}
117+
110118
public static string AsStringWithExpandedEnvVars(this string value, IBuildActions actions)
111119
{
112120
if (string.IsNullOrEmpty(value))

csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ interface IBuildRule
2020
BuildScript Analyse(Autobuilder builder, bool auto);
2121
}
2222

23+
/// <summary>
24+
/// Exception indicating that environment variables are missing or invalid.
25+
/// </summary>
26+
class InvalidEnvironmentException : Exception
27+
{
28+
public InvalidEnvironmentException(string m) : base(m) { }
29+
}
30+
2331
/// <summary>
2432
/// Main application logic, containing all data
2533
/// gathered from the project and filesystem.
@@ -69,7 +77,7 @@ public class Autobuilder
6977
/// List of project/solution files to build.
7078
/// </summary>
7179
public IList<IProjectOrSolution> ProjectsOrSolutionsToBuild => projectsOrSolutionsToBuildLazy.Value;
72-
readonly Lazy<IList<IProjectOrSolution>> projectsOrSolutionsToBuildLazy;
80+
private readonly Lazy<IList<IProjectOrSolution>> projectsOrSolutionsToBuildLazy;
7381

7482
/// <summary>
7583
/// Holds if a given path was found.
@@ -129,7 +137,7 @@ public Autobuilder(IBuildActions actions, AutobuildOptions options)
129137

130138
projectsOrSolutionsToBuildLazy = new Lazy<IList<IProjectOrSolution>>(() =>
131139
{
132-
List<IProjectOrSolution> ret;
140+
List<IProjectOrSolution>? ret;
133141
if (options.Solution.Any())
134142
{
135143
ret = new List<IProjectOrSolution>();
@@ -143,7 +151,7 @@ public Autobuilder(IBuildActions actions, AutobuildOptions options)
143151
return ret;
144152
}
145153

146-
IEnumerable<IProjectOrSolution> FindFiles(string extension, Func<string, ProjectOrSolution> create)
154+
IEnumerable<IProjectOrSolution>? FindFiles(string extension, Func<string, ProjectOrSolution> create)
147155
{
148156
var matchingFiles = GetExtensions(extension).
149157
Select(p => (ProjectOrSolution: create(p.Item1), DistanceFromRoot: p.Item2)).
@@ -178,18 +186,39 @@ IEnumerable<IProjectOrSolution> FindFiles(string extension, Func<string, Project
178186

179187
CodeQLExtractorCSharpRoot = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_ROOT");
180188

181-
CodeQLJavaHome = Actions.GetEnvironmentVariable("CODEQL_JAVA_HOME");
182-
183189
SemmleDist = Actions.GetEnvironmentVariable("SEMMLE_DIST");
184190

191+
CodeQLJavaHome = Actions.GetEnvironmentVariable("CODEQL_JAVA_HOME");
192+
185193
SemmleJavaHome = Actions.GetEnvironmentVariable("SEMMLE_JAVA_HOME");
186194

195+
if(CodeQLJavaHome is null && SemmleJavaHome is null)
196+
throw new InvalidEnvironmentException("The environment variables CODEQL_JAVA_HOME and SEMMLE_JAVA_HOME have not been set.");
197+
187198
SemmlePlatformTools = Actions.GetEnvironmentVariable("SEMMLE_PLATFORM_TOOLS");
188199

189-
if (CodeQLExtractorCSharpRoot == null && SemmleDist == null)
190-
Log(Severity.Error, "The environment variables CODEQL_EXTRACTOR_CSHARP_ROOT and SEMMLE_DIST have not been set.");
200+
if (CodeQLExtractorCSharpRoot is null && SemmleDist is null)
201+
throw new InvalidEnvironmentException("The environment variables CODEQL_EXTRACTOR_CSHARP_ROOT and SEMMLE_DIST have not been set.");
202+
203+
var trapDir = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_TRAP_DIR") ?? Actions.GetEnvironmentVariable("TRAP_FOLDER");
204+
205+
if (trapDir is null)
206+
throw new InvalidEnvironmentException("The environment variables CODEQL_EXTRACTOR_CSHARP_TRAP_DIR and TRAP_FOLDER have not been set.");
207+
208+
TrapDir = trapDir;
209+
210+
var sourceArchiveDir = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR") ?? Actions.GetEnvironmentVariable("SOURCE_ARCHIVE");
211+
212+
if(sourceArchiveDir is null)
213+
throw new InvalidEnvironmentException("The environment variables CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR and SOURCE_ARCHIVE have not been set.");
214+
215+
SourceArchiveDir = sourceArchiveDir;
191216
}
192217

218+
private string TrapDir { get; }
219+
220+
private string SourceArchiveDir { get; }
221+
193222
readonly ILogger logger = new ConsoleLogger(Verbosity.Info);
194223

195224
/// <summary>
@@ -271,9 +300,9 @@ BuildScript CheckExtractorRun(bool warnOnFailure) =>
271300
break;
272301
case CSharpBuildStrategy.Auto:
273302
var cleanTrapFolder =
274-
BuildScript.DeleteDirectory(Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_TRAP_DIR") ?? Actions.GetEnvironmentVariable("TRAP_FOLDER"));
303+
BuildScript.DeleteDirectory(TrapDir);
275304
var cleanSourceArchive =
276-
BuildScript.DeleteDirectory(Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR") ?? Actions.GetEnvironmentVariable("SOURCE_ARCHIVE"));
305+
BuildScript.DeleteDirectory(SourceArchiveDir);
277306
var tryCleanExtractorArgsLogs =
278307
BuildScript.Create(actions =>
279308
{
@@ -376,38 +405,43 @@ BuildScript AutobuildFailure() =>
376405
/// <summary>
377406
/// Value of CODEQL_EXTRACTOR_CSHARP_ROOT environment variable.
378407
/// </summary>
379-
public string CodeQLExtractorCSharpRoot { get; private set; }
408+
private string? CodeQLExtractorCSharpRoot { get; }
380409

381410
/// <summary>
382411
/// Value of CODEQL_JAVA_HOME environment variable.
383412
/// </summary>
384-
public string CodeQLJavaHome { get; private set; }
413+
private string? CodeQLJavaHome { get; }
385414

386415
/// <summary>
387416
/// Value of SEMMLE_DIST environment variable.
388417
/// </summary>
389-
public string SemmleDist { get; private set; }
418+
private string? SemmleDist { get; }
419+
420+
public string Distribution => CodeQLExtractorCSharpRoot ?? SemmleDist!;
421+
422+
public string JavaHome => CodeQLJavaHome ?? SemmleJavaHome!;
390423

391424
/// <summary>
392425
/// Value of SEMMLE_JAVA_HOME environment variable.
393426
/// </summary>
394-
public string SemmleJavaHome { get; private set; }
427+
public string? SemmleJavaHome { get; private set; }
395428

396429
/// <summary>
397430
/// Value of SEMMLE_PLATFORM_TOOLS environment variable.
398431
/// </summary>
399-
public string SemmlePlatformTools { get; private set; }
432+
public string? SemmlePlatformTools { get; private set; }
400433

401434
/// <summary>
402435
/// The absolute path of the odasa executable.
436+
/// null if we are running in CodeQL.
403437
/// </summary>
404-
public string Odasa => SemmleDist == null ? null : Actions.PathCombine(SemmleDist, "tools", "odasa");
438+
public string? Odasa => SemmleDist is null ? null : Actions.PathCombine(SemmleDist, "tools", "odasa");
405439

406440
/// <summary>
407441
/// Construct a command that executed the given <paramref name="cmd"/> wrapped in
408442
/// an <code>odasa --index</code>, unless indexing has been disabled, in which case
409443
/// <paramref name="cmd"/> is run directly.
410444
/// </summary>
411-
internal CommandBuilder MaybeIndex(CommandBuilder builder, string cmd) => Options.Indexing ? builder.IndexCommand(Odasa, cmd) : builder.RunCommand(cmd);
445+
internal CommandBuilder MaybeIndex(CommandBuilder builder, string cmd) => Options.Indexing && !(Odasa is null) ? builder.IndexCommand(Odasa, cmd) : builder.RunCommand(cmd);
412446
}
413447
}

csharp/autobuilder/Semmle.Autobuild/BuildActions.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public interface IBuildActions
2121
/// <param name="env">Additional environment variables.</param>
2222
/// <param name="stdOut">The lines of stdout.</param>
2323
/// <returns>The process exit code.</returns>
24-
int RunProcess(string exe, string args, string workingDirectory, IDictionary<string, string> env, out IList<string> stdOut);
24+
int RunProcess(string exe, string args, string? workingDirectory, IDictionary<string, string>? env, out IList<string> stdOut);
2525

2626
/// <summary>
2727
/// Runs a process but does not capture its output.
@@ -31,7 +31,7 @@ public interface IBuildActions
3131
/// <param name="workingDirectory">The working directory (<code>null</code> for current directory).</param>
3232
/// <param name="env">Additional environment variables.</param>
3333
/// <returns>The process exit code.</returns>
34-
int RunProcess(string exe, string args, string workingDirectory, IDictionary<string, string> env);
34+
int RunProcess(string exe, string args, string? workingDirectory, IDictionary<string, string>? env);
3535

3636
/// <summary>
3737
/// Tests whether a file exists, File.Exists().
@@ -63,7 +63,7 @@ public interface IBuildActions
6363
/// </summary>
6464
/// <param name="name">The name of the variable.</param>
6565
/// <returns>The string value, or null if the variable is not defined.</returns>
66-
string GetEnvironmentVariable(string name);
66+
string? GetEnvironmentVariable(string name);
6767

6868
/// <summary>
6969
/// Gets the current directory, Directory.GetCurrentDirectory().
@@ -130,7 +130,7 @@ class SystemBuildActions : IBuildActions
130130

131131
bool IBuildActions.FileExists(string file) => File.Exists(file);
132132

133-
ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string workingDirectory, IDictionary<string, string> environment, bool redirectStandardOutput)
133+
ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string? workingDirectory, IDictionary<string, string>? environment, bool redirectStandardOutput)
134134
{
135135
var pi = new ProcessStartInfo(exe, arguments)
136136
{
@@ -146,7 +146,7 @@ ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string workin
146146
return pi;
147147
}
148148

149-
int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, IDictionary<string, string> environment)
149+
int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? environment)
150150
{
151151
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, false);
152152
using (var p = Process.Start(pi))
@@ -156,7 +156,7 @@ int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, I
156156
}
157157
}
158158

159-
int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, IDictionary<string, string> environment, out IList<string> stdOut)
159+
int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? environment, out IList<string> stdOut)
160160
{
161161
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, true);
162162
return pi.ReadOutput(out stdOut);
@@ -166,7 +166,7 @@ int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, I
166166

167167
bool IBuildActions.DirectoryExists(string dir) => Directory.Exists(dir);
168168

169-
string IBuildActions.GetEnvironmentVariable(string name) => Environment.GetEnvironmentVariable(name);
169+
string? IBuildActions.GetEnvironmentVariable(string name) => Environment.GetEnvironmentVariable(name);
170170

171171
string IBuildActions.GetCurrentDirectory() => Directory.GetCurrentDirectory();
172172

csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public BuildScript Analyse(Autobuilder builder, bool auto)
4040
chmod.RunCommand("/bin/chmod", $"u+x {scriptPath}");
4141
var chmodScript = builder.Actions.IsWindows() ? BuildScript.Success : BuildScript.Try(chmod.Script);
4242

43-
var dir = Path.GetDirectoryName(scriptPath);
43+
string? dir = Path.GetDirectoryName(scriptPath);
4444

4545
// A specific .NET Core version may be required
4646
return chmodScript & DotNetRule.WithDotNet(builder, environment =>

0 commit comments

Comments
 (0)