diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..f7a664c935 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,51 @@ +[*.cs] +dotnet_analyzer_diagnostic.category-Style.severity = warning +dotnet_analyzer_diagnostic.category-CodeQuality.severity = warning + +# Using `var` is good +dotnet_diagnostic.IDE0008.severity = none + +# Don't need to enumerate every case for `switch` with `default` +dotnet_diagnostic.IDE0010.severity = none + +# Don't "simplify" if statements that throw +dotnet_diagnostic.IDE0016.severity = none + +# Expression bodies are good for methods +dotnet_diagnostic.IDE0022.severity = none + +# Expression bodies are fine for operators +dotnet_diagnostic.IDE0024.severity = none + +# Collection initialization simplification affects JObject, which is dumb +dotnet_diagnostic.IDE0028.severity = none + +# "auto" properties seem pretty useless +dotnet_diagnostic.IDE0032.severity = none + +# "local functions" are just weird, no thank you +dotnet_diagnostic.IDE0039.severity = none + +# "if" statements should only be "simplified" if they're pure functional, +# and these checks don't know that +dotnet_diagnostic.IDE0045.severity = none +dotnet_diagnostic.IDE0046.severity = none +dotnet_diagnostic.IDE0270.severity = none + +# We use "unnecessary" parentheses for clarity +dotnet_diagnostic.IDE0047.severity = none + +# Let me keep my extra spaces for aligning things +dotnet_diagnostic.IDE0055.severity = none + +# OK to call functions that return values and not use them +dotnet_diagnostic.IDE0058.severity = none + +# A `using` inside a namespace is useful as a typedef +dotnet_diagnostic.IDE0065.severity = none + +# Allow namespaces to be independent of folder names +dotnet_diagnostic.IDE0130.severity = none + +# Who cares if it's a JSON formatted string, in a test? +dotnet_diagnostic.JSON002.severity = none diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5a5d29c54b..ec8310ef1c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,7 +5,10 @@ on: branches: - master pull_request: - types: [opened, synchronize, reopened] + types: + - opened + - synchronize + - reopened jobs: build: @@ -14,8 +17,14 @@ jobs: strategy: fail-fast: false matrix: - mono: ['6.8', '6.10', '6.12', 'latest'] - configuration: [Debug, Release] + mono: + - latest + - '6.12' + - '6.10' + - '6.8' + configuration: + - Debug + - Release container: image: mono:${{ matrix.mono }} @@ -27,6 +36,10 @@ jobs: run: | apt-get update || true apt-get install -y apt-transport-https + - name: Setup .NET Core + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '7' - name: Installing build dependencies run: apt-get update && apt-get install -y git - name: Install runtime dependencies @@ -66,7 +79,7 @@ jobs: curl -O https://raw.githubusercontent.com/KSP-CKAN/NetKAN/master/NetKAN/ZeroMiniAVC.netkan && \ mono netkan.exe ZeroMiniAVC.netkan " - if: matrix.configuration == 'release' && ( matrix.mono == '6.8' || matrix.mono == 'latest' ) + if: matrix.configuration == 'release' - name: Upload ckan.exe artifact uses: actions/upload-artifact@v3 @@ -95,14 +108,16 @@ jobs: strategy: fail-fast: false matrix: - configuration: [Debug_NetCore, Release_NetCore] + configuration: + - Debug_NetCore + - Release_NetCore steps: - uses: actions/checkout@v3 - name: Setup .NET Core uses: actions/setup-dotnet@v3 with: - dotnet-version: '5.0.x' + dotnet-version: '7' - name: Restore cache for _build/tools uses: actions/cache@v3 with: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 85603e7f00..9b6e93b8c4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -31,6 +31,10 @@ jobs: echo 'odd_build=true' >> $GITHUB_OUTPUT fi + - name: Setup .NET Core + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '7' - name: Installing build dependencies run: apt-get update && apt-get install -y git make sed gzip fakeroot lintian dpkg-dev gpg createrepo - name: Installing runtime dependencies diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a917fcbc18..719ae366bf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,10 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Setup .NET Core + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '7' - name: Installing build dependencies run: apt-get update && apt-get install -y git make sed libplist-utils xorriso gzip fakeroot lintian rpm wget jq dpkg-dev gpg createrepo - name: Installing runtime dependencies diff --git a/.gitignore b/.gitignore index 8fa9db1fb8..d66419ff80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ /_build/ /.vs/ -/.vscode/ /tools test-results *.userprefs diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..f7c9752af9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,17 @@ +{ + "dotnet.preferCSharpExtension": false, + "dotnet.server.useOmnisharp": true, + "dotnet.defaultSolution": "CKAN.sln", + "dotnet.automaticallyCreateSolutionInWorkspace": false, + "dotnet.backgroundAnalysis.analyzerDiagnosticsScope": "fullSolution", + "dotnet.backgroundAnalysis.compilerDiagnosticsScope": "fullSolution", + "omnisharp.useModernNet": false, + "omnisharp.projectLoadTimeout": 600, + "python.defaultInterpreterPath": "py", + "files.watcherExclude": { + "**/_build/**": true + }, + "nunitTestRunner.projectsPatterns": [ + "_build/out/**/*.Tests.dll" + ] +} diff --git a/AutoUpdate/CKAN-autoupdate.csproj b/AutoUpdate/CKAN-autoupdate.csproj index 7b8c631bae..9d65829fc2 100644 --- a/AutoUpdate/CKAN-autoupdate.csproj +++ b/AutoUpdate/CKAN-autoupdate.csproj @@ -1,7 +1,8 @@ CKAN-AutoUpdateHelper - ..\_build\out\$(AssemblyName)\$(Configuration)\bin\ + ..\_build\out\$(AssemblyName)\$(Configuration)\bin\ + ..\_build\out\$(AssemblyName)\VSCodeIDE\bin\ ..\_build\out\$(AssemblyName)\$(Configuration)\obj\ @@ -16,8 +17,8 @@ false 7 ..\assets\ckan.ico - net45 - v4.5 + net48 + v4.8 512 prompt 4 @@ -28,10 +29,6 @@ - - - - Properties\GlobalAssemblyVersionInfo.cs @@ -48,25 +45,4 @@ - - - - - - - - - - - - - - diff --git a/AutoUpdate/Main.cs b/AutoUpdate/Main.cs index 56e5b4667e..2d32697b02 100644 --- a/AutoUpdate/Main.cs +++ b/AutoUpdate/Main.cs @@ -123,7 +123,7 @@ private static void StartCKAN(string path) // Start CKAN if (IsOnMono()) { - Process.Start("mono", String.Format("\"{0}\"", path)); + Process.Start("mono", string.Format("\"{0}\"", path)); } else { @@ -171,7 +171,7 @@ private static bool IsOnWindows() /// /// Source of unhandled exception /// Info about the exception - private static void UnhandledExceptionEventHandler(Object sender, UnhandledExceptionEventArgs e) + private static void UnhandledExceptionEventHandler(object sender, UnhandledExceptionEventArgs e) { ReportError(Properties.Resources.UnhandledException, e.ExceptionObject); } diff --git a/AutoUpdate/SingleAssemblyResourceManager.cs b/AutoUpdate/SingleAssemblyResourceManager.cs index 48f266d341..3ee0990a59 100644 --- a/AutoUpdate/SingleAssemblyResourceManager.cs +++ b/AutoUpdate/SingleAssemblyResourceManager.cs @@ -1,7 +1,6 @@ using System.IO; using System.Globalization; using System.Resources; -using System.Collections; using System.Reflection; using System.Collections.Generic; @@ -9,7 +8,7 @@ namespace CKAN.AutoUpdateHelper { // Thanks and credit to this guy: https://stackoverflow.com/q/1952638/2422988 - class SingleAssemblyResourceManager : ResourceManager + public class SingleAssemblyResourceManager : ResourceManager { public SingleAssemblyResourceManager(string basename, Assembly assembly) : base(basename, assembly) { @@ -23,7 +22,7 @@ protected override ResourceSet InternalGetResourceSet(CultureInfo culture, // Lazy-load default language (without caring about duplicate assignment in race conditions, no harm done) if (neutralResourcesCulture == null) { - neutralResourcesCulture = GetNeutralResourcesLanguage(this.MainAssembly); + neutralResourcesCulture = GetNeutralResourcesLanguage(MainAssembly); } // If we're asking for the default language, then ask for the @@ -34,7 +33,7 @@ protected override ResourceSet InternalGetResourceSet(CultureInfo culture, } string resourceFileName = GetResourceFileName(culture); - Stream store = this.MainAssembly.GetManifestResourceStream(resourceFileName); + Stream store = MainAssembly.GetManifestResourceStream(resourceFileName); // If we found the appropriate resources in the local assembly if (store != null) diff --git a/Cmdline/Action/Available.cs b/Cmdline/Action/Available.cs index 969fccb449..5fdab4d305 100644 --- a/Cmdline/Action/Available.cs +++ b/Cmdline/Action/Available.cs @@ -1,5 +1,4 @@ using System.Linq; -using System.Collections.Generic; namespace CKAN.CmdLine { diff --git a/Cmdline/Action/Cache.cs b/Cmdline/Action/Cache.cs index a928222985..50332e5bf1 100644 --- a/Cmdline/Action/Cache.cs +++ b/Cmdline/Action/Cache.cs @@ -106,7 +106,9 @@ public int RunSubCommand(GameInstanceManager mgr, CommonOptions opts, SubCommand manager = mgr ?? new GameInstanceManager(user); exitCode = options.Handle(manager, user); if (exitCode != Exit.OK) + { return; + } switch (option) { @@ -214,14 +216,9 @@ private int ShowCacheSizeLimit() private int SetCacheSizeLimit(SetLimitOptions options) { IConfiguration cfg = ServiceLocator.Container.Resolve(); - if (options.Megabytes < 0) - { - cfg.CacheSizeLimit = null; - } - else - { - cfg.CacheSizeLimit = options.Megabytes * (long)1024 * (long)1024; - } + cfg.CacheSizeLimit = options.Megabytes < 0 + ? null : + (long?)(options.Megabytes * 1024 * 1024); return ShowCacheSizeLimit(); } diff --git a/Cmdline/Action/Compat.cs b/Cmdline/Action/Compat.cs index 7be08bc06e..734c3310f9 100644 --- a/Cmdline/Action/Compat.cs +++ b/Cmdline/Action/Compat.cs @@ -82,7 +82,9 @@ public int RunSubCommand(GameInstanceManager manager, CommonOptions opts, SubCom _kspManager = manager ?? new GameInstanceManager(_user); exitCode = comOpts.Handle(_kspManager, _user); if (exitCode != Exit.OK) + { return; + } switch (option) { diff --git a/Cmdline/Action/Filter.cs b/Cmdline/Action/Filter.cs index 9cab436414..3c8ed92688 100644 --- a/Cmdline/Action/Filter.cs +++ b/Cmdline/Action/Filter.cs @@ -42,7 +42,9 @@ public int RunSubCommand(GameInstanceManager mgr, CommonOptions opts, SubCommand manager = mgr ?? new GameInstanceManager(user); exitCode = options.Handle(manager, user); if (exitCode != Exit.OK) + { return; + } switch (option) { diff --git a/Cmdline/Action/GameInstance.cs b/Cmdline/Action/GameInstance.cs index 328abfb408..849d954703 100644 --- a/Cmdline/Action/GameInstance.cs +++ b/Cmdline/Action/GameInstance.cs @@ -179,7 +179,9 @@ public int RunSubCommand(GameInstanceManager manager, CommonOptions opts, SubCom Manager = manager ?? new GameInstanceManager(User); exitCode = options.Handle(Manager, User); if (exitCode != Exit.OK) + { return; + } switch (option) { @@ -461,7 +463,7 @@ private int SetDefaultInstall(DefaultOptions options) string defaultInstance = Manager.Configuration.AutoStartInstance; int defaultInstancePresent = 0; - if (!String.IsNullOrWhiteSpace(defaultInstance)) + if (!string.IsNullOrWhiteSpace(defaultInstance)) { defaultInstancePresent = 1; } @@ -477,7 +479,7 @@ private int SetDefaultInstall(DefaultOptions options) } // Mark the default instance for the user. - if (!String.IsNullOrWhiteSpace(defaultInstance)) + if (!string.IsNullOrWhiteSpace(defaultInstance)) { keys[0] = Manager.Instances.IndexOfKey(defaultInstance); } diff --git a/Cmdline/Action/Install.cs b/Cmdline/Action/Install.cs index 6338bb9440..81b76ef5ef 100644 --- a/Cmdline/Action/Install.cs +++ b/Cmdline/Action/Install.cs @@ -61,7 +61,7 @@ public int RunCommand(CKAN.GameInstance instance, object raw_options) ckan_uri = new Uri(ckan_file); } - string filename = String.Empty; + string filename = string.Empty; // If it is a local file, we already know the filename. If it is remote, create a temporary file and download the remote resource. if (ckan_uri.IsFile) diff --git a/Cmdline/Action/Mark.cs b/Cmdline/Action/Mark.cs index aff716bce4..ead13ffc37 100644 --- a/Cmdline/Action/Mark.cs +++ b/Cmdline/Action/Mark.cs @@ -44,7 +44,9 @@ public int RunSubCommand(GameInstanceManager mgr, CommonOptions opts, SubCommand manager = mgr ?? new GameInstanceManager(user); exitCode = options.Handle(manager, user); if (exitCode != Exit.OK) + { return; + } switch (option) { diff --git a/Cmdline/Action/Remove.cs b/Cmdline/Action/Remove.cs index f28a430fe1..e0634f3136 100644 --- a/Cmdline/Action/Remove.cs +++ b/Cmdline/Action/Remove.cs @@ -50,7 +50,9 @@ public int RunCommand(CKAN.GameInstance instance, object raw_options) foreach (string mod in regMgr.registry.InstalledModules.Select(mod => mod.identifier)) { if (justins.Any(re => re.IsMatch(mod))) + { selectedModules.Add(mod); + } } // Replace the regular expressions with the selected modules diff --git a/Cmdline/Action/Repair.cs b/Cmdline/Action/Repair.cs index 5eaaf32267..198f4dec6e 100644 --- a/Cmdline/Action/Repair.cs +++ b/Cmdline/Action/Repair.cs @@ -60,7 +60,9 @@ public int RunSubCommand(GameInstanceManager manager, CommonOptions opts, SubCom } exitCode = options.Handle(manager, User); if (exitCode != Exit.OK) + { return; + } switch (option) { diff --git a/Cmdline/Action/Replace.cs b/Cmdline/Action/Replace.cs index 5f89e7ffee..7032baa756 100644 --- a/Cmdline/Action/Replace.cs +++ b/Cmdline/Action/Replace.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; using log4net; using CKAN.Versioning; @@ -9,7 +8,7 @@ namespace CKAN.CmdLine { public class Replace : ICommand { - public Replace(CKAN.GameInstanceManager mgr, RepositoryDataManager repoData, IUser user) + public Replace(GameInstanceManager mgr, RepositoryDataManager repoData, IUser user) { manager = mgr; this.repoData = repoData; diff --git a/Cmdline/Action/Repo.cs b/Cmdline/Action/Repo.cs index 074a93d0f7..48dc18d075 100644 --- a/Cmdline/Action/Repo.cs +++ b/Cmdline/Action/Repo.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Net; using Newtonsoft.Json; using CommandLine; @@ -139,7 +137,9 @@ public int RunSubCommand(GameInstanceManager manager, CommonOptions opts, SubCom Manager = manager ?? new GameInstanceManager(User); exitCode = options.Handle(Manager, User); if (exitCode != Exit.OK) + { return; + } switch (option) { @@ -282,7 +282,7 @@ private int AddRepository(RepoAddOptions options) foreach (Repository candidate in repositoryList.repositories) { - if (String.Equals(candidate.name, options.name, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(candidate.name, options.name, StringComparison.OrdinalIgnoreCase)) { options.name = candidate.name; options.uri = candidate.uri.ToString(); diff --git a/Cmdline/Action/Search.cs b/Cmdline/Action/Search.cs index c71b96821e..59edd9912c 100644 --- a/Cmdline/Action/Search.cs +++ b/Cmdline/Action/Search.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; -using CKAN.Games; namespace CKAN.CmdLine { @@ -19,7 +18,7 @@ public int RunCommand(CKAN.GameInstance ksp, object raw_options) SearchOptions options = (SearchOptions)raw_options; // Check the input. - if (String.IsNullOrWhiteSpace(options.search_term) && String.IsNullOrWhiteSpace(options.author_term)) + if (string.IsNullOrWhiteSpace(options.search_term) && string.IsNullOrWhiteSpace(options.author_term)) { user.RaiseError(Properties.Resources.SearchNoTerm); return Exit.BADOPT; @@ -33,7 +32,7 @@ public int RunCommand(CKAN.GameInstance ksp, object raw_options) } // Show how many matches we have. - if (options.all && !String.IsNullOrWhiteSpace(options.author_term)) + if (options.all && !string.IsNullOrWhiteSpace(options.author_term)) { user.RaiseMessage(Properties.Resources.SearchFoundByAuthorWithIncompat, matching_compatible.Count().ToString(), @@ -41,21 +40,21 @@ public int RunCommand(CKAN.GameInstance ksp, object raw_options) options.search_term, options.author_term); } - else if (options.all && String.IsNullOrWhiteSpace(options.author_term)) + else if (options.all && string.IsNullOrWhiteSpace(options.author_term)) { user.RaiseMessage(Properties.Resources.SearchFoundWithIncompat, matching_compatible.Count().ToString(), matching_incompatible.Count().ToString(), options.search_term); } - else if (!options.all && !String.IsNullOrWhiteSpace(options.author_term)) + else if (!options.all && !string.IsNullOrWhiteSpace(options.author_term)) { user.RaiseMessage(Properties.Resources.SearchFoundByAuthor, matching_compatible.Count().ToString(), options.search_term, options.author_term); } - else if (!options.all && String.IsNullOrWhiteSpace(options.author_term)) + else if (!options.all && string.IsNullOrWhiteSpace(options.author_term)) { user.RaiseMessage(Properties.Resources.SearchFound, matching_compatible.Count().ToString(), @@ -77,7 +76,7 @@ public int RunCommand(CKAN.GameInstance ksp, object raw_options) mod.identifier, mod.version, mod.name, - mod.author == null ? "N/A" : String.Join(", ", mod.author), + mod.author == null ? "N/A" : string.Join(", ", mod.author), mod.@abstract); } @@ -94,7 +93,7 @@ public int RunCommand(CKAN.GameInstance ksp, object raw_options) mod.version, GameVersion, mod.name, - mod.author == null ? "N/A" : String.Join(", ", mod.author), + mod.author == null ? "N/A" : string.Join(", ", mod.author), mod.@abstract); } } @@ -125,27 +124,23 @@ public int RunCommand(CKAN.GameInstance ksp, object raw_options) public List PerformSearch(CKAN.GameInstance ksp, string term, string author = null, bool searchIncompatible = false) { // Remove spaces and special characters from the search term. - term = String.IsNullOrWhiteSpace(term) ? string.Empty : CkanModule.nonAlphaNums.Replace(term, ""); - author = String.IsNullOrWhiteSpace(author) ? string.Empty : CkanModule.nonAlphaNums.Replace(author, ""); + term = string.IsNullOrWhiteSpace(term) ? string.Empty : CkanModule.nonAlphaNums.Replace(term, ""); + author = string.IsNullOrWhiteSpace(author) ? string.Empty : CkanModule.nonAlphaNums.Replace(author, ""); var registry = RegistryManager.Instance(ksp, repoData).registry; - if (!searchIncompatible) - { - return registry - .CompatibleModules(ksp.VersionCriteria()) + return searchIncompatible + ? registry + .IncompatibleModules(ksp.VersionCriteria()) // Look for a match in each string. .Where(module => (module.SearchableName.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1 || module.SearchableIdentifier.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1 || module.SearchableAbstract.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1 || module.SearchableDescription.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1) && module.SearchableAuthors.Any((auth) => auth.IndexOf(author, StringComparison.OrdinalIgnoreCase) > -1)) - .ToList(); - } - else - { - return registry - .IncompatibleModules(ksp.VersionCriteria()) + .ToList() + : registry + .CompatibleModules(ksp.VersionCriteria()) // Look for a match in each string. .Where(module => (module.SearchableName.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1 || module.SearchableIdentifier.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1 @@ -153,7 +148,6 @@ public List PerformSearch(CKAN.GameInstance ksp, string term, string || module.SearchableDescription.IndexOf(term, StringComparison.OrdinalIgnoreCase) > -1) && module.SearchableAuthors.Any((auth) => auth.IndexOf(author, StringComparison.OrdinalIgnoreCase) > -1)) .ToList(); - } } /// diff --git a/Cmdline/CKAN-cmdline.csproj b/Cmdline/CKAN-cmdline.csproj index b5f8011a3f..10f9de0ec8 100644 --- a/Cmdline/CKAN-cmdline.csproj +++ b/Cmdline/CKAN-cmdline.csproj @@ -1,7 +1,8 @@ CKAN-CmdLine - ..\_build\out\$(AssemblyName)\$(Configuration)\bin\ + ..\_build\out\$(AssemblyName)\$(Configuration)\bin\ + ..\_build\out\$(AssemblyName)\VSCodeIDE\bin\ ..\_build\out\$(AssemblyName)\$(Configuration)\obj\ @@ -14,11 +15,11 @@ true Debug;Release false - 7 - net45 + 7.3 + net48 CKAN.CmdLine.MainClass ..\assets\ckan.ico - v4.5 + v4.8 512 prompt 4 diff --git a/Cmdline/ConsoleUser.cs b/Cmdline/ConsoleUser.cs index 8f2725b837..99373bdd06 100644 --- a/Cmdline/ConsoleUser.cs +++ b/Cmdline/ConsoleUser.cs @@ -93,7 +93,7 @@ public int RaiseSelectionDialog(string message, params object[] args) } // Validate input. - if (String.IsNullOrWhiteSpace(message)) + if (string.IsNullOrWhiteSpace(message)) { throw new Kraken("Passed message string must be non-empty."); } @@ -130,7 +130,7 @@ public int RaiseSelectionDialog(string message, params object[] args) // Further data validation. foreach (object argument in args) { - if (String.IsNullOrWhiteSpace(argument.ToString())) + if (string.IsNullOrWhiteSpace(argument.ToString())) { throw new Kraken("Candidate may not be empty."); } @@ -142,14 +142,14 @@ public int RaiseSelectionDialog(string message, params object[] args) // List options. for (int i = 0; i < args.Length; i++) { - string CurrentRow = String.Format("{0}", i + 1); + string CurrentRow = string.Format("{0}", i + 1); if (i == defaultSelection) { CurrentRow += "*"; } - CurrentRow += String.Format(") {0}", args[i]); + CurrentRow += string.Format(") {0}", args[i]); RaiseMessage(CurrentRow); } @@ -176,7 +176,7 @@ public int RaiseSelectionDialog(string message, params object[] args) input = input.Trim().ToLower(); // Check for default selection. - if (String.IsNullOrEmpty(input) && defaultSelection >= 0) + if (string.IsNullOrEmpty(input) && defaultSelection >= 0) { return defaultSelection; } diff --git a/Cmdline/Main.cs b/Cmdline/Main.cs index 22593eff5b..4767f8a7d0 100644 --- a/Cmdline/Main.cs +++ b/Cmdline/Main.cs @@ -6,11 +6,8 @@ using System; using System.Net; using System.Diagnostics; -using System.IO; using System.Linq; -using System.Reflection; using System.Runtime.InteropServices; -using System.Text.RegularExpressions; using Autofac; using log4net; @@ -154,7 +151,9 @@ public static int Execute(GameInstanceManager manager, CommonOptions opts, strin { int exitCode = options.Handle(manager, user); if (exitCode != Exit.OK) + { return exitCode; + } // Don't bother with instances or registries yet because some commands don't need them. return RunSimpleAction(cmdline, options, args, user, manager); } @@ -293,7 +292,7 @@ private static int ConsoleUi(GameInstanceManager manager, ConsoleUIOptions opts) { // Debug/verbose output just messes up the screen LogManager.GetRepository().Threshold = Level.Warn; - return CKAN.ConsoleUI.ConsoleUI.Main_(manager, + return ConsoleUI.ConsoleUI.Main_(manager, opts.Theme ?? Environment.GetEnvironmentVariable("CKAN_CONSOLEUI_THEME") ?? "default", opts.Debug); } @@ -352,14 +351,7 @@ public NoGameInstanceKraken() { } public class CmdLineUtil { public static uint GetUID() - { - if (Platform.IsUnix || Platform.IsMac) - { - return getuid(); - } - - return 1; - } + => Platform.IsUnix || Platform.IsMac ? getuid() : 1; [DllImport("libc")] private static extern uint getuid(); diff --git a/Cmdline/Options.cs b/Cmdline/Options.cs index 11e89f0a52..6f676ee0ed 100644 --- a/Cmdline/Options.cs +++ b/Cmdline/Options.cs @@ -289,7 +289,10 @@ private static void CheckMonoVersion(IUser user, int rec_major, int rec_minor, i try { Type type = Type.GetType("Mono.Runtime"); - if (type == null) return; + if (type == null) + { + return; + } MethodInfo display_name = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static); if (display_name != null) @@ -299,15 +302,15 @@ private static void CheckMonoVersion(IUser user, int rec_major, int rec_minor, i if (match.Success) { - int major = Int32.Parse(match.Groups["major"].Value); - int minor = Int32.Parse(match.Groups["minor"].Value); - int patch = Int32.Parse(match.Groups["revision"].Value); + int major = int.Parse(match.Groups["major"].Value); + int minor = int.Parse(match.Groups["minor"].Value); + int patch = int.Parse(match.Groups["revision"].Value); if (major < rec_major || (major == rec_major && minor < rec_minor)) { user.RaiseMessage(Properties.Resources.OptionsMonoWarning, - String.Join(".", major, minor, patch), - String.Join(".", rec_major, rec_minor, rec_patch)); + string.Join(".", major, minor, patch), + string.Join(".", rec_major, rec_minor, rec_patch)); } } } diff --git a/Cmdline/ProgressReporter.cs b/Cmdline/ProgressReporter.cs index 02989d0cfe..333ba656c2 100644 --- a/Cmdline/ProgressReporter.cs +++ b/Cmdline/ProgressReporter.cs @@ -1,4 +1,3 @@ -using System; using System.Text.RegularExpressions; namespace CKAN.CmdLine diff --git a/Cmdline/SingleAssemblyResourceManager.cs b/Cmdline/SingleAssemblyResourceManager.cs index 25f1e19f90..e13699cd00 100644 --- a/Cmdline/SingleAssemblyResourceManager.cs +++ b/Cmdline/SingleAssemblyResourceManager.cs @@ -1,7 +1,6 @@ using System.IO; using System.Globalization; using System.Resources; -using System.Collections; using System.Reflection; using System.Collections.Generic; @@ -9,7 +8,7 @@ namespace CKAN.CmdLine { // Thanks and credit to this guy: https://stackoverflow.com/q/1952638/2422988 - class SingleAssemblyResourceManager : ResourceManager + public class SingleAssemblyResourceManager : ResourceManager { public SingleAssemblyResourceManager(string basename, Assembly assembly) : base(basename, assembly) { @@ -23,7 +22,7 @@ protected override ResourceSet InternalGetResourceSet(CultureInfo culture, // Lazy-load default language (without caring about duplicate assignment in race conditions, no harm done) if (neutralResourcesCulture == null) { - neutralResourcesCulture = GetNeutralResourcesLanguage(this.MainAssembly); + neutralResourcesCulture = GetNeutralResourcesLanguage(MainAssembly); } // If we're asking for the default language, then ask for the @@ -34,7 +33,7 @@ protected override ResourceSet InternalGetResourceSet(CultureInfo culture, } string resourceFileName = GetResourceFileName(culture); - Stream store = this.MainAssembly.GetManifestResourceStream(resourceFileName); + Stream store = MainAssembly.GetManifestResourceStream(resourceFileName); // If we found the appropriate resources in the local assembly if (store != null) diff --git a/ConsoleUI/CKAN-ConsoleUI.csproj b/ConsoleUI/CKAN-ConsoleUI.csproj index 1d774b9e5e..634c192ed8 100644 --- a/ConsoleUI/CKAN-ConsoleUI.csproj +++ b/ConsoleUI/CKAN-ConsoleUI.csproj @@ -1,7 +1,8 @@ CKAN-ConsoleUI - ..\_build\out\$(AssemblyName)\$(Configuration)\bin\ + ..\_build\out\$(AssemblyName)\$(Configuration)\bin\ + ..\_build\out\$(AssemblyName)\VSCodeIDE\bin\ ..\_build\out\$(AssemblyName)\$(Configuration)\obj\ @@ -14,10 +15,10 @@ true Debug;Release false - 7 - net45 + 7.3 + net48 ..\assets\ckan.ico - v4.5 + v4.8 512 prompt 4 diff --git a/ConsoleUI/CompatibleVersionDialog.cs b/ConsoleUI/CompatibleVersionDialog.cs index a3d016812b..50afd03808 100644 --- a/ConsoleUI/CompatibleVersionDialog.cs +++ b/ConsoleUI/CompatibleVersionDialog.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.ComponentModel; -using Autofac; - using CKAN.Versioning; using CKAN.Games; using CKAN.ConsoleUI.Toolkit; diff --git a/ConsoleUI/DownloadImportDialog.cs b/ConsoleUI/DownloadImportDialog.cs index 3bc4e7c5f2..116a96b420 100644 --- a/ConsoleUI/DownloadImportDialog.cs +++ b/ConsoleUI/DownloadImportDialog.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Collections.Generic; -using System.ComponentModel; using CKAN.ConsoleUI.Toolkit; namespace CKAN.ConsoleUI { diff --git a/ConsoleUI/ExitScreen.cs b/ConsoleUI/ExitScreen.cs index 86562f89d1..ad74be0125 100644 --- a/ConsoleUI/ExitScreen.cs +++ b/ConsoleUI/ExitScreen.cs @@ -59,7 +59,7 @@ private void Draw(ConsoleTheme theme) .Replace("{0}", ckanPiece).ToArray(), new FancyLinePiece[] { new FancyLinePiece( - new string(Symbols.horizLine, Console.WindowWidth - 2 -2 * horizMargin), + new string(Symbols.horizLine, Console.WindowWidth - 2 -(2 * horizMargin)), theme.ExitInnerBg, theme.ExitNormalFg) }, }.Concat( @@ -90,7 +90,7 @@ private void drawLine(ConsoleTheme theme, int y, FancyLinePiece[] pieces) foreach (FancyLinePiece p in pieces) { textLen += p.Text.Length; } - int boxW = Console.WindowWidth - 2 * horizMargin; + int boxW = Console.WindowWidth - (2 * horizMargin); int leftPad = (boxW - textLen) / 2; if (leftPad < 0) { leftPad = 0; @@ -157,7 +157,7 @@ IEnumerable InjectReplacement(string p, int i) var pieces = Text.Split(tokens, StringSplitOptions.None); return pieces.Length <= 1 // Stop making new objects if no tokens found - ? Enumerable.Repeat(this, 1) + ? Enumerable.Repeat(this, 1) : pieces.SelectMany(InjectReplacement); } diff --git a/ConsoleUI/GameInstanceAddScreen.cs b/ConsoleUI/GameInstanceAddScreen.cs index b882e40cec..59e7f51ba6 100644 --- a/ConsoleUI/GameInstanceAddScreen.cs +++ b/ConsoleUI/GameInstanceAddScreen.cs @@ -27,20 +27,13 @@ public GameInstanceAddScreen(GameInstanceManager mgr) : base(mgr) /// The basic non-empty and unique checks are good enough for adding. /// protected override bool Valid() - { - if (!nameValid() || !pathValid()) { - return false; - } - return true; - } + => nameValid() && pathValid(); /// /// Put description in top center /// protected override string CenterHeader() - { - return Properties.Resources.InstanceAddTitle; - } + => Properties.Resources.InstanceAddTitle; /// /// Add the instance diff --git a/ConsoleUI/GameInstanceEditScreen.cs b/ConsoleUI/GameInstanceEditScreen.cs index 53b4adfc69..ecf923f9e6 100644 --- a/ConsoleUI/GameInstanceEditScreen.cs +++ b/ConsoleUI/GameInstanceEditScreen.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.ComponentModel; using CKAN.Versioning; -using CKAN.Games; using CKAN.ConsoleUI.Toolkit; namespace CKAN.ConsoleUI { @@ -174,33 +173,22 @@ private static V SortedDictFind(SortedDictionary dict, Func return kvp.Value; } } - return default(V); + return default; } /// /// Put description in top center /// protected override string CenterHeader() - { - return Properties.Resources.InstanceEditTitle; - } + => Properties.Resources.InstanceEditTitle; /// /// Return whether the fields are valid. /// Similar to adding, except leaving the fields unchanged is allowed. /// protected override bool Valid() - { - if (name.Value != ksp.Name - && !nameValid()) { - return false; - } - if (path.Value != ksp.GameDir() - && !pathValid()) { - return false; - } - return true; - } + => (name.Value == ksp.Name || nameValid()) + && (path.Value == ksp.GameDir() || pathValid()); /// /// Save the changes. diff --git a/ConsoleUI/InstallFilterAddDialog.cs b/ConsoleUI/InstallFilterAddDialog.cs index dbb953c2eb..de2ea97265 100644 --- a/ConsoleUI/InstallFilterAddDialog.cs +++ b/ConsoleUI/InstallFilterAddDialog.cs @@ -1,11 +1,4 @@ using System; -using System.Collections.Generic; -using System.ComponentModel; - -using Autofac; - -using CKAN.Versioning; -using CKAN.Games; using CKAN.ConsoleUI.Toolkit; namespace CKAN.ConsoleUI { diff --git a/ConsoleUI/ModInfoScreen.cs b/ConsoleUI/ModInfoScreen.cs index a3ecea46d8..3e55db34df 100644 --- a/ConsoleUI/ModInfoScreen.cs +++ b/ConsoleUI/ModInfoScreen.cs @@ -1,7 +1,5 @@ using System; -using System.Diagnostics; using System.Collections.Generic; -using System.Text.RegularExpressions; using System.Linq; using System.Threading; @@ -31,7 +29,7 @@ public ModInfoScreen(GameInstanceManager mgr, Registry registry, ChangePlan cp, plan = cp; this.registry = registry; - int midL = Console.WindowWidth / 2 - 1; + int midL = (Console.WindowWidth / 2) - 1; AddObject(new ConsoleLabel( 1, 1, -1, @@ -58,8 +56,8 @@ public ModInfoScreen(GameInstanceManager mgr, Registry registry, ChangePlan cp, )); AddObject(new ConsoleLabel( 13, 4, midL - 2, - () => string.Join(", ", Array.ConvertAll( - mod.license.ToArray(), (l => l.ToString()))) + () => string.Join(", ", Array.ConvertAll( + mod.license.ToArray(), l => l.ToString())) )); AddObject(new ConsoleLabel( 3, 5, 12, @@ -74,13 +72,13 @@ public ModInfoScreen(GameInstanceManager mgr, Registry registry, ChangePlan cp, if (mod.install_size > 0) { AddObject(new ConsoleLabel( - midL / 2, 5, midL / 2 + 9, + midL / 2, 5, (midL / 2) + 9, () => "Install:", null, th => th.DimLabelFg )); AddObject(new ConsoleLabel( - midL / 2 + 9, 5, midL - 2, + (midL / 2) + 9, 5, midL - 2, () => CkanModule.FmtSize(mod.install_size) )); } @@ -263,7 +261,7 @@ private int addDependencies(int top = 8) int numConfs = mod.conflicts?.Count ?? 0; if (numDeps + numConfs > 0) { - int midL = Console.WindowWidth / 2 - 1; + int midL = (Console.WindowWidth / 2) - 1; int h = Math.Min(11, numDeps + numConfs + 2); const int lblW = 16; int nameW = midL - 2 - lblW - 2 - 1; @@ -336,7 +334,7 @@ private int addDependencies(int top = 8) private int addVersionDisplay() { - int boxLeft = Console.WindowWidth / 2 + 1, + int boxLeft = (Console.WindowWidth / 2) + 1, boxTop = 3; const int boxRight = -1, boxH = 5; diff --git a/ConsoleUI/ModListHelpDialog.cs b/ConsoleUI/ModListHelpDialog.cs index 5f110337ff..747c0562af 100644 --- a/ConsoleUI/ModListHelpDialog.cs +++ b/ConsoleUI/ModListHelpDialog.cs @@ -22,7 +22,7 @@ public ModListHelpDialog() : base() int btnL = (Console.WindowWidth - btnW) / 2; ConsoleTextBox symbolTb = new ConsoleTextBox( - GetLeft() + 2, GetTop() + 2, Console.WindowWidth / 2 - 1, GetBottom() - 4, + GetLeft() + 2, GetTop() + 2, (Console.WindowWidth / 2) - 1, GetBottom() - 4, false, TextAlign.Center, th => th.PopupBg, @@ -51,7 +51,7 @@ public ModListHelpDialog() : base() )); ConsoleTextBox searchTb = new ConsoleTextBox( - Console.WindowWidth / 2 + 1, GetTop() + 3, GetRight() - 2, GetBottom() - 4, + (Console.WindowWidth / 2) + 1, GetTop() + 3, GetRight() - 2, GetBottom() - 4, false, TextAlign.Center, th => th.PopupBg, diff --git a/ConsoleUI/ModListScreen.cs b/ConsoleUI/ModListScreen.cs index 6c98c0baa6..60bcac5bd9 100644 --- a/ConsoleUI/ModListScreen.cs +++ b/ConsoleUI/ModListScreen.cs @@ -31,7 +31,7 @@ public ModListScreen(GameInstanceManager mgr, RepositoryDataManager repoData, Re debug = dbg; manager = mgr; this.regMgr = regMgr; - this.registry = regMgr.registry; + registry = regMgr.registry; this.repoData = repoData; moduleList = new ConsoleListBox( @@ -75,7 +75,9 @@ public ModListScreen(GameInstanceManager mgr, RepositoryDataManager repoData, Re if (filter.Length <= 1) { // Don't blank the list for just "~" by itself return true; - } else switch (filter.Substring(1, 1)) { + } else + { + switch (filter.Substring(1, 1)) { case "i": return registry.IsInstalled(m.identifier, false); case "u": @@ -106,6 +108,8 @@ public ModListScreen(GameInstanceManager mgr, RepositoryDataManager repoData, Re } return false; } + } + return false; } else { filter = CkanModule.nonAlphaNums.Replace(filter, ""); @@ -347,7 +351,7 @@ private bool ImportDownloads(ConsoleTheme theme) private bool CaptureKey(ConsoleTheme theme) { - ConsoleKeyInfo k = default(ConsoleKeyInfo); + ConsoleKeyInfo k = default; ConsoleMessageDialog keyprompt = new ConsoleMessageDialog(Properties.Resources.ModListPressAKey, new List()); keyprompt.Run(theme, (ConsoleTheme th) => { k = Console.ReadKey(true); @@ -435,11 +439,11 @@ private bool UpdateRegistry(ConsoleTheme theme, bool showNewModsPrompt = true) ); LaunchSubScreen(theme, ps, (ConsoleTheme th) => { HashSet availBefore = new HashSet( - Array.ConvertAll( + Array.ConvertAll( registry.CompatibleModules( manager.CurrentInstance.VersionCriteria() ).ToArray(), - (l => l.identifier) + l => l.identifier ) ); recent.Clear(); diff --git a/ConsoleUI/Program.cs b/ConsoleUI/Program.cs index 2f6e6f299b..da14b854ed 100644 --- a/ConsoleUI/Program.cs +++ b/ConsoleUI/Program.cs @@ -14,7 +14,9 @@ public static class ConsoleUI /// /// Command line arguments [STAThread] + #pragma warning disable IDE0060 public static void Main(string[] args) + #pragma warning restore IDE0060 { Main_(null, null); } diff --git a/ConsoleUI/RepoAddScreen.cs b/ConsoleUI/RepoAddScreen.cs index 0e3629f406..99e972a45c 100644 --- a/ConsoleUI/RepoAddScreen.cs +++ b/ConsoleUI/RepoAddScreen.cs @@ -23,12 +23,7 @@ public RepoAddScreen(IGame game, SortedDictionary reps) /// True if name and URL are valid, false otherwise. /// protected override bool Valid() - { - if (!nameValid() || !urlValid()) { - return false; - } - return true; - } + => nameValid() && urlValid(); /// /// Save the new Repository diff --git a/ConsoleUI/RepoEditScreen.cs b/ConsoleUI/RepoEditScreen.cs index 1807aab1ea..32349fab2d 100644 --- a/ConsoleUI/RepoEditScreen.cs +++ b/ConsoleUI/RepoEditScreen.cs @@ -28,17 +28,8 @@ public RepoEditScreen(IGame game, SortedDictionary reps, Rep /// True if valid, false otherwise /// protected override bool Valid() - { - if (name.Value != repository.name - && !nameValid()) { - return false; - } - if (url.Value != repository.uri.ToString() - && !urlValid()) { - return false; - } - return true; - } + => (name.Value == repository.name || nameValid()) + && (url.Value == repository.uri.ToString() || urlValid()); /// /// Save changes diff --git a/ConsoleUI/SingleAssemblyResourceManager.cs b/ConsoleUI/SingleAssemblyResourceManager.cs index 994305ec28..ecdf62c50d 100644 --- a/ConsoleUI/SingleAssemblyResourceManager.cs +++ b/ConsoleUI/SingleAssemblyResourceManager.cs @@ -1,7 +1,6 @@ using System.IO; using System.Globalization; using System.Resources; -using System.Collections; using System.Reflection; using System.Collections.Generic; @@ -9,12 +8,29 @@ namespace CKAN.ConsoleUI { // Thanks and credit to this guy: https://stackoverflow.com/q/1952638/2422988 - class SingleAssemblyResourceManager : ResourceManager + /// + /// Wrapper around ResourceManager that retrieves strings from the assembly + /// rather than external files + /// + public class SingleAssemblyResourceManager : ResourceManager { - public SingleAssemblyResourceManager(string basename, Assembly assembly) : base(basename, assembly) + /// + /// Initialize the resource manager + /// + /// To be passed to ResourceManager + /// To be passed to ResourceManager + public SingleAssemblyResourceManager(string basename, Assembly assembly) + : base(basename, assembly) { } + /// + /// Provides resources from the assembly to ResourceManager + /// + /// The language to get + /// Set to false to avoid loading if not already cached + /// Just gets passed to base class implementation + /// protected override ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents) { @@ -23,7 +39,7 @@ protected override ResourceSet InternalGetResourceSet(CultureInfo culture, // Lazy-load default language (without caring about duplicate assignment in race conditions, no harm done) if (neutralResourcesCulture == null) { - neutralResourcesCulture = GetNeutralResourcesLanguage(this.MainAssembly); + neutralResourcesCulture = GetNeutralResourcesLanguage(MainAssembly); } // If we're asking for the default language, then ask for the @@ -34,7 +50,7 @@ protected override ResourceSet InternalGetResourceSet(CultureInfo culture, } string resourceFileName = GetResourceFileName(culture); - Stream store = this.MainAssembly.GetManifestResourceStream(resourceFileName); + Stream store = MainAssembly.GetManifestResourceStream(resourceFileName); // If we found the appropriate resources in the local assembly if (store != null) diff --git a/ConsoleUI/Toolkit/ConsoleButton.cs b/ConsoleUI/Toolkit/ConsoleButton.cs index 98aea54123..010d95a369 100644 --- a/ConsoleUI/Toolkit/ConsoleButton.cs +++ b/ConsoleUI/Toolkit/ConsoleButton.cs @@ -35,12 +35,8 @@ public override void Draw(ConsoleTheme theme, bool focused) // Main button text Console.SetCursorPosition(GetLeft(), GetTop()); Console.BackgroundColor = theme.PopupButtonBg; - if (focused) { - Console.ForegroundColor = theme.PopupButtonSelectedFg; - } else { - Console.ForegroundColor = theme.PopupButtonFg; - } - Console.Write(ScreenObject.PadCenter(caption, w)); + Console.ForegroundColor = focused ? theme.PopupButtonSelectedFg : theme.PopupButtonFg; + Console.Write(PadCenter(caption, w)); // Right shadow if (theme.PopupButtonShadow.HasValue) @@ -93,8 +89,8 @@ public override void OnKeyPress(ConsoleKeyInfo k) } } - private string caption; - private Action choiceEvent; + private readonly string caption; + private readonly Action choiceEvent; private readonly string shadowStrip; } } diff --git a/ConsoleUI/Toolkit/ConsoleChoiceDialog.cs b/ConsoleUI/Toolkit/ConsoleChoiceDialog.cs index a9f493629b..50d4d19ab6 100644 --- a/ConsoleUI/Toolkit/ConsoleChoiceDialog.cs +++ b/ConsoleUI/Toolkit/ConsoleChoiceDialog.cs @@ -84,11 +84,11 @@ public ConsoleChoiceDialog(string m, string hdr, List c, Func process = null) { base.Run(theme, process); - return cancelled ? default(ChoiceT) : choices.Selection; + return cancelled ? default : choices.Selection; } - private ConsoleListBox choices; - private bool cancelled; + private readonly ConsoleListBox choices; + private bool cancelled; } } diff --git a/ConsoleUI/Toolkit/ConsoleDialog.cs b/ConsoleUI/Toolkit/ConsoleDialog.cs index 3a73809040..6bbd02b539 100644 --- a/ConsoleUI/Toolkit/ConsoleDialog.cs +++ b/ConsoleUI/Toolkit/ConsoleDialog.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; namespace CKAN.ConsoleUI.Toolkit { diff --git a/ConsoleUI/Toolkit/ConsoleDoubleFrame.cs b/ConsoleUI/Toolkit/ConsoleDoubleFrame.cs index d27a35db54..f77d3e8e94 100644 --- a/ConsoleUI/Toolkit/ConsoleDoubleFrame.cs +++ b/ConsoleUI/Toolkit/ConsoleDoubleFrame.cs @@ -91,11 +91,11 @@ private void writeTitleRow(string title, int w) /// public override bool Focusable() { return false; } - private Func getTopTitle; - private Func getMidTitle; - private Func getColor; - private bool doubleBorder; - private int middleRow; + private readonly Func getTopTitle; + private readonly Func getMidTitle; + private readonly Func getColor; + private readonly bool doubleBorder; + private readonly int middleRow; } } diff --git a/ConsoleUI/Toolkit/ConsoleField.cs b/ConsoleUI/Toolkit/ConsoleField.cs index 9e13ab1cf3..5aaf25fe3b 100644 --- a/ConsoleUI/Toolkit/ConsoleField.cs +++ b/ConsoleUI/Toolkit/ConsoleField.cs @@ -1,5 +1,4 @@ using System; -using CKAN.ConsoleUI.Toolkit; namespace CKAN.ConsoleUI.Toolkit { @@ -49,9 +48,7 @@ public ConsoleField(int l, int t, int r, string val = "") public event ChangeListener OnChange; private void Changed() { - if (OnChange != null) { - OnChange(this, Value); - } + OnChange?.Invoke(this, Value); } /// @@ -89,11 +86,9 @@ public override void Draw(ConsoleTheme theme, bool focused) Console.ForegroundColor = theme.FieldGhostFg; Console.Write(GhostText().PadRight(w)); } else { - if (focused) { - Console.ForegroundColor = theme.FieldFocusedFg; - } else { - Console.ForegroundColor = theme.FieldBlurredFg; - } + Console.ForegroundColor = focused + ? theme.FieldFocusedFg + : theme.FieldBlurredFg; Console.Write(FormatExactWidth(Value.Substring(leftPos), w)); } } @@ -126,11 +121,9 @@ public override void OnKeyPress(ConsoleKeyInfo k) break; case ConsoleKey.Delete: if (Position < Value.Length) { - if ((k.Modifiers & ConsoleModifiers.Control) == 0) { - Value = Value.Substring(0, Position) + Value.Substring(Position + 1); - } else { - Value = Value.Substring(0, Position); - } + Value = (k.Modifiers & ConsoleModifiers.Control) == 0 + ? Value.Substring(0, Position) + Value.Substring(Position + 1) + : Value.Substring(0, Position); Changed(); } break; @@ -160,7 +153,7 @@ public override void OnKeyPress(ConsoleKeyInfo k) Blur((k.Modifiers & ConsoleModifiers.Shift) == 0); break; default: - if (!Char.IsControl(k.KeyChar)) { + if (!char.IsControl(k.KeyChar)) { if (Position < Value.Length) { Value = Value.Substring(0, Position) + k.KeyChar + Value.Substring(Position); } else { diff --git a/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs b/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs index 1597e2eec9..36919347d0 100644 --- a/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs +++ b/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs @@ -24,9 +24,9 @@ public ConsoleFileMultiSelectDialog(string title, string startPath, string filPa curDir = new DirectoryInfo(startPath); filePattern = filPat; - int w = (Console.WindowWidth > idealW + 2 * hPad) + int w = (Console.WindowWidth > idealW + (2 * hPad)) ? idealW - : Console.WindowWidth - 2 * hPad; + : Console.WindowWidth - (2 * hPad); int left = (Console.WindowWidth - w) / 2; int right = -left; @@ -73,8 +73,8 @@ public ConsoleFileMultiSelectDialog(string title, string startPath, string filPa Width = 9, Renderer = (FileSystemInfo fi) => getLength(fi), Comparer = (a, b) => { - FileInfo fa = a as FileInfo, fb = b as FileInfo; - return fa == null + FileInfo fb = b as FileInfo; + return !(a is FileInfo fa) ? (fb == null ? 0 : -1) : (fb == null ? 1 : fa.Length.CompareTo(fb.Length)); } @@ -111,8 +111,8 @@ public ConsoleFileMultiSelectDialog(string title, string startPath, string filPa AddBinding(Keys.CtrlA, (object sender, ConsoleTheme theme) => { foreach (FileSystemInfo fi in contents) { if (!isDir(fi)) { - FileInfo file = fi as FileInfo; - if (file != null) { + if (fi is FileInfo file) + { chosenFiles.Add(file); } } @@ -137,18 +137,21 @@ public ConsoleFileMultiSelectDialog(string title, string startPath, string filPa private bool selectRow() { if (isDir(fileList.Selection)) { - DirectoryInfo di = fileList.Selection as DirectoryInfo; - if (di != null) { + if (fileList.Selection is DirectoryInfo di) + { curDir = di; pathField.Value = curDir.FullName; fileList.SetData(getFileList()); } } else { - FileInfo fi = fileList.Selection as FileInfo; - if (fi != null) { - if (chosenFiles.Contains(fi)) { + if (fileList.Selection is FileInfo fi) + { + if (chosenFiles.Contains(fi)) + { chosenFiles.Remove(fi); - } else { + } + else + { chosenFiles.Add(fi); } } @@ -226,18 +229,11 @@ private static bool pathEquals(FileSystemInfo a, FileSystemInfo b) } private string getLength(FileSystemInfo fi) - { - if (isDir(fi)) { - return Properties.Resources.FileSelectDirSize; - } else { - FileInfo file = fi as FileInfo; - if (file != null) { - return CkanModule.FmtSize(file.Length); - } else { - return Properties.Resources.FileSelectDirSize; - } - } - } + => isDir(fi) + ? Properties.Resources.FileSelectDirSize + : fi is FileInfo file + ? CkanModule.FmtSize(file.Length) + : Properties.Resources.FileSelectDirSize; private long totalChosenSize() { @@ -250,12 +246,9 @@ private long totalChosenSize() } private string getRowSymbol(FileSystemInfo fi) - { - if (!isDir(fi) && chosenFiles.Contains(fi as FileInfo)) { - return chosen; - } - return ""; - } + => !isDir(fi) && chosenFiles.Contains(fi as FileInfo) + ? chosen + : ""; private string getRowName(FileSystemInfo fi) { @@ -298,19 +291,19 @@ private int compareNames(FileSystemInfo a, FileSystemInfo b) } } - private List contents; - private ConsoleField pathField; - private ConsoleListBox fileList; - private DirectoryInfo curDir; + private List contents; + private readonly ConsoleField pathField; + private readonly ConsoleListBox fileList; + private DirectoryInfo curDir; - private HashSet chosenFiles = new HashSet(); + private readonly HashSet chosenFiles = new HashSet(); - private string filePattern; + private readonly string filePattern; private static readonly string chosen = Symbols.checkmark; private const int idealW = 76; - private int labelW => Properties.Resources.FileSelectDirectory.Length; + private int labelW => Properties.Resources.FileSelectDirectory.Length; private const int hPad = 2; private const int top = 2; private const int bottom = -2; diff --git a/ConsoleUI/Toolkit/ConsoleFrame.cs b/ConsoleUI/Toolkit/ConsoleFrame.cs index 1d9bc859b1..15a9c15c02 100644 --- a/ConsoleUI/Toolkit/ConsoleFrame.cs +++ b/ConsoleUI/Toolkit/ConsoleFrame.cs @@ -75,9 +75,9 @@ public override void Draw(ConsoleTheme theme, bool focused) /// public override bool Focusable() { return false; } - private Func getTitle; - private Func getColor; - private bool doubleBorder; + private readonly Func getTitle; + private readonly Func getColor; + private readonly bool doubleBorder; } } diff --git a/ConsoleUI/Toolkit/ConsoleLabel.cs b/ConsoleUI/Toolkit/ConsoleLabel.cs index a59f8678a0..ebbb9e95ac 100644 --- a/ConsoleUI/Toolkit/ConsoleLabel.cs +++ b/ConsoleUI/Toolkit/ConsoleLabel.cs @@ -33,16 +33,8 @@ public override void Draw(ConsoleTheme theme, bool focused) { int w = GetRight() - GetLeft() + 1; Console.SetCursorPosition(GetLeft(), GetTop()); - if (getBgColor == null) { - Console.BackgroundColor = theme.LabelBg; - } else { - Console.BackgroundColor = getBgColor(theme); - } - if (getFgColor == null) { - Console.ForegroundColor = theme.LabelFg; - } else { - Console.ForegroundColor = getFgColor(theme); - } + Console.BackgroundColor = getBgColor == null ? theme.LabelBg : getBgColor(theme); + Console.ForegroundColor = getFgColor == null ? theme.LabelFg : getFgColor(theme); try { Console.Write(FormatExactWidth(labelFunc(), w)); } catch (Exception ex) { @@ -55,9 +47,9 @@ public override void Draw(ConsoleTheme theme, bool focused) /// public override bool Focusable() { return false; } - private Func labelFunc; - private Func getBgColor; - private Func getFgColor; + private readonly Func labelFunc; + private readonly Func getBgColor; + private readonly Func getFgColor; } } diff --git a/ConsoleUI/Toolkit/ConsoleListBox.cs b/ConsoleUI/Toolkit/ConsoleListBox.cs index 38c4b6d44c..ba6581afed 100644 --- a/ConsoleUI/Toolkit/ConsoleListBox.cs +++ b/ConsoleUI/Toolkit/ConsoleListBox.cs @@ -82,15 +82,10 @@ public string FilterString { /// /// Currently selected row's object /// - public RowT Selection { - get { - if (selectedRow >= 0 && selectedRow < (sortedFilteredData?.Count ?? 0)) { - return sortedFilteredData[selectedRow]; - } else { - return default (RowT); - } - } - } + public RowT Selection + => selectedRow >= 0 && selectedRow < (sortedFilteredData?.Count ?? 0) + ? sortedFilteredData[selectedRow] + : default; /// /// Return the number of rows shown in the box @@ -201,7 +196,7 @@ public override void Draw(ConsoleTheme theme, bool focused) theme, r, t + scrollTop, b, sortedFilteredData.Count > 0 - ? t + 1 + scrollTop + (h - 2 - scrollTop) * selectedRow / sortedFilteredData.Count + ? t + 1 + scrollTop + ((h - 2 - scrollTop) * selectedRow / sortedFilteredData.Count) : -1 ); } @@ -251,7 +246,7 @@ public override void OnKeyPress(ConsoleKeyInfo k) break; default: // Go backwards if (k.Modifiers & ConsoleModifiers.Shift) - if (!Char.IsControl(k.KeyChar) + if (!char.IsControl(k.KeyChar) && (k.Modifiers | ConsoleModifiers.Shift) == ConsoleModifiers.Shift) { bool forward = (k.Modifiers & ConsoleModifiers.Shift) == 0; @@ -350,30 +345,21 @@ public void SetData(IList newData) } private string FmtHdr(int colIndex, int w) - { - ConsoleListBoxColumn col = columns[colIndex]; - if (colIndex == sortColIndex) { - return FormatExactWidth( - col.Header + " " + (sortDir == ListSortDirection.Ascending ? sortUp : sortDown), - w - ); - } else { - return FormatExactWidth(col.Header, w); - } - } + => colIndex == sortColIndex + ? FormatExactWidth( + columns[colIndex].Header + " " + + (sortDir == ListSortDirection.Ascending ? sortUp : sortDown), + w) + : FormatExactWidth(columns[colIndex].Header, w); private void filterAndSort() { // Keep the same row highlighted when the number of rows changes RowT oldSelect = Selection; - if (string.IsNullOrEmpty(filterStr) || filterCheck == null) { - sortedFilteredData = new List(data); - } else { - sortedFilteredData = new List(data).FindAll( - r => filterCheck(r, filterStr) - ); - } + sortedFilteredData = string.IsNullOrEmpty(filterStr) || filterCheck == null + ? new List(data) + : new List(data).FindAll(r => filterCheck(r, filterStr)); // Semantic sort for versions rather than lexicographical if (sortColIndex >= 0 && sortColIndex < columns.Count) { @@ -395,40 +381,31 @@ private void filterAndSort() } private Comparison getComparer(ConsoleListBoxColumn col, bool ascending) - { - if (ascending) { - return col.Comparer - ?? ((a, b) => col.Renderer(a).Trim().CompareTo(col.Renderer(b).Trim())); - - } else if (col.Comparer != null) { - return (a, b) => col.Comparer(b, a); - } else { - return (a, b) => col.Renderer(b).Trim().CompareTo(col.Renderer(a).Trim()); - } - } + => ascending + ? col.Comparer + ?? ((a, b) => col.Renderer(a).Trim().CompareTo(col.Renderer(b).Trim())) + : col.Comparer != null + ? (Comparison)((RowT a, RowT b) => col.Comparer(b, a)) + : ((RowT a, RowT b) => col.Renderer(b).Trim().CompareTo(col.Renderer(a).Trim())); // Sometimes type safety can be a minor hindrance; // this would just be "first || second" in C private int IntOr(Func first, Func second) { int a = first(); - if (a != 0) { - return a; - } else { - return second(); - } + return a != 0 ? a : second(); } - private List sortedFilteredData; - private IList data; - private IList> columns; - private Func filterCheck; - private ConsolePopupMenu sortMenu; + private List sortedFilteredData; + private IList data; + private readonly IList> columns; + private readonly Func filterCheck; + private ConsolePopupMenu sortMenu; - private int defaultSortColumn = 0; - private int sortColIndex; - private ListSortDirection sortDir; - private string filterStr = ""; + private readonly int defaultSortColumn = 0; + private int sortColIndex; + private ListSortDirection sortDir; + private string filterStr = ""; private int topRow = 0; private int selectedRow = 0; diff --git a/ConsoleUI/Toolkit/ConsoleMessageDialog.cs b/ConsoleUI/Toolkit/ConsoleMessageDialog.cs index ef8126ce06..7f34d14a8e 100644 --- a/ConsoleUI/Toolkit/ConsoleMessageDialog.cs +++ b/ConsoleUI/Toolkit/ConsoleMessageDialog.cs @@ -27,7 +27,7 @@ public ConsoleMessageDialog(string m, List btns, Func hdr = null CenterHeader = hdr; } - int btnW = btns.Count * buttonWidth + (btns.Count - 1) * buttonPadding; + int btnW = (btns.Count * buttonWidth) + ((btns.Count - 1) * buttonPadding); if (w < btnW + 4) { // Widen the window to fit the buttons // Buttons will NOT wrap - use ConsoleChoiceDialog @@ -46,13 +46,13 @@ public ConsoleMessageDialog(string m, List btns, Func hdr = null // Calculate vertical position including offset int t, b; if (vertOffset <= 0) { - t = (Console.WindowHeight - h) / 2 + vertOffset; + t = ((Console.WindowHeight - h) / 2) + vertOffset; if (t < 1) { t = 2; } b = t + h - 1; } else { - b = (Console.WindowHeight - h) / 2 + h - 1; + b = ((Console.WindowHeight - h) / 2) + h - 1; if (b >= Console.WindowHeight - 1) { b = Console.WindowHeight - 1; } diff --git a/ConsoleUI/Toolkit/ConsolePopupMenu.cs b/ConsoleUI/Toolkit/ConsolePopupMenu.cs index c1558d9fe5..3d8026d91e 100644 --- a/ConsoleUI/Toolkit/ConsolePopupMenu.cs +++ b/ConsoleUI/Toolkit/ConsolePopupMenu.cs @@ -66,13 +66,10 @@ public bool Run(ConsoleTheme theme, int right, int top) if (options[selectedOption].OnExec != null) { val = options[selectedOption].OnExec(theme); } - if (options[selectedOption].SubMenu != null) { - options[selectedOption].SubMenu.Run( + options[selectedOption].SubMenu?.Run( theme, right - 2, - top + selectedOption + 2 - ); - } + top + selectedOption + 2); break; case ConsoleKey.F10: case ConsoleKey.Escape: @@ -156,23 +153,17 @@ private void DrawFooter(ConsoleTheme theme) } private string AnnotatedCaption(ConsoleMenuOption opt) - { - if (opt.SubMenu != null) { - return opt.Caption.PadRight(longestLength - 1) + submenuIndicator; - } else if (opt.RadioActive != null) { - if (opt.RadioActive()) { - return $"({Symbols.dot}) {opt.Caption}".PadRight(longestLength); - } else { - return $"( ) {opt.Caption}".PadRight(longestLength); - } - } else { - return opt.Caption.PadRight(longestLength - opt.Key.Length) + opt.Key; - } - } + => opt.SubMenu != null + ? opt.Caption.PadRight(longestLength - 1) + submenuIndicator + : opt.RadioActive != null + ? opt.RadioActive() + ? $"({Symbols.dot}) {opt.Caption}".PadRight(longestLength) + : $"( ) {opt.Caption}".PadRight(longestLength) + : opt.Caption.PadRight(longestLength - opt.Key.Length) + opt.Key; - private List options; - private int longestLength; - private int selectedOption = 0; + private readonly List options; + private readonly int longestLength; + private int selectedOption = 0; private static readonly string submenuIndicator = ">"; } diff --git a/ConsoleUI/Toolkit/ConsoleProgressBar.cs b/ConsoleUI/Toolkit/ConsoleProgressBar.cs index 77f93b35a5..ac07f3579b 100644 --- a/ConsoleUI/Toolkit/ConsoleProgressBar.cs +++ b/ConsoleUI/Toolkit/ConsoleProgressBar.cs @@ -63,8 +63,8 @@ public override void Draw(ConsoleTheme theme, bool focused) /// public override bool Focusable() { return false; } - private Func captionFunc; - private Func percentFunc; + private readonly Func captionFunc; + private readonly Func percentFunc; } } diff --git a/ConsoleUI/Toolkit/ConsoleScreen.cs b/ConsoleUI/Toolkit/ConsoleScreen.cs index 7eeb1cf8e5..d51e48f4a1 100644 --- a/ConsoleUI/Toolkit/ConsoleScreen.cs +++ b/ConsoleUI/Toolkit/ConsoleScreen.cs @@ -78,7 +78,7 @@ protected virtual string MenuTip() /// /// Tell IUser clients that we have the ability to interact with the user /// - public bool Headless { get { return false; } } + public bool Headless => false; // These functions can be implemented the same on all screens, // so they are not virtual. @@ -128,7 +128,7 @@ public int RaiseSelectionDialog(string message, params object[] args) { ConsoleMessageDialog d = new ConsoleMessageDialog( string.Join("", messagePieces) + message, - new List(Array.ConvertAll(args, p => p.ToString())) + new List(Array.ConvertAll(args, p => p.ToString())) ); messagePieces.Clear(); int val = d.Run(userTheme); @@ -191,7 +191,7 @@ protected virtual void Message(string message, params object[] args) // But there's nothing intrinsic to the API that tells us which strings // to combine. So we'll just save them all and then combine them // when a function is called that takes input. - private List messagePieces = new List(); + private readonly List messagePieces = new List(); /// /// Update a user visible progress bar diff --git a/ConsoleUI/Toolkit/ConsoleTextBox.cs b/ConsoleUI/Toolkit/ConsoleTextBox.cs index 8e9418c7fe..5a4c8466e4 100644 --- a/ConsoleUI/Toolkit/ConsoleTextBox.cs +++ b/ConsoleUI/Toolkit/ConsoleTextBox.cs @@ -68,7 +68,7 @@ private void rewrapLines() prevTextW = w; int h = GetBottom() - GetTop() + 1; float scrollFrac = displayLines.Count > h - ? (float)topLine / ((float)displayLines.Count - h) + ? topLine / ((float)displayLines.Count - h) : 0; displayLines.Clear(); foreach (string line in lines) { @@ -140,16 +140,8 @@ public override void Draw(ConsoleTheme theme, bool focused) rewrapLines(); } - if (getBgColor != null) { - Console.BackgroundColor = getBgColor(theme); - } else { - Console.BackgroundColor = theme.TextBoxBg; - } - if (getFgColor != null) { - Console.ForegroundColor = getFgColor(theme); - } else { - Console.ForegroundColor = theme.TextBoxFg; - } + Console.BackgroundColor = getBgColor != null ? getBgColor(theme) : theme.TextBoxBg; + Console.ForegroundColor = getFgColor != null ? getFgColor(theme) : theme.TextBoxFg; for (int y = GetTop(); y <= GetBottom(); ++y, ++index) { Console.SetCursorPosition(l, y); if (index < displayLines.Count) { @@ -158,7 +150,7 @@ public override void Draw(ConsoleTheme theme, bool focused) Console.Write(displayLines[index].PadRight(w)); break; case TextAlign.Center: - Console.Write(ScreenObject.PadCenter(displayLines[index], w)); + Console.Write(PadCenter(displayLines[index], w)); break; case TextAlign.Right: Console.Write(displayLines[index].PadLeft(w)); @@ -174,7 +166,7 @@ public override void Draw(ConsoleTheme theme, bool focused) DrawScrollbar( theme, GetRight(), GetTop(), GetBottom(), - GetTop() + 1 + (h - 3) * topLine / (displayLines.Count - h) + GetTop() + 1 + ((h - 3) * topLine / (displayLines.Count - h)) ); } } @@ -252,13 +244,13 @@ public void AddScrollBindings(ScreenContainer cont, bool drawMore = false) private bool needScroll = false; private int prevTextW; - private bool scrollToBottom; + private readonly bool scrollToBottom; private int topLine; - private TextAlign align; - private SynchronizedCollection lines = new SynchronizedCollection(); - private SynchronizedCollection displayLines = new SynchronizedCollection(); - private Func getBgColor; - private Func getFgColor; + private readonly TextAlign align; + private readonly SynchronizedCollection lines = new SynchronizedCollection(); + private readonly SynchronizedCollection displayLines = new SynchronizedCollection(); + private readonly Func getBgColor; + private readonly Func getFgColor; } /// diff --git a/ConsoleUI/Toolkit/Formatting.cs b/ConsoleUI/Toolkit/Formatting.cs index 390992914d..a23998c44d 100644 --- a/ConsoleUI/Toolkit/Formatting.cs +++ b/ConsoleUI/Toolkit/Formatting.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text.RegularExpressions; namespace CKAN.ConsoleUI.Toolkit { diff --git a/ConsoleUI/Toolkit/Keys.cs b/ConsoleUI/Toolkit/Keys.cs index 09bfcd3236..51976202a6 100644 --- a/ConsoleUI/Toolkit/Keys.cs +++ b/ConsoleUI/Toolkit/Keys.cs @@ -7,8 +7,8 @@ namespace CKAN.ConsoleUI.Toolkit { /// public static class Keys { - private const char LinuxEnter = (Char)10; - private const char WindowsEnter = (Char)13; + private const char LinuxEnter = (char)10; + private const char WindowsEnter = (char)13; /// /// Representation of enter key for key bindings @@ -29,98 +29,98 @@ public static class Keys { /// Representation of escape key for key bindings /// public static readonly ConsoleKeyInfo Escape = new ConsoleKeyInfo( - (Char)27, ConsoleKey.Escape, false, false, false + (char)27, ConsoleKey.Escape, false, false, false ); /// /// Representation of F1 for key bindings /// public static readonly ConsoleKeyInfo F1 = new ConsoleKeyInfo( - (Char)0, ConsoleKey.F1, false, false, false + (char)0, ConsoleKey.F1, false, false, false ); /// /// Representation of F2 for key bindings /// public static readonly ConsoleKeyInfo F2 = new ConsoleKeyInfo( - (Char)0, ConsoleKey.F2, false, false, false + (char)0, ConsoleKey.F2, false, false, false ); /// /// Representation of F5 for key bindings /// public static readonly ConsoleKeyInfo F5 = new ConsoleKeyInfo( - (Char)0, ConsoleKey.F5, false, false, false + (char)0, ConsoleKey.F5, false, false, false ); /// /// Representation of F8 for key bindings /// public static readonly ConsoleKeyInfo F8 = new ConsoleKeyInfo( - (Char)0, ConsoleKey.F8, false, false, false + (char)0, ConsoleKey.F8, false, false, false ); /// /// Representation of F9 for key bindings /// public static readonly ConsoleKeyInfo F9 = new ConsoleKeyInfo( - (Char)0, ConsoleKey.F9, false, false, false + (char)0, ConsoleKey.F9, false, false, false ); /// /// Representation of F10 for key bindings /// public static readonly ConsoleKeyInfo F10 = new ConsoleKeyInfo( - (Char)0, ConsoleKey.F10, false, false, false + (char)0, ConsoleKey.F10, false, false, false ); /// /// Representation of Apps for key bindings /// public static readonly ConsoleKeyInfo Apps = new ConsoleKeyInfo( - (Char)0, ConsoleKey.Applications, false, false, false + (char)0, ConsoleKey.Applications, false, false, false ); /// /// Representation of down arrow for key bindings /// public static readonly ConsoleKeyInfo DownArrow = new ConsoleKeyInfo( - (Char)0, ConsoleKey.DownArrow, false, false, false + (char)0, ConsoleKey.DownArrow, false, false, false ); /// /// Representation of up arrow for key bindings /// public static readonly ConsoleKeyInfo UpArrow = new ConsoleKeyInfo( - (Char)0, ConsoleKey.UpArrow, false, false, false + (char)0, ConsoleKey.UpArrow, false, false, false ); /// /// Representation of home for key bindings /// public static readonly ConsoleKeyInfo Home = new ConsoleKeyInfo( - (Char)0, ConsoleKey.Home, false, false, false + (char)0, ConsoleKey.Home, false, false, false ); /// /// Representation of end for key bindings /// public static readonly ConsoleKeyInfo End = new ConsoleKeyInfo( - (Char)0, ConsoleKey.End, false, false, false + (char)0, ConsoleKey.End, false, false, false ); /// /// Representation of page up for key bindings /// public static readonly ConsoleKeyInfo PageUp = new ConsoleKeyInfo( - (Char)0, ConsoleKey.PageUp, false, false, false + (char)0, ConsoleKey.PageUp, false, false, false ); /// /// Representation of page down for key bindings /// public static readonly ConsoleKeyInfo PageDown = new ConsoleKeyInfo( - (Char)0, ConsoleKey.PageDown, false, false, false + (char)0, ConsoleKey.PageDown, false, false, false ); /// @@ -129,11 +129,11 @@ public static class Keys { /// public static readonly ConsoleKeyInfo[] Plus = new ConsoleKeyInfo[] { new ConsoleKeyInfo( - (Char)'+', + '+', Platform.IsWindows ? ConsoleKey.OemPlus : ConsoleKey.Add, false, false, false ), new ConsoleKeyInfo( - (Char)'+', + '+', Platform.IsWindows ? ConsoleKey.OemPlus : ConsoleKey.Add, true, false, false ) @@ -143,7 +143,7 @@ public static class Keys { /// Representation of minus key for key bindings /// public static readonly ConsoleKeyInfo Minus = new ConsoleKeyInfo( - (Char)'-', + '-', Platform.IsWindows ? ConsoleKey.OemMinus : ConsoleKey.Subtract, false, false, false ); @@ -152,56 +152,56 @@ public static class Keys { /// Representation of Ctrl+A for key bindings /// public static readonly ConsoleKeyInfo CtrlA = new ConsoleKeyInfo( - (Char)1, ConsoleKey.A, false, false, true + (char)1, ConsoleKey.A, false, false, true ); /// /// Representation of Ctrl+D for key bindings /// public static readonly ConsoleKeyInfo CtrlD = new ConsoleKeyInfo( - (Char)4, ConsoleKey.D, false, false, true + (char)4, ConsoleKey.D, false, false, true ); /// /// Representation of Ctrl+F for key bindings /// public static readonly ConsoleKeyInfo CtrlF = new ConsoleKeyInfo( - (Char)6, ConsoleKey.F, false, false, true + (char)6, ConsoleKey.F, false, false, true ); /// /// Representation of Ctrl+L for key bindings /// public static readonly ConsoleKeyInfo CtrlL = new ConsoleKeyInfo( - (Char)12, ConsoleKey.Clear, false, false, false + (char)12, ConsoleKey.Clear, false, false, false ); /// /// Representation of Ctrl+Q for key bindings /// public static readonly ConsoleKeyInfo CtrlQ = new ConsoleKeyInfo( - (Char)17, ConsoleKey.Q, false, false, true + (char)17, ConsoleKey.Q, false, false, true ); /// /// Representation of Ctrl+R for key bindings /// public static readonly ConsoleKeyInfo CtrlR = new ConsoleKeyInfo( - (Char)18, ConsoleKey.R, false, false, true + (char)18, ConsoleKey.R, false, false, true ); /// /// Representation of Ctrl+U for key bindings /// public static readonly ConsoleKeyInfo CtrlU = new ConsoleKeyInfo( - (Char)21, ConsoleKey.U, false, false, true + (char)21, ConsoleKey.U, false, false, true ); /// /// Representation of Alt+H for key bindings /// public static readonly ConsoleKeyInfo AltH = new ConsoleKeyInfo( - (Char)'h', ConsoleKey.H, false, true, false + 'h', ConsoleKey.H, false, true, false ); /// @@ -209,49 +209,49 @@ public static class Keys { /// Does not work on MacOSX, so we /// public static readonly ConsoleKeyInfo AltX = new ConsoleKeyInfo( - (Char)'x', ConsoleKey.X, false, true, false + 'x', ConsoleKey.X, false, true, false ); /// /// Representation of letter 'a' for key bindings /// public static readonly ConsoleKeyInfo A = new ConsoleKeyInfo( - (Char)'a', ConsoleKey.A, false, false, false + 'a', ConsoleKey.A, false, false, false ); /// /// Representation of letter 'd' for key bindings /// public static readonly ConsoleKeyInfo D = new ConsoleKeyInfo( - (Char)'d', ConsoleKey.D, false, false, false + 'd', ConsoleKey.D, false, false, false ); /// /// Representation of letter 'e' for key bindings /// public static readonly ConsoleKeyInfo E = new ConsoleKeyInfo( - (Char)'e', ConsoleKey.E, false, false, false + 'e', ConsoleKey.E, false, false, false ); /// /// Representation of letter 'n' for key bindings /// public static readonly ConsoleKeyInfo N = new ConsoleKeyInfo( - (Char)'n', ConsoleKey.N, false, false, false + 'n', ConsoleKey.N, false, false, false ); /// /// Representation of letter 'r' for key bindings /// public static readonly ConsoleKeyInfo R = new ConsoleKeyInfo( - (Char)'r', ConsoleKey.R, false, false, false + 'r', ConsoleKey.R, false, false, false ); /// /// Representation of letter 'y' for key bindings /// public static readonly ConsoleKeyInfo Y = new ConsoleKeyInfo( - (Char)'y', ConsoleKey.Y, false, false, false + 'y', ConsoleKey.Y, false, false, false ); } diff --git a/ConsoleUI/Toolkit/ScreenContainer.cs b/ConsoleUI/Toolkit/ScreenContainer.cs index efb10c2e77..802b9e1530 100644 --- a/ConsoleUI/Toolkit/ScreenContainer.cs +++ b/ConsoleUI/Toolkit/ScreenContainer.cs @@ -176,13 +176,9 @@ protected void Interact(ConsoleTheme theme) /// Currently focused ScreenObject /// protected ScreenObject Focused() - { - if (focusIndex >= 0 && focusIndex < objects.Count) { - return objects[focusIndex]; - } else { - return null; - } - } + => focusIndex >= 0 && focusIndex < objects.Count + ? objects[focusIndex] + : null; /// /// Set the focus to a given ScreenObject @@ -222,12 +218,9 @@ private void DrawFooter(ConsoleTheme theme) Console.ForegroundColor = theme.FooterKeyFg; Console.Write(tipList[i].Key); Console.ForegroundColor = theme.FooterDescriptionFg; - string remainder; - if (tipList[i].Key == tipList[i].Description.Substring(0, 1)) { - remainder = tipList[i].Description.Substring(1); - } else { - remainder = $" - {tipList[i].Description}"; - } + string remainder = tipList[i].Key == tipList[i].Description.Substring(0, 1) + ? tipList[i].Description.Substring(1) + : $" - {tipList[i].Description}"; int maxW = Console.WindowWidth - Console.CursorLeft - 1; if (remainder.Length > maxW && maxW > 0) { Console.Write(remainder.Substring(0, maxW)); @@ -251,23 +244,21 @@ private void Blur(ScreenObject source, bool forward) focusIndex = 0; break; } - if (forward) { - focusIndex = (focusIndex + 1) % objects.Count; - } else { - focusIndex = (focusIndex + objects.Count - 1) % objects.Count; - } + focusIndex = forward + ? (focusIndex + 1) % objects.Count + : (focusIndex + objects.Count - 1) % objects.Count; } while (!objects[focusIndex].Focusable()); } } private bool done = false; - private List objects = new List(); + private readonly List objects = new List(); private int focusIndex = 0; - private Dictionary bindings = new Dictionary(); - private List tips = new List(); - private object screenLock = new object(); + private readonly Dictionary bindings = new Dictionary(); + private readonly List tips = new List(); + private readonly object screenLock = new object(); private static readonly string tipSeparator = $" {Symbols.vertLine} "; } @@ -287,7 +278,7 @@ public ScreenTip(string key, string descrip, Func dispIf = null) { Key = key; Description = descrip; - DisplayIf = dispIf != null ? dispIf : () => true; + DisplayIf = dispIf ?? (() => true); } /// diff --git a/ConsoleUI/Toolkit/ScreenObject.cs b/ConsoleUI/Toolkit/ScreenObject.cs index 169c7a0a9f..f13b6bf35c 100644 --- a/ConsoleUI/Toolkit/ScreenObject.cs +++ b/ConsoleUI/Toolkit/ScreenObject.cs @@ -69,15 +69,15 @@ public static string TruncateLength(string val, int w) /// /// Custom key bindings for this UI element /// - public Dictionary Bindings = - new Dictionary(); + public Dictionary Bindings = + new Dictionary(); /// /// Add a custom key binding /// /// Key to bind /// Action to bind to key - public void AddBinding(ConsoleKeyInfo k, ConsoleScreen.KeyAction a) + public void AddBinding(ConsoleKeyInfo k, ScreenContainer.KeyAction a) { Bindings.Add(k, a); } @@ -87,7 +87,7 @@ public void AddBinding(ConsoleKeyInfo k, ConsoleScreen.KeyAction a) /// /// Keys to bind /// Action to bind to key - public void AddBinding(IEnumerable keys, ConsoleScreen.KeyAction a) + public void AddBinding(IEnumerable keys, ScreenContainer.KeyAction a) { foreach (ConsoleKeyInfo k in keys) { AddBinding(k, a); @@ -189,12 +189,10 @@ public virtual void OnKeyPress(ConsoleKeyInfo k) { } /// protected void Blur(bool forward) { - if (OnBlur != null) { - OnBlur(this, forward); - } + OnBlur?.Invoke(this, forward); } - private int left, top, right, bottom; + private readonly int left, top, right, bottom; private static readonly string scrollUp = "^"; private static readonly string scrollDown = "v"; diff --git a/Core/CKAN-core.csproj b/Core/CKAN-core.csproj index 9be3f782ad..6bb5d4e083 100644 --- a/Core/CKAN-core.csproj +++ b/Core/CKAN-core.csproj @@ -1,7 +1,8 @@ CKAN - ..\_build\out\$(AssemblyName)\$(Configuration)\bin\ + ..\_build\out\$(AssemblyName)\$(Configuration)\bin\ + ..\_build\out\$(AssemblyName)\VSCodeIDE\bin\ ..\_build\out\$(AssemblyName)\$(Configuration)\obj\ @@ -14,18 +15,18 @@ true Debug;Release;Debug_NetCore;Release_NetCore false - 7 + 7.3 IDE1006 - net5.0 + net7.0 - net45 + net48 @@ -44,14 +45,14 @@ - + - + diff --git a/Core/CKANPathUtils.cs b/Core/CKANPathUtils.cs index 1e8286347b..bbef46c3aa 100644 --- a/Core/CKANPathUtils.cs +++ b/Core/CKANPathUtils.cs @@ -126,11 +126,9 @@ public static string GetLeadingPathElements(string path) { path = NormalizePath(path); - if (Regex.IsMatch(path, "/")) - { - return Regex.Replace(path, @"(^.*)/.+", "$1"); - } - return String.Empty; + return Regex.IsMatch(path, "/") + ? Regex.Replace(path, @"(^.*)/.+", "$1") + : string.Empty; } /// @@ -188,7 +186,7 @@ public static string ToAbsolute(string path, string root) { throw new PathErrorKraken( path, - String.Format(Properties.Resources.PathUtilsAlreadyAbsolute, path) + string.Format(Properties.Resources.PathUtilsAlreadyAbsolute, path) ); } @@ -196,7 +194,7 @@ public static string ToAbsolute(string path, string root) { throw new PathErrorKraken( root, - String.Format(Properties.Resources.PathUtilsNotRoot, root) + string.Format(Properties.Resources.PathUtilsNotRoot, root) ); } diff --git a/Core/CompatibleGameVersions.cs b/Core/CompatibleGameVersions.cs index d03b516882..ec5c4ea4bb 100644 --- a/Core/CompatibleGameVersions.cs +++ b/Core/CompatibleGameVersions.cs @@ -5,7 +5,7 @@ namespace CKAN { [JsonConverter(typeof(CompatibleGameVersionsConverter))] - class CompatibleGameVersions + public class CompatibleGameVersions { public string GameVersionWhenWritten { get; set; } diff --git a/Core/Configuration/JsonConfiguration.cs b/Core/Configuration/JsonConfiguration.cs index 5478f20524..526f0e35f2 100644 --- a/Core/Configuration/JsonConfiguration.cs +++ b/Core/Configuration/JsonConfiguration.cs @@ -78,10 +78,7 @@ private class GameInstanceEntry // // Where the config file is located. // - public string ConfigFile - { - get => configFile; - } + public string ConfigFile => configFile; public string DownloadCacheDir { @@ -128,14 +125,7 @@ public long? CacheSizeLimit { lock (_lock) { - if (value < 0) - { - config.CacheSizeLimit = null; - } - else - { - config.CacheSizeLimit = value; - } + config.CacheSizeLimit = value < 0 ? null : value; SaveConfig(); } @@ -156,14 +146,7 @@ public int RefreshRate { lock (_lock) { - if (value <= 0) - { - config.RefreshRate = null; - } - else - { - config.RefreshRate = value; - } + config.RefreshRate = value <= 0 ? null : (int?)value; SaveConfig(); } diff --git a/Core/Configuration/Win32RegistryConfiguration.cs b/Core/Configuration/Win32RegistryConfiguration.cs index cf86f886e7..92dbbdffc5 100644 --- a/Core/Configuration/Win32RegistryConfiguration.cs +++ b/Core/Configuration/Win32RegistryConfiguration.cs @@ -22,7 +22,7 @@ public class Win32RegistryConfiguration : IConfiguration public string DownloadCacheDir { - get { return GetRegistryValue(@"DownloadCacheDir", defaultDownloadCacheDir); } + get => GetRegistryValue(@"DownloadCacheDir", defaultDownloadCacheDir); set { if (string.IsNullOrEmpty(value)) @@ -62,7 +62,7 @@ public long? CacheSizeLimit public int RefreshRate { - get { return GetRegistryValue(@"RefreshRate", 0); } + get => GetRegistryValue(@"RefreshRate", 0); set { if (value <= 0) @@ -76,24 +76,25 @@ public int RefreshRate } } - private int InstanceCount - { - get { return GetRegistryValue(@"KSPInstanceCount", 0); } - } + private int InstanceCount => GetRegistryValue(@"KSPInstanceCount", 0); public string AutoStartInstance { - get { return GetRegistryValue(@"KSPAutoStartInstance", ""); } - set { SetAutoStartInstance(value??String.Empty); } + get => GetRegistryValue(@"KSPAutoStartInstance", ""); + #pragma warning disable IDE0027 + set { SetAutoStartInstance(value ?? string.Empty); } + #pragma warning restore IDE0027 } public string Language { - get { return GetRegistryValue("Language", null); } + get => GetRegistryValue("Language", null); set { if (Utilities.AvailableLanguages.Contains(value)) + { SetRegistryValue("Language", value); + } } } diff --git a/Core/Converters/JsonIgnoreBadUrlConverter.cs b/Core/Converters/JsonIgnoreBadUrlConverter.cs index b34afb15f7..c68b9393f6 100644 --- a/Core/Converters/JsonIgnoreBadUrlConverter.cs +++ b/Core/Converters/JsonIgnoreBadUrlConverter.cs @@ -18,7 +18,9 @@ public override object ReadJson( string value = reader.Value?.ToString(); if (value == null) + { return null; + } try { @@ -43,10 +45,7 @@ public override bool CanConvert(Type object_type) /// Opt out of writing anything, otherwise things go horribly wrong when we try /// to write to the registry. /// - public override bool CanWrite - { - get { return false; } - } + public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { diff --git a/Core/Converters/JsonOldResourceUrlConverter.cs b/Core/Converters/JsonOldResourceUrlConverter.cs index 3f9345cef1..d68ae18ef7 100644 --- a/Core/Converters/JsonOldResourceUrlConverter.cs +++ b/Core/Converters/JsonOldResourceUrlConverter.cs @@ -32,10 +32,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist return token.ToObject(); } - public override bool CanWrite - { - get { return false; } - } + public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { @@ -44,4 +41,3 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s } } - diff --git a/Core/Converters/JsonPropertyNamesChangedConverter.cs b/Core/Converters/JsonPropertyNamesChangedConverter.cs index a9e125567b..1c169102d4 100644 --- a/Core/Converters/JsonPropertyNamesChangedConverter.cs +++ b/Core/Converters/JsonPropertyNamesChangedConverter.cs @@ -53,8 +53,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist var changes = mapping; foreach (JProperty jp in jo.Properties()) { - string name; - if (!changes.TryGetValue(jp.Name, out name)) + if (!changes.TryGetValue(jp.Name, out string name)) { name = jp.Name; } @@ -72,12 +71,9 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist // No property, maybe there's a field FieldInfo field = objectType.GetTypeInfo().DeclaredFields.FirstOrDefault(fi => (fi.GetCustomAttribute()?.PropertyName ?? fi.Name) == name); - if (field != null) - { - field.SetValue(instance, - GetValue(field.GetCustomAttribute(), - jp.Value, field.FieldType, serializer)); - } + field?.SetValue(instance, + GetValue(field.GetCustomAttribute(), + jp.Value, field.FieldType, serializer)); } } return instance; diff --git a/Core/Converters/JsonRelationshipConverter.cs b/Core/Converters/JsonRelationshipConverter.cs index 058d1d0dca..7d5ca3a553 100644 --- a/Core/Converters/JsonRelationshipConverter.cs +++ b/Core/Converters/JsonRelationshipConverter.cs @@ -46,13 +46,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist return null; } - public override bool CanWrite - { - get - { - return false; - } - } + public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { diff --git a/Core/Exporters/DelimeterSeparatedValueExporter.cs b/Core/Exporters/DelimeterSeparatedValueExporter.cs index 83edad6e22..fa9648082e 100644 --- a/Core/Exporters/DelimeterSeparatedValueExporter.cs +++ b/Core/Exporters/DelimeterSeparatedValueExporter.cs @@ -83,71 +83,39 @@ public void Export(IRegistryQuerier registry, Stream stream) } private string WriteUri(Uri uri) - { - return uri != null ? QuoteIfNecessary(uri.ToString()) : string.Empty; - } + => uri != null + ? QuoteIfNecessary(uri.ToString()) + : string.Empty; private string WriteRepository(ResourcesDescriptor resources) - { - if (resources != null && resources.repository != null) - { - return QuoteIfNecessary(resources.repository.ToString()); - } - - return string.Empty; - } + => resources != null && resources.repository != null + ? QuoteIfNecessary(resources.repository.ToString()) + : string.Empty; private string WriteHomepage(ResourcesDescriptor resources) - { - if (resources != null && resources.homepage != null) - { - return QuoteIfNecessary(resources.homepage.ToString()); - } - - return string.Empty; - } + => resources != null && resources.homepage != null + ? QuoteIfNecessary(resources.homepage.ToString()) + : string.Empty; private string WriteBugtracker(ResourcesDescriptor resources) - { - if (resources != null && resources.bugtracker != null) - { - return QuoteIfNecessary(resources.bugtracker.ToString()); - } - - return string.Empty; - } + => resources != null && resources.bugtracker != null + ? QuoteIfNecessary(resources.bugtracker.ToString()) + : string.Empty; private string WriteSpaceDock(ResourcesDescriptor resources) - { - if (resources != null && resources.spacedock != null) - { - return QuoteIfNecessary(resources.spacedock.ToString()); - } - - return string.Empty; - } + => resources != null && resources.spacedock != null + ? QuoteIfNecessary(resources.spacedock.ToString()) + : string.Empty; private string WriteCurse(ResourcesDescriptor resources) - { - if (resources != null && resources.curse != null) - { - return QuoteIfNecessary(resources.curse.ToString()); - } - - return string.Empty; - } + => resources != null && resources.curse != null + ? QuoteIfNecessary(resources.curse.ToString()) + : string.Empty; private string QuoteIfNecessary(string value) - { - if (value != null && value.IndexOf(_delimeter, StringComparison.Ordinal) >= 0) - { - return "\"" + value + "\""; - } - else - { - return value; - } - } + => value != null && value.IndexOf(_delimeter, StringComparison.Ordinal) >= 0 + ? "\"" + value + "\"" + : value; public enum Delimeter { diff --git a/Core/Extensions/CryptoExtensions.cs b/Core/Extensions/CryptoExtensions.cs index 9b08eb3b5a..2dc2d88cdf 100644 --- a/Core/Extensions/CryptoExtensions.cs +++ b/Core/Extensions/CryptoExtensions.cs @@ -21,7 +21,7 @@ public static class CryptoExtensions /// A cancellation token that can be used to abort the hash /// The requested hash of the input stream public static byte[] ComputeHash(this HashAlgorithm hashAlgo, Stream stream, - IProgress progress, CancellationToken cancelToken = default(CancellationToken)) + IProgress progress, CancellationToken cancelToken = default) { const int bufSize = 1024 * 1024; var buffer = new byte[bufSize]; diff --git a/Core/Extensions/DictionaryExtensions.cs b/Core/Extensions/DictionaryExtensions.cs index 0f34b17944..2ab1ae94f1 100644 --- a/Core/Extensions/DictionaryExtensions.cs +++ b/Core/Extensions/DictionaryExtensions.cs @@ -14,7 +14,7 @@ public static bool DictionaryEquals(this IDictionary a, public static V GetOrDefault(this Dictionary dict, K key) { - V val = default(V); + V val = default; if (key != null) { dict.TryGetValue(key, out val); diff --git a/Core/Extensions/EnumerableExtensions.cs b/Core/Extensions/EnumerableExtensions.cs index 3c9974e18c..a6d4aef63e 100644 --- a/Core/Extensions/EnumerableExtensions.cs +++ b/Core/Extensions/EnumerableExtensions.cs @@ -10,12 +10,9 @@ namespace CKAN.Extensions public static class EnumerableExtensions { public static ICollection AsCollection(this IEnumerable source) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - - return source is ICollection collection ? collection : source.ToArray(); - } + => source == null + ? throw new ArgumentNullException(nameof(source)) + : source is ICollection collection ? collection : source.ToArray(); #if NET45 @@ -117,6 +114,8 @@ public static TimeSpan Sum(this IEnumerable source) public static IEnumerable ZipMany(this IEnumerable seq1, IEnumerable seq2, Func> func) => seq1.Zip(seq2, func).SelectMany(seqs => seqs); +#if NETFRAMEWORK + /// /// Eliminate duplicate elements based on the value returned by a callback /// @@ -126,6 +125,8 @@ public static IEnumerable ZipMany(this IEnumerable seq1, IEnumera public static IEnumerable DistinctBy(this IEnumerable seq, Func func) => seq.GroupBy(func).Select(grp => grp.First()); +#endif + /// /// Generate a sequence from a linked list /// @@ -140,7 +141,7 @@ public static IEnumerable TraverseNodes(this T start, Func getNext) } } -#if NET45 +#if NETFRAMEWORK /// /// Make pairs out of the elements of two sequences @@ -151,6 +152,10 @@ public static IEnumerable TraverseNodes(this T start, Func getNext) public static IEnumerable> Zip(this IEnumerable seq1, IEnumerable seq2) => seq1.Zip(seq2, (item1, item2) => new Tuple(item1, item2)); +#endif + +#if NET45 + /// /// Enable a `foreach` over a sequence of tuples /// @@ -197,6 +202,8 @@ public static void Deconstruct(this Tuple tuple, item4 = tuple.Item4; } +#endif + /// /// Enable a `foreach` over a sequence of key value pairs /// @@ -209,8 +216,6 @@ public static void Deconstruct(this KeyValuePair kvp, out T1 key val = kvp.Value; } -#endif - } /// @@ -241,19 +246,17 @@ public IEnumerator GetEnumerator() } IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + => GetEnumerator(); private IEnumerator GetMemoizingEnumerator() { - for (Int32 index = 0; TryGetItem(index, out T item); ++index) + for (int index = 0; TryGetItem(index, out T item); ++index) { yield return item; } } - private bool TryGetItem(Int32 index, out T item) + private bool TryGetItem(int index, out T item) { lock (gate) { @@ -262,12 +265,12 @@ private bool TryGetItem(Int32 index, out T item) // The iteration may have completed while waiting for the lock if (isCacheComplete) { - item = default(T); + item = default; return false; } if (!enumerator.MoveNext()) { - item = default(T); + item = default; isCacheComplete = true; enumerator.Dispose(); return false; @@ -279,10 +282,8 @@ private bool TryGetItem(Int32 index, out T item) } } - private bool IsItemInCache(Int32 index) - { - return index < cache.Count; - } + private bool IsItemInCache(int index) + => index < cache.Count; private readonly IEnumerable source; private IEnumerator enumerator; diff --git a/Core/Extensions/IOExtensions.cs b/Core/Extensions/IOExtensions.cs index ab597a8ba7..9178520be4 100644 --- a/Core/Extensions/IOExtensions.cs +++ b/Core/Extensions/IOExtensions.cs @@ -66,7 +66,7 @@ public static DriveInfo GetDrive(this DirectoryInfo dir) /// Stream from which to copy /// Stream to which to copy /// Callback to notify as we traverse the input, called with count of bytes received - public static void CopyTo(this Stream src, Stream dest, IProgress progress, CancellationToken cancelToken = default(CancellationToken)) + public static void CopyTo(this Stream src, Stream dest, IProgress progress, CancellationToken cancelToken = default) { // CopyTo says its default buffer is 81920, but we want more than 1 update for a 100 KiB file const int bufSize = 16384; diff --git a/Core/FileIdentifier.cs b/Core/FileIdentifier.cs index 3eb7ede37e..626dfe8811 100644 --- a/Core/FileIdentifier.cs +++ b/Core/FileIdentifier.cs @@ -60,12 +60,7 @@ private static bool CheckGZip(Stream stream) } // Compare against the magic numbers. - if (buffer.SequenceEqual(gzip_identifier)) - { - return true; - } - - return false; + return buffer.SequenceEqual(gzip_identifier); } /// @@ -148,12 +143,9 @@ private static bool CheckZip(Stream stream) } // Compare against the magic numbers. - if (buffer.SequenceEqual(zip_identifier) || buffer.SequenceEqual(zip_identifier_empty) || buffer.SequenceEqual(zip_identifier_spanned)) - { - return true; - } - - return false; + return buffer.SequenceEqual(zip_identifier) + || buffer.SequenceEqual(zip_identifier_empty) + || buffer.SequenceEqual(zip_identifier_spanned); } /// @@ -184,14 +176,7 @@ public static FileType IdentifyFile(Stream stream) stream.Seek (0, SeekOrigin.Begin); using (ICSharpCode.SharpZipLib.GZip.GZipInputStream gz_stream = new ICSharpCode.SharpZipLib.GZip.GZipInputStream (stream)) { - if (CheckTar(gz_stream)) - { - type = FileType.TarGz; - } - else - { - type = FileType.GZip; - } + type = CheckTar(gz_stream) ? FileType.TarGz : FileType.GZip; } } else if (CheckTar(stream)) diff --git a/Core/GameInstance.cs b/Core/GameInstance.cs index dbae00f7ad..01f8e191bc 100644 --- a/Core/GameInstance.cs +++ b/Core/GameInstance.cs @@ -125,7 +125,7 @@ private void SetupCkanDirectories() public void SetCompatibleVersions(List compatibleVersions) { - this._compatibleVersions = compatibleVersions.Distinct().ToList(); + _compatibleVersions = compatibleVersions.Distinct().ToList(); SaveCompatibleVersions(); } @@ -144,7 +144,7 @@ private void SaveCompatibleVersions() private void LoadCompatibleVersions() { - String path = CompatibleGameVersionsFile(); + string path = CompatibleGameVersionsFile(); if (File.Exists(path)) { CompatibleGameVersions compatibleGameVersions = JsonConvert.DeserializeObject(File.ReadAllText(path)); @@ -162,7 +162,7 @@ private string CompatibleGameVersionsFile() => Path.Combine(CkanDir(), game.CompatibleVersionsFile); public List GetCompatibleVersions() - => new List(this._compatibleVersions); + => new List(_compatibleVersions); public HashSet GetSuppressedCompatWarningIdentifiers => SuppressedCompatWarningIdentifiers.LoadFrom(Version(), SuppressedCompatWarningIdentifiersFile).Identifiers; @@ -183,10 +183,12 @@ public string[] InstallFilters ? JsonConvert.DeserializeObject(File.ReadAllText(InstallFiltersFile)) : new string[] { }; + #pragma warning disable IDE0027 set { File.WriteAllText(InstallFiltersFile, JsonConvert.SerializeObject(value)); } + #pragma warning restore IDE0027 } private string InstallFiltersFile => Path.Combine(CkanDir(), "install_filters.json"); @@ -367,7 +369,7 @@ public string ToAbsoluteGameDir(string path) /// public string DllPathToIdentifier(string relative_path) { - var paths = Enumerable.Repeat(game.PrimaryModDirectoryRelative, 1) + var paths = Enumerable.Repeat(game.PrimaryModDirectoryRelative, 1) .Concat(game.AlternateModDirectoriesRelative); if (!paths.Any(p => relative_path.StartsWith($"{p}/", StringComparison.CurrentCultureIgnoreCase))) { diff --git a/Core/GameInstanceManager.cs b/Core/GameInstanceManager.cs index 46affb2c3f..e8cb2b3b8f 100644 --- a/Core/GameInstanceManager.cs +++ b/Core/GameInstanceManager.cs @@ -50,15 +50,12 @@ public class GameInstanceManager : IDisposable public string AutoStartInstance { - get - { - return HasInstance(Configuration.AutoStartInstance) - ? Configuration.AutoStartInstance - : null; - } + get => HasInstance(Configuration.AutoStartInstance) + ? Configuration.AutoStartInstance + : null; private set { - if (!String.IsNullOrEmpty(value) && !HasInstance(value)) + if (!string.IsNullOrEmpty(value) && !HasInstance(value)) { throw new InvalidKSPInstanceKraken(value); } @@ -66,10 +63,7 @@ private set } } - public SortedList Instances - { - get { return new SortedList(instances); } - } + public SortedList Instances => new SortedList(instances); public GameInstanceManager(IUser user, IConfiguration configuration = null) { @@ -212,10 +206,7 @@ public GameInstance AddInstance(GameInstance instance) public GameInstance AddInstance(string path, string name, IUser user) { var game = DetermineGame(new DirectoryInfo(path), user); - if (game == null) - return null; - - return AddInstance(new GameInstance(game, path, name, user)); + return game == null ? null : AddInstance(new GameInstance(game, path, name, user)); } /// @@ -294,12 +285,12 @@ public void FakeInstance(IGame game, string newName, string newPath, GameVersion { fileMgr.WriteAllText( Path.Combine(newPath, b), - String.Format("build id = {0}", version.Build)); + string.Format("build id = {0}", version.Build)); } } // Create the readme.txt WITHOUT build number. - fileMgr.WriteAllText(Path.Combine(newPath, "readme.txt"), String.Format("Version {0}", new GameVersion(version.Major, version.Minor, version.Patch).ToString())); + fileMgr.WriteAllText(Path.Combine(newPath, "readme.txt"), string.Format("Version {0}", new GameVersion(version.Major, version.Minor, version.Patch).ToString())); // Create the needed folder structure and the readme.txt for DLCs that should be simulated. if (dlcs != null) @@ -310,18 +301,20 @@ public void FakeInstance(IGame game, string newName, string newPath, GameVersion GameVersion dlcVersion = dlc.Value; if (!dlcDetector.AllowedOnBaseVersion(version)) + { throw new WrongGameVersionKraken( version, string.Format(Properties.Resources.GameInstanceFakeDLCNotAllowed, game.ShortName, dlcDetector.ReleaseGameVersion, dlcDetector.IdentifierBaseName)); + } string dlcDir = Path.Combine(newPath, dlcDetector.InstallPath()); fileMgr.CreateDirectory(dlcDir); fileMgr.WriteAllText( Path.Combine(dlcDir, "readme.txt"), - String.Format("Version {0}", dlcVersion)); + string.Format("Version {0}", dlcVersion)); } } @@ -337,7 +330,7 @@ public void FakeInstance(IGame game, string newName, string newPath, GameVersion /// /// A unused valid instance name. /// The name to use as a base. - /// Could not find a valid name. + /// Could not find a valid name. public string GetNextValidInstanceName(string name) { // Check if the current name is valid @@ -376,7 +369,7 @@ private bool InstanceNameIsValid(string name) { // Discard null, empty strings and white space only strings. // Look for the current name in the list of loaded instances. - return !String.IsNullOrWhiteSpace(name) && !HasInstance(name); + return !string.IsNullOrWhiteSpace(name) && !HasInstance(name); } /// @@ -595,12 +588,12 @@ public bool TrySetupCache(string path, out string failureReason) } /// - /// Releases all resource used by the object. + /// Releases all resource used by the object. /// - /// Call when you are finished using the . The - /// method leaves the in an unusable state. After calling , you must - /// release all references to the so the garbage collector can reclaim the memory that - /// the was occupying. + /// Call when you are finished using the . The + /// method leaves the in an unusable state. After calling , you must + /// release all references to the so the garbage collector can reclaim the memory that + /// the was occupying. public void Dispose() { if (Cache != null) diff --git a/Core/Games/KerbalSpaceProgram.cs b/Core/Games/KerbalSpaceProgram.cs index 51c3ffcfad..216ad4d19e 100644 --- a/Core/Games/KerbalSpaceProgram.cs +++ b/Core/Games/KerbalSpaceProgram.cs @@ -167,7 +167,9 @@ public void RebuildSubdirectories(string absGameRoot) { string sAbsolutePath = Path.Combine(absGameRoot, Path.Combine(sRelativePath)); if (!Directory.Exists(sAbsolutePath)) + { Directory.CreateDirectory(sAbsolutePath); + } } } @@ -225,7 +227,7 @@ public List KnownVersions } public GameVersion[] EmbeddedGameVersions - => JsonConvert.DeserializeObject( + => JsonConvert.DeserializeObject( new StreamReader(Assembly.GetExecutingAssembly() .GetManifestResourceStream("CKAN.builds-ksp.json")) .ReadToEnd()) @@ -234,7 +236,7 @@ public GameVersion[] EmbeddedGameVersions .ToArray(); public GameVersion[] ParseBuildsJson(JToken json) - => json.ToObject() + => json.ToObject() .Builds .Select(b => GameVersion.Parse(b.Value)) .ToArray(); @@ -325,11 +327,7 @@ private static string KSPDirectory(string steamPath) // Try with the lowercase version. installPath = Path.Combine(steamPath, "steamapps", "common", "Kerbal Space Program"); - if (Directory.Exists(installPath)) - { - return installPath; - } - return null; + return Directory.Exists(installPath) ? installPath : null; } /// diff --git a/Core/Games/KerbalSpaceProgram/DLC/BreakingGroundDlcDetector.cs b/Core/Games/KerbalSpaceProgram/DLC/BreakingGroundDlcDetector.cs index eff74221aa..4802af14f1 100644 --- a/Core/Games/KerbalSpaceProgram/DLC/BreakingGroundDlcDetector.cs +++ b/Core/Games/KerbalSpaceProgram/DLC/BreakingGroundDlcDetector.cs @@ -1,7 +1,3 @@ -using System.Collections.Generic; - -using CKAN.Games.KerbalSpaceProgram; - namespace CKAN.Games.KerbalSpaceProgram.DLC { /// diff --git a/Core/Games/KerbalSpaceProgram/DLC/IDlcDetector.cs b/Core/Games/KerbalSpaceProgram/DLC/IDlcDetector.cs index b442591380..54e11b1933 100644 --- a/Core/Games/KerbalSpaceProgram/DLC/IDlcDetector.cs +++ b/Core/Games/KerbalSpaceProgram/DLC/IDlcDetector.cs @@ -1,5 +1,4 @@ using CKAN.Versioning; -using CKAN.Games; namespace CKAN.DLC { diff --git a/Core/Games/KerbalSpaceProgram/DLC/MakingHistoryDlcDetector.cs b/Core/Games/KerbalSpaceProgram/DLC/MakingHistoryDlcDetector.cs index 84965b80da..ef946905e1 100644 --- a/Core/Games/KerbalSpaceProgram/DLC/MakingHistoryDlcDetector.cs +++ b/Core/Games/KerbalSpaceProgram/DLC/MakingHistoryDlcDetector.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; -using CKAN.Games.KerbalSpaceProgram; - namespace CKAN.Games.KerbalSpaceProgram.DLC { /// diff --git a/Core/Games/KerbalSpaceProgram/DLC/StandardDlcDetectorBase.cs b/Core/Games/KerbalSpaceProgram/DLC/StandardDlcDetectorBase.cs index 0e8eb946b9..a707d38245 100644 --- a/Core/Games/KerbalSpaceProgram/DLC/StandardDlcDetectorBase.cs +++ b/Core/Games/KerbalSpaceProgram/DLC/StandardDlcDetectorBase.cs @@ -5,7 +5,6 @@ using CKAN.DLC; using CKAN.Versioning; -using CKAN.Games; namespace CKAN.Games.KerbalSpaceProgram.DLC { @@ -25,7 +24,7 @@ public abstract class StandardDlcDetectorBase : IDlcDetector private readonly string DirectoryBaseName; private readonly Dictionary CanonicalVersions; - private IGame game; + private readonly IGame game; private static readonly Regex VersionPattern = new Regex( @"^Version\s+(?\S+)", @@ -38,10 +37,14 @@ protected StandardDlcDetectorBase(IGame game, string identifierBaseName, GameVer protected StandardDlcDetectorBase(IGame game, string identifierBaseName, string directoryBaseName, GameVersion releaseGameVersion, Dictionary canonicalVersions = null) { if (string.IsNullOrWhiteSpace(identifierBaseName)) + { throw new ArgumentException("Value must be provided.", nameof(identifierBaseName)); + } if (string.IsNullOrWhiteSpace(directoryBaseName)) + { throw new ArgumentException("Value must be provided.", nameof(directoryBaseName)); + } this.game = game; IdentifierBaseName = identifierBaseName; @@ -71,7 +74,9 @@ public virtual bool IsInstalled(GameInstance ksp, out string identifier, out Unm var versionStr = match.Groups["version"].Value; if (CanonicalVersions.ContainsKey(versionStr)) + { versionStr = CanonicalVersions[versionStr]; + } version = new UnmanagedModuleVersion(versionStr); break; diff --git a/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspBuildIdVersionProvider.cs b/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspBuildIdVersionProvider.cs index c3bed58b8e..3983673b55 100644 --- a/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspBuildIdVersionProvider.cs +++ b/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspBuildIdVersionProvider.cs @@ -33,7 +33,7 @@ public bool TryGetVersion(string directory, out GameVersion result) if (foundVersions.Count < 1) { - result = default(GameVersion); + result = default; return false; } if (foundVersions.Count > 1) @@ -66,7 +66,7 @@ private bool TryGetVersionFromFile(string file, out GameVersion result) } } - result = default(GameVersion); + result = default; return false; } diff --git a/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspBuildMap.cs b/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspBuildMap.cs index 45aab06f7e..d528d59e18 100644 --- a/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspBuildMap.cs +++ b/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspBuildMap.cs @@ -8,7 +8,6 @@ using Newtonsoft.Json; using CKAN.Versioning; -using CKAN.Configuration; namespace CKAN.Games.KerbalSpaceProgram.GameVersionProviders { @@ -39,7 +38,6 @@ public sealed class KspBuildMap : IKspBuildMap private static readonly ILog Log = LogManager.GetLogger(typeof(KspBuildMap)); private readonly object _buildMapLock = new object(); - private readonly IConfiguration _configuration; private JBuilds _jBuilds; public GameVersion this[string buildId] @@ -48,8 +46,7 @@ public GameVersion this[string buildId] { EnsureBuildMap(); - string version; - return _jBuilds.Builds.TryGetValue(buildId, out version) ? GameVersion.Parse(version) : null; + return _jBuilds.Builds.TryGetValue(buildId, out string version) ? GameVersion.Parse(version) : null; } } @@ -64,23 +61,29 @@ public List KnownVersions } } - public KspBuildMap(IConfiguration configuration) + public KspBuildMap() { - _configuration = configuration; } private void EnsureBuildMap() { - if (ReferenceEquals(_jBuilds, null)) + if (_jBuilds is null) { lock (_buildMapLock) { - if (ReferenceEquals(_jBuilds, null)) + if (_jBuilds is null) { // Check for a cached copy of the remote build map - if (TrySetCachedBuildMap()) return; + if (TrySetCachedBuildMap()) + { + return; + } // If that doesn't exist, use the copy from when we were compiled - if (TrySetEmbeddedBuildMap()) return; + if (TrySetEmbeddedBuildMap()) + { + return; + } + Log.Warn("Could not load build map from cached or embedded copy"); } } @@ -93,7 +96,11 @@ private void EnsureBuildMap() public void Refresh() { Log.Debug("Refreshing build map from server"); - if (TrySetRemoteBuildMap()) return; + if (TrySetRemoteBuildMap()) + { + return; + } + Log.Warn("Could not refresh the build map from remote server"); } diff --git a/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspReadmeVersionProvider.cs b/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspReadmeVersionProvider.cs index e484a60d1b..c5453f483f 100644 --- a/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspReadmeVersionProvider.cs +++ b/Core/Games/KerbalSpaceProgram/GameVersionProviders/KspReadmeVersionProvider.cs @@ -31,7 +31,7 @@ public bool TryGetVersion(string directory, out GameVersion result) } } - result = default(GameVersion); + result = default; return false; } } diff --git a/Core/Games/KerbalSpaceProgram2.cs b/Core/Games/KerbalSpaceProgram2.cs index a8405a0883..580709d7a7 100644 --- a/Core/Games/KerbalSpaceProgram2.cs +++ b/Core/Games/KerbalSpaceProgram2.cs @@ -142,7 +142,9 @@ public void RebuildSubdirectories(string absGameRoot) const string dataDir = "KSP2_x64_Data"; var path = Path.Combine(absGameRoot, dataDir); if (!Directory.Exists(path)) + { Directory.CreateDirectory(path); + } } public string DefaultCommandLine => @@ -244,11 +246,7 @@ private static string GameDirectory(string steamPath) // Try with the lowercase version. installPath = Path.Combine(steamPath, "steamapps", "common", "Kerbal Space Program 2"); - if (Directory.Exists(installPath)) - { - return installPath; - } - return null; + return Directory.Exists(installPath) ? installPath : null; } private static readonly ILog log = LogManager.GetLogger(typeof(KerbalSpaceProgram2)); diff --git a/Core/ModuleInstaller.cs b/Core/ModuleInstaller.cs index 3e5b7a0d09..ed13591d6b 100644 --- a/Core/ModuleInstaller.cs +++ b/Core/ModuleInstaller.cs @@ -1496,10 +1496,9 @@ public static string StripV(string version) { Match match = Regex.Match(version, @"^(?\d\:)?[vV]+(ersion)?[_.]*(?\d.*)$"); - if (match.Success) - return match.Groups["num"].Value + match.Groups["ver"].Value; - else - return version; + return match.Success + ? match.Groups["num"].Value + match.Groups["ver"].Value + : version; } /// diff --git a/Core/Net/AutoUpdate.cs b/Core/Net/AutoUpdate.cs index 628180a3b1..1eef7b8c79 100644 --- a/Core/Net/AutoUpdate.cs +++ b/Core/Net/AutoUpdate.cs @@ -4,7 +4,6 @@ using System.Diagnostics; using System.Reflection; -using log4net; using Newtonsoft.Json; using CKAN.Versioning; @@ -168,7 +167,7 @@ public void StartUpdateProcess(bool launchCKANAfterUpdate, IUser user = null) { Verb = "runas", FileName = updaterFilename, - Arguments = String.Format(@"{0} ""{1}"" ""{2}"" {3}", -pid, exePath, ckanFilename, launchCKANAfterUpdate ? "launch" : "nolaunch"), + Arguments = string.Format(@"{0} ""{1}"" ""{2}"" {3}", -pid, exePath, ckanFilename, launchCKANAfterUpdate ? "launch" : "nolaunch"), UseShellExecute = false, // Make child's stdin a pipe so it can tell when we exit RedirectStandardInput = true, @@ -188,13 +187,13 @@ public static void SetExecutable(string fileName) string command = string.Format("+x \"{0}\"", fileName); - ProcessStartInfo permsinfo = new ProcessStartInfo("chmod", command); - permsinfo.UseShellExecute = false; + ProcessStartInfo permsinfo = new ProcessStartInfo("chmod", command) + { + UseShellExecute = false + }; Process permsprocess = Process.Start(permsinfo); permsprocess.WaitForExit(); } } - - private static readonly ILog log = LogManager.GetLogger(typeof(AutoUpdate)); } } diff --git a/Core/Net/Net.cs b/Core/Net/Net.cs index db2cc6aa80..12d1f68294 100644 --- a/Core/Net/Net.cs +++ b/Core/Net/Net.cs @@ -66,10 +66,10 @@ public static string Download(Uri url, out string etag, string filename = null, => Download(url.OriginalString, out etag, filename, user); public static string Download(Uri url, string filename = null, IUser user = null) - => Download(url, out string etag, filename, user); + => Download(url, out _, filename, user); public static string Download(string url, string filename = null, IUser user = null) - => Download(url, out string etag, filename, user); + => Download(url, out _, filename, user); public static string Download(string url, out string etag, string filename = null, IUser user = null) { @@ -323,9 +323,9 @@ public static Uri GetRawUri(Uri remoteUri) 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.Count < 6 + || (string.Compare(segments[3], "blob/", StringComparison.OrdinalIgnoreCase) != 0 + && string.Compare(segments[3], "tree/", StringComparison.OrdinalIgnoreCase) != 0)) { log.WarnFormat("Remote non-raw GitHub URL is in an unknown format, using as is."); return remoteUri; diff --git a/Core/Net/NetAsyncDownloader.cs b/Core/Net/NetAsyncDownloader.cs index c32f77271f..ca9c7c4bb9 100644 --- a/Core/Net/NetAsyncDownloader.cs +++ b/Core/Net/NetAsyncDownloader.cs @@ -56,9 +56,8 @@ public void Download(Uri url, string path) { ResetAgent(); // Check whether to use an auth token for this host - string token; if (url.IsAbsoluteUri - && ServiceLocator.Container.Resolve().TryGetAuthToken(url.Host, out token) + && ServiceLocator.Container.Resolve().TryGetAuthToken(url.Host, out string token) && !string.IsNullOrEmpty(token)) { log.InfoFormat("Using auth token for {0}", url.Host); @@ -129,8 +128,8 @@ private void ResetAgent() private readonly object dlMutex = new object(); // NOTE: Never remove anything from this, because closures have indexes into it! // (Clearing completely after completion is OK) - private List downloads = new List(); - private List queuedDownloads = new List(); + private readonly List downloads = new List(); + private readonly List queuedDownloads = new List(); private int completed_downloads; // For inter-thread communication @@ -228,7 +227,9 @@ public void DownloadAndWait(IList targets) { throw new MissingCertificateKraken(); } + #pragma warning disable IDE0011 else switch ((wex.Response as HttpWebResponse)?.StatusCode) + #pragma warning restore IDE0011 { // Handle HTTP 403 used for throttling case HttpStatusCode.Forbidden: @@ -314,7 +315,7 @@ private void DownloadModule(NetAsyncDownloaderDownloadPart dl) // Schedule for us to get back progress reports. dl.Progress += (ProgressPercentage, BytesReceived, TotalBytesToReceive) => - FileProgressReport(index, ProgressPercentage, BytesReceived, TotalBytesToReceive); + FileProgressReport(index, BytesReceived, TotalBytesToReceive); // And schedule a notification if we're done (or if something goes wrong) dl.Done += (sender, args, etag) => @@ -364,7 +365,7 @@ private void triggerCompleted() /// The percent complete /// The bytes downloaded /// The total amount of bytes we expect to download - private void FileProgressReport(int index, int percent, long bytesDownloaded, long bytesToDownload) + private void FileProgressReport(int index, long bytesDownloaded, long bytesToDownload) { NetAsyncDownloaderDownloadPart download = downloads[index]; @@ -390,7 +391,10 @@ private void FileProgressReport(int index, int percent, long bytesDownloaded, lo foreach (NetAsyncDownloaderDownloadPart t in downloads.ToList()) { if (t == null) + { continue; + } + if (t.bytesLeft > 0) { totalBytesPerSecond += t.bytesPerSecond; @@ -403,14 +407,17 @@ private void FileProgressReport(int index, int percent, long bytesDownloaded, lo { // Somehow managed to get a NullRef for t here if (dl == null) + { continue; + } + totalBytesLeft += dl.target.size; totalSize += dl.target.size; } int totalPercentage = (int)(((totalSize - totalBytesLeft) * 100) / (totalSize)); User.RaiseProgress( - String.Format(Properties.Resources.NetAsyncDownloaderProgress, + string.Format(Properties.Resources.NetAsyncDownloaderProgress, CkanModule.FmtSize(totalBytesPerSecond), CkanModule.FmtSize(totalBytesLeft)), totalPercentage); diff --git a/Core/Net/NetAsyncModulesDownloader.cs b/Core/Net/NetAsyncModulesDownloader.cs index fa28c9682d..280ab0fd47 100644 --- a/Core/Net/NetAsyncModulesDownloader.cs +++ b/Core/Net/NetAsyncModulesDownloader.cs @@ -117,7 +117,7 @@ public void CancelDownload() private const string defaultMimeType = "application/octet-stream"; - private List modules; + private readonly List modules; private readonly NetAsyncDownloader downloader; private IUser User => downloader.User; private readonly NetModuleCache cache; diff --git a/Core/Net/NetFileCache.cs b/Core/Net/NetFileCache.cs index d582619c52..46f56a262e 100644 --- a/Core/Net/NetFileCache.cs +++ b/Core/Net/NetFileCache.cs @@ -27,11 +27,11 @@ namespace CKAN [PermissionSet(SecurityAction.Demand, Name="FullTrust")] public class NetFileCache : IDisposable { - private FileSystemWatcher watcher; + private readonly FileSystemWatcher watcher; // hash => full file path private Dictionary cachedFiles; - private string cachePath; - private GameInstanceManager manager; + private readonly string cachePath; + private readonly GameInstanceManager manager; private static readonly Regex cacheFileRegex = new Regex("^[0-9A-F]{8}-", RegexOptions.Compiled); private static readonly ILog log = LogManager.GetLogger(typeof (NetFileCache)); @@ -85,12 +85,12 @@ public NetFileCache(string path) } /// - /// Releases all resource used by the object. + /// Releases all resource used by the object. /// - /// Call when you are finished using the . The - /// method leaves the in an unusable state. After calling - /// , you must release all references to the so the garbage - /// collector can reclaim the memory that the was occupying. + /// Call when you are finished using the . The + /// method leaves the in an unusable state. After calling + /// , you must release all references to the so the garbage + /// collector can reclaim the memory that the was occupying. public void Dispose() { // All we really need to do is clear our FileSystemWatcher. @@ -106,19 +106,18 @@ private string GetInProgressFileName(string hash, string description) { Directory.CreateDirectory(InProgressPath); return Directory.EnumerateFiles(InProgressPath) - .Where(path => new FileInfo(path).Name.StartsWith(hash)) - .FirstOrDefault() + .FirstOrDefault(path => new FileInfo(path).Name.StartsWith(hash)) // If not found, return the name to create ?? Path.Combine(InProgressPath, $"{hash}-{description}"); } public string GetInProgressFileName(Uri url, string description) - => GetInProgressFileName(NetFileCache.CreateURLHash(url), + => GetInProgressFileName(CreateURLHash(url), description); public string GetInProgressFileName(List urls, string description) { - var filenames = urls?.Select(url => GetInProgressFileName(NetFileCache.CreateURLHash(url), description)) + var filenames = urls?.Select(url => GetInProgressFileName(CreateURLHash(url), description)) .ToArray(); return filenames?.FirstOrDefault(filename => File.Exists(filename)) ?? filenames?.FirstOrDefault(); @@ -204,18 +203,12 @@ public string GetCachedFilename(Uri url, DateTime? remoteTimestamp = null) // for. string found = scanDirectory(files, hash, remoteTimestamp); - if (!string.IsNullOrEmpty(found)) - { - return found; - } - - return null; + return string.IsNullOrEmpty(found) ? null : found; } private string scanDirectory(Dictionary files, string findHash, DateTime? remoteTimestamp = null) { - string file; - if (files.TryGetValue(findHash, out file)) + if (files.TryGetValue(findHash, out string file)) { log.DebugFormat("Found file {0}", file); // Check local vs remote timestamps; if local is older, then it's invalid. @@ -315,7 +308,7 @@ public void EnforceSizeLimit(long bytes, Registry registry) // Now get all the files in all the caches, including in progress... List files = allFiles(true); // ... and sort them by compatibility and timestamp... - files.Sort((a, b) => compareFiles(hashMap, aggregateCriteria, a, b)); + files.Sort((a, b) => compareFiles(hashMap, a, b)); // ... and delete them till we're under the limit foreach (FileInfo fi in files) @@ -336,16 +329,14 @@ public void EnforceSizeLimit(long bytes, Registry registry) } } - private int compareFiles(Dictionary> hashMap, GameVersionCriteria crit, FileInfo a, FileInfo b) + private int compareFiles(Dictionary> hashMap, FileInfo a, FileInfo b) { // Compatible modules for file A - List modulesA; - hashMap.TryGetValue(a.Name.Substring(0, 8), out modulesA); + hashMap.TryGetValue(a.Name.Substring(0, 8), out List modulesA); bool compatA = modulesA?.Any() ?? false; // Compatible modules for file B - List modulesB; - hashMap.TryGetValue(b.Name.Substring(0, 8), out modulesB); + hashMap.TryGetValue(b.Name.Substring(0, 8), out List modulesB); bool compatB = modulesB?.Any() ?? false; if (modulesA == null && modulesB != null) @@ -423,7 +414,7 @@ public string Store(Uri url, string path, string description = null, bool move = "description isn't as filesystem safe as we thought... (#1266)" ); - string fullName = String.Format("{0}-{1}", hash, Path.GetFileName(description)); + string fullName = string.Format("{0}-{1}", hash, Path.GetFileName(description)); string targetPath = Path.Combine(cachePath, fullName); // Purge hashes associated with the new file @@ -486,8 +477,8 @@ private void PurgeHashes(TxFileManager tx_file, string file) /// public void RemoveAll() { - var dirs = Enumerable.Repeat(cachePath, 1) - .Concat(Enumerable.Repeat(InProgressPath, 1)) + var dirs = Enumerable.Repeat(cachePath, 1) + .Concat(Enumerable.Repeat(InProgressPath, 1)) .Concat(legacyDirs()); foreach (string dir in dirs) { @@ -573,7 +564,7 @@ public static string CreateURLHash(Uri url) /// /// SHA1 hash, in all-caps hexadecimal format /// - public string GetFileHashSha1(string filePath, IProgress progress, CancellationToken cancelToken = default(CancellationToken)) + public string GetFileHashSha1(string filePath, IProgress progress, CancellationToken cancelToken = default) => GetFileHash(filePath, "sha1", sha1Cache, progress, cancelToken); /// @@ -584,7 +575,7 @@ public static string CreateURLHash(Uri url) /// /// SHA256 hash, in all-caps hexadecimal format /// - public string GetFileHashSha256(string filePath, IProgress progress, CancellationToken cancelToken = default(CancellationToken)) + public string GetFileHashSha256(string filePath, IProgress progress, CancellationToken cancelToken = default) => GetFileHash(filePath, "sha256", sha256Cache, progress, cancelToken); /// @@ -598,9 +589,8 @@ public static string CreateURLHash(Uri url) private string GetFileHash(string filePath, string hashSuffix, Dictionary cache, IProgress progress, CancellationToken cancelToken) where T: HashAlgorithm, new() { - string hash = null; string hashFile = $"{filePath}.{hashSuffix}"; - if (cache.TryGetValue(filePath, out hash)) + if (cache.TryGetValue(filePath, out string hash)) { return hash; } @@ -627,7 +617,7 @@ private string GetFileHash(string filePath, string hashSuffix, Dictionary sha1Cache = new Dictionary(); - private Dictionary sha256Cache = new Dictionary(); + private readonly Dictionary sha1Cache = new Dictionary(); + private readonly Dictionary sha256Cache = new Dictionary(); } } diff --git a/Core/Net/NetModuleCache.cs b/Core/Net/NetModuleCache.cs index a8cc61ec9b..8ca3b271b5 100644 --- a/Core/Net/NetModuleCache.cs +++ b/Core/Net/NetModuleCache.cs @@ -78,8 +78,7 @@ public bool IsMaybeCachedZip(CkanModule m) ?? false; public string GetCachedFilename(CkanModule m) => m.download?.Select(dlUri => cache.GetCachedFilename(dlUri, m.release_date)) - .Where(filename => filename != null) - .FirstOrDefault(); + .FirstOrDefault(filename => filename != null); public void GetSizeInfo(out int numFiles, out long numBytes, out long bytesFree) { cache.GetSizeInfo(out numFiles, out numBytes, out bytesFree); @@ -124,7 +123,7 @@ public string DescribeAvailability(CkanModule m) /// /// SHA1 hash, in all-caps hexadecimal format /// - public string GetFileHashSha1(string filePath, IProgress progress, CancellationToken cancelToken = default(CancellationToken)) + public string GetFileHashSha1(string filePath, IProgress progress, CancellationToken cancelToken = default) => cache.GetFileHashSha1(filePath, progress, cancelToken); /// @@ -135,7 +134,7 @@ public string DescribeAvailability(CkanModule m) /// /// SHA256 hash, in all-caps hexadecimal format /// - public string GetFileHashSha256(string filePath, IProgress progress, CancellationToken cancelToken = default(CancellationToken)) + public string GetFileHashSha256(string filePath, IProgress progress, CancellationToken cancelToken = default) => cache.GetFileHashSha256(filePath, progress, cancelToken); /// @@ -150,7 +149,7 @@ public string DescribeAvailability(CkanModule m) /// /// Name of the new file in the cache /// - public string Store(CkanModule module, string path, IProgress progress, string description = null, bool move = false, CancellationToken cancelToken = default(CancellationToken)) + public string Store(CkanModule module, string path, IProgress progress, string description = null, bool move = false, CancellationToken cancelToken = default) { // ZipValid takes a lot longer than the hash steps, so scale them 60:20:20 const int zipValidPercent = 60; @@ -161,13 +160,17 @@ public string DescribeAvailability(CkanModule m) // Check file exists FileInfo fi = new FileInfo(path); if (!fi.Exists) + { throw new FileNotFoundKraken(path); + } // Check file size if (module.download_size > 0 && fi.Length != module.download_size) + { throw new InvalidModuleFileKraken(module, path, string.Format( Properties.Resources.NetModuleCacheBadLength, module, path, fi.Length, module.download_size)); + } cancelToken.ThrowIfCancellationRequested(); @@ -187,7 +190,7 @@ public string DescribeAvailability(CkanModule m) { // Check SHA1 match string sha1 = GetFileHashSha1(path, new Progress(percent => - progress?.Report(zipValidPercent + percent * hashSha1Percent / 100)), cancelToken); + progress?.Report(zipValidPercent + (percent * hashSha1Percent / 100))), cancelToken); if (sha1 != module.download_hash.sha1) { throw new InvalidModuleFileKraken(module, path, string.Format( @@ -197,7 +200,7 @@ public string DescribeAvailability(CkanModule m) // Check SHA256 match string sha256 = GetFileHashSha256(path, new Progress(percent => - progress?.Report(zipValidPercent + hashSha1Percent + percent * hashSha256Percent / 100)), cancelToken); + progress?.Report(zipValidPercent + hashSha1Percent + (percent * hashSha256Percent / 100))), cancelToken); if (sha256 != module.download_hash.sha256) { throw new InvalidModuleFileKraken(module, path, string.Format( @@ -318,6 +321,6 @@ public bool Purge(CkanModule module) return true; } - private NetFileCache cache; + private readonly NetFileCache cache; } } diff --git a/Core/Net/RedirectingTimeoutWebClient.cs b/Core/Net/RedirectingTimeoutWebClient.cs index bb87bb7072..000cc8b359 100644 --- a/Core/Net/RedirectingTimeoutWebClient.cs +++ b/Core/Net/RedirectingTimeoutWebClient.cs @@ -54,10 +54,15 @@ protected override WebRequest GetWebRequest(Uri address) protected override WebResponse GetWebResponse(WebRequest request) { if (request == null) + { return null; + } + var response = base.GetWebResponse(request); if (response == null) + { return null; + } if (response is HttpWebResponse hwr) { @@ -85,8 +90,8 @@ protected override WebResponse GetWebResponse(WebRequest request) return response; } - private int timeout; - private string mimeType; + private readonly int timeout; + private readonly string mimeType; private static readonly Dictionary permanentRedirects = new Dictionary(); private static readonly ILog log = LogManager.GetLogger(typeof(RedirectingTimeoutWebClient)); } diff --git a/Core/Platform.cs b/Core/Platform.cs index 360f47045c..1754c58a30 100644 --- a/Core/Platform.cs +++ b/Core/Platform.cs @@ -24,21 +24,20 @@ static Platform() /// Are we on a Mac? /// /// true if is mac; otherwise, false. - public static readonly bool IsMac = IsRunningOnMac(); + public static readonly bool IsMac = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); /// /// Are we on a Unix (including Linux, but *not* Mac) system. - /// Note that Mono thinks Mac is Unix! So we need to negate Mac explicitly. /// /// true if is unix; otherwise, false. - public static readonly bool IsUnix = Environment.OSVersion.Platform == PlatformID.Unix && !IsMac; + public static readonly bool IsUnix = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); /// /// Are we on a flavour of Windows? This is implemented internally by checking /// if we're not on Unix or Mac. /// /// true if is windows; otherwise, false. - public static readonly bool IsWindows = !IsUnix && !IsMac; + public static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); /// /// Are we on Mono? @@ -53,66 +52,31 @@ static Platform() /// /// Are we running in an X11 environment? /// - public static readonly bool IsX11 = IsUnix && !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DISPLAY")); - - - // From https://github.com/mono/monodevelop/blob/master/main/src/core/Mono.Texteditor/Mono.TextEditor/Platform.cs - // Environment.OSVersion.Platform returns Unix for Mac OS X as of Mono v4.0.0: - // https://bugzilla.xamarin.com/show_bug.cgi?id=13345 - // So we have to detect it another way - private static bool IsRunningOnMac() - { - IntPtr buf = IntPtr.Zero; - try - { - buf = Marshal.AllocHGlobal(8192); - // This is a hacktastic way of getting sysname from uname () - if (uname(buf) == 0) - { - string os = Marshal.PtrToStringAnsi(buf); - if (os == "Darwin") - return true; - } - } - catch - { - } - finally - { - if (buf != IntPtr.Zero) - Marshal.FreeHGlobal(buf); - } - return false; - } - - [DllImport("libc")] - private static extern int uname(IntPtr buf); + public static readonly bool IsX11 = + IsUnix + && !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DISPLAY")); private static bool IsOnMonoFourOrLater() { if (!IsMono) + { return false; + } // Get Mono's display name and parse the version - Type type = Type.GetType("Mono.Runtime"); string display_name = - (string) type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null); + (string)Type.GetType("Mono.Runtime") + .GetMethod("GetDisplayName", + BindingFlags.NonPublic | BindingFlags.Static) + .Invoke(null, null); var match = versionMatcher.Match(display_name); - if (match.Success) - { - int majorVersion = Int32.Parse(match.Groups["majorVersion"].Value); - return majorVersion >= 4; - } - else - { - return false; - } + return match.Success + && int.Parse(match.Groups["majorVersion"].Value) >= 4; } - private static readonly Regex versionMatcher = new Regex( - "^\\s*(?\\d+)\\.\\d+\\.\\d+\\s*\\(", - RegexOptions.Compiled - ); + private static readonly Regex versionMatcher = + new Regex("^\\s*(?\\d+)\\.\\d+\\.\\d+\\s*\\(", + RegexOptions.Compiled); } } diff --git a/Core/Registry/CompatibilitySorter.cs b/Core/Registry/CompatibilitySorter.cs index 00f85bd435..b956b0be2b 100644 --- a/Core/Registry/CompatibilitySorter.cs +++ b/Core/Registry/CompatibilitySorter.cs @@ -148,11 +148,11 @@ private Dictionary> CompatibleProviders( .GroupBy(kvp => kvp.Value.AllAvailable() .All(m => !m.IsCompatible(CompatibleVersions)) // No versions compatible == incompatible - ? (bool?)false + ? false : kvp.Value.AllAvailable() .All(m => m.depends == null) // No dependencies == compatible - ? (bool?)true + ? true // Need to investigate this one more later : (bool?)null) .Select(grp => new Tuple>( diff --git a/Core/Registry/IRegistryQuerier.cs b/Core/Registry/IRegistryQuerier.cs index 767c29c517..7d144b475d 100644 --- a/Core/Registry/IRegistryQuerier.cs +++ b/Core/Registry/IRegistryQuerier.cs @@ -6,7 +6,6 @@ using log4net; using CKAN.Versioning; -using CKAN.Extensions; using CKAN.Games; namespace CKAN @@ -286,10 +285,14 @@ public static ModuleReplacement GetReplacement(this IRegistryQuerier querier, Ck { // Mod is not installed, so we don't care about replacements if (installedVersion == null) + { return null; + } // No replaced_by relationship if (installedVersion.replaced_by == null) + { return null; + } // Get the identifier from the replaced_by relationship, if it exists ModuleRelationshipDescriptor replacedBy = installedVersion.replaced_by; @@ -324,7 +327,10 @@ public static ModuleReplacement GetReplacement(this IRegistryQuerier querier, Ck return replacement; } } - else return replacement; + else + { + return replacement; + } } } return null; diff --git a/Core/Registry/InstalledModule.cs b/Core/Registry/InstalledModule.cs index 61c501886a..25467a8c95 100644 --- a/Core/Registry/InstalledModule.cs +++ b/Core/Registry/InstalledModule.cs @@ -24,6 +24,7 @@ public class InstalledModuleFile public InstalledModuleFile(string path, GameInstance ksp) { string absolute_path = ksp.ToAbsoluteGameDir(path); + // TODO: What is the net performance cost of calculating this? Big files are not quick to hash! sha1_sum = Sha1Sum(absolute_path); } @@ -84,7 +85,8 @@ public class InstalledModule // TODO: Our InstalledModuleFile already knows its path, so this could just // be a list. However we've left it as a dictionary for now to maintain // registry format compatibility. - [JsonProperty] private Dictionary installed_files; + [JsonProperty] + private Dictionary installed_files; public IEnumerable Files => installed_files.Keys; public string identifier => source_module.identifier; diff --git a/Core/Registry/Registry.cs b/Core/Registry/Registry.cs index 4e27ae0db7..3c5e0036c4 100644 --- a/Core/Registry/Registry.cs +++ b/Core/Registry/Registry.cs @@ -642,8 +642,7 @@ public CkanModule GetModuleByVersion(string ident, ModuleVersion version) try { return getAvail(ident)?.Select(am => am.ByVersion(version)) - .Where(m => m != null) - .FirstOrDefault(); + .FirstOrDefault(m => m != null); } catch { @@ -700,9 +699,13 @@ private void BuildProvidesIndexFor(AvailableModule am) foreach (string provided in m.ProvidesList) { if (providers.TryGetValue(provided, out HashSet provs)) + { provs.Add(am); + } else + { providers.Add(provided, new HashSet() { am }); + } } } } @@ -1082,7 +1085,10 @@ public ModuleVersion InstalledVersion(string modIdentifier, bool with_provides=t // Finally we have our provided checks. We'll skip these if // withProvides is false. - if (!with_provides) return null; + if (!with_provides) + { + return null; + } var provided = ProvidedByInstalled(); @@ -1315,6 +1321,7 @@ public IEnumerable GetAllHosts() // Older clients expect these properties and can handle them being empty ("{}") but not null + #pragma warning disable IDE0052 [JsonProperty("available_modules", NullValueHandling = NullValueHandling.Include)] [JsonConverter(typeof(JsonAlwaysEmptyObjectConverter))] @@ -1324,6 +1331,7 @@ public IEnumerable GetAllHosts() NullValueHandling = NullValueHandling.Include)] [JsonConverter(typeof(JsonAlwaysEmptyObjectConverter))] private readonly Dictionary legacyDownloadCountsDoNotUse = new Dictionary(); + #pragma warning restore IDE0052 } } diff --git a/Core/Registry/RegistryManager.cs b/Core/Registry/RegistryManager.cs index 483ce46979..5eb19de77a 100644 --- a/Core/Registry/RegistryManager.cs +++ b/Core/Registry/RegistryManager.cs @@ -52,7 +52,7 @@ public static bool IsInstanceMaybeLocked(string ckanDirPath) // enforce this being an instance (via Instance() above) private RegistryManager(string path, GameInstance inst, RepositoryDataManager repoData) { - this.gameInstance = inst; + gameInstance = inst; this.path = Path.Combine(path, "registry.json"); lockfilePath = InstanceRegistryLockPath(path); @@ -103,19 +103,21 @@ private RegistryManager(string path, GameInstance inst, RepositoryDataManager re // what's going on here. /// - /// Releases all resource used by the object. + /// Releases all resource used by the object. /// - /// Call when you are finished using the . The - /// method leaves the in an unusable state. After - /// calling , you must release all references to the so - /// the garbage collector can reclaim the memory that the was occupying. + /// Call when you are finished using the . The + /// method leaves the in an unusable state. After + /// calling , you must release all references to the so + /// the garbage collector can reclaim the memory that the was occupying. public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } + #pragma warning disable IDE0060 protected void Dispose(bool safeToAlsoFreeManagedObjects) + #pragma warning restore IDE0060 { // Right now we just release our lock, and leave everything else // to the GC, but if we were implementing the full pattern we'd also @@ -135,7 +137,7 @@ protected void Dispose(bool safeToAlsoFreeManagedObjects) /// /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// is reclaimed by garbage collection. /// ~RegistryManager() { @@ -175,7 +177,7 @@ private void CheckStaleLock() return; } log.DebugFormat("Lock file contents: {0}", contents); - if (Int32.TryParse(contents, out int pid)) + if (int.TryParse(contents, out int pid)) { // File contains a valid integer. try @@ -551,7 +553,7 @@ public bool ScanUnmanagedFiles() log.Info(Properties.Resources.GameInstanceScanning); using (var tx = CkanTransaction.CreateTransactionScope()) { - var dlls = Enumerable.Repeat(gameInstance.game.PrimaryModDirectoryRelative, 1) + var dlls = Enumerable.Repeat(gameInstance.game.PrimaryModDirectoryRelative, 1) .Concat(gameInstance.game.AlternateModDirectoriesRelative) .Select(relDir => gameInstance.ToAbsoluteGameDir(relDir)) .Where(absDir => Directory.Exists(absDir)) diff --git a/Core/Relationships/RelationshipResolver.cs b/Core/Relationships/RelationshipResolver.cs index 918d0f9388..473f810ea8 100644 --- a/Core/Relationships/RelationshipResolver.cs +++ b/Core/Relationships/RelationshipResolver.cs @@ -16,7 +16,7 @@ namespace CKAN /// Resolves relationships between mods. Primarily used to satisfy missing dependencies and to check for conflicts on proposed installs. /// /// - /// All constructors start with currently installed modules, to remove + /// All constructors start with currently installed modules, to remove /// public class RelationshipResolver { @@ -559,7 +559,7 @@ private IEnumerable BreadthFirstSearch(IEnumerable private IEnumerable allDependers(CkanModule module, Func followReason = null) - => BreadthFirstSearch(Enumerable.Repeat(module, 1), + => BreadthFirstSearch(Enumerable.Repeat(module, 1), (searching, found) => ReasonsFor(searching).Where(followReason ?? AnyRelationship) .Select(r => r.Parent) @@ -611,7 +611,7 @@ public ParallelQuery>> Supporters( /// The keys are the mods that the user chose that led to the conflict being in the list! /// Use this for coloring/labelling rows, use ConflictDescriptions for reporting the conflicts to the user. /// - public Dictionary ConflictList + public Dictionary ConflictList => conflicts .SelectMany(kvp => UserReasonsFor(kvp.Key).Select(k => new KeyValuePair(k, kvp))) .GroupBy(kvp => kvp.Key) @@ -879,7 +879,9 @@ public Replacement(CkanModule module) { if (module == null) { + #pragma warning disable IDE0016 throw new ArgumentNullException(); + #pragma warning restore IDE0016 } Parent = module; } @@ -894,7 +896,9 @@ public Suggested(CkanModule module) { if (module == null) { + #pragma warning disable IDE0016 throw new ArgumentNullException(); + #pragma warning restore IDE0016 } Parent = module; } @@ -909,7 +913,9 @@ public Depends(CkanModule module) { if (module == null) { + #pragma warning disable IDE0016 throw new ArgumentNullException(); + #pragma warning restore IDE0016 } Parent = module; } @@ -928,7 +934,9 @@ public Recommended(CkanModule module, int providesIndex) { if (module == null) { + #pragma warning disable IDE0016 throw new ArgumentNullException(); + #pragma warning restore IDE0016 } Parent = module; ProvidesIndex = providesIndex; diff --git a/Core/Relationships/SanityChecker.cs b/Core/Relationships/SanityChecker.cs index bb0e845d7e..ab36d3fc20 100644 --- a/Core/Relationships/SanityChecker.cs +++ b/Core/Relationships/SanityChecker.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; - -using CKAN.Extensions; using CKAN.Versioning; namespace CKAN diff --git a/Core/Repositories/AvailableModule.cs b/Core/Repositories/AvailableModule.cs index 00d4fc0a75..94b9f5bd1e 100644 --- a/Core/Repositories/AvailableModule.cs +++ b/Core/Repositories/AvailableModule.cs @@ -70,7 +70,9 @@ public static AvailableModule Merge(IEnumerable availMods) new SortedDictionary(); [OnError] + #pragma warning disable IDE0051, IDE0060 private void OnError(StreamingContext context, ErrorContext errorContext) + #pragma warning restore IDE0051, IDE0060 { log.WarnFormat("Discarding CkanModule, failed to parse {0}: {1}", errorContext.Path, errorContext.Error.GetBaseException().Message); @@ -83,8 +85,10 @@ private void OnError(StreamingContext context, ErrorContext errorContext) private void Add(CkanModule module) { if (!module.identifier.Equals(identifier)) + { throw new ArgumentException( string.Format("This AvailableModule is for tracking {0} not {1}", identifier, module.identifier)); + } log.DebugFormat("Adding to available module: {0}", module); module_version[module.version] = module; diff --git a/Core/Repositories/ReadProgressStream.cs b/Core/Repositories/ReadProgressStream.cs index c60eb3d03b..854b461779 100644 --- a/Core/Repositories/ReadProgressStream.cs +++ b/Core/Repositories/ReadProgressStream.cs @@ -42,7 +42,9 @@ protected ContainerStream(Stream stream) { if (stream == null) { + #pragma warning disable IDE0016 throw new ArgumentNullException("stream"); + #pragma warning restore IDE0016 } inner = stream; } @@ -56,10 +58,12 @@ protected ContainerStream(Stream stream) public override long Position { get => inner.Position; + #pragma warning disable IDE0027 set { inner.Position = value; } + #pragma warning restore IDE0027 } public override void Flush() { diff --git a/Core/Repositories/Repository.cs b/Core/Repositories/Repository.cs index be1e37d356..8dd85c5f5c 100644 --- a/Core/Repositories/Repository.cs +++ b/Core/Repositories/Repository.cs @@ -42,7 +42,7 @@ public Repository(string name, string uri, int priority) this.priority = priority; } - public override bool Equals(Object other) + public override bool Equals(object other) => Equals(other as Repository); public bool Equals(Repository other) diff --git a/Core/Repositories/RepositoryData.cs b/Core/Repositories/RepositoryData.cs index 3352ff3daf..3bfd700d92 100644 --- a/Core/Repositories/RepositoryData.cs +++ b/Core/Repositories/RepositoryData.cs @@ -150,7 +150,7 @@ public static RepositoryData FromJson(string path, IProgress progress) ? null : new ProgressImmediate(p => // Treat CkanModule creation as the last 50% - progress.Report(50 + p / 2))), + progress.Report(50 + (p / 2)))), }; return JsonSerializer.Create(settings) .Deserialize(jStream); diff --git a/Core/Repositories/RepositoryDataManager.cs b/Core/Repositories/RepositoryDataManager.cs index fc51bbc590..1908f6fcef 100644 --- a/Core/Repositories/RepositoryDataManager.cs +++ b/Core/Repositories/RepositoryDataManager.cs @@ -77,8 +77,7 @@ public IEnumerable GetAllAvailableModules(IEnumerable GetRepoDatas(repos) .Select(data => data.DownloadCounts.TryGetValue(identifier, out int count) ? (int?)count : null) - .Where(count => count != null) - .FirstOrDefault(); + .FirstOrDefault(count => count != null); #endregion @@ -144,10 +143,9 @@ public UpdateResult Update(Repository[] repos, .DistinctBy(r => r.uri) .Where(r => r.uri.IsFile || skipETags - || (etags.TryGetValue(r.uri, out string etag) - ? !File.Exists(GetRepoDataPath(r)) - || etag != Net.CurrentETag(r.uri) - : true)) + || (!etags.TryGetValue(r.uri, out string etag) + || !File.Exists(GetRepoDataPath(r)) + || etag != Net.CurrentETag(r.uri))) .ToArray(); if (toUpdate.Length < 1) { diff --git a/Core/Repositories/RepositoryList.cs b/Core/Repositories/RepositoryList.cs index d5efcca9e8..c8a2f2a2d0 100644 --- a/Core/Repositories/RepositoryList.cs +++ b/Core/Repositories/RepositoryList.cs @@ -17,7 +17,7 @@ public static RepositoryList DefaultRepositories(IGame game) } catch { - return default(RepositoryList); + return default; } } } diff --git a/Core/ServiceLocator.cs b/Core/ServiceLocator.cs index 24d60e7e27..1ba9fa817f 100644 --- a/Core/ServiceLocator.cs +++ b/Core/ServiceLocator.cs @@ -25,10 +25,12 @@ public static IContainer Container return _container; } + #pragma warning disable IDE0027 set { _container = value; } + #pragma warning restore IDE0027 } private static void Init() diff --git a/Core/SingleAssemblyResourceManager.cs b/Core/SingleAssemblyResourceManager.cs index cb452c67ef..30db7db008 100644 --- a/Core/SingleAssemblyResourceManager.cs +++ b/Core/SingleAssemblyResourceManager.cs @@ -8,7 +8,7 @@ namespace CKAN { // Thanks and credit to this guy: https://stackoverflow.com/q/1952638/2422988 - class SingleAssemblyResourceManager : ResourceManager + public class SingleAssemblyResourceManager : ResourceManager { public SingleAssemblyResourceManager(string basename, Assembly assembly) : base(basename, assembly) { @@ -22,7 +22,7 @@ protected override ResourceSet InternalGetResourceSet(CultureInfo culture, // Lazy-load default language (without caring about duplicate assignment in race conditions, no harm done) if (neutralResourcesCulture == null) { - neutralResourcesCulture = GetNeutralResourcesLanguage(this.MainAssembly); + neutralResourcesCulture = GetNeutralResourcesLanguage(MainAssembly); } // If we're asking for the default language, then ask for the @@ -33,7 +33,7 @@ protected override ResourceSet InternalGetResourceSet(CultureInfo culture, } string resourceFileName = GetResourceFileName(culture); - Stream store = this.MainAssembly.GetManifestResourceStream(resourceFileName); + Stream store = MainAssembly.GetManifestResourceStream(resourceFileName); // If we found the appropriate resources in the local assembly if (store != null) diff --git a/Core/SuppressedCompatWarningIdentifiers.cs b/Core/SuppressedCompatWarningIdentifiers.cs index 525f0ea968..1de097fb91 100644 --- a/Core/SuppressedCompatWarningIdentifiers.cs +++ b/Core/SuppressedCompatWarningIdentifiers.cs @@ -8,7 +8,7 @@ namespace CKAN { - class SuppressedCompatWarningIdentifiers + public class SuppressedCompatWarningIdentifiers { public GameVersion GameVersionWhenWritten; public HashSet Identifiers = new HashSet(); diff --git a/Core/Types/CkanModule.cs b/Core/Types/CkanModule.cs index 1b72b48bbe..25a77d2626 100644 --- a/Core/Types/CkanModule.cs +++ b/Core/Types/CkanModule.cs @@ -13,7 +13,6 @@ using Newtonsoft.Json; using CKAN.Versioning; -using CKAN.Extensions; using CKAN.Games; namespace CKAN @@ -217,16 +216,18 @@ public ModuleVersion spec_version get { if (specVersion == null) + { specVersion = new ModuleVersion("1"); + } + return specVersion; } + #pragma warning disable IDE0027 set { - if (value == null) - specVersion = new ModuleVersion("1"); - else - specVersion = value; + specVersion = value ?? new ModuleVersion("1"); } + #pragma warning restore IDE0027 } [JsonProperty("tags", Order = 16, NullValueHandling = NullValueHandling.Ignore)] @@ -327,7 +328,7 @@ public CkanModule( this.version = version; this.download = new List { download }; this.kind = kind; - this._comparator = comparator ?? ServiceLocator.Container.Resolve(); + _comparator = comparator ?? ServiceLocator.Container.Resolve(); CheckHealth(); CalculateSearchables(); } @@ -391,10 +392,10 @@ private void CheckHealth() /// private void CalculateSearchables() { - SearchableIdentifier = identifier == null ? string.Empty : CkanModule.nonAlphaNums.Replace(identifier, ""); - SearchableName = name == null ? string.Empty : CkanModule.nonAlphaNums.Replace(name, ""); - SearchableAbstract = @abstract == null ? string.Empty : CkanModule.nonAlphaNums.Replace(@abstract, ""); - SearchableDescription = description == null ? string.Empty : CkanModule.nonAlphaNums.Replace(description, ""); + SearchableIdentifier = identifier == null ? string.Empty : nonAlphaNums.Replace(identifier, ""); + SearchableName = name == null ? string.Empty : nonAlphaNums.Replace(name, ""); + SearchableAbstract = @abstract == null ? string.Empty : nonAlphaNums.Replace(@abstract, ""); + SearchableDescription = description == null ? string.Empty : nonAlphaNums.Replace(description, ""); SearchableAuthors = new List(); if (author == null) @@ -405,7 +406,7 @@ private void CalculateSearchables() { foreach (string auth in author) { - SearchableAuthors.Add(CkanModule.nonAlphaNums.Replace(auth, "")); + SearchableAuthors.Add(nonAlphaNums.Replace(auth, "")); } } } @@ -457,8 +458,10 @@ public static CkanModule FromIDandVersion(IRegistryQuerier registry, string mod, if (module == null || (ksp_version != null && !module.IsCompatible(ksp_version))) + { throw new ModuleNotFoundKraken(ident, version, string.Format(Properties.Resources.CkanModuleNotAvailable, ident, version)); + } } else { @@ -466,8 +469,10 @@ public static CkanModule FromIDandVersion(IRegistryQuerier registry, string mod, ?? registry.InstalledModule(mod)?.Module; if (module == null) + { throw new ModuleNotFoundKraken(mod, null, string.Format(Properties.Resources.CkanModuleNotInstalledOrAvailable, mod)); + } } return module; } @@ -587,12 +592,9 @@ protected bool Equals(CkanModule other) => string.Equals(identifier, other.identifier) && version.Equals(other.version); public override bool Equals(object obj) - { - if (obj is null) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((CkanModule)obj); - } + => !(obj is null) + && (ReferenceEquals(this, obj) + || (obj.GetType() == GetType() && Equals((CkanModule)obj))); public bool MetadataEquals(CkanModule other) { @@ -607,7 +609,9 @@ public bool MetadataEquals(CkanModule other) for (int i = 0; i < install.Length; i++) { if (!install[i].Equals(other.install[i])) + { return false; + } } } if (install_size != other.install_size) @@ -616,20 +620,30 @@ public bool MetadataEquals(CkanModule other) } if (!RelationshipsAreEquivalent(conflicts, other.conflicts)) + { return false; + } if (!RelationshipsAreEquivalent(depends, other.depends)) + { return false; + } if (!RelationshipsAreEquivalent(recommends, other.recommends)) + { return false; + } if (provides != other.provides) { if (provides == null || other.provides == null) + { return false; + } else if (!provides.OrderBy(i => i).SequenceEqual(other.provides.OrderBy(i => i))) + { return false; + } } return true; } @@ -637,16 +651,22 @@ public bool MetadataEquals(CkanModule other) private static bool RelationshipsAreEquivalent(List a, List b) { if (a == b) + { // If they're the same exact object they must be equivalent return true; + } if (a == null || b == null) + { // If they're not the same exact object and either is null then must not be equivalent return false; + } if (a.Count != b.Count) + { // If their counts different they must not be equivalent return false; + } // Sort the lists so we can compare each relationship var aSorted = a.OrderBy(i => i.ToString()).ToList(); @@ -833,11 +853,11 @@ public static void GetMinMaxVersions(IEnumerable modVersions, } GameVersion relMin = rel.EarliestCompatibleGameVersion(); GameVersion relMax = rel.LatestCompatibleGameVersion(); - if (minGame == null || !minGame.IsAny && (minGame > relMin || relMin.IsAny)) + if (minGame == null || (!minGame.IsAny && (minGame > relMin || relMin.IsAny))) { minGame = relMin; } - if (maxGame == null || !maxGame.IsAny && (maxGame < relMax || relMax.IsAny)) + if (maxGame == null || (!maxGame.IsAny && (maxGame < relMax || relMax.IsAny))) { maxGame = relMax; } diff --git a/Core/Types/GameComparator/GrasGameComparator.cs b/Core/Types/GameComparator/GrasGameComparator.cs index 51df90cb8b..2216037d27 100644 --- a/Core/Types/GameComparator/GrasGameComparator.cs +++ b/Core/Types/GameComparator/GrasGameComparator.cs @@ -9,22 +9,22 @@ namespace CKAN /// public class GrasGameComparator : BaseGameComparator { - static readonly StrictGameComparator strict = new StrictGameComparator(); - static readonly GameVersion v103 = GameVersion.Parse("1.0.3"); - static readonly GameVersion v104 = GameVersion.Parse("1.0.4"); + private static readonly StrictGameComparator strict = new StrictGameComparator(); + private static readonly GameVersion v103 = GameVersion.Parse("1.0.3"); + private static readonly GameVersion v104 = GameVersion.Parse("1.0.4"); public override bool Compatible(GameVersionCriteria gameVersionCriteria, CkanModule module) { // If it's strictly compatible, then it's compatible. if (strict.Compatible(gameVersionCriteria, module)) + { return true; + } // If we're in strict mode, and it's not strictly compatible, then it's // not compatible. - if (module.ksp_version_strict) - return false; - - return base.Compatible(gameVersionCriteria, module); + return !module.ksp_version_strict + && base.Compatible(gameVersionCriteria, module); } public override bool SingleVersionsCompatible (GameVersion gameVersion, CkanModule module) @@ -34,10 +34,8 @@ public override bool SingleVersionsCompatible (GameVersion gameVersion, CkanModu // If we're running KSP 1.0.4, then allow the mod to run if we would have // considered it compatible under 1.0.3 (as 1.0.4 was "just a hotfix"). - if (gameVersion.Equals(v104)) - return strict.SingleVersionsCompatible(v103, module); - - return false; + return gameVersion.Equals(v104) + && strict.SingleVersionsCompatible(v103, module); } } } diff --git a/Core/Types/Kraken.cs b/Core/Types/Kraken.cs index bc05a4add2..4ec8f869ed 100644 --- a/Core/Types/Kraken.cs +++ b/Core/Types/Kraken.cs @@ -387,10 +387,7 @@ public class ModNotInstalledKraken : Kraken { public readonly string mod; - public override string Message - { - get { return string.Format(Properties.Resources.KrakenNotInstalled, mod); } - } + public override string Message => string.Format(Properties.Resources.KrakenNotInstalled, mod); // TODO: Since we override message, should we really allow users to pass in a reason // here? Is there a way we can check if that was set, and then access it directly from @@ -453,7 +450,7 @@ public class RegistryInUseKraken : Kraken public RegistryInUseKraken(string path, string reason = null, Exception inner_exception = null) :base(reason, inner_exception) { - this.lockfilePath = path; + lockfilePath = path; } public override string ToString() @@ -531,7 +528,7 @@ public class InstanceNameTakenKraken : Kraken public InstanceNameTakenKraken(string name, string reason = null) : base(reason) { - this.instName = name; + instName = name; } } diff --git a/Core/Types/License.cs b/Core/Types/License.cs index 8eb7202c88..b618ac1132 100644 --- a/Core/Types/License.cs +++ b/Core/Types/License.cs @@ -3,8 +3,6 @@ using Newtonsoft.Json; -using CKAN.Extensions; - namespace CKAN { /// @@ -61,8 +59,6 @@ public License(string license) /// Returns the license as a string. /// public override string ToString() - { - return license; - } + => license; } } diff --git a/Core/Types/ModuleInstallDescriptor.cs b/Core/Types/ModuleInstallDescriptor.cs index e73968a1e6..49095dbf97 100644 --- a/Core/Types/ModuleInstallDescriptor.cs +++ b/Core/Types/ModuleInstallDescriptor.cs @@ -150,40 +150,85 @@ public override bool Equals(object other) public bool Equals(ModuleInstallDescriptor otherStanza) { if (otherStanza == null) + { // Not even the right type! return false; + } + if (CKANPathUtils.NormalizePath(file) != CKANPathUtils.NormalizePath(otherStanza.file)) + { return false; + } + if (CKANPathUtils.NormalizePath(find) != CKANPathUtils.NormalizePath(otherStanza.find)) + { return false; + } + if (find_regexp != otherStanza.find_regexp) + { return false; + } + if (CKANPathUtils.NormalizePath(install_to) != CKANPathUtils.NormalizePath(otherStanza.install_to)) + { return false; + } + if (@as != otherStanza.@as) + { return false; + } + if ((filter == null) != (otherStanza.filter == null)) + { return false; + } + if (filter != null && !filter.SequenceEqual(otherStanza.filter)) + { return false; + } + if ((filter_regexp == null) != (otherStanza.filter_regexp == null)) + { return false; + } + if (filter_regexp != null && !filter_regexp.SequenceEqual(otherStanza.filter_regexp)) + { return false; + } + if (find_matches_files != otherStanza.find_matches_files) + { return false; + } + if ((include_only == null) != (otherStanza.include_only == null)) + { return false; + } + if (include_only != null && !include_only.SequenceEqual(otherStanza.include_only)) + { return false; + } + if ((include_only_regexp == null) != (otherStanza.include_only_regexp == null)) + { return false; + } + if (include_only_regexp != null && !include_only_regexp.SequenceEqual(otherStanza.include_only_regexp)) + { return false; + } + return true; } @@ -302,14 +347,7 @@ private bool IsWanted(string path, int? matchWhere) return true; } - if (include_only != null || include_only_regexp != null) - { - return false; - } - else - { - return true; - } + return include_only == null && include_only_regexp == null; } /// @@ -334,8 +372,10 @@ public List FindInstallableFiles(ZipFile zipfile, GameInstance // The installation path cannot contain updirs if (install_to.Contains("/../") || install_to.EndsWith("/..")) + { throw new BadInstallLocationKraken(string.Format( Properties.Resources.ModuleInstallDescriptorInvalidInstallPath, install_to)); + } if (ksp == null) { @@ -376,7 +416,7 @@ public List FindInstallableFiles(ZipFile zipfile, GameInstance EnsurePattern(); // `find` is supposed to match the "topmost" folder. Find it. - var shortestMatch = find == null ? (int?)null + var shortestMatch = find == null ? null : zipfile.Cast() .Select(entry => inst_pattern.Match(entry.Name.Replace('\\', '/'))) .Where(match => match.Success) @@ -421,7 +461,7 @@ public List FindInstallableFiles(ZipFile zipfile, GameInstance if (files.Count == 0) { // We have null as the first argument here, because we don't know which module we're installing - throw new BadMetadataKraken(null, String.Format( + throw new BadMetadataKraken(null, string.Format( Properties.Resources.ModuleInstallDescriptorNoFilesFound, DescribeMatch())); } @@ -456,7 +496,7 @@ internal string TransformOutputName(IGame game, string outputName, string instal RegexOptions.Compiled); if (!leadingRE.IsMatch(outputName)) { - throw new BadMetadataKraken(null, String.Format( + throw new BadMetadataKraken(null, string.Format( "Output file name ({0}) not matching leading path of stanza ({1})", outputName, leadingPathToRemove)); } diff --git a/Core/Types/ReleaseStatus.cs b/Core/Types/ReleaseStatus.cs index a3155e1507..4d89ee8107 100644 --- a/Core/Types/ReleaseStatus.cs +++ b/Core/Types/ReleaseStatus.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using Newtonsoft.Json; @@ -47,7 +46,7 @@ public ReleaseStatus(string status) { throw new BadMetadataKraken( null, - String.Format(Properties.Resources.ReleaseStatusInvalid, status) + string.Format(Properties.Resources.ReleaseStatusInvalid, status) ); } diff --git a/Core/Types/TimeLog.cs b/Core/Types/TimeLog.cs index 8705b72a14..fbb032e6ae 100644 --- a/Core/Types/TimeLog.cs +++ b/Core/Types/TimeLog.cs @@ -13,9 +13,7 @@ public class TimeLog public TimeSpan Time; public static string GetPath(string dir) - { - return Path.Combine(dir, filename); - } + => Path.Combine(dir, filename); public static TimeLog Load(string path) { @@ -34,10 +32,8 @@ public void Save(string path) File.WriteAllText(path, JsonConvert.SerializeObject(this, Formatting.Indented)); } - public override String ToString() - { - return Time.TotalHours.ToString("N1"); - } + public override string ToString() + => Time.TotalHours.ToString("N1"); private readonly Stopwatch playTime = new Stopwatch(); diff --git a/Core/User.cs b/Core/User.cs index e161fdcd3d..7d94cb44a4 100644 --- a/Core/User.cs +++ b/Core/User.cs @@ -33,10 +33,7 @@ public class NullUser : IUser /// /// NullUser is headless. Variable not used for NullUser. /// - public bool Headless - { - get { return true; } - } + public bool Headless => true; /// /// NullUser returns true. diff --git a/Core/Versioning/GameVersion.cs b/Core/Versioning/GameVersion.cs index 09e2c718f6..1efe095fb0 100644 --- a/Core/Versioning/GameVersion.cs +++ b/Core/Versioning/GameVersion.cs @@ -124,7 +124,9 @@ public GameVersion() public GameVersion(int major) { if (major < 0) + { throw new ArgumentOutOfRangeException("major"); + } _major = major; _minor = Undefined; @@ -143,10 +145,14 @@ public GameVersion(int major) public GameVersion(int major, int minor) { if (major < 0) + { throw new ArgumentOutOfRangeException("major"); + } if (minor < 0) + { throw new ArgumentOutOfRangeException("minor"); + } _major = major; _minor = minor; @@ -166,13 +172,19 @@ public GameVersion(int major, int minor) public GameVersion(int major, int minor, int patch) { if (major < 0) + { throw new ArgumentOutOfRangeException("major"); + } if (minor < 0) + { throw new ArgumentOutOfRangeException("minor"); + } if (patch < 0) + { throw new ArgumentOutOfRangeException("patch"); + } _major = major; _minor = minor; @@ -193,16 +205,24 @@ public GameVersion(int major, int minor, int patch) public GameVersion(int major, int minor, int patch, int build) { if (major < 0) + { throw new ArgumentOutOfRangeException("major", major, $"{major}"); + } if (minor < 0) + { throw new ArgumentOutOfRangeException("minor", minor, $"{minor}"); + } if (patch < 0) + { throw new ArgumentOutOfRangeException("patch", patch, $"{patch}"); + } if (build < 0) + { throw new ArgumentOutOfRangeException("build", build, $"{build}"); + } _major = major; _minor = minor; @@ -213,12 +233,12 @@ public GameVersion(int major, int minor, int patch, int build) } /// - /// Converts the value of the current to its equivalent + /// Converts the value of the current to its equivalent /// representation. /// /// /// - /// The representation of the values of the major, minor, patch, and build components of + /// The representation of the values of the major, minor, patch, and build components of /// the current object as depicted in the following format. Each component is /// separated by a period character ('.'). Square brackets ('[' and ']') indicate a component that will not /// appear in the return value if the component is not defined: @@ -343,7 +363,7 @@ public static bool TryParse(string input, out GameVersion result) if (input == "any") { - result = GameVersion.Any; + result = Any; return true; } @@ -364,43 +384,71 @@ public static bool TryParse(string input, out GameVersion result) if (majorGroup.Success) { if (!int.TryParse(majorGroup.Value, out major)) + { return false; - if (major < 0 || major == Int32.MaxValue) + } + + if (major < 0 || major == int.MaxValue) + { major = Undefined; + } } if (minorGroup.Success) { if (!int.TryParse(minorGroup.Value, out minor)) + { return false; - if (minor < 0 || minor == Int32.MaxValue) + } + + if (minor < 0 || minor == int.MaxValue) + { minor = Undefined; + } } if (patchGroup.Success) { if (!int.TryParse(patchGroup.Value, out patch)) + { return false; - if (patch < 0 || patch == Int32.MaxValue) + } + + if (patch < 0 || patch == int.MaxValue) + { patch = Undefined; + } } if (buildGroup.Success) { if (!int.TryParse(buildGroup.Value, out build)) + { return false; - if (build < 0 || build == Int32.MaxValue) + } + + if (build < 0 || build == int.MaxValue) + { build = Undefined; + } } if (minor == Undefined) + { result = new GameVersion(major); + } else if (patch == Undefined) + { result = new GameVersion(major, minor); + } else if (build == Undefined) + { result = new GameVersion(major, minor, patch); + } else + { result = new GameVersion(major, minor, patch, build); + } return true; } @@ -542,8 +590,16 @@ public sealed partial class GameVersion : IEquatable /// public bool Equals(GameVersion obj) { - if (obj is null) return false; - if (ReferenceEquals(obj, this)) return true; + if (obj is null) + { + return false; + } + + if (ReferenceEquals(obj, this)) + { + return true; + } + return _major == obj._major && _minor == obj._minor && _patch == obj._patch && _build == obj._build; } @@ -561,8 +617,16 @@ public bool Equals(GameVersion obj) /// public override bool Equals(object obj) { - if (obj is null) return false; - if (ReferenceEquals(obj, this)) return true; + if (obj is null) + { + return false; + } + + if (ReferenceEquals(obj, this)) + { + return true; + } + return obj is GameVersion gv && Equals(gv); } @@ -833,13 +897,19 @@ public sealed partial class GameVersion public static GameVersion Min(params GameVersion[] versions) { if (versions == null) + { throw new ArgumentNullException("versions"); + } if (!versions.Any()) + { throw new ArgumentException("Value cannot be empty.", "versions"); + } if (versions.Any(i => i == null)) + { throw new ArgumentException("Value cannot contain null.", "versions"); + } return versions.Min(); } @@ -847,13 +917,19 @@ public static GameVersion Min(params GameVersion[] versions) public static GameVersion Max(params GameVersion[] versions) { if (versions == null) + { throw new ArgumentNullException("versions"); + } if (!versions.Any()) + { throw new ArgumentException("Value cannot be empty.", "versions"); + } if (versions.Any(i => i == null)) + { throw new ArgumentException("Value cannot contain null.", "versions"); + } return versions.Max(); } diff --git a/Core/Versioning/GameVersionBound.cs b/Core/Versioning/GameVersionBound.cs index 5777942bda..f125d03494 100644 --- a/Core/Versioning/GameVersionBound.cs +++ b/Core/Versioning/GameVersionBound.cs @@ -17,11 +17,15 @@ public GameVersionBound() public GameVersionBound(GameVersion value, bool inclusive) { - if (ReferenceEquals(value, null)) + if (value is null) + { throw new ArgumentNullException("value"); + } if (!value.IsAny && !value.IsFullyDefined) + { throw new ArgumentException("Version must be either fully undefined or fully defined.", "value"); + } Value = value; Inclusive = inclusive; @@ -68,16 +72,32 @@ public sealed partial class GameVersionBound : IEquatable { public bool Equals(GameVersionBound other) { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; + if (other is null) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + return Equals(Value, other.Value) && Inclusive == other.Inclusive; } public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj is GameVersionBound && Equals((GameVersionBound) obj); + if (obj is null) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + return obj is GameVersionBound bound && Equals(bound); } public override int GetHashCode() @@ -104,13 +124,19 @@ public sealed partial class GameVersionBound public static GameVersionBound Lowest(params GameVersionBound[] versionBounds) { if (versionBounds == null) + { throw new ArgumentNullException("versionBounds"); + } if (!versionBounds.Any()) + { throw new ArgumentException("Value cannot be empty.", "versionBounds"); + } if (versionBounds.Any(i => i == null)) + { throw new ArgumentException("Value cannot contain null.", "versionBounds"); + } return versionBounds .OrderBy(i => i == Unbounded) @@ -129,13 +155,19 @@ public static GameVersionBound Lowest(params GameVersionBound[] versionBounds) public static GameVersionBound Highest(params GameVersionBound[] versionBounds) { if (versionBounds == null) + { throw new ArgumentNullException("versionBounds"); + } if (!versionBounds.Any()) + { throw new ArgumentException("Value cannot be empty.", "versionBounds"); + } if (versionBounds.Any(i => i == null)) + { throw new ArgumentException("Value cannot contain null.", "versionBounds"); + } return versionBounds .OrderBy(i => i == Unbounded) diff --git a/Core/Versioning/GameVersionCriteria.cs b/Core/Versioning/GameVersionCriteria.cs index b71df9130e..e7a6435e2b 100644 --- a/Core/Versioning/GameVersionCriteria.cs +++ b/Core/Versioning/GameVersionCriteria.cs @@ -8,13 +8,13 @@ namespace CKAN.Versioning { public class GameVersionCriteria : IEquatable { - private List _versions = new List(); + private readonly List _versions = new List(); public GameVersionCriteria(GameVersion v) { if (v != null) { - this._versions.Add(v); + _versions.Add(v); } } @@ -22,10 +22,10 @@ public GameVersionCriteria(GameVersion v, List compatibleVersions) { if (v != null) { - this._versions.Add(v); + _versions.Add(v); } - this._versions.AddRange(compatibleVersions); - this._versions = this._versions.Distinct().ToList(); + _versions.AddRange(compatibleVersions); + _versions = _versions.Distinct().ToList(); } public IList Versions => _versions.AsReadOnly(); @@ -46,14 +46,13 @@ public override bool Equals(object obj) // From IEquatable public bool Equals(GameVersionCriteria other) - => other == null ? false - : !_versions.Except(other._versions).Any() - && !other._versions.Except(_versions).Any(); + => other != null && !_versions.Except(other._versions).Any() + && !other._versions.Except(_versions).Any(); public override int GetHashCode() - => _versions.Aggregate(19, (code, vers) => code * 31 + vers.GetHashCode()); + => _versions.Aggregate(19, (code, vers) => (code * 31) + vers.GetHashCode()); - public override String ToString() + public override string ToString() => string.Format(Properties.Resources.GameVersionCriteriaToString, string.Join(", ", _versions.Select(v => v.ToString()))); diff --git a/Core/Versioning/GameVersionRange.cs b/Core/Versioning/GameVersionRange.cs index d366c8e8ee..20bcc84d60 100644 --- a/Core/Versioning/GameVersionRange.cs +++ b/Core/Versioning/GameVersionRange.cs @@ -16,11 +16,15 @@ public sealed partial class GameVersionRange public GameVersionRange(GameVersionBound lower, GameVersionBound upper) { - if (ReferenceEquals(lower, null)) + if (lower is null) + { throw new ArgumentNullException("lower"); + } - if (ReferenceEquals(upper, null)) + if (upper is null) + { throw new ArgumentNullException("upper"); + } Lower = lower; Upper = upper; @@ -35,8 +39,10 @@ public GameVersionRange(GameVersion lower, GameVersion upper) public GameVersionRange IntersectWith(GameVersionRange other) { - if (ReferenceEquals(other, null)) + if (other is null) + { throw new ArgumentNullException("other"); + } var highestLow = GameVersionBound.Highest(Lower, other.Lower); var lowestHigh = GameVersionBound.Lowest(Upper, other.Upper); @@ -51,8 +57,10 @@ private bool Intersects(GameVersionRange other) public bool IsSupersetOf(GameVersionRange other) { - if (ReferenceEquals(other, null)) + if (other is null) + { throw new ArgumentNullException("other"); + } var lowerIsOkay = Lower.Value.IsAny || (Lower.Value < other.Lower.Value) @@ -84,12 +92,16 @@ private static string DeriveString(GameVersionRange versionRange) sb.Append(versionRange.Lower.Inclusive ? '[' : '('); if (versionRange.Lower.Value != null) + { sb.Append(versionRange.Lower.Value); + } sb.Append(','); if (versionRange.Upper.Value != null) + { sb.Append(versionRange.Upper.Value); + } sb.Append(versionRange.Upper.Inclusive ? ']' : ')'); @@ -129,16 +141,32 @@ public sealed partial class GameVersionRange : IEquatable { public bool Equals(GameVersionRange other) { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; + if (other is null) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + return Equals(Lower, other.Lower) && Equals(Upper, other.Upper); } public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj is GameVersionRange && Equals((GameVersionRange) obj); + if (obj is null) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + return obj is GameVersionRange range && Equals(range); } public override int GetHashCode() diff --git a/Core/Versioning/ModuleVersion.cs b/Core/Versioning/ModuleVersion.cs index 7c5ac2883b..ef3d656efc 100644 --- a/Core/Versioning/ModuleVersion.cs +++ b/Core/Versioning/ModuleVersion.cs @@ -41,13 +41,15 @@ public partial class ModuleVersion /// /// Initializes a new instance of the class using the specified string. /// - /// A in the appropriate format. + /// A in the appropriate format. public ModuleVersion(string version) { var match = Pattern.Match(version); if (!match.Success) + { throw new FormatException("Input string was not in a correct format."); + } // If we have an epoch, then record it. if (match.Groups["epoch"].Value.Length > 0) @@ -77,10 +79,10 @@ public ModuleVersion IncrementEpoch() /// /// Converts the value of the current object to its equivalent - /// representation. + /// representation. /// /// - /// The representation of the current object. + /// The representation of the current object. /// /// /// /// The return value should not be considered safe for use in file paths. @@ -103,7 +105,9 @@ public partial class ModuleVersion : IEquatable public override bool Equals(object obj) { if (ReferenceEquals(this, obj)) + { return true; + } return obj is ModuleVersion version && Equals(version); } @@ -111,7 +115,9 @@ public override bool Equals(object obj) public bool Equals(ModuleVersion other) { if (ReferenceEquals(this, other)) + { return true; + } return CompareTo(other) == 0; } @@ -312,30 +318,42 @@ Comparison numComp(string v1, string v2) if (!int.TryParse(v1.Substring(0, minimumLength1), out var integer1)) + { integer1 = 0; + } if (!int.TryParse(v2.Substring(0, minimumLength2), out var integer2)) + { integer2 = 0; + } comparison.CompareTo = integer1.CompareTo(integer2); return comparison; } if (other == null) + { throw new ArgumentNullException(nameof(other)); + } if (other._epoch == _epoch && other._version.Equals(_version)) + { return 0; + } // Compare epochs first. if (_epoch != other._epoch) + { return _epoch > other._epoch ? 1 : -1; + } // Epochs are the same. Do the dance described in // https://github.com/KSP-CKAN/CKAN/blob/master/Spec.md#version-ordering var tuple = new Tuple(_string, other._string); if (ComparisonCache.TryGetValue(tuple, out var ret)) + { return ret; + } Comparison comp; comp.FirstRemainder = _version; @@ -602,10 +620,14 @@ public partial class ModuleVersion public static ModuleVersion Max(ModuleVersion ver1, ModuleVersion ver2) { if (ver1 == null) + { throw new ArgumentNullException(nameof(ver1)); + } if (ver2 == null) + { throw new ArgumentNullException(nameof(ver2)); + } return ver1.IsGreaterThan(ver2) ? ver1 : ver2; } @@ -623,10 +645,14 @@ public static ModuleVersion Max(ModuleVersion ver1, ModuleVersion ver2) public static ModuleVersion Min(ModuleVersion ver1, ModuleVersion ver2) { if (ver1 == null) + { throw new ArgumentNullException(nameof(ver1)); + } if (ver2 == null) + { throw new ArgumentNullException(nameof(ver2)); + } return ver1.IsLessThan(ver2) ? ver1 : ver2; } @@ -634,9 +660,9 @@ public static ModuleVersion Min(ModuleVersion ver1, ModuleVersion ver2) /// /// Converts the specified string to a new instance of the class. /// - /// A in the appropriate format. + /// A in the appropriate format. /// - /// A new instance representing the specified . + /// A new instance representing the specified . /// public static explicit operator ModuleVersion(string version) { diff --git a/Core/Versioning/ProvidesModuleVersion.cs b/Core/Versioning/ProvidesModuleVersion.cs index 8ec52cf448..2ec3a23962 100644 --- a/Core/Versioning/ProvidesModuleVersion.cs +++ b/Core/Versioning/ProvidesModuleVersion.cs @@ -29,8 +29,6 @@ public ProvidesModuleVersion(string identifier, string version) : base(version) /// The returned value is not a real version string and is for display purposes only. /// public override string ToString() - { - return _string; - } + => _string; } } diff --git a/Core/Versioning/UnmanagedModuleVersion.cs b/Core/Versioning/UnmanagedModuleVersion.cs index 44f0113421..f71cc77980 100644 --- a/Core/Versioning/UnmanagedModuleVersion.cs +++ b/Core/Versioning/UnmanagedModuleVersion.cs @@ -19,8 +19,6 @@ public UnmanagedModuleVersion(string version) : base(version ?? "0") } public override string ToString() - { - return _string; - } + => _string; } } diff --git a/GUI/CKAN-GUI.csproj b/GUI/CKAN-GUI.csproj index 50736ea53a..6a0e37ee50 100644 --- a/GUI/CKAN-GUI.csproj +++ b/GUI/CKAN-GUI.csproj @@ -1,7 +1,8 @@ CKAN-GUI - ..\_build\out\$(AssemblyName)\$(Configuration)\bin\ + ..\_build\out\$(AssemblyName)\$(Configuration)\bin\ + ..\_build\out\$(AssemblyName)\VSCodeIDE\bin\ ..\_build\out\$(AssemblyName)\$(Configuration)\obj\ @@ -14,20 +15,28 @@ true Debug;Release false - 7 - net45 + 7.3 + net48 ..\assets\ckan.ico - v4.5 + v4.8 512 prompt 4 IDE1006 + + true + diff --git a/GUI/Controls/ChooseProvidedMods.cs b/GUI/Controls/ChooseProvidedMods.cs index 17b1abb817..60cb9dde73 100644 --- a/GUI/Controls/ChooseProvidedMods.cs +++ b/GUI/Controls/ChooseProvidedMods.cs @@ -46,13 +46,7 @@ public CkanModule Wait() return task.Task.Result; } - public ListView.SelectedListViewItemCollection SelectedItems - { - get - { - return ChooseProvidedModsListView.SelectedItems; - } - } + public ListView.SelectedListViewItemCollection SelectedItems => ChooseProvidedModsListView.SelectedItems; public event Action OnSelectedItemsChanged; diff --git a/GUI/Controls/ChooseRecommendedMods.cs b/GUI/Controls/ChooseRecommendedMods.cs index a1ef0cbc77..a28ec8c08d 100644 --- a/GUI/Controls/ChooseRecommendedMods.cs +++ b/GUI/Controls/ChooseRecommendedMods.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using System.Windows.Forms; -using CKAN.Extensions; using CKAN.Versioning; using CKAN.GUI.Attributes; @@ -184,7 +183,9 @@ private void RecommendedModsToggleCheckbox_CheckedChanged(object sender, EventAr foreach (ListViewItem item in RecommendedModsListView.Items) { if (item.Checked != state) + { item.Checked = state; + } } MarkConflicts(); RecommendedModsListView.EndUpdate(); diff --git a/GUI/Controls/DeleteDirectories.cs b/GUI/Controls/DeleteDirectories.cs index dab1b62d85..ab9fdccde7 100644 --- a/GUI/Controls/DeleteDirectories.cs +++ b/GUI/Controls/DeleteDirectories.cs @@ -4,8 +4,6 @@ using System.Threading.Tasks; using System.Collections.Generic; using System.Windows.Forms; - -using CKAN.Extensions; using CKAN.GUI.Attributes; namespace CKAN.GUI @@ -98,7 +96,7 @@ protected override void OnHelpRequested(HelpEventArgs evt) evt.Handled = Util.TryOpenWebPage(HelpURLs.DeleteDirectories); } - private void DirectoriesListView_ItemSelectionChanged(Object sender, ListViewItemSelectionChangedEventArgs e) + private void DirectoriesListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { ContentsListView.Items.Clear(); ContentsListView.Items.AddRange( diff --git a/GUI/Controls/DropdownMenuButton.cs b/GUI/Controls/DropdownMenuButton.cs index f99fe7c70e..c1bdbb12e6 100644 --- a/GUI/Controls/DropdownMenuButton.cs +++ b/GUI/Controls/DropdownMenuButton.cs @@ -33,7 +33,7 @@ protected override void OnPaint(PaintEventArgs pevent) if (Menu != null) { int arrowX = ClientRectangle.Width - 14, - arrowY = ClientRectangle.Height / 2 - 1; + arrowY = (ClientRectangle.Height / 2) - 1; pevent.Graphics.FillPolygon( Enabled ? SystemBrushes.ControlText : SystemBrushes.ButtonShadow, diff --git a/GUI/Controls/EditModSearch.cs b/GUI/Controls/EditModSearch.cs index fd209a29e2..0e8a87206d 100644 --- a/GUI/Controls/EditModSearch.cs +++ b/GUI/Controls/EditModSearch.cs @@ -112,7 +112,7 @@ private void ImmediateHandler(object sender, EventArgs e) } catch (Kraken k) { - Main.Instance.AddStatusMessage(k.Message); + Main.Instance?.AddStatusMessage(k.Message); } } @@ -241,7 +241,9 @@ private static string CombinePieces(string joined, string piece) private void SearchDetails_ApplySearch(object sender, EventArgs e) { if (suppressSearch) + { return; + } var knownLabels = Main.Instance.ManageMods.mainModList.ModuleLabels.LabelsFor(Main.Instance.CurrentInstance.Name).ToList(); diff --git a/GUI/Controls/EditModpack.cs b/GUI/Controls/EditModpack.cs index dd45adb145..8799e2c7ef 100644 --- a/GUI/Controls/EditModpack.cs +++ b/GUI/Controls/EditModpack.cs @@ -18,20 +18,20 @@ public EditModpack() { InitializeComponent(); - this.ToolTip.SetToolTip(IdentifierTextBox, Properties.Resources.EditModpackTooltipIdentifier); - this.ToolTip.SetToolTip(NameTextBox, Properties.Resources.EditModpackTooltipName); - this.ToolTip.SetToolTip(AbstractTextBox, Properties.Resources.EditModpackTooltipAbstract); - this.ToolTip.SetToolTip(VersionTextBox, Properties.Resources.EditModpackTooltipVersion); - this.ToolTip.SetToolTip(GameVersionMinComboBox, Properties.Resources.EditModpackTooltipGameVersionMin); - this.ToolTip.SetToolTip(GameVersionMaxComboBox, Properties.Resources.EditModpackTooltipGameVersionMax); - this.ToolTip.SetToolTip(LicenseComboBox, Properties.Resources.EditModpackTooltipLicense); - this.ToolTip.SetToolTip(IncludeVersionsCheckbox, Properties.Resources.EditModpackTooltipIncludeVersions); - this.ToolTip.SetToolTip(DependsRadioButton, Properties.Resources.EditModpackTooltipDepends); - this.ToolTip.SetToolTip(RecommendsRadioButton, Properties.Resources.EditModpackTooltipRecommends); - this.ToolTip.SetToolTip(SuggestsRadioButton, Properties.Resources.EditModpackTooltipSuggests); - this.ToolTip.SetToolTip(IgnoreRadioButton, Properties.Resources.EditModpackTooltipIgnore); - this.ToolTip.SetToolTip(CancelExportButton, Properties.Resources.EditModpackTooltipCancel); - this.ToolTip.SetToolTip(ExportModpackButton, Properties.Resources.EditModpackTooltipExport); + ToolTip.SetToolTip(IdentifierTextBox, Properties.Resources.EditModpackTooltipIdentifier); + ToolTip.SetToolTip(NameTextBox, Properties.Resources.EditModpackTooltipName); + ToolTip.SetToolTip(AbstractTextBox, Properties.Resources.EditModpackTooltipAbstract); + ToolTip.SetToolTip(VersionTextBox, Properties.Resources.EditModpackTooltipVersion); + ToolTip.SetToolTip(GameVersionMinComboBox, Properties.Resources.EditModpackTooltipGameVersionMin); + ToolTip.SetToolTip(GameVersionMaxComboBox, Properties.Resources.EditModpackTooltipGameVersionMax); + ToolTip.SetToolTip(LicenseComboBox, Properties.Resources.EditModpackTooltipLicense); + ToolTip.SetToolTip(IncludeVersionsCheckbox, Properties.Resources.EditModpackTooltipIncludeVersions); + ToolTip.SetToolTip(DependsRadioButton, Properties.Resources.EditModpackTooltipDepends); + ToolTip.SetToolTip(RecommendsRadioButton, Properties.Resources.EditModpackTooltipRecommends); + ToolTip.SetToolTip(SuggestsRadioButton, Properties.Resources.EditModpackTooltipSuggests); + ToolTip.SetToolTip(IgnoreRadioButton, Properties.Resources.EditModpackTooltipIgnore); + ToolTip.SetToolTip(CancelExportButton, Properties.Resources.EditModpackTooltipCancel); + ToolTip.SetToolTip(ExportModpackButton, Properties.Resources.EditModpackTooltipExport); } [ForbidGUICalls] diff --git a/GUI/Controls/InstallationHistory.cs b/GUI/Controls/InstallationHistory.cs index 6295248dcc..fa847f1623 100644 --- a/GUI/Controls/InstallationHistory.cs +++ b/GUI/Controls/InstallationHistory.cs @@ -16,7 +16,7 @@ public InstallationHistory() public void LoadHistory(GameInstance inst, GUIConfiguration config, RepositoryDataManager repoData) { this.inst = inst; - this.registry = RegistryManager.Instance(inst, repoData).registry; + registry = RegistryManager.Instance(inst, repoData).registry; this.config = config; Util.Invoke(this, () => { @@ -38,7 +38,7 @@ public void LoadHistory(GameInstance inst, GUIConfiguration config, RepositoryDa Splitter.Panel1MinSize = Splitter.SplitterDistance = TimestampColumn.Width + SystemInformation.VerticalScrollBarWidth - + 4 * SystemInformation.BorderSize.Width; + + (4 * SystemInformation.BorderSize.Width); HistoryListView.EndUpdate(); HistoryListView_ItemSelectionChanged(null, null); UseWaitCursor = false; @@ -70,7 +70,7 @@ protected override void OnHelpRequested(HelpEventArgs evt) evt.Handled = Util.TryOpenWebPage(HelpURLs.InstallationHistory); } - private void HistoryListView_ItemSelectionChanged(Object sender, ListViewItemSelectionChangedEventArgs e) + private void HistoryListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { UseWaitCursor = true; Task.Factory.StartNew(() => @@ -190,7 +190,7 @@ private CkanModule SaneLatestAvail(string identifier) } } - private void ModsListView_ItemSelectionChanged(Object sender, ListViewItemSelectionChangedEventArgs e) + private void ModsListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { var mod = ModsListView.SelectedItems .Cast() diff --git a/GUI/Controls/LeftRightRowPanel.cs b/GUI/Controls/LeftRightRowPanel.cs index 6ee1196f36..95c210d323 100644 --- a/GUI/Controls/LeftRightRowPanel.cs +++ b/GUI/Controls/LeftRightRowPanel.cs @@ -62,7 +62,9 @@ public LeftRightRowPanel() /// true if the borders of the panels should be shown, false to hide them. /// Useful for debugging. /// + #pragma warning disable IDE0051 private bool BordersVisible + #pragma warning restore IDE0051 { get => BorderStyle == BorderStyle.FixedSingle; set diff --git a/GUI/Controls/ManageMods.Designer.cs b/GUI/Controls/ManageMods.Designer.cs index 44772b35b0..6aecdbb1a9 100644 --- a/GUI/Controls/ManageMods.Designer.cs +++ b/GUI/Controls/ManageMods.Designer.cs @@ -86,9 +86,9 @@ private void InitializeComponent() this.ModListContextMenuStrip.SuspendLayout(); this.ModListHeaderContextMenuStrip.SuspendLayout(); this.SuspendLayout(); - // + // // Tooltip - // + // this.ToolTip.AutoPopDelay = 10000; this.ToolTip.InitialDelay = 250; this.ToolTip.ReshowDelay = 250; @@ -300,6 +300,7 @@ private void InitializeComponent() this.ModGrid.BackgroundColor = System.Drawing.SystemColors.Window; this.ModGrid.EnableHeadersVisualStyles = false; this.ModGrid.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.SystemColors.Control; + this.ModGrid.ColumnHeadersDefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Control; this.ModGrid.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.SystemColors.ControlText; this.ModGrid.DefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText; this.ModGrid.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.None; diff --git a/GUI/Controls/ManageMods.cs b/GUI/Controls/ManageMods.cs index fc8e6bdc73..b319806cd1 100644 --- a/GUI/Controls/ManageMods.cs +++ b/GUI/Controls/ManageMods.cs @@ -107,7 +107,9 @@ private List ChangeSet var orig = currentChangeSet; currentChangeSet = value; if (!ReferenceEquals(orig, value)) + { ChangeSetUpdated(); + } } } @@ -216,7 +218,7 @@ private void ConflictsUpdated(Dictionary prevConflicts) private void RefreshToolButton_Click(object sender, EventArgs e) { // If user is holding Shift or Ctrl, force a full update - Main.Instance.UpdateRepo((Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0); + Main.Instance.UpdateRepo((ModifierKeys & (Keys.Control | Keys.Shift)) != 0); } #region Filter dropdown @@ -337,74 +339,74 @@ private void editLabelsToolStripMenuItem_Click(object sender, EventArgs e) private void tagFilterButton_Click(object sender, EventArgs e) { var clicked = sender as ToolStripMenuItem; - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.Tag, clicked.Tag as ModuleTag, null), merge); } private void customFilterButton_Click(object sender, EventArgs e) { var clicked = sender as ToolStripMenuItem; - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.CustomLabel, null, clicked.Tag as ModuleLabel), merge); } private void FilterCompatibleButton_Click(object sender, EventArgs e) { - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.Compatible), merge); } private void FilterInstalledButton_Click(object sender, EventArgs e) { - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.Installed), merge); } private void FilterInstalledUpdateButton_Click(object sender, EventArgs e) { - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.InstalledUpdateAvailable), merge); } private void FilterReplaceableButton_Click(object sender, EventArgs e) { - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.Replaceable), merge); } private void FilterCachedButton_Click(object sender, EventArgs e) { - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.Cached), merge); } private void FilterUncachedButton_Click(object sender, EventArgs e) { - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.Uncached), merge); } private void FilterNewButton_Click(object sender, EventArgs e) { - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.NewInRepository), merge); } private void FilterNotInstalledButton_Click(object sender, EventArgs e) { - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.NotInstalled), merge); } private void FilterIncompatibleButton_Click(object sender, EventArgs e) { - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.Incompatible), merge); } private void FilterAllButton_Click(object sender, EventArgs e) { - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; Filter(ModList.FilterToSavedSearch(GUIModFilter.All), merge); } @@ -571,7 +573,7 @@ private void ModGrid_HeaderMouseClick(object sender, DataGridViewCellMouseEventA // Left click -> sort by new column / change sorting direction. if (e.Button == MouseButtons.Left) { - if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) + if ((ModifierKeys & Keys.Shift) == Keys.Shift) { AddSort(ModGrid.Columns[e.ColumnIndex]); } @@ -666,14 +668,20 @@ private void ModGrid_KeyDown(object sender, KeyEventArgs e) case Keys.Home: // First row. if (ModGrid.Rows.Count > 0) //Handles for empty filters + { ModGrid.CurrentCell = ModGrid.Rows[0].Cells[SelectableColumnIndex()]; + } + e.Handled = true; break; case Keys.End: // Last row. if (ModGrid.Rows.Count > 0) //Handles for empty filters + { ModGrid.CurrentCell = ModGrid.Rows[ModGrid.Rows.Count - 1].Cells[SelectableColumnIndex()]; + } + e.Handled = true; break; @@ -753,14 +761,20 @@ private void ModGrid_CellContentClick(object sender, DataGridViewCellEventArgs e private void ModGrid_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e) { if (e.Button != MouseButtons.Left) + { return; + } if (e.RowIndex < 0) + { return; + } DataGridViewRow row = ModGrid.Rows[e.RowIndex]; if (!(row.Cells[0] is DataGridViewCheckBoxCell)) + { 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; @@ -773,7 +787,9 @@ private void ModGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e int column_index = e.ColumnIndex; if (row_index < 0 || column_index < 0) + { return; + } DataGridView grid = sender as DataGridView; DataGridViewRow row = grid?.Rows[row_index]; @@ -785,7 +801,9 @@ private void ModGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e DataGridViewLinkCell cell = gridCell as DataGridViewLinkCell; string cmd = cell?.Value.ToString(); if (!string.IsNullOrEmpty(cmd)) + { Utilities.ProcessStartURL(cmd); + } } else { @@ -927,11 +945,15 @@ public void FocusMod(string key, bool exactMatch, bool showAsFirst = false) GUIMod mod = row.Tag as GUIMod; bool row_match; if (exactMatch) + { row_match = mod.Name == key || mod.Identifier == key; + } else + { row_match = mod.Name.StartsWith(key, StringComparison.OrdinalIgnoreCase) || mod.Abbrevation.StartsWith(key, StringComparison.OrdinalIgnoreCase) || mod.Identifier.StartsWith(key, StringComparison.OrdinalIgnoreCase); + } if (row_match && first_match == null) { @@ -964,7 +986,9 @@ public void FocusMod(string key, bool exactMatch, bool showAsFirst = false) ModGrid.CurrentCell = match.Cells[SelectableColumnIndex()]; if (showAsFirst) + { ModGrid.FirstDisplayedScrollingRowIndex = match.Index; + } } else { @@ -1092,7 +1116,9 @@ public void UpdateFilters() private void _UpdateFilters() { if (ModGrid == null || mainModList?.full_list_of_mod_rows == null) + { return; + } // Each time a row in DataGridViewRow is changed, DataGridViewRow updates the view. Which is slow. // To make the filtering process faster, Copy the list of rows. Filter out the hidden and replace the @@ -1220,7 +1246,7 @@ private bool _UpdateModsList(Dictionary old_modules = null) Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListPopulatingList); // Update our mod listing - mainModList.ConstructModList(gui_mods as IReadOnlyCollection, + mainModList.ConstructModList(gui_mods, Main.Instance.CurrentInstance.Name, Main.Instance.CurrentInstance.game, ChangeSet); @@ -1232,25 +1258,25 @@ private bool _UpdateModsList(Dictionary old_modules = null) var has_unheld_updates = mainModList.Modules.Any(mod => mod.HasUpdate && !Main.Instance.LabelsHeld(mod.Identifier)); Util.Invoke(menuStrip2, () => { - FilterCompatibleButton.Text = String.Format(Properties.Resources.MainModListCompatible, + FilterCompatibleButton.Text = string.Format(Properties.Resources.MainModListCompatible, mainModList.CountModsByFilter(GUIModFilter.Compatible)); - FilterInstalledButton.Text = String.Format(Properties.Resources.MainModListInstalled, + FilterInstalledButton.Text = string.Format(Properties.Resources.MainModListInstalled, mainModList.CountModsByFilter(GUIModFilter.Installed)); - FilterInstalledUpdateButton.Text = String.Format(Properties.Resources.MainModListUpgradeable, + FilterInstalledUpdateButton.Text = string.Format(Properties.Resources.MainModListUpgradeable, mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable)); - FilterReplaceableButton.Text = String.Format(Properties.Resources.MainModListReplaceable, + FilterReplaceableButton.Text = string.Format(Properties.Resources.MainModListReplaceable, mainModList.CountModsByFilter(GUIModFilter.Replaceable)); - FilterCachedButton.Text = String.Format(Properties.Resources.MainModListCached, + FilterCachedButton.Text = string.Format(Properties.Resources.MainModListCached, mainModList.CountModsByFilter(GUIModFilter.Cached)); - FilterUncachedButton.Text = String.Format(Properties.Resources.MainModListUncached, + FilterUncachedButton.Text = string.Format(Properties.Resources.MainModListUncached, mainModList.CountModsByFilter(GUIModFilter.Uncached)); - FilterNewButton.Text = String.Format(Properties.Resources.MainModListNewlyCompatible, + FilterNewButton.Text = string.Format(Properties.Resources.MainModListNewlyCompatible, mainModList.CountModsByFilter(GUIModFilter.NewInRepository)); - FilterNotInstalledButton.Text = String.Format(Properties.Resources.MainModListNotInstalled, + FilterNotInstalledButton.Text = string.Format(Properties.Resources.MainModListNotInstalled, mainModList.CountModsByFilter(GUIModFilter.NotInstalled)); - FilterIncompatibleButton.Text = String.Format(Properties.Resources.MainModListIncompatible, + FilterIncompatibleButton.Text = string.Format(Properties.Resources.MainModListIncompatible, mainModList.CountModsByFilter(GUIModFilter.Incompatible)); - FilterAllButton.Text = String.Format(Properties.Resources.MainModListAll, + FilterAllButton.Text = string.Format(Properties.Resources.MainModListAll, mainModList.CountModsByFilter(GUIModFilter.All)); UpdateAllToolButton.Enabled = has_unheld_updates; @@ -1517,7 +1543,9 @@ private void NavInit() navHistory.IsReadOnly = false; var currentMod = SelectedModule; if (currentMod != null) + { navHistory.AddToHistory(currentMod); + } } private void NavUpdateUI() @@ -1534,13 +1562,17 @@ private void NavSelectMod(GUIMod module) public void NavGoBackward() { if (navHistory.CanNavigateBackward) + { NavGoToMod(navHistory.NavigateBackward()); + } } public void NavGoForward() { if (navHistory.CanNavigateForward) + { NavGoToMod(navHistory.NavigateForward()); + } } private void NavGoToMod(GUIMod module) @@ -1574,7 +1606,9 @@ protected override bool ProcessCmdKey(ref Message msg, Keys keyData) case Keys.Control | Keys.S: if (ChangeSet != null && ChangeSet.Any()) + { ApplyToolButton_Click(null, null); + } return true; } diff --git a/GUI/Controls/ModInfo.cs b/GUI/Controls/ModInfo.cs index 34b6e318af..73c3119789 100644 --- a/GUI/Controls/ModInfo.cs +++ b/GUI/Controls/ModInfo.cs @@ -158,7 +158,7 @@ private void UpdateTagsAndLabels(CkanModule mod) foreach (ModuleTag tag in tags) { MetadataTagsLabelsPanel.Controls.Add(TagLabelLink( - tag.Name, tag, new LinkLabelLinkClickedEventHandler(this.TagLinkLabel_LinkClicked) + tag.Name, tag, new LinkLabelLinkClickedEventHandler(TagLinkLabel_LinkClicked) )); } } @@ -170,7 +170,7 @@ private void UpdateTagsAndLabels(CkanModule mod) foreach (ModuleLabel mlbl in labels) { MetadataTagsLabelsPanel.Controls.Add(TagLabelLink( - mlbl.Name, mlbl, new LinkLabelLinkClickedEventHandler(this.LabelLinkLabel_LinkClicked) + mlbl.Name, mlbl, new LinkLabelLinkClickedEventHandler(LabelLinkLabel_LinkClicked) )); } } @@ -198,7 +198,7 @@ private LinkLabel TagLabelLink(string name, object tag, LinkLabelLinkClickedEven private void TagLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { var link = sender as LinkLabel; - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; OnChangeFilter?.Invoke( ModList.FilterToSavedSearch(GUIModFilter.Tag, link.Tag as ModuleTag, null), merge); @@ -207,7 +207,7 @@ private void TagLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventAr private void LabelLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { var link = sender as LinkLabel; - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; OnChangeFilter?.Invoke( ModList.FilterToSavedSearch(GUIModFilter.CustomLabel, null, link.Tag as ModuleLabel), merge); diff --git a/GUI/Controls/ModInfoTabs/Metadata.cs b/GUI/Controls/ModInfoTabs/Metadata.cs index 6fea26e068..ec6b99f428 100644 --- a/GUI/Controls/ModInfoTabs/Metadata.cs +++ b/GUI/Controls/ModInfoTabs/Metadata.cs @@ -113,7 +113,7 @@ private void OnAuthorClick(object sender, LinkLabelLinkClickedEventArgs e) { var link = sender as LinkLabel; var author = link.Text; - var merge = (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0; + var merge = (ModifierKeys & (Keys.Control | Keys.Shift)) != 0; OnChangeFilter?.Invoke( new SavedSearch() { diff --git a/GUI/Controls/ModInfoTabs/Relationships.cs b/GUI/Controls/ModInfoTabs/Relationships.cs index 09a3798afc..6a3fc22a61 100644 --- a/GUI/Controls/ModInfoTabs/Relationships.cs +++ b/GUI/Controls/ModInfoTabs/Relationships.cs @@ -105,7 +105,7 @@ private void ReverseRelationshipsCheckbox_Click(object sender, EventArgs e) ReverseRelationshipsCheckbox.CheckState == CheckState.Unchecked // If user holds ctrl or shift, go to "sticky" indeterminate state, // else normal checked - ? (Control.ModifierKeys & (Keys.Control | Keys.Shift)) != 0 + ? (ModifierKeys & (Keys.Control | Keys.Shift)) != 0 ? CheckState.Indeterminate : CheckState.Checked : CheckState.Unchecked; diff --git a/GUI/Controls/TriStateToggle.cs b/GUI/Controls/TriStateToggle.cs index 6d245d8419..f89a04c895 100644 --- a/GUI/Controls/TriStateToggle.cs +++ b/GUI/Controls/TriStateToggle.cs @@ -28,7 +28,7 @@ public TriStateToggle() Controls.Add(BothRadioButton); Controls.Add(NoRadioButton); - Size = new Size(3 * buttonXOffset + 1, 20); + Size = new Size((3 * buttonXOffset) + 1, 20); ResumeLayout(false); PerformLayout(); @@ -36,12 +36,9 @@ public TriStateToggle() public bool? Value { - get - { - return YesRadioButton.Checked ? (bool?)true - : NoRadioButton.Checked ? (bool?)false - : null; - } + get => YesRadioButton.Checked ? true + : NoRadioButton.Checked ? (bool?)false + : null; set { if (!value.HasValue) @@ -66,7 +63,7 @@ private RadioButton MakeRadioButton(int index, Bitmap icon, string tooltip, bool var rb = new RadioButton() { Appearance = Appearance.Button, - BackColor = check ? SystemColors.Highlight : RadioButton.DefaultBackColor, + BackColor = check ? SystemColors.Highlight : DefaultBackColor, FlatStyle = FlatStyle.Flat, Location = new Point(index * buttonXOffset, 0), Size = new Size(buttonWidth, 20), @@ -90,7 +87,7 @@ private void RadioButtonChanged(object sender, EventArgs e) } else { - butt.BackColor = RadioButton.DefaultBackColor; + butt.BackColor = DefaultBackColor; } } diff --git a/GUI/Controls/UnmanagedFiles.cs b/GUI/Controls/UnmanagedFiles.cs index f3313cf831..0102d4b331 100644 --- a/GUI/Controls/UnmanagedFiles.cs +++ b/GUI/Controls/UnmanagedFiles.cs @@ -25,7 +25,7 @@ public void LoadFiles(GameInstance inst, RepositoryDataManager repoData, IUser u { this.inst = inst; this.user = user; - this.registry = RegistryManager.Instance(inst, repoData).registry; + registry = RegistryManager.Instance(inst, repoData).registry; Util.Invoke(this, _UpdateGameFolderTree); } diff --git a/GUI/Controls/Wait.cs b/GUI/Controls/Wait.cs index d298a6b8ed..c37353bb90 100644 --- a/GUI/Controls/Wait.cs +++ b/GUI/Controls/Wait.cs @@ -40,6 +40,8 @@ public void StartWaiting(Action mainWork, public event Action OnCancel; public event Action OnOk; + #pragma warning disable IDE0027 + public bool RetryEnabled { [ForbidGUICalls] @@ -73,6 +75,8 @@ public bool ProgressIndeterminate } } + #pragma warning restore IDE0027 + public void SetProgress(string label, long remaining, long total) { if (total > 0) diff --git a/GUI/Dialogs/CloneGameInstanceDialog.cs b/GUI/Dialogs/CloneGameInstanceDialog.cs index c86e6e0bf7..f5627c6e80 100644 --- a/GUI/Dialogs/CloneGameInstanceDialog.cs +++ b/GUI/Dialogs/CloneGameInstanceDialog.cs @@ -71,7 +71,9 @@ private void buttonInstancePathSelection_Click(object sender, EventArgs e) // Show the FileDialog and let the user search for the game directory. if (instanceDialog.ShowDialog(this) != DialogResult.OK || !File.Exists(instanceDialog.FileName)) + { return; + } // Write the path to the textbox textBoxClonePath.Text = Path.GetDirectoryName(instanceDialog.FileName); @@ -90,12 +92,12 @@ private async void buttonOK_Click(object sender, EventArgs e) string newPath = textBoxNewPath.Text; // Do some basic checks. - if (String.IsNullOrWhiteSpace(newName)) + if (string.IsNullOrWhiteSpace(newName)) { user.RaiseError(Properties.Resources.CloneFakeKspDialogEnterName); return; } - if (String.IsNullOrWhiteSpace(newPath)) + if (string.IsNullOrWhiteSpace(newPath)) { user.RaiseError(Properties.Resources.CloneFakeKspDialogEnterPath); return; diff --git a/GUI/Dialogs/CompatibleGameVersionsDialog.cs b/GUI/Dialogs/CompatibleGameVersionsDialog.cs index adcc967c2a..f996d4d721 100644 --- a/GUI/Dialogs/CompatibleGameVersionsDialog.cs +++ b/GUI/Dialogs/CompatibleGameVersionsDialog.cs @@ -21,7 +21,7 @@ public partial class CompatibleGameVersionsDialog : Form /// true to center the dialog on the screen, false to center on the parent public CompatibleGameVersionsDialog(GameInstance inst, bool centerScreen) { - this._inst = inst; + _inst = inst; InitializeComponent(); if (centerScreen) @@ -145,7 +145,7 @@ private void ClearSelectionButton_Click(object sender, EventArgs e) private void CancelButton_Click(object sender, EventArgs e) { DialogResult = DialogResult.Cancel; - this.Close(); + Close(); } private void SaveButton_Click(object sender, EventArgs e) @@ -155,7 +155,7 @@ private void SaveButton_Click(object sender, EventArgs e) ); DialogResult = DialogResult.OK; - this.Close(); + Close(); } } } diff --git a/GUI/Dialogs/DownloadsFailedDialog.cs b/GUI/Dialogs/DownloadsFailedDialog.cs index b46df1c5c4..e807677075 100644 --- a/GUI/Dialogs/DownloadsFailedDialog.cs +++ b/GUI/Dialogs/DownloadsFailedDialog.cs @@ -59,8 +59,8 @@ public DownloadsFailedDialog( ExplanationLabel.Height + ExplanationLabel.Padding.Vertical + DownloadsGrid.ColumnHeadersHeight - + DownloadsGrid.RowCount - * DownloadsGrid.RowTemplate.Height + + (DownloadsGrid.RowCount + * DownloadsGrid.RowTemplate.Height) + DownloadsGrid.Margin.Vertical + DownloadsGrid.Padding.Vertical + BottomButtonPanel.Height); @@ -190,7 +190,9 @@ public DownloadRow(object data, Exception exc) /// True if Skip column has a checkmark /// /// + #pragma warning disable IDE0027 public bool Skip { get => !Retry; set { Retry = !value; } } + #pragma warning restore IDE0027 /// /// This row's data object /// diff --git a/GUI/Dialogs/EditLabelsDialog.cs b/GUI/Dialogs/EditLabelsDialog.cs index b5e1c3241e..21443bec92 100644 --- a/GUI/Dialogs/EditLabelsDialog.cs +++ b/GUI/Dialogs/EditLabelsDialog.cs @@ -34,7 +34,7 @@ private void LoadTree() { LabelSelectionTree.BeginUpdate(); LabelSelectionTree.Nodes.Clear(); - var groups = this.labels.Labels + var groups = labels.Labels .GroupBy(l => l.InstanceName) .OrderBy(g => g.Key == null) .ThenBy(g => g.Key); @@ -65,7 +65,7 @@ private void LoadTree() // Select the new node representing the label we're editing LabelSelectionTree.SelectedNode = LabelSelectionTree.Nodes.Cast() .SelectMany(nd => nd.Nodes.Cast()) - .FirstOrDefault(nd => nd.Tag as ModuleLabel == currentlyEditing); + .FirstOrDefault(nd => (nd.Tag as ModuleLabel) == currentlyEditing); LabelSelectionTree.BeforeSelect += LabelSelectionTree_BeforeSelect; } LabelSelectionTree.ExpandAll(); @@ -88,7 +88,7 @@ protected override void OnHelpButtonClicked(CancelEventArgs evt) evt.Cancel = Util.TryOpenWebPage(HelpURLs.Labels); } - private void LabelSelectionTree_BeforeSelect(Object sender, TreeViewCancelEventArgs e) + private void LabelSelectionTree_BeforeSelect(object sender, TreeViewCancelEventArgs e) { if (e.Node == null) { diff --git a/GUI/Dialogs/ManageGameInstancesDialog.cs b/GUI/Dialogs/ManageGameInstancesDialog.cs index 56bfd055a0..8e93a44878 100644 --- a/GUI/Dialogs/ManageGameInstancesDialog.cs +++ b/GUI/Dialogs/ManageGameInstancesDialog.cs @@ -119,12 +119,16 @@ private string[] rowItems(GameInstance instance, bool includeGame, bool includeP }; if (includeGame) + { list.Add(instance.game.ShortName); + } list.Add(FormatVersion(instance.Version())); if (includePlayTime) + { list.Add(instance.playTime?.ToString() ?? ""); + } list.Add(instance.GameDir().Replace('/', Path.DirectorySeparatorChar)); return list.ToArray(); @@ -158,7 +162,9 @@ private void AddToCKANMenuItem_Click(object sender, EventArgs e) { if (_instanceDialog.ShowDialog(this) != DialogResult.OK || !File.Exists(_instanceDialog.FileName)) + { return; + } var path = Path.GetDirectoryName(_instanceDialog.FileName); try @@ -254,7 +260,9 @@ private void GameInstancesListView_SelectedIndexChanged(object sender, EventArgs UpdateButtonState(); if (GameInstancesListView.SelectedItems.Count == 0) + { return; + } string instName = (string)GameInstancesListView.SelectedItems[0].Tag; SetAsDefaultCheckbox.Checked = _manager.AutoStartInstance?.Equals(instName) ?? false; @@ -307,7 +315,9 @@ private void RenameButton_Click(object sender, EventArgs e) // show the dialog, and only continue if the user selected "OK" _renameInstanceDialog = new RenameInstanceDialog(); if (_renameInstanceDialog.ShowRenameInstanceDialog(instance) != DialogResult.OK) + { return; + } // proceed with instance rename _manager.RenameInstance(instance, _renameInstanceDialog.GetResult()); diff --git a/GUI/Dialogs/SelectionDialog.cs b/GUI/Dialogs/SelectionDialog.cs index bad631d34b..2baa2b9613 100644 --- a/GUI/Dialogs/SelectionDialog.cs +++ b/GUI/Dialogs/SelectionDialog.cs @@ -5,7 +5,7 @@ namespace CKAN.GUI { public partial class SelectionDialog : Form { - int currentSelected; + private int currentSelected; public SelectionDialog () { @@ -25,7 +25,7 @@ public int ShowSelectionDialog (string message, params object[] args) int return_cancel = -1; // Validate input. - if (String.IsNullOrWhiteSpace(message)) + if (string.IsNullOrWhiteSpace(message)) { throw new Kraken("Passed message string must be non-empty."); } @@ -68,7 +68,7 @@ public int ShowSelectionDialog (string message, params object[] args) // Further data validation. foreach (object argument in args) { - if (String.IsNullOrWhiteSpace(argument.ToString())) + if (string.IsNullOrWhiteSpace(argument.ToString())) { throw new Kraken("Candidate may not be empty."); } @@ -79,7 +79,7 @@ public int ShowSelectionDialog (string message, params object[] args) { if (defaultSelection == i) { - Util.Invoke(OptionsList, () => OptionsList.Items.Add(String.Concat(args[i].ToString(), " -- Default"))); + Util.Invoke(OptionsList, () => OptionsList.Items.Add(string.Concat(args[i].ToString(), " -- Default"))); } else diff --git a/GUI/Dialogs/SettingsDialog.cs b/GUI/Dialogs/SettingsDialog.cs index b8cc04dc53..a93d1646d7 100644 --- a/GUI/Dialogs/SettingsDialog.cs +++ b/GUI/Dialogs/SettingsDialog.cs @@ -34,7 +34,7 @@ public SettingsDialog(RegistryManager regMgr, IUser user) this.regMgr = regMgr; if (Platform.IsMono) { - this.ClearCacheMenu.Renderer = new FlatToolStripRenderer(); + ClearCacheMenu.Renderer = new FlatToolStripRenderer(); } config = ServiceLocator.Container.Resolve(); } @@ -253,7 +253,7 @@ private void PurgeAllMenuItem_Click(object sender, EventArgs e) out int cacheFileCount, out long cacheSize, out _); YesNoDialog deleteConfirmationDialog = new YesNoDialog(); - string confirmationText = String.Format( + string confirmationText = string.Format( Properties.Resources.SettingsDialogDeleteConfirm, cacheFileCount, CkanModule.FmtSize(cacheSize)); @@ -553,14 +553,8 @@ private void CheckForUpdatesButton_Click(object sender, EventArgs e) { AutoUpdate.Instance.FetchLatestReleaseInfo(); var latestVersion = AutoUpdate.Instance.latestUpdate.Version; - if (latestVersion.IsGreaterThan(new ModuleVersion(Meta.GetVersion(VersionFormat.Short))) && AutoUpdate.Instance.IsFetched()) - { - InstallUpdateButton.Enabled = true; - } - else - { - InstallUpdateButton.Enabled = false; - } + InstallUpdateButton.Enabled = latestVersion.IsGreaterThan(new ModuleVersion(Meta.GetVersion(VersionFormat.Short))) + && AutoUpdate.Instance.IsFetched(); LatestVersionLabel.Text = latestVersion.ToString(); } @@ -635,7 +629,9 @@ private void RefreshTextBox_TextChanged(object sender, EventArgs e) private void RefreshTextBox_KeyPress(object sender, KeyPressEventArgs e) { if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar)) + { e.Handled = true; + } } private void PauseRefreshCheckBox_CheckedChanged(object sender, EventArgs e) @@ -643,9 +639,13 @@ private void PauseRefreshCheckBox_CheckedChanged(object sender, EventArgs e) Main.Instance.configuration.RefreshPaused = PauseRefreshCheckBox.Checked; if (Main.Instance.configuration.RefreshPaused) + { Main.Instance.refreshTimer.Stop(); + } else + { Main.Instance.refreshTimer.Start(); + } } } } diff --git a/GUI/Dialogs/YesNoDialog.cs b/GUI/Dialogs/YesNoDialog.cs index a4b5be7950..27b4057731 100644 --- a/GUI/Dialogs/YesNoDialog.cs +++ b/GUI/Dialogs/YesNoDialog.cs @@ -42,7 +42,7 @@ public Tuple ShowSuppressableYesNoDialog(Form parentForm, st private void Setup(string text, string yesText, string noText) { - var height = Util.StringHeight(CreateGraphics(), text, DescriptionLabel.Font, ClientSize.Width - 25) + 2 * 54; + var height = Util.StringHeight(CreateGraphics(), text, DescriptionLabel.Font, ClientSize.Width - 25) + (2 * 54); DescriptionLabel.Text = text; DescriptionLabel.TextAlign = text.Contains("\n") ? HorizontalAlignment.Left diff --git a/GUI/Labels/ModuleLabel.cs b/GUI/Labels/ModuleLabel.cs index 7921fcf1ff..b99cd71b2b 100644 --- a/GUI/Labels/ModuleLabel.cs +++ b/GUI/Labels/ModuleLabel.cs @@ -1,4 +1,3 @@ -using System.Linq; using System.Drawing; using System.ComponentModel; using System.Collections.Generic; diff --git a/GUI/Labels/ModuleLabelList.cs b/GUI/Labels/ModuleLabelList.cs index 52357efc88..1275f90c7b 100644 --- a/GUI/Labels/ModuleLabelList.cs +++ b/GUI/Labels/ModuleLabelList.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Collections.Generic; using System.IO; diff --git a/GUI/Localization/fr-FR/Main.fr-FR.resx b/GUI/Localization/fr-FR/Main.fr-FR.resx index db5551213e..9798ee9ff6 100644 --- a/GUI/Localization/fr-FR/Main.fr-FR.resx +++ b/GUI/Localization/fr-FR/Main.fr-FR.resx @@ -252,7 +252,4 @@ &Historique d'installation... - - CKAN - diff --git a/GUI/Localization/it-IT/Main.it-IT.resx b/GUI/Localization/it-IT/Main.it-IT.resx index 3e76c2c54c..9998cebe73 100644 --- a/GUI/Localization/it-IT/Main.it-IT.resx +++ b/GUI/Localization/it-IT/Main.it-IT.resx @@ -234,7 +234,4 @@ Tempo di &Gioco... - - CKAN - diff --git a/GUI/Localization/ko-KR/Main.ko-KR.resx b/GUI/Localization/ko-KR/Main.ko-KR.resx index 1a4656c9fd..a6c364af36 100644 --- a/GUI/Localization/ko-KR/Main.ko-KR.resx +++ b/GUI/Localization/ko-KR/Main.ko-KR.resx @@ -237,7 +237,4 @@ 플레이 타임... - - CKAN - diff --git a/GUI/Localization/nl-NL/Main.nl-NL.resx b/GUI/Localization/nl-NL/Main.nl-NL.resx index 27b7f05f4f..8e3216a29c 100644 --- a/GUI/Localization/nl-NL/Main.nl-NL.resx +++ b/GUI/Localization/nl-NL/Main.nl-NL.resx @@ -252,7 +252,4 @@ Installatiegeschiedenis... - - CKAN - diff --git a/GUI/Localization/pl-PL/Main.pl-PL.resx b/GUI/Localization/pl-PL/Main.pl-PL.resx index 461e935480..3d418ed9fe 100644 --- a/GUI/Localization/pl-PL/Main.pl-PL.resx +++ b/GUI/Localization/pl-PL/Main.pl-PL.resx @@ -237,7 +237,4 @@ Czas gry... - - CKAN - diff --git a/GUI/Localization/pt-BR/Main.pt-BR.resx b/GUI/Localization/pt-BR/Main.pt-BR.resx index d7d3c88d1e..19dd92430c 100644 --- a/GUI/Localization/pt-BR/Main.pt-BR.resx +++ b/GUI/Localization/pt-BR/Main.pt-BR.resx @@ -237,7 +237,4 @@ Tempo de jogo... - - CKAN - diff --git a/GUI/Localization/ru-RU/Main.ru-RU.resx b/GUI/Localization/ru-RU/Main.ru-RU.resx index dd63561169..bb1dcff29c 100644 --- a/GUI/Localization/ru-RU/Main.ru-RU.resx +++ b/GUI/Localization/ru-RU/Main.ru-RU.resx @@ -237,7 +237,4 @@ Время &игры... - - CKAN - diff --git a/GUI/Main/Main.cs b/GUI/Main/Main.cs index 6a6d7532e6..9c5611d0b6 100644 --- a/GUI/Main/Main.cs +++ b/GUI/Main/Main.cs @@ -58,11 +58,18 @@ public Main(string[] cmdlineArgs, GameInstanceManager mgr) { focusIdent = cmdlineArgs[1]; if (focusIdent.StartsWith("//")) + { focusIdent = focusIdent.Substring(2); + } else if (focusIdent.StartsWith("ckan://")) + { focusIdent = focusIdent.Substring(7); + } + if (focusIdent.EndsWith("/")) + { focusIdent = focusIdent.Substring(0, focusIdent.Length - 1); + } } Configuration.IConfiguration mainConfig = ServiceLocator.Container.Resolve(); @@ -123,7 +130,7 @@ public Main(string[] cmdlineArgs, GameInstanceManager mgr) HandleCreated += (sender, e) => X11.SetWMClass("CKAN", "CKAN", Handle); } - currentUser = new GUIUser(this, this.Wait); + currentUser = new GUIUser(this, Wait); if (mgr != null) { // With a working GUI, assign a GUIUser to the GameInstanceManager to replace the ConsoleUser @@ -243,7 +250,7 @@ protected override void OnShown(EventArgs e) } catch (RegistryInUseKraken kraken) { - if (Main.Instance.YesNoDialog( + if (Instance.YesNoDialog( kraken.ToString(), Properties.Resources.MainDeleteLockfileYes, Properties.Resources.MainDeleteLockfileNo)) @@ -325,7 +332,7 @@ private void manageGameInstancesMenuItem_Click(object sender, EventArgs e) } catch (RegistryInUseKraken kraken) { - if (Main.Instance.YesNoDialog( + if (Instance.YesNoDialog( kraken.ToString(), Properties.Resources.MainDeleteLockfileYes, Properties.Resources.MainDeleteLockfileNo)) @@ -397,13 +404,19 @@ private void CurrentInstanceUpdated(bool allowRepoUpdate) { log.Debug("Asking user if they wish for auto-updates"); if (new AskUserForAutoUpdatesDialog().ShowDialog(this) == DialogResult.OK) + { configuration.CheckForUpdatesOnLaunch = true; + } + configuration.CheckForUpdatesOnLaunchNoNag = true; } var pluginsPath = Path.Combine(CurrentInstance.CkanDir(), "Plugins"); if (!Directory.Exists(pluginsPath)) + { Directory.CreateDirectory(pluginsPath); + } + pluginController = new PluginController(pluginsPath, true); CurrentInstance.game.RebuildSubdirectories(CurrentInstance.GameDir()); @@ -688,7 +701,7 @@ private void InstallFromCkanFiles(string[] files) var myIncompat = toInstall.Where(mod => allIncompat.Contains(mod.identifier)).ToList(); if (!myIncompat.Any() // Confirm installation of incompatible like the Versions tab does - || Main.Instance.YesNoDialog( + || Instance.YesNoDialog( string.Format(Properties.Resources.ModpackInstallIncompatiblePrompt, string.Join(Environment.NewLine, myIncompat), crit.ToSummaryString(CurrentInstance.game)), @@ -861,7 +874,9 @@ public void LaunchGame() { var split = configuration.CommandLineArguments.Split(' '); if (split.Length == 0) + { return; + } var registry = RegistryManager.Instance(CurrentInstance, repoData).registry; @@ -985,7 +1000,7 @@ private void EnableMainWindow() * if childcontrol had focus. Depending on optimization steps, * parent.childcontrol.Enabled = true does not necessarily * re-enable the parent.*/ - this.Focus(); + Focus(); }); } diff --git a/GUI/Main/Main.resx b/GUI/Main/Main.resx index 827076d636..aa1f3d90c7 100644 --- a/GUI/Main/Main.resx +++ b/GUI/Main/Main.resx @@ -164,5 +164,4 @@ Play &time... &Unmanaged files... Installation &history... - CKAN diff --git a/GUI/Main/MainDialogs.cs b/GUI/Main/MainDialogs.cs index a8fcf0d347..bc94ee7b6a 100644 --- a/GUI/Main/MainDialogs.cs +++ b/GUI/Main/MainDialogs.cs @@ -28,7 +28,7 @@ public void RecreateDialogs() [ForbidGUICalls] public void AddStatusMessage(string text, params object[] args) { - string msg = String.Format(text, args); + string msg = string.Format(text, args); // No newlines in status bar Util.Invoke(statusStrip1, () => StatusLabel.ToolTipText = StatusLabel.Text = msg.Replace("\r\n", " ").Replace("\n", " ") @@ -39,7 +39,7 @@ public void AddStatusMessage(string text, params object[] args) [ForbidGUICalls] public void ErrorDialog(string text, params object[] args) { - errorDialog.ShowErrorDialog(String.Format(text, args)); + errorDialog.ShowErrorDialog(string.Format(text, args)); } public bool YesNoDialog(string text, string yesText = null, string noText = null) diff --git a/GUI/Main/MainDownload.cs b/GUI/Main/MainDownload.cs index fe2be98adf..be15d1218c 100644 --- a/GUI/Main/MainDownload.cs +++ b/GUI/Main/MainDownload.cs @@ -19,7 +19,9 @@ private void ModInfo_OnDownloadClick(GUIMod gmod) public void StartDownload(GUIMod module) { if (module == null || !module.IsCKAN) + { return; + } ShowWaitDialog(); if (downloader != null) diff --git a/GUI/Main/MainHistory.cs b/GUI/Main/MainHistory.cs index d0892dd8bf..22a9b65d01 100644 --- a/GUI/Main/MainHistory.cs +++ b/GUI/Main/MainHistory.cs @@ -1,8 +1,6 @@ using System; using System.Linq; -using CKAN.Extensions; - // Don't warn if we use our own obsolete properties #pragma warning disable 0618 diff --git a/GUI/Main/MainRecommendations.cs b/GUI/Main/MainRecommendations.cs index 0ca754d0b7..2031436ba5 100644 --- a/GUI/Main/MainRecommendations.cs +++ b/GUI/Main/MainRecommendations.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using System.Linq; -using CKAN.Extensions; using CKAN.Versioning; using CKAN.GUI.Attributes; diff --git a/GUI/Model/GUIConfiguration.cs b/GUI/Model/GUIConfiguration.cs index dede7a7777..423e6b3339 100644 --- a/GUI/Model/GUIConfiguration.cs +++ b/GUI/Model/GUIConfiguration.cs @@ -9,7 +9,7 @@ namespace CKAN.GUI { - [XmlRootAttribute("Configuration")] + [XmlRoot("Configuration")] public class GUIConfiguration { public string CommandLineArguments = ""; @@ -81,8 +81,10 @@ public void SetColumnVisibility(string name, bool vis) public Point WindowLoc { - get { return windowLocation; } + get => windowLocation; + #pragma warning disable IDE0027 set { windowLocation = value; } + #pragma warning restore IDE0027 } /// @@ -139,7 +141,9 @@ private static GUIConfiguration LoadConfiguration(string path) if (e is InvalidOperationException) // Exception thrown in Windows / .NET { if (e.InnerException != null) + { additionalErrorData = ": " + e.InnerException.Message; + } } else if (e is XmlException) // Exception thrown in Mono { @@ -209,7 +213,7 @@ private static void SaveConfiguration(GUIConfiguration configuration) } } - [XmlRootAttribute("SavedSearch")] + [XmlRoot("SavedSearch")] public class SavedSearch { public string Name; diff --git a/GUI/Model/GUIMod.cs b/GUI/Model/GUIMod.cs index 1f500e47c2..2d098330af 100644 --- a/GUI/Model/GUIMod.cs +++ b/GUI/Model/GUIMod.cs @@ -25,7 +25,7 @@ public sealed class GUIMod : INotifyPropertyChanged /// public CkanModule SelectedMod { - get { return selectedMod; } + get => selectedMod; set { if (!(selectedMod?.Equals(value) ?? value?.Equals(selectedMod) ?? true)) @@ -152,7 +152,7 @@ public GUIMod(InstalledModule instMod, LatestVersion = InstalledVersion; } // For mods not known to the registry LatestCompatibleMod is null, however the installed module might be compatible - IsIncompatible = incompatible ?? LatestCompatibleMod == null && !instMod.Module.IsCompatible(current_game_version); + IsIncompatible = incompatible ?? (LatestCompatibleMod == null && !instMod.Module.IsCompatible(current_game_version)); } /// @@ -298,8 +298,11 @@ public void UpdateIsCached() public CkanModule ToCkanModule() { if (!IsCKAN) + { throw new InvalidCastException(Properties.Resources.GUIModMethodNotCKAN); - var mod = Mod as CkanModule; + } + + var mod = Mod; return mod; } @@ -422,7 +425,9 @@ public void SetReplaceChecked(DataGridViewRow row, DataGridViewColumn col, bool? bool value = set_value_to ?? old_value; IsReplaceChecked = value; if (old_value != value) + { replace_cell.Value = value; + } } } @@ -447,9 +452,21 @@ public void SetAutoInstallChecked(DataGridViewRow row, DataGridViewColumn col, b public override bool Equals(object obj) { - if (obj is null) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; + if (obj is null) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + return Equals((GUIMod) obj); } diff --git a/GUI/Model/ModChange.cs b/GUI/Model/ModChange.cs index a60405b2f2..942402836b 100644 --- a/GUI/Model/ModChange.cs +++ b/GUI/Model/ModChange.cs @@ -59,7 +59,7 @@ public ModChange(CkanModule mod, GUIModChangeType changeType) } public ModChange(CkanModule mod, GUIModChangeType changeType, SelectionReason reason) - : this(mod, changeType, Enumerable.Repeat(reason, 1)) + : this(mod, changeType, Enumerable.Repeat(reason, 1)) { } @@ -73,9 +73,21 @@ public ModChange(CkanModule mod, GUIModChangeType changeType, IEnumerable