Utils: generate solution and project files

This commit is contained in:
Zev Spitz
2022-01-16 03:27:32 +02:00
parent e18ff85b2e
commit cd0c4420e1
4 changed files with 125 additions and 13 deletions

View File

@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using static System.IO.Path;
namespace DotnetUtils; namespace DotnetUtils;
@@ -18,10 +19,7 @@ public static class Extensions {
rootPath.IsNullOrWhitespace() rootPath.IsNullOrWhitespace()
) { return path; } ) { return path; }
var path1 = path.TrimEnd('\\'); path = path.TrimEnd('\\'); // remove trailing backslash, if present
rootPath = rootPath.TrimEnd('\\'); return GetRelativePath(rootPath, path.TrimEnd('\\'));
if (!path1.StartsWith(rootPath, StringComparison.InvariantCultureIgnoreCase)) { return path; }
return path1[(rootPath.Length + 1)..]; // ignore the initial /
} }
} }

View File

@@ -0,0 +1,56 @@
using System.Diagnostics;
namespace DotnetUtils;
public static class Methods {
public static ProcessResult RunProcess(string filename, string arguments) {
var process = new Process() {
StartInfo = {
FileName = filename,
Arguments = arguments,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
},
EnableRaisingEvents = true
};
return RunProcess(process);
}
public static ProcessResult RunProcess(Process process, string input = "") {
var (output, error) = ("", "");
var (redirectOut, redirectErr) = (
process.StartInfo.RedirectStandardOutput,
process.StartInfo.RedirectStandardError
);
if (redirectOut) {
process.OutputDataReceived += (s, ea) => output += ea.Data + "\n";
}
if (redirectErr) {
process.ErrorDataReceived += (s, ea) => error += ea.Data + "\n";
}
if (!process.Start()) {
throw new InvalidOperationException();
};
if (redirectOut) { process.BeginOutputReadLine(); }
if (redirectErr) { process.BeginErrorReadLine(); }
if (!string.IsNullOrEmpty(input)) {
process.StandardInput.WriteLine(input);
process.StandardInput.Close();
}
process.WaitForExit();
return new ProcessResult(process.ExitCode, output, error);
}
}
public sealed record ProcessResult(int ExitCode, string StdOut, string StdErr) {
public override string? ToString() =>
StdOut +
(StdOut is not (null or "") && ExitCode > 0 ? "\n" : "") +
(ExitCode > 0 ?
$"{ExitCode}\n{StdErr}" :
"");
}

View File

@@ -1,5 +1,4 @@
using System.Reflection; using static System.IO.Directory;
using static System.IO.Directory;
using static System.IO.Path; using static System.IO.Path;
using static DotnetUtils.Globals; using static DotnetUtils.Globals;
@@ -17,6 +16,14 @@ public record PortInfo(
MatchCasing = MatchCasing.CaseInsensitive MatchCasing = MatchCasing.CaseInsensitive
}; };
// .NET namespaces cannot have a digit as the first character
// For games whose name starts with a digit, we map the name to a specific string
private static readonly Dictionary<string, string> specialGameNames = new() {
{ "3-D_Plot", "ThreeDPlot" },
{ "3-D_Tic-Tac-Toe", "ThreeDTicTacToe" },
{ "23_Matches", "TwentyThreeMatches"}
};
public static PortInfo? Create(string fullPath, string langKeyword) { public static PortInfo? Create(string fullPath, string langKeyword) {
var folderName = GetFileName(fullPath); var folderName = GetFileName(fullPath);
var parts = folderName.Split('_', 2); var parts = folderName.Split('_', 2);
@@ -27,9 +34,11 @@ public record PortInfo(
(int?)null; (int?)null;
var gameName = var gameName =
parts.Length > 1 ? parts.Length == 0 ?
parts[1].Replace("_", "") : null :
null; specialGameNames.TryGetValue(parts[1], out var specialName) ?
specialName :
parts[1].Replace("_", "").Replace("-", "");
if (index is 0 or null || gameName is null) { return null; } if (index is 0 or null || gameName is null) { return null; }

View File

@@ -1,6 +1,8 @@
using DotnetUtils; using System.Diagnostics;
using DotnetUtils;
using static System.Console; using static System.Console;
using static System.IO.Path; using static System.IO.Path;
using static DotnetUtils.Methods;
var infos = PortInfos.Get; var infos = PortInfos.Get;
@@ -11,7 +13,10 @@ var actions = new (Action action, string description)[] {
(multipleSlns, "Output multiple sln files"), (multipleSlns, "Output multiple sln files"),
(missingProj, "Output missing project file"), (missingProj, "Output missing project file"),
(unexpectedProjName, "Output misnamed project files"), (unexpectedProjName, "Output misnamed project files"),
(multipleProjs, "Output multiple project files") (multipleProjs, "Output multiple project files"),
(generateMissingSlns, "Generate solution files when missing"),
(generateMissingProjs, "Generate project files when missing")
}; };
foreach (var (_, description, index) in actions.WithIndex()) { foreach (var (_, description, index) in actions.WithIndex()) {
@@ -159,8 +164,52 @@ void multipleProjs() {
WriteLine(item.LangPath); WriteLine(item.LangPath);
WriteLine(); WriteLine();
printProjs(item); printProjs(item);
} }
WriteLine(); WriteLine();
WriteLine($"Count: {data.Length}"); WriteLine($"Count: {data.Length}");
} }
void generateMissingSlns() {
foreach (var item in infos.Where(x => !x.Slns.Any())) {
var result = RunProcess("dotnet", $"new sln -n {item.GameName} -o {item.LangPath}");
WriteLine(result);
var slnFullPath = Combine(item.LangPath, $"{item.GameName}.sln");
foreach (var proj in item.Projs) {
result = RunProcess("dotnet", $"sln {slnFullPath} add {proj}");
WriteLine(result);
}
}
}
void generateMissingProjs() {
foreach (var item in infos.Where(x => !x.Projs.Any())) {
var (langArg, langVersion) = item.Lang switch {
"csharp" => ("\"C#\"", 10),
"vbnet" => ("\"VB\"", 16.9),
_ => throw new InvalidOperationException()
};
var result = RunProcess("dotnet", $"new console --language {langArg} --name {item.GameName}.{item.ProjExt} -o {item.LangPath} -f net6.0 --langversion {langVersion}");
WriteLine(result);
var projFullPath = Combine(item.LangPath, $"{item.GameName}.{item.ProjExt}");
if (item.Slns.Length == 1) {
result = RunProcess("dotnet", $"sln {item.Slns[0]} add {projFullPath}");
WriteLine(result);
}
}
}
void checkProjects() {
// warn if project files do not:
// target .NET 6
// implicit using
// nullable enable
// warn if none og the projects have:
// output type exe
}
void tryBuild() {
// if has code files, try to build
}