From 8e7d6c4d2ec101058b0b4100be575ebbb7e199be Mon Sep 17 00:00:00 2001 From: Paul Hebble Date: Wed, 4 Sep 2024 12:50:02 -0500 Subject: [PATCH] Avoid index out of range --- AutoUpdate/CKAN-autoupdate.csproj | 2 + AutoUpdate/Main.cs | 22 +++--- Cmdline/Action/Import.cs | 2 +- Cmdline/Action/Show.cs | 53 +++++++------- Cmdline/Action/Upgrade.cs | 9 ++- Cmdline/ConsoleUser.cs | 4 +- Cmdline/Main.cs | 37 +++++----- .../Toolkit/ConsoleFileMultiSelectDialog.cs | 2 +- ConsoleUI/Toolkit/Symbols.cs | 7 +- Core/AutoUpdate/GithubReleaseCkanUpdate.cs | 17 ++++- Core/Converters/JsonSingleOrArrayConverter.cs | 8 ++- .../JsonToGamesDictionaryConverter.cs | 7 +- .../DelimiterSeparatedValueExporter.cs | 16 +++-- Core/Extensions/DictionaryExtensions.cs | 2 +- Core/Extensions/EnumExtensions.cs | 2 +- Core/GameInstance.cs | 59 ++++++++------- Core/GameInstanceManager.cs | 2 +- Core/ModuleInstaller.cs | 8 +-- Core/Net/Net.cs | 31 ++++---- Core/Net/NetFileCache.cs | 4 +- Core/Net/NetModuleCache.cs | 11 ++- Core/Registry/CompatibilitySorter.cs | 4 +- Core/Registry/Registry.cs | 2 +- Core/Registry/RegistryManager.cs | 6 +- Core/Relationships/RelationshipResolver.cs | 2 +- Core/Repositories/AvailableModule.cs | 2 +- Core/Repositories/RepositoryDataManager.cs | 6 +- Core/Types/CkanModule.cs | 2 +- Core/Versioning/ModuleVersion.cs | 10 +-- GUI/Controls/ChooseRecommendedMods.cs | 15 ++-- GUI/Controls/EditModSearches.cs | 21 +++++- GUI/Controls/EditModpack.cs | 2 +- GUI/Controls/ManageMods.cs | 42 +++++++---- GUI/Controls/ModInfoTabs/Metadata.cs | 2 +- GUI/Controls/ModInfoTabs/Relationships.cs | 8 +-- GUI/Controls/UnmanagedFiles.cs | 23 ++++-- GUI/Dialogs/GameCommandLineOptionsDialog.cs | 10 ++- GUI/Dialogs/ManageGameInstancesDialog.cs | 30 +++++--- GUI/Dialogs/NewRepoDialog.cs | 5 +- GUI/Dialogs/SelectionDialog.cs | 4 +- GUI/Dialogs/SettingsDialog.cs | 72 +++++++++++-------- GUI/Main/Main.cs | 15 ++-- GUI/Model/GUIMod.cs | 11 ++- GUI/Util.cs | 3 +- Netkan/ConsoleUser.cs | 4 +- Netkan/Model/Metadata.cs | 11 +-- Netkan/Processors/Inflator.cs | 2 +- Netkan/Processors/QueueHandler.cs | 2 +- Netkan/Program.cs | 21 +++--- Netkan/Sources/Avc/JsonAvcToGameVersion.cs | 70 +++++++++--------- Netkan/Sources/Curse/CurseFile.cs | 14 ++-- Netkan/Sources/Curse/CurseMod.cs | 6 +- .../VersionedOverrideTransformer.cs | 2 +- Netkan/Validators/PluginsValidator.cs | 2 +- Tests/Core/ModuleInstallerTests.cs | 2 +- Tests/Core/Net/NetAsyncDownloaderTests.cs | 2 +- Tests/Core/Registry/RegistryManager.cs | 6 +- .../Relationships/RelationshipResolver.cs | 2 +- Tests/Core/Types/CkanModuleTests.cs | 4 +- Tests/GUI/ThreadSafetyTests.cs | 4 +- 60 files changed, 465 insertions(+), 291 deletions(-) diff --git a/AutoUpdate/CKAN-autoupdate.csproj b/AutoUpdate/CKAN-autoupdate.csproj index b0c4aaec2f..68385ade6b 100644 --- a/AutoUpdate/CKAN-autoupdate.csproj +++ b/AutoUpdate/CKAN-autoupdate.csproj @@ -33,6 +33,8 @@ + + diff --git a/AutoUpdate/Main.cs b/AutoUpdate/Main.cs index 4d384dc32f..5c888a56ce 100644 --- a/AutoUpdate/Main.cs +++ b/AutoUpdate/Main.cs @@ -28,18 +28,22 @@ public static int Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionEventHandler; - if (args.Length != 4) + if (//args is not [string pid_str, + // string local_path, + // string updated_path, + // string launch and ("launch" or "nolaunch")] + args.Length < 4 + || args[0] is not string pid_str + || args[1] is not string local_path + || args[2] is not string updated_path + || args[3] is not (string launch and ("launch" or "nolaunch"))) { - ReportError("{0}: AutoUpdater.exe pid oldPath newPath [no]launch", Properties.Resources.Usage); + ReportError("{0}: AutoUpdater.exe pid oldPath newPath [no]launch", + Properties.Resources.Usage); return ExitBADOPT; } - - // Yes, it's a global variable, but we're an ephemeral singleton so :shrug: - fromGui = (args[3] == "launch"); - - int pid = int.Parse(args[0]); - string local_path = args[1]; - string updated_path = args[2]; + int pid = int.Parse(pid_str); + fromGui = (launch == "launch"); if (!File.Exists(updated_path)) { diff --git a/Cmdline/Action/Import.cs b/Cmdline/Action/Import.cs index d676d219a6..beaa389cce 100644 --- a/Cmdline/Action/Import.cs +++ b/Cmdline/Action/Import.cs @@ -53,7 +53,7 @@ public int RunCommand(CKAN.GameInstance instance, object options) var toInstall = new List(); var installer = new ModuleInstaller(instance, manager.Cache, user); var regMgr = RegistryManager.Instance(instance, repoData); - installer.ImportFiles(toImport, user, mod => toInstall.Add(mod), regMgr.registry, !opts?.Headless ?? false); + installer.ImportFiles(toImport, user, toInstall.Add, regMgr.registry, !opts?.Headless ?? false); if (toInstall.Count > 0) { HashSet? possibleConfigOnlyDirs = null; diff --git a/Cmdline/Action/Show.cs b/Cmdline/Action/Show.cs index 4f5b7f5c8d..ea85c22d19 100644 --- a/Cmdline/Action/Show.cs +++ b/Cmdline/Action/Show.cs @@ -76,13 +76,15 @@ public int RunCommand(CKAN.GameInstance instance, object raw_options) user.RaiseMessage(""); continue; } - else if (matches.Count() == 1) + else if (//matches is [CkanModule oneMod] + matches.Count == 1 + && matches[0] is CkanModule oneMod) { // If there is only 1 match, display it. - user.RaiseMessage(Properties.Resources.ShowFoundOne, matches[0].name); + user.RaiseMessage(Properties.Resources.ShowFoundOne, oneMod.name); user.RaiseMessage(""); - moduleToShow = matches[0]; + moduleToShow = oneMod; } else { @@ -281,10 +283,14 @@ private int ShowMod(CkanModule module, ShowOptions opts) module.resources.remoteSWInfo); } - if (!opts.without_files && !module.IsDLC) + if (!opts.without_files && !module.IsDLC + //&& module.download is [Uri url, ..] + && module.download != null + && module.download.Count > 0 + && module.download[0] is Uri url) { // Compute the CKAN filename. - string file_uri_hash = NetFileCache.CreateURLHash(module.download?[0]); + string file_uri_hash = NetFileCache.CreateURLHash(url); string file_name = CkanModule.StandardName(module.identifier, module.version); user.RaiseMessage(""); @@ -313,35 +319,28 @@ private void ShowVersionTable(CKAN.GameInstance inst, List modules) var versions = modules.Select(m => m.version.ToString()).ToList(); var gameVersions = modules.Select(m => { - CkanModule.GetMinMaxVersions(new List() { m }, out _, out _, out GameVersion? minKsp, out GameVersion? maxKsp); + CkanModule.GetMinMaxVersions(new List() { m }, out _, out _, + out GameVersion? minKsp, out GameVersion? maxKsp); return GameVersionRange.VersionSpan(inst.game, minKsp ?? GameVersion.Any, maxKsp ?? GameVersion.Any); }).ToList(); - string[] headers = new string[] { - Properties.Resources.ShowVersionHeader, - Properties.Resources.ShowGameVersionsHeader - }; - int versionLength = Math.Max(headers[0].Length, versions.Max(v => v.Length)); - int gameVersionLength = Math.Max(headers[1].Length, gameVersions.Max(v => v.Length)); + int versionLength = Math.Max(Properties.Resources.ShowVersionHeader.Length, + versions.Max(v => v.Length)); + int gameVersionLength = Math.Max(Properties.Resources.ShowGameVersionsHeader.Length, + gameVersions.Max(v => v.Length)); user.RaiseMessage(""); - user.RaiseMessage( - "{0} {1}", - headers[0].PadRight(versionLength), - headers[1].PadRight(gameVersionLength) - ); - user.RaiseMessage( - "{0} {1}", - new string('-', versionLength), - new string('-', gameVersionLength) - ); + user.RaiseMessage("{0} {1}", + Properties.Resources.ShowVersionHeader.PadRight(versionLength), + Properties.Resources.ShowGameVersionsHeader.PadRight(gameVersionLength)); + user.RaiseMessage("{0} {1}", + new string('-', versionLength), + new string('-', gameVersionLength)); for (int row = 0; row < versions.Count; ++row) { - user.RaiseMessage( - "{0} {1}", - versions[row].PadRight(versionLength), - gameVersions[row].PadRight(gameVersionLength) - ); + user.RaiseMessage("{0} {1}", + versions[row].PadRight(versionLength), + gameVersions[row].PadRight(gameVersionLength)); } } diff --git a/Cmdline/Action/Upgrade.cs b/Cmdline/Action/Upgrade.cs index 1fd5b9e659..70dae0f6a7 100644 --- a/Cmdline/Action/Upgrade.cs +++ b/Cmdline/Action/Upgrade.cs @@ -55,7 +55,12 @@ public int RunCommand(CKAN.GameInstance instance, object raw_options) return Exit.BADOPT; } - if (!options.upgrade_all && options.modules?[0] == "ckan" && AutoUpdate.CanUpdate) + if (!options.upgrade_all + //&& options.modules is ["ckan"] + && options.modules != null + && options.modules.Count > 0 + && options.modules[0] is "ckan" + && AutoUpdate.CanUpdate) { if (options.dev_build && options.stable_release) { @@ -196,7 +201,7 @@ private void UpgradeModules(NetModuleCache cache, installer.Upgrade(modules, downloader, ref possibleConfigOnlyDirs, regMgr, true, true, true), - m => modules.Add(m)); + modules.Add); } /// diff --git a/Cmdline/ConsoleUser.cs b/Cmdline/ConsoleUser.cs index 8b1edc204b..8159699c70 100644 --- a/Cmdline/ConsoleUser.cs +++ b/Cmdline/ConsoleUser.cs @@ -105,7 +105,9 @@ public int RaiseSelectionDialog(string message, params object[] args) // Check if we have a default selection. int defaultSelection = -1; - if (args[0] is int v) + if (//args is [int v, ..] + args.Length > 0 + && args[0] is int v) { // Check that the default selection makes sense. defaultSelection = v; diff --git a/Cmdline/Main.cs b/Cmdline/Main.cs index 8fa3239854..3618e0b613 100644 --- a/Cmdline/Main.cs +++ b/Cmdline/Main.cs @@ -87,32 +87,35 @@ public static int Execute(GameInstanceManager? manager, CommonOptions? opts, str // It breaks command-specific help, for starters. try { - switch (args[0]) + if (args.Length > 0) { - case "repair": - return (new Repair(repoData)).RunSubCommand(manager, opts, new SubCommandOptions(args)); + switch (args[0]) + { + case "repair": + return (new Repair(repoData)).RunSubCommand(manager, opts, new SubCommandOptions(args)); - case "instance": - return (new GameInstance()).RunSubCommand(manager, opts, new SubCommandOptions(args)); + case "instance": + return (new GameInstance()).RunSubCommand(manager, opts, new SubCommandOptions(args)); - case "compat": - return (new Compat()).RunSubCommand(manager, opts, new SubCommandOptions(args)); + case "compat": + return (new Compat()).RunSubCommand(manager, opts, new SubCommandOptions(args)); - case "repo": - return (new Repo(repoData)).RunSubCommand(manager, opts, new SubCommandOptions(args)); + case "repo": + return (new Repo(repoData)).RunSubCommand(manager, opts, new SubCommandOptions(args)); - case "authtoken": - return (new AuthToken()).RunSubCommand(manager, opts, new SubCommandOptions(args)); + case "authtoken": + return (new AuthToken()).RunSubCommand(manager, opts, new SubCommandOptions(args)); - case "cache": - return (new Cache()).RunSubCommand(manager, opts, new SubCommandOptions(args)); + case "cache": + return (new Cache()).RunSubCommand(manager, opts, new SubCommandOptions(args)); - case "mark": - return (new Mark(repoData)).RunSubCommand(manager, opts, new SubCommandOptions(args)); + case "mark": + return (new Mark(repoData)).RunSubCommand(manager, opts, new SubCommandOptions(args)); - case "filter": - return (new Filter()).RunSubCommand(manager, opts, new SubCommandOptions(args)); + case "filter": + return (new Filter()).RunSubCommand(manager, opts, new SubCommandOptions(args)); + } } } catch (NoGameInstanceKraken) diff --git a/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs b/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs index 20ed445d17..80abd56276 100644 --- a/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs +++ b/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs @@ -73,7 +73,7 @@ public ConsoleFileMultiSelectDialog(ConsoleTheme theme, getRowName, compareNames, null), new ConsoleListBoxColumn( Properties.Resources.FileSelectSizeHeader, - (FileSystemInfo fi) => getLength(fi), + getLength, (a, b) => { var fb = b as FileInfo; return a is not FileInfo fa diff --git a/ConsoleUI/Toolkit/Symbols.cs b/ConsoleUI/Toolkit/Symbols.cs index 5f09159f48..31086667ce 100644 --- a/ConsoleUI/Toolkit/Symbols.cs +++ b/ConsoleUI/Toolkit/Symbols.cs @@ -145,7 +145,12 @@ private static Encoding GetCodePage(int which) /// public static readonly char leftHalfBlock = cp437c(0xdd); - private static char cp437c(byte num) => dosCodePage.GetChars(new byte[] {num})[0]; + private static char cp437c(byte num) => //dosCodePage.GetChars(new byte[] {num}) is [char val] + dosCodePage.GetChars(new byte[] {num}) is char[] chars + && chars.Length > 0 + && chars[0] is char val + ? val + : (char)0; private static string cp437s(byte num) => $"{cp437c(num)}"; } diff --git a/Core/AutoUpdate/GithubReleaseCkanUpdate.cs b/Core/AutoUpdate/GithubReleaseCkanUpdate.cs index 3da2428228..903186f25b 100644 --- a/Core/AutoUpdate/GithubReleaseCkanUpdate.cs +++ b/Core/AutoUpdate/GithubReleaseCkanUpdate.cs @@ -85,8 +85,21 @@ internal static string ExtractReleaseNotes(string releaseBody) { const string divider = "\r\n---\r\n"; // Get at most two pieces, the first is the image, the second is the release notes - string[] notesArray = releaseBody.Split(new string[] { divider }, 2, StringSplitOptions.None); - return notesArray.Length > 1 ? notesArray[1] : notesArray[0]; + //return releaseBody.Split(new string[] { divider }, + // 2, StringSplitOptions.None) switch { + // [_, string val, ..] => val, + // [string val] => val, + // _ => "", + //}; + var array = releaseBody.Split(new string[] { divider }, + 2, StringSplitOptions.None); + return array.Length > 1 + && array[1] is string val + ? val + : array.Length == 1 + && array[0] is string val2 + ? val2 + : ""; } private static readonly Uri latestCKANReleaseApiUrl = diff --git a/Core/Converters/JsonSingleOrArrayConverter.cs b/Core/Converters/JsonSingleOrArrayConverter.cs index 4b2f4a5092..49259920f1 100644 --- a/Core/Converters/JsonSingleOrArrayConverter.cs +++ b/Core/Converters/JsonSingleOrArrayConverter.cs @@ -28,8 +28,12 @@ public class JsonSingleOrArrayConverter : JsonConverter public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { - var list = value as List; - serializer.Serialize(writer, list?.Count == 1 ? list[0] : value); + serializer.Serialize(writer, //value is List and [T val] + value is List list + && list.Count == 1 + && list[0] is T val + ? val + : value); } /// diff --git a/Core/Converters/JsonToGamesDictionaryConverter.cs b/Core/Converters/JsonToGamesDictionaryConverter.cs index f63ec570d1..75711b95e7 100644 --- a/Core/Converters/JsonToGamesDictionaryConverter.cs +++ b/Core/Converters/JsonToGamesDictionaryConverter.cs @@ -57,8 +57,11 @@ public class JsonToGamesDictionaryConverter : JsonConverter { return token.ToObject(objectType); } - var valueType = objectType.GetGenericArguments()[1]; - if (Activator.CreateInstance(objectType) is IDictionary obj + if (//objectType.GetGenericArguments() is [_, var valueType, ..] + objectType.GetGenericArguments() is Type[] types + && types.Length > 0 + && types[1] is var valueType + && Activator.CreateInstance(objectType) is IDictionary obj && !IsTokenEmpty(token)) { foreach (var gameName in KnownGames.AllGameShortNames()) diff --git a/Core/Exporters/DelimiterSeparatedValueExporter.cs b/Core/Exporters/DelimiterSeparatedValueExporter.cs index 70443da735..2d9170a097 100644 --- a/Core/Exporters/DelimiterSeparatedValueExporter.cs +++ b/Core/Exporters/DelimiterSeparatedValueExporter.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; +using System.Collections.Generic; namespace CKAN.Exporters { @@ -53,7 +54,7 @@ public void Export(RegistryManager manager, IRegistryQuerier registry, Stream st QuoteIfNecessary(mod.Module.description), QuoteIfNecessary(mod.Module.author == null ? "" : string.Join(";", mod.Module.author)), QuoteIfNecessary(mod.Module.kind), - WriteUri(mod.Module.download?[0]), + WriteUri(mod.Module.download), mod.Module.download_size, mod.Module.ksp_version, mod.Module.ksp_version_min, @@ -71,9 +72,16 @@ public void Export(RegistryManager manager, IRegistryQuerier registry, Stream st } private string WriteUri(Uri? uri) - => uri != null - ? QuoteIfNecessary(uri.ToString()) - : string.Empty; + => uri != null ? QuoteIfNecessary(uri.ToString()) + : string.Empty; + + private string WriteUri(List? uris) + => WriteUri(//uris is [Uri uri, ..] + uris != null + && uris.Count > 0 + && uris[0] is Uri uri + ? uri + : null); private string WriteRepository(ResourcesDescriptor? resources) => resources != null && resources.repository != null diff --git a/Core/Extensions/DictionaryExtensions.cs b/Core/Extensions/DictionaryExtensions.cs index 53fcefd036..a6b86710c9 100644 --- a/Core/Extensions/DictionaryExtensions.cs +++ b/Core/Extensions/DictionaryExtensions.cs @@ -9,7 +9,7 @@ public static bool DictionaryEquals(this IDictionary? a, IDictionary? b) => a == null ? b == null : b != null && a.Count == b.Count - && a.Keys.All(k => b.ContainsKey(k)) + && a.Keys.All(b.ContainsKey) && b.Keys.All(k => a.ContainsKey(k) && EqualityComparer.Default.Equals(a[k], b[k])); diff --git a/Core/Extensions/EnumExtensions.cs b/Core/Extensions/EnumExtensions.cs index bd6e6bbdb7..43e09ed27c 100644 --- a/Core/Extensions/EnumExtensions.cs +++ b/Core/Extensions/EnumExtensions.cs @@ -7,7 +7,7 @@ public static class EnumExtensions { public static bool HasAnyFlag(this Enum val, params Enum[] flags) - => flags.Any(f => val.HasFlag(f)); + => flags.Any(val.HasFlag); } } diff --git a/Core/GameInstance.cs b/Core/GameInstance.cs index 7d82f20c0f..42a99a16f0 100644 --- a/Core/GameInstance.cs +++ b/Core/GameInstance.cs @@ -157,7 +157,7 @@ private void LoadCompatibleVersions() is CompatibleGameVersions compatibleGameVersions) { _compatibleVersions = compatibleGameVersions.Versions - .Select(v => GameVersion.Parse(v)) + .Select(GameVersion.Parse) .ToList(); // Get version without throwing exceptions for null @@ -380,41 +380,38 @@ public bool HasManagedFiles(Registry registry, string absPath) public void PlayGame(string command, Action? onExit = null) { - var split = (command ?? "").Split(' '); - if (split.Length == 0) + if (game.AdjustCommandLine(command.Split(' '), Version()) + //is [string binary, ..] and string[] split + is string[] split + && split.Length > 0 + && split[0] is string binary) { - return; - } - - split = game.AdjustCommandLine(split, Version()); - var binary = split[0]; - var args = string.Join(" ", split.Skip(1)); - - try - { - Directory.SetCurrentDirectory(GameDir()); - Process p = new Process() + try { - StartInfo = new ProcessStartInfo() + Directory.SetCurrentDirectory(GameDir()); + Process p = new Process() + { + StartInfo = new ProcessStartInfo() + { + FileName = binary, + Arguments = string.Join(" ", split.Skip(1)) + }, + EnableRaisingEvents = true + }; + + p.Exited += (sender, e) => { - FileName = binary, - Arguments = args - }, - EnableRaisingEvents = true - }; + playTime?.Stop(CkanDir()); + onExit?.Invoke(); + }; - p.Exited += (sender, e) => + p.Start(); + playTime?.Start(); + } + catch (Exception exception) { - playTime?.Stop(CkanDir()); - onExit?.Invoke(); - }; - - p.Start(); - playTime?.Start(); - } - catch (Exception exception) - { - User.RaiseError(Properties.Resources.GameInstancePlayGameFailed, exception.Message); + User.RaiseError(Properties.Resources.GameInstancePlayGameFailed, exception.Message); + } } } diff --git a/Core/GameInstanceManager.cs b/Core/GameInstanceManager.cs index 12a5326dba..53d0fac8f5 100644 --- a/Core/GameInstanceManager.cs +++ b/Core/GameInstanceManager.cs @@ -544,7 +544,7 @@ private void LoadInstances() try { var game = KnownGames.knownGames.FirstOrDefault(g => g.ShortName == gameName) - ?? KnownGames.knownGames[0]; + ?? KnownGames.knownGames.First(); log.DebugFormat("Loading {0} from {1}", name, path); // Add unconditionally, sort out invalid instances downstream instances.Add(name, new GameInstance(game, path, name, User)); diff --git a/Core/ModuleInstaller.cs b/Core/ModuleInstaller.cs index 1fad9768fd..79dd52d696 100644 --- a/Core/ModuleInstaller.cs +++ b/Core/ModuleInstaller.cs @@ -341,7 +341,7 @@ private List InstallModule(CkanModule module, var dllFolders = files .Select(f => instance.ToRelativeGameDir(f.destination)) .Where(relPath => instance.DllPathToIdentifier(relPath) == module.identifier) - .Select(relPath => Path.GetDirectoryName(relPath)) + .Select(Path.GetDirectoryName) .ToHashSet(); // Make sure that the DLL is actually included in the install // (NearFutureElectrical, NearFutureElectrical-Core) @@ -715,7 +715,7 @@ public void UninstallList(IEnumerable mods, } var instDlc = mods - .Select(ident => registry_manager.registry.InstalledModule(ident)) + .Select(registry_manager.registry.InstalledModule) .OfType() .FirstOrDefault(m => m.Module.IsDLC); if (instDlc != null) @@ -750,7 +750,7 @@ public void UninstallList(IEnumerable mods, User.RaiseMessage(Properties.Resources.ModuleInstallerAboutToRemove); User.RaiseMessage(""); - foreach (var module in goners.Select(m => registry_manager.registry.InstalledModule(m)) + foreach (var module in goners.Select(registry_manager.registry.InstalledModule) .OfType()) { User.RaiseMessage(" * {0} {1}", module.Module.name, module.Module.version); @@ -901,7 +901,7 @@ private void Uninstall(string identifier, (Directory.Exists(directory) ? Directory.EnumerateFileSystemEntries(directory, "*", SearchOption.AllDirectories) : Enumerable.Empty()) - .Select(f => instance.ToRelativeGameDir(f)) + .Select(instance.ToRelativeGameDir) .ToArray(), out string[] removable, out string[] notRemovable); diff --git a/Core/Net/Net.cs b/Core/Net/Net.cs index a429ff666a..926ccbaf92 100644 --- a/Core/Net/Net.cs +++ b/Core/Net/Net.cs @@ -312,34 +312,35 @@ public static Uri GetRawUri(Uri remoteUri) // // And that the fourth segment (index 3) is either "blob/" or "tree/" - var remoteUriBuilder = new UriBuilder(remoteUri) - { - // Replace host with raw host - Host = "raw.githubusercontent.com" - }; - // Check that the path is what we expect var segments = remoteUri.Segments.ToList(); - if (segments.Count >= 4 - && string.Compare(segments[3], "raw/", StringComparison.OrdinalIgnoreCase) == 0) + if (//segments is [_, _, _, "raw/", ..] + segments.Count > 3 + && segments[3] is "raw/") { log.InfoFormat("Remote GitHub URL is in raw format, using as is."); return remoteUri; } - if (segments.Count < 6 - || (string.Compare(segments[3], "blob/", StringComparison.OrdinalIgnoreCase) != 0 - && string.Compare(segments[3], "tree/", StringComparison.OrdinalIgnoreCase) != 0)) + if (//segments is not [_, _, _, "blob/" or "tree/", _, _, ..] + segments.Count < 6 + || segments[3] is not ("blob/" or "tree/")) { log.WarnFormat("Remote non-raw GitHub URL is in an unknown format, using as is."); return remoteUri; } - // Remove "blob/" or "tree/" segment from raw URI - segments.RemoveAt(3); - remoteUriBuilder.Path = string.Join("", segments); + var remoteUriBuilder = new UriBuilder(remoteUri) + { + // Replace host with raw host + Host = "raw.githubusercontent.com", + // Remove "blob/" or "tree/" segment from raw URI + Path = string.Join("", segments.Take(3) + .Concat(segments.Skip(4))), + }; - log.InfoFormat("Canonicalized non-raw GitHub URL to: {0}", remoteUriBuilder.Uri); + log.InfoFormat("Canonicalized non-raw GitHub URL to: {0}", + remoteUriBuilder.Uri); return remoteUriBuilder.Uri; } diff --git a/Core/Net/NetFileCache.cs b/Core/Net/NetFileCache.cs index f7660d8f27..bd6ebc10ef 100644 --- a/Core/Net/NetFileCache.cs +++ b/Core/Net/NetFileCache.cs @@ -124,7 +124,7 @@ public string GetInProgressFileName(Uri url, string description) { var filenames = urls?.Select(url => GetInProgressFileName(CreateURLHash(url), description)) .ToArray(); - return filenames?.FirstOrDefault(filename => File.Exists(filename)) + return filenames?.FirstOrDefault(File.Exists) ?? filenames?.FirstOrDefault(); } @@ -287,7 +287,7 @@ private HashSet legacyDirs() => manager?.Instances.Values .Where(ksp => ksp.Valid) .Select(ksp => ksp.DownloadCacheDir()) - .Where(dir => Directory.Exists(dir)) + .Where(Directory.Exists) .ToHashSet() ?? new HashSet(); diff --git a/Core/Net/NetModuleCache.cs b/Core/Net/NetModuleCache.cs index 375990015d..1cbfc4e953 100644 --- a/Core/Net/NetModuleCache.cs +++ b/Core/Net/NetModuleCache.cs @@ -60,7 +60,7 @@ public void MoveFrom(string fromDir) cache.MoveFrom(fromDir); } public bool IsCached(CkanModule m) - => m.download?.Any(dlUri => cache.IsCached(dlUri)) + => m.download?.Any(cache.IsCached) ?? false; public bool IsCached(CkanModule m, out string? outFilename) { @@ -231,7 +231,14 @@ public string Store(CkanModule module, cancelToken?.ThrowIfCancellationRequested(); } // If no exceptions, then everything is fine - var success = cache.Store(module.download?[0]!, path, description ?? module.StandardName(), move); + var success = //module.download is [Uri url, ..] + module.download != null + && module.download.Count > 0 + && module.download[0] is Uri url + ? cache.Store(url, path, + description ?? module.StandardName(), + move) + : ""; // Make sure completion is signalled so progress bars go away progress?.Report(100); ModStored?.Invoke(module); diff --git a/Core/Registry/CompatibilitySorter.cs b/Core/Registry/CompatibilitySorter.cs index 3433cb2ccc..84a15dac6c 100644 --- a/Core/Registry/CompatibilitySorter.cs +++ b/Core/Registry/CompatibilitySorter.cs @@ -140,7 +140,7 @@ private Dictionary> CompatibleProviders( .GroupBy(kvp => kvp.Key, kvp => kvp.Value) .ToDictionary(grp => grp.Key, - grp => AvailableModule.Merge(grp)) + AvailableModule.Merge) // Group into trivially [in]compatible (false/true) and indeterminate (null) .AsParallel() .GroupBy(kvp => kvp.Value.AllAvailable() @@ -196,7 +196,7 @@ private void CheckDepends(string identifie // For each of those identifiers, if it is provided by at least one module, get all the modules // that provide it (and make sure each is only once in the list) var candidates = RelationshipIdentifiers(rel) - .Where(ident => providers.ContainsKey(ident)) + .Where(providers.ContainsKey) .SelectMany(ident => providers[ident]) .Distinct(); diff --git a/Core/Registry/Registry.cs b/Core/Registry/Registry.cs index 89c7595d8e..d7c2df19e9 100644 --- a/Core/Registry/Registry.cs +++ b/Core/Registry/Registry.cs @@ -874,7 +874,7 @@ public void RegisterModule(CkanModule mod, var inconsistencies = new List(); // We always work with relative files, so let's get some! - var relativeFiles = absoluteFiles.Select(x => inst.ToRelativeGameDir(x)) + var relativeFiles = absoluteFiles.Select(inst.ToRelativeGameDir) .ToHashSet(Platform.PathComparer); // For now, it's always cool if a module wants to register a directory. diff --git a/Core/Registry/RegistryManager.cs b/Core/Registry/RegistryManager.cs index 0cd0f02ea9..c0a694e5c6 100644 --- a/Core/Registry/RegistryManager.cs +++ b/Core/Registry/RegistryManager.cs @@ -562,8 +562,8 @@ public bool ScanUnmanagedFiles() { var dlls = Enumerable.Repeat(gameInstance.game.PrimaryModDirectoryRelative, 1) .Concat(gameInstance.game.AlternateModDirectoriesRelative) - .Select(relDir => gameInstance.ToAbsoluteGameDir(relDir)) - .Where(absDir => Directory.Exists(absDir)) + .Select(gameInstance.ToAbsoluteGameDir) + .Where(Directory.Exists) // EnumerateFiles is *case-sensitive* in its pattern, which causes // DLL files to be missed under Linux; we have to pick .dll, .DLL, or scanning // GameData *twice*. @@ -572,7 +572,7 @@ public bool ScanUnmanagedFiles() .SelectMany(absDir => Directory.EnumerateFiles(absDir, "*", SearchOption.AllDirectories)) .Where(file => file.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase)) - .Select(absPath => gameInstance.ToRelativeGameDir(absPath)) + .Select(gameInstance.ToRelativeGameDir) .Where(relPath => !gameInstance.game.StockFolders.Any(f => relPath.StartsWith($"{f}/"))) .GroupBy(relPath => gameInstance.DllPathToIdentifier(relPath) ?? "") .ToDictionary(grp => grp.Key, diff --git a/Core/Relationships/RelationshipResolver.cs b/Core/Relationships/RelationshipResolver.cs index 3bcc6bfa41..287aaee759 100644 --- a/Core/Relationships/RelationshipResolver.cs +++ b/Core/Relationships/RelationshipResolver.cs @@ -369,7 +369,7 @@ private void ResolveStanza(List? stanza, } } - CkanModule candidate = candidates[0]; + CkanModule candidate = candidates.First(); // Finally, check our candidate against everything which might object // to it being installed; that's all the mods which are fixed in our diff --git a/Core/Repositories/AvailableModule.cs b/Core/Repositories/AvailableModule.cs index 139fdd4dfe..25e466d57c 100644 --- a/Core/Repositories/AvailableModule.cs +++ b/Core/Repositories/AvailableModule.cs @@ -211,7 +211,7 @@ public GameVersion LatestCompatibleGameVersion(List realVersions) .Aggregate((best, r) => r.Upper == GameVersionBound.Highest(best.Upper, r.Upper) ? r : best); - return realVersions?.LastOrDefault(v => bestRange.Contains(v)) + return realVersions?.LastOrDefault(bestRange.Contains) // This is needed for when we have no real versions loaded, such as tests ?? module_version.Values.Select(m => m.LatestCompatibleGameVersion()) .Max() diff --git a/Core/Repositories/RepositoryDataManager.cs b/Core/Repositories/RepositoryDataManager.cs index dc33aeb7f7..d6798bde57 100644 --- a/Core/Repositories/RepositoryDataManager.cs +++ b/Core/Repositories/RepositoryDataManager.cs @@ -110,8 +110,8 @@ public void Prepopulate(List repos, IProgress? percentProgress) } public TimeSpan LastUpdate(IEnumerable repos) - => repos.Distinct().Where(r => repoDataStale(r)) - .Select(r => RepoUpdateTimestamp(r)) + => repos.Distinct().Where(repoDataStale) + .Select(RepoUpdateTimestamp) .OfType() .Select(dt => DateTime.Now - dt) .DefaultIfEmpty(TimeSpan.Zero) @@ -327,7 +327,7 @@ private bool repoDataStale(Repository r) private IEnumerable GetRepoDatas(IEnumerable? repos) => repos?.OrderBy(repo => repo.priority) .ThenBy(repo => repo.name) - .Select(repo => GetRepoData(repo)) + .Select(GetRepoData) .OfType() ?? Enumerable.Empty(); diff --git a/Core/Types/CkanModule.cs b/Core/Types/CkanModule.cs index 73aee6e356..3292d8d021 100644 --- a/Core/Types/CkanModule.cs +++ b/Core/Types/CkanModule.cs @@ -533,7 +533,7 @@ public GameVersion LatestCompatibleRealGameVersion(List realVers) private GameVersion LatestCompatibleRealGameVersion(GameVersionRange range, List realVers) - => (realVers?.LastOrDefault(v => range.Contains(v)) + => (realVers?.LastOrDefault(range.Contains) ?? LatestCompatibleGameVersion()); public bool IsMetapackage => kind == "metapackage"; diff --git a/Core/Versioning/ModuleVersion.cs b/Core/Versioning/ModuleVersion.cs index 13a3cfb4c7..1e5ea0bbe3 100644 --- a/Core/Versioning/ModuleVersion.cs +++ b/Core/Versioning/ModuleVersion.cs @@ -230,17 +230,19 @@ Comparison stringComp(string v1, string v2) // Then compare the two strings, and return our comparison state. // Override sorting of '.' to higher than other characters. - if (str1.Length > 0 && str2.Length > 0) + if (//str1 is [char first1, ..] && str2 is [char first2, ..] + str1.Length > 0 && str1[0] is var first1 + && str2.Length > 0 && str2[0] is var first2) { - if (str1[0] != '.' && str2[0] == '.') + if (first1 != '.' && first2 == '.') { comparison.CompareTo = -1; } - else if (str1[0] == '.' && str2[0] != '.') + else if (first1 == '.' && first2 != '.') { comparison.CompareTo = 1; } - else if (str1[0] == '.' && str2[0] == '.') + else if (first1 == '.' && first2 == '.') { if (str1.Length == 1 && str2.Length > 1) { diff --git a/GUI/Controls/ChooseRecommendedMods.cs b/GUI/Controls/ChooseRecommendedMods.cs index cdc609690d..aa270bd595 100644 --- a/GUI/Controls/ChooseRecommendedMods.cs +++ b/GUI/Controls/ChooseRecommendedMods.cs @@ -69,7 +69,7 @@ public void LoadRecommendations(IRegistryQuerier registry, if (Platform.IsMono) { // Workaround: make sure the ListView headers are drawn - Util.Invoke(this, () => RecommendedModsListView.EndUpdate()); + Util.Invoke(this, RecommendedModsListView.EndUpdate); } task = new TaskCompletionSource?>(); return task.Task.Result; @@ -190,19 +190,26 @@ private IEnumerable getRecSugRows( && kvp.Value.Item1 && !uncheckLabels.Any(mlbl => mlbl.ContainsModule(game, kvp.Key.identifier)))) - .OrderBy(item => item.SubItems[1].Text) + .OrderBy(SecondColumn) .Concat(suggestions.Select(kvp => getRecSugItem(cache, kvp.Key, string.Join(", ", kvp.Value), SuggestionsGroup, false)) - .OrderBy(item => item.SubItems[1].Text)) + .OrderBy(SecondColumn)) .Concat(supporters.Select(kvp => getRecSugItem(cache, kvp.Key, string.Join(", ", kvp.Value.OrderBy(s => s)), SupportedByGroup, false)) - .OrderBy(item => item.SubItems[1].Text)); + .OrderBy(SecondColumn)); + + private string SecondColumn(ListViewItem item) + => //item.SubItems is [_, {Text: string text}, ..] + item.SubItems.Count > 1 + && item.SubItems[0].Text is string text + ? text + : ""; private ListViewItem getRecSugItem(NetModuleCache cache, CkanModule module, diff --git a/GUI/Controls/EditModSearches.cs b/GUI/Controls/EditModSearches.cs index 9c70959855..1a9a03fa3d 100644 --- a/GUI/Controls/EditModSearches.cs +++ b/GUI/Controls/EditModSearches.cs @@ -34,7 +34,12 @@ public void Clear() { RemoveSearch(editors[i]); } - editors[0].Clear(); + if (//editors is [var editor] + editors.Count == 1 + && editors[0] is var editor) + { + editor.Clear(); + } } public void ExpandCollapse() @@ -66,7 +71,12 @@ public void SetSearches(List searches) } if (searches.Count < 1) { - editors[0].Clear(); + if (//editors is [var editor] + editors.Count == 1 + && editors[0] is var editor) + { + editor.Clear(); + } } else { @@ -149,7 +159,12 @@ private void RemoveSearch(EditModSearch which) editors.Remove(which); Controls.Remove(which); // Make sure the top label is always visible - editors[0].ShowLabel = true; + if (//editors is [var editor, ..] + editors.Count > 0 + && editors[0] is var editor) + { + editor.ShowLabel = true; + } AddSearchButton.Top = editors[^1].Top; diff --git a/GUI/Controls/EditModpack.cs b/GUI/Controls/EditModpack.cs index fece3177c1..4b4388ec3b 100644 --- a/GUI/Controls/EditModpack.cs +++ b/GUI/Controls/EditModpack.cs @@ -81,7 +81,7 @@ public bool Wait(IUser user) if (Platform.IsMono) { // Workaround: make sure the ListView headers are drawn - Util.Invoke(this, () => RelationshipsListView.EndUpdate()); + Util.Invoke(this, RelationshipsListView.EndUpdate); } this.user = user; task = new TaskCompletionSource(); diff --git a/GUI/Controls/ManageMods.cs b/GUI/Controls/ManageMods.cs index 7b6481ba85..f263823bfa 100644 --- a/GUI/Controls/ManageMods.cs +++ b/GUI/Controls/ManageMods.cs @@ -526,7 +526,7 @@ private void setInstalledColumnsVisible(bool visible) if (guiConfig != null) { var hiddenColumnNames = guiConfig.HiddenColumnNames; - foreach (var colName in installedColumnNames.Where(nm => ModGrid.Columns.Contains(nm))) + foreach (var colName in installedColumnNames.Where(ModGrid.Columns.Contains)) { ModGrid.Columns[colName].Visible = visible && !hiddenColumnNames.Contains(colName); } @@ -561,9 +561,11 @@ public void MarkAllUpdates() AddSort(UpdateCol, true); UpdateFilters(); // Select the top row and scroll the list to it. - if (ModGrid.Rows.Count > 0) + if (//ModGrid.Rows is [DataGridViewRow row, ..] + ModGrid.Rows.Count > 0 + && ModGrid.Rows[0] is DataGridViewRow row) { - ModGrid.CurrentCell = ModGrid.Rows[0].Cells[SelectableColumnIndex()]; + ModGrid.CurrentCell = row.Cells[SelectableColumnIndex()]; } } }); @@ -773,9 +775,12 @@ private void ModGrid_KeyDown(object? sender, KeyEventArgs? e) { case Keys.Home: // First row. - if (ModGrid.Rows.Count > 0) //Handles for empty filters + // Handles for empty filters + if (//ModGrid.Rows is [DataGridViewRow top, ..] + ModGrid.Rows.Count > 0 + && ModGrid.Rows[0] is DataGridViewRow top) { - ModGrid.CurrentCell = ModGrid.Rows[0].Cells[SelectableColumnIndex()]; + ModGrid.CurrentCell = top.Cells[SelectableColumnIndex()]; } e.Handled = true; @@ -783,9 +788,12 @@ private void ModGrid_KeyDown(object? sender, KeyEventArgs? e) case Keys.End: // Last row. - if (ModGrid.Rows.Count > 0) //Handles for empty filters + // Handles for empty filters + if (//ModGrid.Rows is [.., DataGridViewRow bottom] + ModGrid.Rows.Count > 0 + && ModGrid.Rows[^1] is DataGridViewRow bottom) { - ModGrid.CurrentCell = ModGrid.Rows[^1].Cells[SelectableColumnIndex()]; + ModGrid.CurrentCell = bottom.Cells[SelectableColumnIndex()]; } e.Handled = true; @@ -873,20 +881,21 @@ private void ModGrid_CellMouseDoubleClick(object? sender, DataGridViewCellMouseE { return; } - if (e.RowIndex < 0) { return; } DataGridViewRow row = ModGrid.Rows[e.RowIndex]; - if (row.Cells[0] is not DataGridViewCheckBoxCell) + if (//row.Cells is not [DataGridViewCheckBoxCell cell, ..] + row.Cells.Count < 1 + || row.Cells[0] is not DataGridViewCheckBoxCell cell) { return; } // Need to change the state here, because the user hasn't clicked on a checkbox. - row.Cells[0].Value = !(bool)row.Cells[0].Value; + cell.Value = !(bool)cell.Value; ModGrid.CommitEdit(DataGridViewDataErrorContexts.Commit); } @@ -1552,7 +1561,10 @@ private void ModGrid_CurrentCellDirtyStateChanged(object? sender, EventArgs? e) private void SetSort(DataGridViewColumn col) { - if (SortColumns.Count == 1 && SortColumns[0] == col.Name) + if (//SortColumns is [string colName] + SortColumns.Count == 1 + && SortColumns[0] is string colName + && colName == col.Name) { descending[0] = !descending[0]; } @@ -1762,9 +1774,11 @@ public void ResetFilterAndSelectModOnList(CkanModule module) } public GUIMod? SelectedModule => - ModGrid.SelectedRows.Count == 0 - ? null - : ModGrid.SelectedRows[0]?.Tag as GUIMod; + //ModGrid.SelectedRows is [{Tag: GUIMod gmod}, ..] + ModGrid.SelectedRows.Count > 0 + && ModGrid.SelectedRows[0] is {Tag: GUIMod gmod} + ? gmod + : null; public void CloseSearch(Point screenCoords) { diff --git a/GUI/Controls/ModInfoTabs/Metadata.cs b/GUI/Controls/ModInfoTabs/Metadata.cs index 2d42b93c17..dd8079fe22 100644 --- a/GUI/Controls/ModInfoTabs/Metadata.cs +++ b/GUI/Controls/ModInfoTabs/Metadata.cs @@ -100,7 +100,7 @@ private void UpdateAuthorLinks(List authors) AuthorsPanel.SuspendLayout(); AuthorsPanel.Controls.Clear(); AuthorsPanel.Controls.AddRange( - authors.Select(a => AuthorLink(a)).ToArray()); + authors.Select(AuthorLink).ToArray()); AuthorsPanel.ResumeLayout(); } diff --git a/GUI/Controls/ModInfoTabs/Relationships.cs b/GUI/Controls/ModInfoTabs/Relationships.cs index f6d45d9082..21c36cc2a5 100644 --- a/GUI/Controls/ModInfoTabs/Relationships.cs +++ b/GUI/Controls/ModInfoTabs/Relationships.cs @@ -273,7 +273,7 @@ private static IEnumerable GetModRelationships(CkanModul } private IEnumerable ForwardRelationships(IRegistryQuerier registry, CkanModule module, GameVersionCriteria crit) - => (module.provides?.Select(p => providedNode(p)) + => (module.provides?.Select(providedNode) ?? Enumerable.Empty()) .Concat(kindsOfRelationships.SelectMany(relationship => GetModRelationships(module, relationship).Select(dependency => @@ -328,12 +328,12 @@ private IEnumerable ForwardRelationships(IRegistryQuerier registry, Ck // Nothing found, don't return a node return null; } - else if (childNodes.Count == 1 - && childNodes[0].Tag is CkanModule module + else if (//childNodes is [var node and {Tag: CkanModule module}] + childNodes[0] is var node and {Tag: CkanModule module} && relDescr.ContainsAny(new string[] { module.identifier })) { // Only one exact match module, return a simple node - return childNodes[0]; + return node; } else { diff --git a/GUI/Controls/UnmanagedFiles.cs b/GUI/Controls/UnmanagedFiles.cs index 624c918ad1..c618117823 100644 --- a/GUI/Controls/UnmanagedFiles.cs +++ b/GUI/Controls/UnmanagedFiles.cs @@ -132,7 +132,12 @@ private void ExpandAllButton_Click(object? sender, EventArgs? e) { GameFolderTree.BeginUpdate(); GameFolderTree.ExpandAll(); - GameFolderTree.Nodes[0].EnsureVisible(); + if (//GameFolderTree.Nodes is [TreeNode top, ..] + GameFolderTree.Nodes.Count > 0 + && GameFolderTree.Nodes[0] is TreeNode top) + { + top.EnsureVisible(); + } GameFolderTree.EndUpdate(); GameFolderTree.Focus(); } @@ -141,20 +146,28 @@ private void CollapseAllButton_Click(object? sender, EventArgs? e) { GameFolderTree.BeginUpdate(); GameFolderTree.CollapseAll(); - GameFolderTree.Nodes[0].Expand(); + if (//GameFolderTree.Nodes is [TreeNode top, ..] + GameFolderTree.Nodes.Count > 0 + && GameFolderTree.Nodes[0] is TreeNode top) + { + top.Expand(); + } GameFolderTree.EndUpdate(); GameFolderTree.Focus(); } private void ResetCollapseButton_Click(object? sender, EventArgs? e) { - if (inst != null) + if (inst != null + //&& GameFolderTree.Nodes is [TreeNode top, ..] + && GameFolderTree.Nodes.Count > 0 + && GameFolderTree.Nodes[0] is TreeNode top) { GameFolderTree.BeginUpdate(); GameFolderTree.CollapseAll(); - GameFolderTree.Nodes[0].Expand(); + top.Expand(); ExpandDefaultModDir(inst.game); - GameFolderTree.Nodes[0].EnsureVisible(); + top.EnsureVisible(); GameFolderTree.EndUpdate(); GameFolderTree.Focus(); } diff --git a/GUI/Dialogs/GameCommandLineOptionsDialog.cs b/GUI/Dialogs/GameCommandLineOptionsDialog.cs index 364f2bb514..5f0d003612 100644 --- a/GUI/Dialogs/GameCommandLineOptionsDialog.cs +++ b/GUI/Dialogs/GameCommandLineOptionsDialog.cs @@ -89,7 +89,15 @@ private void ResetToDefaultsButton_Click(object? sender, EventArgs? e) private void AddButton_Click(object? sender, EventArgs? e) { (CmdLineGrid.DataSource as BindingList)?.AddNew(); - CmdLineGrid.CurrentCell = CmdLineGrid.Rows[CmdLineGrid.RowCount - 1].Cells[0]; + if (//CmdLineGrid.Rows is [.., var last] + //&& last.Cells is [var first, ..] + CmdLineGrid.Rows.Count > 0 + && CmdLineGrid.Rows[^1] is DataGridViewRow last + && last.Cells.Count > 0 + && last.Cells[0] is var first) + { + CmdLineGrid.CurrentCell = first; + } CmdLineGrid.BeginEdit(false); } diff --git a/GUI/Dialogs/ManageGameInstancesDialog.cs b/GUI/Dialogs/ManageGameInstancesDialog.cs index bea3c8aca1..f99f969e0d 100644 --- a/GUI/Dialogs/ManageGameInstancesDialog.cs +++ b/GUI/Dialogs/ManageGameInstancesDialog.cs @@ -202,7 +202,9 @@ private void ImportFromSteamMenuItem_Click(object? sender, EventArgs? e) private void CloneGameInstanceMenuItem_Click(object? sender, EventArgs? e) { - if (GameInstancesListView.SelectedItems[0].Tag is string instName) + if (//GameInstancesListView.SelectedItems is [{Tag: string instName}, ..] + GameInstancesListView.SelectedItems.Count > 0 + && GameInstancesListView.SelectedItems[0] is {Tag: string instName}) { var old_instance = manager.CurrentInstance; @@ -229,8 +231,9 @@ private void UseSelectedInstance() return; } - var selected = GameInstancesListView.SelectedItems[0]; - if (selected?.Tag is string instName) + if (//GameInstancesListView.SelectedItems is [{Tag: string instName}, ..] + GameInstancesListView.SelectedItems.Count > 0 + && GameInstancesListView.SelectedItems[0] is {Tag: string instName}) { try { @@ -254,8 +257,9 @@ private void SetAsDefaultCheckbox_Click(object? sender, EventArgs? e) return; } - var selected = GameInstancesListView.SelectedItems[0]; - if (selected?.Tag is string instName) + if (//GameInstancesListView.SelectedItems is [{Tag: string instName}, ..] + GameInstancesListView.SelectedItems.Count > 0 + && GameInstancesListView.SelectedItems[0] is {Tag: string instName}) { try { @@ -271,7 +275,9 @@ private void SetAsDefaultCheckbox_Click(object? sender, EventArgs? e) private void GameInstancesListView_SelectedIndexChanged(object? sender, EventArgs? e) { - if (GameInstancesListView.SelectedItems[0].Tag is string instName) + if (//GameInstancesListView.SelectedItems is [{Tag: string instName}, ..] + GameInstancesListView.SelectedItems.Count > 0 + && GameInstancesListView.SelectedItems[0] is {Tag: string instName}) { UpdateButtonState(); @@ -313,7 +319,9 @@ private void GameInstancesListView_KeyDown(object? sender, KeyEventArgs? e) private void OpenDirectoryMenuItem_Click(object? sender, EventArgs? e) { - if (GameInstancesListView.SelectedItems[0].Tag is string instName) + if (//GameInstancesListView.SelectedItems is [{Tag: string instName}, ..] + GameInstancesListView.SelectedItems.Count > 0 + && GameInstancesListView.SelectedItems[0] is {Tag: string instName}) { string path = manager.Instances[instName].GameDir(); @@ -329,7 +337,9 @@ private void OpenDirectoryMenuItem_Click(object? sender, EventArgs? e) private void RenameButton_Click(object? sender, EventArgs? e) { - if (GameInstancesListView.SelectedItems[0].Tag is string instName) + if (//GameInstancesListView.SelectedItems is [{Tag: string instName}, ..] + GameInstancesListView.SelectedItems.Count > 0 + && GameInstancesListView.SelectedItems[0] is {Tag: string instName}) { // show the dialog, and only continue if the user selected "OK" var renameInstanceDialog = new RenameInstanceDialog(); @@ -363,7 +373,9 @@ private void UpdateButtonState() = CloneGameInstanceMenuItem.Enabled = HasSelections; ForgetButton.Enabled = HasSelections - && GameInstancesListView.SelectedItems[0].Tag is string instName + //&& GameInstancesListView.SelectedItems is [{Tag: string instName}, ..] + && GameInstancesListView.SelectedItems.Count > 0 + && GameInstancesListView.SelectedItems[0] is {Tag: string instName} && instName != manager.CurrentInstance?.Name; ImportFromSteamMenuItem.Enabled = manager.SteamLibrary.Games.Length > 0; } diff --git a/GUI/Dialogs/NewRepoDialog.cs b/GUI/Dialogs/NewRepoDialog.cs index 78e54626e2..f3cd3ee5c6 100644 --- a/GUI/Dialogs/NewRepoDialog.cs +++ b/GUI/Dialogs/NewRepoDialog.cs @@ -36,8 +36,9 @@ private void NewRepoDialog_Load(object? sender, EventArgs? e) private void ReposListBox_SelectedIndexChanged(object? sender, EventArgs? e) { - if (ReposListBox.SelectedItems.Count > 0 - && ReposListBox.SelectedItems[0].Tag is Repository r) + if (//ReposListBox.SelectedItems is [{Tag: Repository r}, ..] + ReposListBox.SelectedItems.Count > 0 + && ReposListBox.SelectedItems[0] is {Tag: Repository r}) { RepoNameTextBox.Text = r.name; RepoUrlTextBox.Text = r.uri.ToString(); diff --git a/GUI/Dialogs/SelectionDialog.cs b/GUI/Dialogs/SelectionDialog.cs index 62105f23a9..8e24487215 100644 --- a/GUI/Dialogs/SelectionDialog.cs +++ b/GUI/Dialogs/SelectionDialog.cs @@ -50,7 +50,9 @@ public int ShowSelectionDialog (string message, params object[] args) Util.Invoke(OptionsList, OptionsList.Items.Clear); // Check if we have a default option. - if (args[0] is int v) + if (//args is [int v, ..] + args.Length > 0 + && args[0] is int v) { // Check that the default selection makes sense. defaultSelection = v; diff --git a/GUI/Dialogs/SettingsDialog.cs b/GUI/Dialogs/SettingsDialog.cs index 07f5deeeee..57df389c9e 100644 --- a/GUI/Dialogs/SettingsDialog.cs +++ b/GUI/Dialogs/SettingsDialog.cs @@ -338,19 +338,26 @@ private void EnableDisableRepoButtons() // re-added automatically at load, so empty repos isn't a valid state. // To remove the last one, add its replacement first. && ReposListBox.Items.Count > 1; - UpRepoButton.Enabled = ReposListBox.SelectedIndices.Count > 0 - && ReposListBox.SelectedIndices[0] > 0 - && ReposListBox.SelectedIndices[0] < ReposListBox.Items.Count; - DownRepoButton.Enabled = ReposListBox.SelectedIndices.Count > 0 - && ReposListBox.SelectedIndices[0] < ReposListBox.Items.Count - 1 - && ReposListBox.SelectedIndices[0] >= 0; + UpRepoButton.Enabled = + //ReposListBox.SelectedIndices is [int i and > 0, ..] + ReposListBox.SelectedIndices.Count > 0 + && ReposListBox.SelectedIndices[0] is int i + && i > 0 + && i < ReposListBox.Items.Count; + DownRepoButton.Enabled = + //ReposListBox.SelectedIndices is [int j and >= 0, ..] + ReposListBox.SelectedIndices.Count > 0 + && ReposListBox.SelectedIndices[0] is int j + && j > 0 + && j < ReposListBox.Items.Count - 1; } private void DeleteRepoButton_Click(object? sender, EventArgs? e) { YesNoDialog deleteConfirmationDialog = new YesNoDialog(); - if (ReposListBox.SelectedItems.Count > 0 - && ReposListBox.SelectedItems[0].Tag is Repository repo + if (//ReposListBox.SelectedItems is [{Tag: Repository repo}, ..] + ReposListBox.SelectedItems.Count > 0 + && ReposListBox.SelectedItems[0] is {Tag: Repository repo} && deleteConfirmationDialog.ShowYesNoDialog(this, string.Format(Properties.Resources.SettingsDialogRepoDeleteConfirm, repo.name), @@ -401,9 +408,12 @@ private void NewRepoButton_Click(object? sender, EventArgs? e) private void UpRepoButton_Click(object? sender, EventArgs? e) { - if (ReposListBox.SelectedIndices.Count > 0 - && ReposListBox.SelectedIndices[0] != 0 - && ReposListBox.SelectedItems[0].Tag is Repository selected) + if (//ReposListBox.SelectedIndices is [> 0, ..] + ReposListBox.SelectedIndices.Count > 0 + && ReposListBox.SelectedIndices[0] > 0 + //&& ReposListBox.SelectedItems is [{Tag: Repository selected}, ..] + && ReposListBox.SelectedItems.Count > 0 + && ReposListBox.SelectedItems[0] is {Tag: Repository selected}) { var prev = ReposListBox.Items.OfType() .Select(item => item.Tag as Repository) @@ -421,14 +431,18 @@ private void UpRepoButton_Click(object? sender, EventArgs? e) private void DownRepoButton_Click(object? sender, EventArgs? e) { - if (ReposListBox.SelectedIndices.Count > 0 - && ReposListBox.SelectedIndices[0] != ReposListBox.Items.Count - 1 - && ReposListBox.SelectedItems[0].Tag is Repository selected) + if (//ReposListBox.SelectedIndices is [int i, ..] + ReposListBox.SelectedIndices.Count > 0 + && ReposListBox.SelectedIndices[0] is int i + && i < ReposListBox.Items.Count - 1 + //&& ReposListBox.SelectedItems is [{Tag: Repository selected}] + && ReposListBox.SelectedItems.Count > 0 + && ReposListBox.SelectedItems[0] is {Tag: Repository selected}) { - var next = ReposListBox.Items.Cast() - .Select(item => item.Tag as Repository) - .OfType() - .FirstOrDefault(r => r.priority == selected.priority + 1); + var next = ReposListBox.Items.Cast() + .Select(item => item.Tag as Repository) + .OfType() + .FirstOrDefault(r => r.priority == selected.priority + 1); ++selected.priority; RepositoryMoved = true; if (next != null) @@ -573,16 +587,18 @@ private bool validNewAuthToken(string host, string token) private void DeleteAuthTokenButton_Click(object? sender, EventArgs? e) { - if (AuthTokensListBox.SelectedItems.Count > 0) - { - var item = AuthTokensListBox.SelectedItems[0].Tag as string; - var host = item?.Split('|')[0].Trim(); - if (host != null) - { - coreConfig.SetAuthToken(host, null); - RefreshAuthTokensListBox(); - DeleteAuthTokenButton.Enabled = false; - } + if (//AuthTokensListBox.SelectedItems is [{Tag: string item}, ..] + AuthTokensListBox.SelectedItems.Count > 0 + && AuthTokensListBox.SelectedItems[0] is {Tag: string item} + //&& item.Split('|') is [var firstPiece, ..] + && item.Split('|') is string[] pieces + && pieces.Length > 0 + && pieces[0] is string firstPiece) + { + var host = firstPiece.Trim(); + coreConfig.SetAuthToken(host, null); + RefreshAuthTokensListBox(); + DeleteAuthTokenButton.Enabled = false; } } diff --git a/GUI/Main/Main.cs b/GUI/Main/Main.cs index 7e0d3be90a..f327406a1a 100644 --- a/GUI/Main/Main.cs +++ b/GUI/Main/Main.cs @@ -61,19 +61,22 @@ public partial class Main : Form, IMessageFilter public Main(string[] cmdlineArgs, GameInstanceManager? mgr) { log.Info("Starting the GUI"); - if (cmdlineArgs.Length >= 2) + if (//cmdlineArgs is [_, string focusIdent, ..] + cmdlineArgs.Length > 1 + && cmdlineArgs[1] is string focusIdent) { - focusIdent = cmdlineArgs[1]; - if (focusIdent.StartsWith("//")) + if (//focusIdent is ['/', '/', .. var rest] + focusIdent.Length > 2) { focusIdent = focusIdent[2..]; } - else if (focusIdent.StartsWith("ckan://")) + else if (//focusIdent is ['c', 'k', 'a', 'n', ':', '/', '/', .. var rest2] + focusIdent.StartsWith("ckan://")) { focusIdent = focusIdent[7..]; } - - if (focusIdent.EndsWith("/")) + if (//focusIdent is [.. var start, '/'] + focusIdent.EndsWith("/")) { focusIdent = focusIdent[..^1]; } diff --git a/GUI/Model/GUIMod.cs b/GUI/Model/GUIMod.cs index 3ee8c74463..2cd8708d2e 100644 --- a/GUI/Model/GUIMod.cs +++ b/GUI/Model/GUIMod.cs @@ -8,8 +8,6 @@ using System.Runtime.Versioning; #endif -using Autofac; - using CKAN.Versioning; namespace CKAN.GUI @@ -223,7 +221,14 @@ public GUIMod(CkanModule mod, Name = mod.name.Trim(); Abstract = mod.@abstract.Trim(); Description = mod.description?.Trim() ?? string.Empty; - Abbrevation = new string(Name.Split(' ').Where(s => s.Length > 0).Select(s => s[0]).ToArray()); + Abbrevation = new string(Name.Split(' ') + .Select(s => //s is [char first, ..] + s.Length > 0 + && s[0] is char first + ? (char?)first + : null) + .OfType() + .ToArray()); HasReplacement = registry.GetReplacement(mod, current_game_version) != null; DownloadSize = mod.download_size == 0 ? Properties.Resources.GUIModNSlashA : CkanModule.FmtSize(mod.download_size); diff --git a/GUI/Util.cs b/GUI/Util.cs index 7b06cc1a24..27103529b5 100644 --- a/GUI/Util.cs +++ b/GUI/Util.cs @@ -286,7 +286,8 @@ public static EventHandler Debounce( public static Color BlendColors(Color[] colors) => colors.Length < 1 ? Color.Empty - : colors.Length == 1 ? colors[0] + //: colors is [var c] ? c + : colors.Length == 1 && colors[0] is var c ? c : colors.Aggregate((back, fore) => fore.AlphaBlendWith(1f / colors.Length, back)); public static Color AlphaBlendWith(this Color c1, float alpha, Color c2) diff --git a/Netkan/ConsoleUser.cs b/Netkan/ConsoleUser.cs index 87691921c9..d4ac8c8807 100644 --- a/Netkan/ConsoleUser.cs +++ b/Netkan/ConsoleUser.cs @@ -107,7 +107,9 @@ public int RaiseSelectionDialog(string message, params object[] args) // Check if we have a default selection. int defaultSelection = -1; - if (args[0] is int v) + if (//args is [int v, ..] + args.Length > 0 + && args[0] is int v) { // Check that the default selection makes sense. defaultSelection = v; diff --git a/Netkan/Model/Metadata.cs b/Netkan/Model/Metadata.cs index 411486246f..a137211f94 100644 --- a/Netkan/Model/Metadata.cs +++ b/Netkan/Model/Metadata.cs @@ -123,10 +123,13 @@ public Metadata(YamlMappingNode yaml) : this(yaml?.ToJObject()) } public static Metadata Merge(Metadata[] modules) - => modules.Length == 1 ? modules[0] - : PropertySortTransformer.SortProperties( - new Metadata(MergeJson(modules.Select(m => m._json) - .ToArray()))); + => //modules is [var m] + modules.Length == 1 + && modules[0] is var m + ? m + : PropertySortTransformer.SortProperties( + new Metadata(MergeJson(modules.Select(m => m._json) + .ToArray()))); private static JObject MergeJson(JObject[] jsons) { diff --git a/Netkan/Processors/Inflator.cs b/Netkan/Processors/Inflator.cs index fd2183ffd0..f6918151bd 100644 --- a/Netkan/Processors/Inflator.cs +++ b/Netkan/Processors/Inflator.cs @@ -60,7 +60,7 @@ internal IEnumerable Inflate(string filename, Metadata[] netkans, Tran foreach (Metadata ckan in ckans) { - ckanValidator.ValidateCkan(ckan, netkans[0]); + ckanValidator.ValidateCkan(ckan, netkans.First()); } log.Debug("Output successfully passed post-validation"); return ckans; diff --git a/Netkan/Processors/QueueHandler.cs b/Netkan/Processors/QueueHandler.cs index be1de8585b..5807d3b48e 100644 --- a/Netkan/Processors/QueueHandler.cs +++ b/Netkan/Processors/QueueHandler.cs @@ -162,7 +162,7 @@ private IEnumerable Inflate(Message msg) netkans.First().StagingReason); try { - ckans = inflator.Inflate($"{netkans[0].Identifier}.netkan", netkans, opts) + ckans = inflator.Inflate($"{netkans.First().Identifier}.netkan", netkans, opts) .ToArray(); } catch (Exception e) diff --git a/Netkan/Program.cs b/Netkan/Program.cs index e4059edfa9..ed75e9436d 100644 --- a/Netkan/Program.cs +++ b/Netkan/Program.cs @@ -62,12 +62,18 @@ public static int Main(string[] args) return ExitOk; } - if (Options.Queues != null && !string.IsNullOrEmpty(Options.Queues)) + if (Options.Queues != null + && !string.IsNullOrEmpty(Options.Queues) + && Options.Queues.Split(new char[] { ',' }, 2) + //is [var input, var output] + is string[] array + && array.Length == 2 + && array[0] is var input + && array[1] is var output) { - var queues = Options.Queues.Split(new char[] { ',' }, 2); var qh = new QueueHandler( - queues[0], - queues[1], + input, + output, Options.CacheDir, Options.OutputDir, Options.OverwriteCache, @@ -92,8 +98,7 @@ public static int Main(string[] args) Options.GitHubToken, Options.GitLabToken, Options.PreRelease, - game - ); + game); var ckans = inf.Inflate( Options.File, netkans, @@ -101,8 +106,8 @@ public static int Main(string[] args) ParseReleases(Options.Releases), ParseSkipReleases(Options.SkipReleases), ParseHighestVersion(Options.HighestVersion), - netkans[0].Staged, - netkans[0].StagingReason)) + netkans.First().Staged, + netkans.First().StagingReason)) .ToArray(); foreach (Metadata ckan in ckans) { diff --git a/Netkan/Sources/Avc/JsonAvcToGameVersion.cs b/Netkan/Sources/Avc/JsonAvcToGameVersion.cs index a4012b678a..bfd49087ec 100644 --- a/Netkan/Sources/Avc/JsonAvcToGameVersion.cs +++ b/Netkan/Sources/Avc/JsonAvcToGameVersion.cs @@ -36,20 +36,23 @@ public override bool CanConvert(Type objectType) { case JTokenType.String: var tokenArray = token.ToString().Split('.'); - - if (tokenArray.Length > 0) + if (//tokenArray is [var majorToken, ..] + tokenArray.Length > 0 + && tokenArray[0] is var majorToken) { - major = tokenArray[0]; - } - - if (tokenArray.Length > 1) - { - minor = tokenArray[1]; - } - - if (tokenArray.Length > 2) - { - patch = tokenArray[2]; + major = majorToken; + if (//tokenArray is [_, var minorToken, ..] + tokenArray.Length > 1 + && tokenArray[1] is var minorToken) + { + minor = minorToken; + if (//tokenArray is [_, _, var patchToken, ..] + tokenArray.Length > 2 + && tokenArray[2] is var patchToken) + { + patch = patchToken; + } + } } break; case JTokenType.Object: @@ -121,27 +124,30 @@ public override bool CanConvert(Type objectType) { case JTokenType.String: var tokenArray = token.ToString().Split('.'); - - if (tokenArray.Length > 0) - { - major = tokenArray[0]; - } - - if (tokenArray.Length > 1) - { - minor = tokenArray[1]; - } - - if (tokenArray.Length > 2) + if (//tokenArray is [var majorToken, ..] + tokenArray.Length > 0 + && tokenArray[0] is var majorToken) { - patch = tokenArray[2]; + major = majorToken; + if (//tokenArray is [_, var minorToken, ..] + tokenArray.Length > 1 + && tokenArray[1] is var minorToken) + { + minor = minorToken; + if (//tokenArray is [_, _, var patchToken, ..] + tokenArray.Length > 2 + && tokenArray[2] is var patchToken) + { + patch = patchToken; + if (//tokenArray is [_, _, _, var buildToken, ..] + tokenArray.Length > 3 + && tokenArray[3] is var buildToken) + { + build = buildToken; + } + } + } } - - if (tokenArray.Length > 3) - { - build = tokenArray[3]; - } - break; case JTokenType.Object: major = token.Value("MAJOR") ?? major; diff --git a/Netkan/Sources/Curse/CurseFile.cs b/Netkan/Sources/Curse/CurseFile.cs index fa2eedf69c..3f502b1d2c 100755 --- a/Netkan/Sources/Curse/CurseFile.cs +++ b/Netkan/Sources/Curse/CurseFile.cs @@ -66,9 +66,11 @@ public string GetFilename() if (_filename == null) { Match match = Regex.Match(GetDownloadUrl(), "[^/]*\\.zip"); - _filename = match.Groups.Count > 0 - ? match.Groups[0].Value - : GetCurseIdVersion(); + _filename = //match.Groups is [var grp, ..] + match.Groups.Count > 0 + && match.Groups[0] is var grp + ? grp.Value + : GetCurseIdVersion(); } return _filename; } @@ -82,9 +84,11 @@ public string GetFileVersion() if (_fileVersion == null) { Match match = Regex.Match(GetDownloadUrl(), "(v?[0-9][0-9a-z.]*[0-9a-z])[^0-9]*\\.zip"); - if (match.Groups.Count > 1) + if (//match.Groups is [_, var grp, ..] + match.Groups.Count > 1 + && match.Groups[1] is var grp) { - _fileVersion = match.Groups[1].Value; + _fileVersion = grp.Value; } else { diff --git a/Netkan/Sources/Curse/CurseMod.cs b/Netkan/Sources/Curse/CurseMod.cs index 7e5efce20a..349617aab4 100755 --- a/Netkan/Sources/Curse/CurseMod.cs +++ b/Netkan/Sources/Curse/CurseMod.cs @@ -68,9 +68,11 @@ public string GetName() // Matches the longest sequence of letters and spaces ending in two letters from the beggining of the string // This is to filter out version information Match match = Regex.Match(title ?? "", "^([A-Za-z ]*[A-Za-z][A-Za-z])"); - if (match.Groups.Count > 1) + if (//match.Groups is [_, var grp, ..] + match.Groups.Count > 1 + && match.Groups[1] is var grp) { - _name = match.Groups[1].Value; + _name = grp.Value; } else { diff --git a/Netkan/Transformers/VersionedOverrideTransformer.cs b/Netkan/Transformers/VersionedOverrideTransformer.cs index f3090dd11f..e52c8e5201 100644 --- a/Netkan/Transformers/VersionedOverrideTransformer.cs +++ b/Netkan/Transformers/VersionedOverrideTransformer.cs @@ -156,7 +156,7 @@ private void ProcessOverrideStanza(JObject overrideStanza, JObject metadata) if (overrideStanza.TryGetValue("override", out JToken? overrideBlock) && overrideBlock is JObject overrides) { - if (gameVersionProperties.Any(p => overrides.ContainsKey(p))) + if (gameVersionProperties.Any(overrides.ContainsKey)) { ModuleService.ApplyVersions( metadata, diff --git a/Netkan/Validators/PluginsValidator.cs b/Netkan/Validators/PluginsValidator.cs index d280f36500..6b9584e99d 100644 --- a/Netkan/Validators/PluginsValidator.cs +++ b/Netkan/Validators/PluginsValidator.cs @@ -41,7 +41,7 @@ public void Validate(Metadata metadata) .OrderBy(f => f) .ToList(); var dllIdentifiers = dllPaths - .Select(p => inst.DllPathToIdentifier(p)) + .Select(inst.DllPathToIdentifier) .Where(ident => !string.IsNullOrEmpty(ident) && !identifiersToIgnore.Contains(ident)) .ToHashSet(); diff --git a/Tests/Core/ModuleInstallerTests.cs b/Tests/Core/ModuleInstallerTests.cs index 7fdf30524c..1a38eab009 100644 --- a/Tests/Core/ModuleInstallerTests.cs +++ b/Tests/Core/ModuleInstallerTests.cs @@ -654,7 +654,7 @@ public void GroupFilesByRemovable_WithFiles_CorrectOutput(string relRoot, var game = new KerbalSpaceProgram(); var registry = RegistryManager.Instance(inst.KSP, repoData.Manager).registry; // Make files to be registered to another mod - var absFiles = registeredFiles.Select(f => inst.KSP.ToAbsoluteGameDir(f)) + var absFiles = registeredFiles.Select(inst.KSP.ToAbsoluteGameDir) .ToList(); foreach (var absPath in absFiles) { diff --git a/Tests/Core/Net/NetAsyncDownloaderTests.cs b/Tests/Core/Net/NetAsyncDownloaderTests.cs index d359c908fc..925285c39e 100644 --- a/Tests/Core/Net/NetAsyncDownloaderTests.cs +++ b/Tests/Core/Net/NetAsyncDownloaderTests.cs @@ -69,7 +69,7 @@ public void DownloadAndWait_WithValidFileUrls_SetsTargetsSize(params string[] pa { // Arrange var downloader = new NetAsyncDownloader(new NullUser()); - var fromPaths = pathsWithinTestData.Select(p => TestData.DataDir(p)).ToArray(); + var fromPaths = pathsWithinTestData.Select(TestData.DataDir).ToArray(); var targets = fromPaths.Select(p => new NetAsyncDownloader.DownloadTargetFile(new Uri(p), Path.GetTempFileName())) .ToArray(); diff --git a/Tests/Core/Registry/RegistryManager.cs b/Tests/Core/Registry/RegistryManager.cs index 7716b89d69..c6c5c1d62d 100644 --- a/Tests/Core/Registry/RegistryManager.cs +++ b/Tests/Core/Registry/RegistryManager.cs @@ -198,9 +198,9 @@ public void ScanUnmanagedFiles_WithDLLs_FindsUnregisteredOnly(string[] registere var gameInst = dispInst.KSP; var regMgr = RegistryManager.Instance(gameInst, repoData.Manager); var registry = regMgr.registry; - var absReg = registered.Select(p => gameInst.ToAbsoluteGameDir(p)) + var absReg = registered.Select(gameInst.ToAbsoluteGameDir) .ToList(); - var absUnreg = unregistered.Select(p => gameInst.ToAbsoluteGameDir(p)) + var absUnreg = unregistered.Select(gameInst.ToAbsoluteGameDir) .ToArray(); // Create all the files @@ -225,7 +225,7 @@ public void ScanUnmanagedFiles_WithDLLs_FindsUnregisteredOnly(string[] registere // Assert CollectionAssert.AreEquivalent( unregistered, - registry.InstalledDlls.Select(ident => registry.DllPath(ident)) + registry.InstalledDlls.Select(registry.DllPath) .ToArray()); } } diff --git a/Tests/Core/Relationships/RelationshipResolver.cs b/Tests/Core/Relationships/RelationshipResolver.cs index 39ab8b70b7..cc882606f1 100644 --- a/Tests/Core/Relationships/RelationshipResolver.cs +++ b/Tests/Core/Relationships/RelationshipResolver.cs @@ -1051,7 +1051,7 @@ public void UninstallingConflictingModule_InstallingRecursiveDependencies_Resolv registry.RegisterModule(eve, new List(), ksp.KSP, false); registry.RegisterModule(eveDefaultConfig, new List(), ksp.KSP, false); - Assert.DoesNotThrow(() => registry.CheckSanity()); + Assert.DoesNotThrow(registry.CheckSanity); List modulesToInstall; List modulesToRemove; diff --git a/Tests/Core/Types/CkanModuleTests.cs b/Tests/Core/Types/CkanModuleTests.cs index 32f5fb4aff..0da61b28d9 100644 --- a/Tests/Core/Types/CkanModuleTests.cs +++ b/Tests/Core/Types/CkanModuleTests.cs @@ -330,7 +330,7 @@ public void InternetArchiveDownload_NoHash_NullURL() public void GroupByDownloads_WithModules_GroupsBySharedURLs(string[] moduleJsons, params string[][] correctGroups) { // Arrange - var modules = moduleJsons.Select(j => CkanModule.FromJson(j)) + var modules = moduleJsons.Select(CkanModule.FromJson) .ToArray(); // Turn [null] into [] as Workaround for params argument not allowing no values // (params argument itself is a workaround for TestCase not allowing string[][]) @@ -449,7 +449,7 @@ public void LatestCompatibleRealGameVersion_WithVersions_Works(string moduleJs // Arrange var module = CkanModule.FromJson(moduleJson); var correctVersion = GameVersion.Parse(correct); - var realVersions = real.Select(v => GameVersion.Parse(v)).ToList(); + var realVersions = real.Select(GameVersion.Parse).ToList(); // Act var latestCompat = module.LatestCompatibleRealGameVersion(realVersions); diff --git a/Tests/GUI/ThreadSafetyTests.cs b/Tests/GUI/ThreadSafetyTests.cs index 1696077f34..01fa7be04c 100644 --- a/Tests/GUI/ThreadSafetyTests.cs +++ b/Tests/GUI/ThreadSafetyTests.cs @@ -25,7 +25,7 @@ public void GUIAssemblyModule_MethodsWithForbidGUICalls_DontCallGUI() var mainModule = ModuleDefinition.ReadModule(Assembly.GetAssembly(typeof(CKAN.GUI.Main))! .Location); var allMethods = mainModule.Types - .SelectMany(t => GetAllNestedTypes(t)) + .SelectMany(GetAllNestedTypes) .SelectMany(t => t.Methods) .ToArray(); var calls = allMethods.Where(hasForbidGUIAttribute) @@ -46,7 +46,7 @@ public void GUIAssemblyModule_MethodsWithForbidGUICalls_DontCallGUI() private IEnumerable GetAllNestedTypes(TypeDefinition td) => Enumerable.Repeat(td, 1) - .Concat(td.NestedTypes.SelectMany(nested => GetAllNestedTypes(nested))); + .Concat(td.NestedTypes.SelectMany(GetAllNestedTypes)); private IEnumerable FindStartedTasks(MethodDefinition md) => StartNewCalls(md).Select(FindStartNewArgument)