From 40aebb74c65e0c7300b5f4fcb066f3fd2b2a5fdd Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 12 Apr 2022 21:01:13 -0400 Subject: [PATCH] enable nullable annotations in installer (#837) --- .../Framework/InstallerContext.cs | 4 +- .../Framework/InstallerPaths.cs | 2 - src/SMAPI.Installer/InteractiveInstaller.cs | 81 +++++++++++-------- src/SMAPI.Installer/Program.cs | 8 +- 4 files changed, 52 insertions(+), 43 deletions(-) diff --git a/src/SMAPI.Installer/Framework/InstallerContext.cs b/src/SMAPI.Installer/Framework/InstallerContext.cs index 23d5b17c..a2c63dd8 100644 --- a/src/SMAPI.Installer/Framework/InstallerContext.cs +++ b/src/SMAPI.Installer/Framework/InstallerContext.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.IO; using StardewModdingAPI.Toolkit; using StardewModdingAPI.Toolkit.Framework.GameScanning; @@ -46,7 +44,7 @@ namespace StardewModdingAPI.Installer.Framework /// Get the installer's version number. public ISemanticVersion GetInstallerVersion() { - var raw = this.GetType().Assembly.GetName().Version; + var raw = this.GetType().Assembly.GetName().Version!; return new SemanticVersion(raw); } diff --git a/src/SMAPI.Installer/Framework/InstallerPaths.cs b/src/SMAPI.Installer/Framework/InstallerPaths.cs index fd9d1be6..0976eceb 100644 --- a/src/SMAPI.Installer/Framework/InstallerPaths.cs +++ b/src/SMAPI.Installer/Framework/InstallerPaths.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.IO; using StardewModdingAPI.Toolkit.Framework; diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index b07c0461..5138173a 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -1,8 +1,7 @@ -#nullable disable - using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; @@ -37,6 +36,7 @@ namespace StardewModdingApi.Installer /// Get the absolute file or folder paths to remove when uninstalling SMAPI. /// The folder for Stardew Valley and SMAPI. /// The folder for SMAPI mods. + [SuppressMessage("ReSharper", "StringLiteralTypo", Justification = "These are valid file names.")] private IEnumerable GetUninstallPaths(DirectoryInfo installDir, DirectoryInfo modsDir) { string GetInstallPath(string path) => Path.Combine(installDir.FullName, path); @@ -166,7 +166,7 @@ namespace StardewModdingApi.Installer } // get game path from CLI - string gamePathArg = null; + string? gamePathArg = null; { int pathIndex = Array.LastIndexOf(args, "--game-path") + 1; if (pathIndex >= 1 && args.Length >= pathIndex) @@ -191,8 +191,8 @@ namespace StardewModdingApi.Installer ** show theme selector ****/ // get theme writers - var lightBackgroundWriter = new ColorfulConsoleWriter(context.Platform, ColorfulConsoleWriter.GetDefaultColorSchemeConfig(MonitorColorScheme.LightBackground)); - var darkBackgroundWriter = new ColorfulConsoleWriter(context.Platform, ColorfulConsoleWriter.GetDefaultColorSchemeConfig(MonitorColorScheme.DarkBackground)); + ColorfulConsoleWriter lightBackgroundWriter = new(context.Platform, ColorfulConsoleWriter.GetDefaultColorSchemeConfig(MonitorColorScheme.LightBackground)); + ColorfulConsoleWriter darkBackgroundWriter = new(context.Platform, ColorfulConsoleWriter.GetDefaultColorSchemeConfig(MonitorColorScheme.DarkBackground)); // print question this.PrintPlain("Which text looks more readable?"); @@ -239,7 +239,7 @@ namespace StardewModdingApi.Installer ** collect details ****/ // get game path - DirectoryInfo installDir = this.InteractivelyGetInstallPath(toolkit, context, gamePathArg); + DirectoryInfo? installDir = this.InteractivelyGetInstallPath(toolkit, context, gamePathArg); if (installDir == null) { this.PrintError("Failed finding your game path."); @@ -451,7 +451,7 @@ namespace StardewModdingApi.Installer } // find target folder - ModFolder targetMod = targetMods.FirstOrDefault(p => p.Manifest?.UniqueID?.Equals(sourceMod.Manifest.UniqueID, StringComparison.OrdinalIgnoreCase) == true); + ModFolder? targetMod = targetMods.FirstOrDefault(p => p.Manifest?.UniqueID?.Equals(sourceMod.Manifest.UniqueID, StringComparison.OrdinalIgnoreCase) == true); DirectoryInfo defaultTargetFolder = new(Path.Combine(paths.ModsPath, sourceMod.Directory.Name)); DirectoryInfo targetFolder = targetMod?.Directory ?? defaultTargetFolder; this.PrintDebug(targetFolder.FullName == defaultTargetFolder.FullName @@ -534,27 +534,45 @@ namespace StardewModdingApi.Installer /// Print a message without formatting. /// The text to print. - private void PrintPlain(string text) => Console.WriteLine(text); + private void PrintPlain(string text) + { + Console.WriteLine(text); + } /// Print a debug message. /// The text to print. - private void PrintDebug(string text) => this.ConsoleWriter.WriteLine(text, ConsoleLogLevel.Debug); + private void PrintDebug(string text) + { + this.ConsoleWriter.WriteLine(text, ConsoleLogLevel.Debug); + } /// Print a debug message. /// The text to print. - private void PrintInfo(string text) => this.ConsoleWriter.WriteLine(text, ConsoleLogLevel.Info); + private void PrintInfo(string text) + { + this.ConsoleWriter.WriteLine(text, ConsoleLogLevel.Info); + } /// Print a warning message. /// The text to print. - private void PrintWarning(string text) => this.ConsoleWriter.WriteLine(text, ConsoleLogLevel.Warn); + private void PrintWarning(string text) + { + this.ConsoleWriter.WriteLine(text, ConsoleLogLevel.Warn); + } /// Print a warning message. /// The text to print. - private void PrintError(string text) => this.ConsoleWriter.WriteLine(text, ConsoleLogLevel.Error); + private void PrintError(string text) + { + this.ConsoleWriter.WriteLine(text, ConsoleLogLevel.Error); + } /// Print a success message. /// The text to print. - private void PrintSuccess(string text) => this.ConsoleWriter.WriteLine(text, ConsoleLogLevel.Success); + private void PrintSuccess(string text) + { + this.ConsoleWriter.WriteLine(text, ConsoleLogLevel.Success); + } /// Interactively delete a file or folder path, and block until deletion completes. /// The file or folder path. @@ -580,7 +598,7 @@ namespace StardewModdingApi.Installer /// The file or folder to copy. /// The folder to copy into. /// A filter which matches directories and files to copy, or null to match all. - private void RecursiveCopy(FileSystemInfo source, DirectoryInfo targetFolder, Func filter = null) + private void RecursiveCopy(FileSystemInfo source, DirectoryInfo targetFolder, Func? filter = null) { if (filter != null && !filter(source)) return; @@ -596,7 +614,7 @@ namespace StardewModdingApi.Installer case DirectoryInfo sourceDir: DirectoryInfo targetSubfolder = new(Path.Combine(targetFolder.FullName, sourceDir.Name)); - foreach (var entry in sourceDir.EnumerateFileSystemInfos()) + foreach (FileSystemInfo entry in sourceDir.EnumerateFileSystemInfos()) this.RecursiveCopy(entry, targetSubfolder, filter); break; @@ -610,7 +628,7 @@ namespace StardewModdingApi.Installer /// The message to print. /// The allowed options (not case sensitive). /// The indentation to prefix to output. - private string InteractivelyChoose(string message, string[] options, string indent = "", Action print = null) + private string InteractivelyChoose(string message, string[] options, string indent = "", Action? print = null) { print ??= this.PrintInfo; @@ -618,8 +636,8 @@ namespace StardewModdingApi.Installer { print(indent + message); Console.Write(indent); - string input = Console.ReadLine()?.Trim().ToLowerInvariant(); - if (!options.Contains(input)) + string? input = Console.ReadLine()?.Trim().ToLowerInvariant(); + if (input == null || !options.Contains(input)) { print($"{indent}That's not a valid option."); continue; @@ -632,7 +650,7 @@ namespace StardewModdingApi.Installer /// The mod toolkit. /// The installer context. /// The path specified as a command-line argument (if any), which should override automatic path detection. - private DirectoryInfo InteractivelyGetInstallPath(ModToolkit toolkit, InstallerContext context, string specifiedPath) + private DirectoryInfo? InteractivelyGetInstallPath(ModToolkit toolkit, InstallerContext context, string? specifiedPath) { // use specified path if (specifiedPath != null) @@ -699,7 +717,7 @@ namespace StardewModdingApi.Installer // get path from user Console.WriteLine(); this.PrintInfo($"Type the file path to the game directory (the one containing '{Constants.GameDllName}'), then press enter."); - string path = Console.ReadLine()?.Trim(); + string? path = Console.ReadLine()?.Trim(); if (string.IsNullOrWhiteSpace(path)) { this.PrintWarning("You must specify a directory path to continue."); @@ -712,13 +730,13 @@ namespace StardewModdingApi.Installer : path.Replace("\\ ", " "); // in Linux/macOS, spaces in paths may be escaped if copied from the command line if (path.StartsWith("~/")) { - string home = Environment.GetEnvironmentVariable("HOME") ?? Environment.GetEnvironmentVariable("USERPROFILE"); + string home = Environment.GetEnvironmentVariable("HOME") ?? Environment.GetEnvironmentVariable("USERPROFILE")!; path = Path.Combine(home, path.Substring(2)); } // get directory if (File.Exists(path)) - path = Path.GetDirectoryName(path); + path = Path.GetDirectoryName(path)!; DirectoryInfo directory = new(path); // validate path @@ -765,7 +783,7 @@ namespace StardewModdingApi.Installer // game folder which contains the installer, if any { - DirectoryInfo curPath = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory; + DirectoryInfo? curPath = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory; while (curPath?.Parent != null) // must be in a folder (not at the root) { if (context.LooksLikeGameFolder(curPath)) @@ -787,7 +805,7 @@ namespace StardewModdingApi.Installer } } - /// Interactively move mods out of the appdata directory. + /// Interactively move mods out of the app data directory. /// The directory which should contain all mods. /// The installer directory containing packaged mods. private void InteractivelyRemoveAppDataMods(DirectoryInfo properModsDir, DirectoryInfo packagedModsDir) @@ -847,7 +865,7 @@ namespace StardewModdingApi.Installer /// Move a filesystem entry to a new parent directory. /// The filesystem entry to move. /// The destination path. - /// We can't use or , because those don't work across partitions. + /// We can't use or , because those don't work across partitions. private void Move(FileSystemInfo entry, string newPath) { // file @@ -874,15 +892,12 @@ namespace StardewModdingApi.Installer /// The file or folder info. private bool ShouldCopy(FileSystemInfo entry) { - switch (entry.Name) + return entry.Name switch { - case "mcs": - return false; // ignore macOS symlink - case "Mods": - return false; // Mods folder handled separately - default: - return true; - } + "mcs" => false, // ignore macOS symlink + "Mods" => false, // Mods folder handled separately + _ => true + }; } } } diff --git a/src/SMAPI.Installer/Program.cs b/src/SMAPI.Installer/Program.cs index 5139513f..dc452a46 100644 --- a/src/SMAPI.Installer/Program.cs +++ b/src/SMAPI.Installer/Program.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Diagnostics.CodeAnalysis; using System.IO; @@ -17,7 +15,7 @@ namespace StardewModdingApi.Installer *********/ /// The absolute path of the installer folder. [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute", Justification = "The assembly location is never null in this context.")] - private static readonly string InstallerPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + private static readonly string InstallerPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!; /// The absolute path of the folder containing the unzipped installer files. private static readonly string ExtractedBundlePath = Path.Combine(Path.GetTempPath(), $"SMAPI-installer-{Guid.NewGuid():N}"); @@ -68,14 +66,14 @@ namespace StardewModdingApi.Installer /// Method called when assembly resolution fails, which may return a manually resolved assembly. /// The event sender. /// The event arguments. - private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs e) + private static Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs e) { try { AssemblyName name = new(e.Name); foreach (FileInfo dll in new DirectoryInfo(Program.InternalFilesPath).EnumerateFiles("*.dll")) { - if (name.Name.Equals(AssemblyName.GetAssemblyName(dll.FullName).Name, StringComparison.OrdinalIgnoreCase)) + if (name.Name != null && name.Name.Equals(AssemblyName.GetAssemblyName(dll.FullName).Name, StringComparison.OrdinalIgnoreCase)) return Assembly.LoadFrom(dll.FullName); } return null;