diff options
Diffstat (limited to 'src/SMAPI/Utilities')
-rw-r--r-- | src/SMAPI/Utilities/CaseInsensitivePathCache.cs | 4 | ||||
-rw-r--r-- | src/SMAPI/Utilities/Keybind.cs | 5 | ||||
-rw-r--r-- | src/SMAPI/Utilities/KeybindList.cs | 11 | ||||
-rw-r--r-- | src/SMAPI/Utilities/PerScreen.cs | 36 | ||||
-rw-r--r-- | src/SMAPI/Utilities/SDate.cs | 55 |
5 files changed, 61 insertions, 50 deletions
diff --git a/src/SMAPI/Utilities/CaseInsensitivePathCache.cs b/src/SMAPI/Utilities/CaseInsensitivePathCache.cs index 4596fdce..2ac1b9f9 100644 --- a/src/SMAPI/Utilities/CaseInsensitivePathCache.cs +++ b/src/SMAPI/Utilities/CaseInsensitivePathCache.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using System.IO; @@ -81,7 +79,7 @@ namespace StardewModdingAPI.Utilities return relativePath; // already cached - if (this.RelativePathCache.Value.TryGetValue(relativePath, out string resolved)) + if (this.RelativePathCache.Value.TryGetValue(relativePath, out string? resolved)) return resolved; // file exists but isn't cached for some reason diff --git a/src/SMAPI/Utilities/Keybind.cs b/src/SMAPI/Utilities/Keybind.cs index 7b1acf1d..3455ce77 100644 --- a/src/SMAPI/Utilities/Keybind.cs +++ b/src/SMAPI/Utilities/Keybind.cs @@ -1,7 +1,6 @@ -#nullable disable - using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using StardewModdingAPI.Framework; @@ -44,7 +43,7 @@ namespace StardewModdingAPI.Utilities /// <param name="input">The keybind string. See remarks on <see cref="ToString"/> for format details.</param> /// <param name="parsed">The parsed keybind, if valid.</param> /// <param name="errors">The parse errors, if any.</param> - public static bool TryParse(string input, out Keybind parsed, out string[] errors) + public static bool TryParse(string input, [NotNullWhen(true)] out Keybind? parsed, out string[] errors) { // empty input if (string.IsNullOrWhiteSpace(input)) diff --git a/src/SMAPI/Utilities/KeybindList.cs b/src/SMAPI/Utilities/KeybindList.cs index 7b2c396b..aa12a37a 100644 --- a/src/SMAPI/Utilities/KeybindList.cs +++ b/src/SMAPI/Utilities/KeybindList.cs @@ -1,7 +1,6 @@ -#nullable disable - using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using StardewModdingAPI.Toolkit.Serialization; @@ -42,7 +41,7 @@ namespace StardewModdingAPI.Utilities /// <exception cref="FormatException">The <paramref name="input"/> format is invalid.</exception> public static KeybindList Parse(string input) { - return KeybindList.TryParse(input, out KeybindList parsed, out string[] errors) + return KeybindList.TryParse(input, out KeybindList? parsed, out string[] errors) ? parsed : throw new SParseException($"Can't parse {nameof(Keybind)} from invalid value '{input}'.\n{string.Join("\n", errors)}"); } @@ -51,7 +50,7 @@ namespace StardewModdingAPI.Utilities /// <param name="input">The keybind string. See remarks on <see cref="ToString"/> for format details.</param> /// <param name="parsed">The parsed keybind list, if valid.</param> /// <param name="errors">The errors that occurred while parsing the input, if any.</param> - public static bool TryParse(string input, out KeybindList parsed, out string[] errors) + public static bool TryParse(string? input, [NotNullWhen(true)] out KeybindList? parsed, out string[] errors) { // empty input if (string.IsNullOrWhiteSpace(input)) @@ -69,7 +68,7 @@ namespace StardewModdingAPI.Utilities if (string.IsNullOrWhiteSpace(rawSet)) continue; - if (!Keybind.TryParse(rawSet, out Keybind keybind, out string[] curErrors)) + if (!Keybind.TryParse(rawSet, out Keybind? keybind, out string[] curErrors)) rawErrors.AddRange(curErrors); else keybinds.Add(keybind); @@ -151,7 +150,7 @@ namespace StardewModdingAPI.Utilities } /// <summary>Get the keybind which is currently down, if any. If there are multiple keybinds down, the first one is returned.</summary> - public Keybind GetKeybindCurrentlyDown() + public Keybind? GetKeybindCurrentlyDown() { return this.Keybinds.FirstOrDefault(p => p.GetState().IsDown()); } diff --git a/src/SMAPI/Utilities/PerScreen.cs b/src/SMAPI/Utilities/PerScreen.cs index afe3ba91..6c2e436b 100644 --- a/src/SMAPI/Utilities/PerScreen.cs +++ b/src/SMAPI/Utilities/PerScreen.cs @@ -1,8 +1,7 @@ -#nullable disable - using System; using System.Collections.Generic; using System.Linq; +using StardewModdingAPI.Framework; namespace StardewModdingAPI.Utilities { @@ -39,15 +38,14 @@ namespace StardewModdingAPI.Utilities ** Public methods *********/ /// <summary>Construct an instance.</summary> + /// <remarks><strong>Limitation with nullable reference types:</strong> when the underlying type <typeparamref name="T"/> is nullable, this sets the default value to null regardless of whether you marked the type parameter nullable. To avoid that, set the default value with the 'createNewState' argument instead.</remarks> public PerScreen() - : this(null) { } + : this(null, nullExpected: true) { } /// <summary>Construct an instance.</summary> /// <param name="createNewState">Create the initial state for a screen.</param> public PerScreen(Func<T> createNewState) - { - this.CreateNewState = createNewState ?? (() => default); - } + : this(createNewState, nullExpected: false) { } /// <summary>Get all active values by screen ID. This doesn't initialize the value for a screen ID if it's not created yet.</summary> public IEnumerable<KeyValuePair<int, T>> GetActiveValues() @@ -61,7 +59,7 @@ namespace StardewModdingAPI.Utilities public T GetValueForScreen(int screenId) { this.RemoveDeadScreens(); - return this.States.TryGetValue(screenId, out T state) + return this.States.TryGetValue(screenId, out T? state) ? state : this.States[screenId] = this.CreateNewState(); } @@ -85,6 +83,30 @@ namespace StardewModdingAPI.Utilities /********* ** Private methods *********/ + /// <summary>Construct an instance.</summary> + /// <param name="createNewState">Create the initial state for a screen.</param> + /// <param name="nullExpected">Whether a null <paramref name="createNewState"/> value is expected.</param> + /// <remarks>This constructor only exists to maintain backwards compatibility. In SMAPI 4.0.0, the overload that passes <c>nullExpected: false</c> should throw an exception instead.</remarks> + private PerScreen(Func<T>? createNewState, bool nullExpected) + { + if (createNewState is null) + { + createNewState = (() => default!); + + if (!nullExpected) + { + SCore.DeprecationManager.Warn( + SCore.DeprecationManager.GetModFromStack(), + $"calling the {nameof(PerScreen<T>)} constructor with null", + "3.14.0", + DeprecationLevel.Notice + ); + } + } + + this.CreateNewState = createNewState; + } + /// <summary>Remove screens which are no longer active.</summary> private void RemoveDeadScreens() { diff --git a/src/SMAPI/Utilities/SDate.cs b/src/SMAPI/Utilities/SDate.cs index b10bc3da..1d4e4489 100644 --- a/src/SMAPI/Utilities/SDate.cs +++ b/src/SMAPI/Utilities/SDate.cs @@ -1,6 +1,5 @@ -#nullable disable - using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Newtonsoft.Json; using StardewModdingAPI.Framework; @@ -24,7 +23,7 @@ namespace StardewModdingAPI.Utilities private readonly int DaysInSeason = 28; /// <summary>The core SMAPI translations.</summary> - internal static Translator Translations; + internal static Translator? Translations; /********* @@ -94,7 +93,8 @@ namespace StardewModdingAPI.Utilities /// <summary>Get a date from a game date instance.</summary> /// <param name="date">The world date.</param> - public static SDate From(WorldDate date) + [return: NotNullIfNotNull("date")] + public static SDate? From(WorldDate? date) { if (date == null) return null; @@ -170,14 +170,14 @@ namespace StardewModdingAPI.Utilities ****/ /// <summary>Get whether this instance is equal to another.</summary> /// <param name="other">The other value to compare.</param> - public bool Equals(SDate other) + public bool Equals(SDate? other) { return this == other; } /// <summary>Get whether this instance is equal to another.</summary> /// <param name="obj">The other value to compare.</param> - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is SDate other && this == other; } @@ -195,7 +195,7 @@ namespace StardewModdingAPI.Utilities /// <param name="date">The base date to compare.</param> /// <param name="other">The other date to compare.</param> /// <returns>The equality of the dates</returns> - public static bool operator ==(SDate date, SDate other) + public static bool operator ==(SDate? date, SDate? other) { return date?.DaysSinceStart == other?.DaysSinceStart; } @@ -203,7 +203,7 @@ namespace StardewModdingAPI.Utilities /// <summary>Get whether one date is not equal to another.</summary> /// <param name="date">The base date to compare.</param> /// <param name="other">The other date to compare.</param> - public static bool operator !=(SDate date, SDate other) + public static bool operator !=(SDate? date, SDate? other) { return date?.DaysSinceStart != other?.DaysSinceStart; } @@ -211,7 +211,7 @@ namespace StardewModdingAPI.Utilities /// <summary>Get whether one date is more than another.</summary> /// <param name="date">The base date to compare.</param> /// <param name="other">The other date to compare.</param> - public static bool operator >(SDate date, SDate other) + public static bool operator >(SDate? date, SDate? other) { return date?.DaysSinceStart > other?.DaysSinceStart; } @@ -219,7 +219,7 @@ namespace StardewModdingAPI.Utilities /// <summary>Get whether one date is more than or equal to another.</summary> /// <param name="date">The base date to compare.</param> /// <param name="other">The other date to compare.</param> - public static bool operator >=(SDate date, SDate other) + public static bool operator >=(SDate? date, SDate? other) { return date?.DaysSinceStart >= other?.DaysSinceStart; } @@ -227,7 +227,7 @@ namespace StardewModdingAPI.Utilities /// <summary>Get whether one date is less than or equal to another.</summary> /// <param name="date">The base date to compare.</param> /// <param name="other">The other date to compare.</param> - public static bool operator <=(SDate date, SDate other) + public static bool operator <=(SDate? date, SDate? other) { return date?.DaysSinceStart <= other?.DaysSinceStart; } @@ -235,7 +235,7 @@ namespace StardewModdingAPI.Utilities /// <summary>Get whether one date is less than another.</summary> /// <param name="date">The base date to compare.</param> /// <param name="other">The other date to compare.</param> - public static bool operator <(SDate date, SDate other) + public static bool operator <(SDate? date, SDate? other) { return date?.DaysSinceStart < other?.DaysSinceStart; } @@ -250,9 +250,10 @@ namespace StardewModdingAPI.Utilities /// <param name="year">The year.</param> /// <param name="allowDayZero">Whether to allow 0 spring Y1 as a valid date.</param> /// <exception cref="ArgumentException">One of the arguments has an invalid value (like day 35).</exception> + [SuppressMessage("ReSharper", "ConstantConditionalAccessQualifier", Justification = "The nullability is validated in this constructor.")] private SDate(int day, string season, int year, bool allowDayZero) { - season = season?.Trim().ToLowerInvariant(); + season = season?.Trim().ToLowerInvariant()!; // null-checked below // validate if (season == null) @@ -288,25 +289,17 @@ namespace StardewModdingAPI.Utilities /// <param name="day">The day of month.</param> private DayOfWeek GetDayOfWeek(int day) { - switch (day % 7) + return (day % 7) switch { - case 0: - return DayOfWeek.Sunday; - case 1: - return DayOfWeek.Monday; - case 2: - return DayOfWeek.Tuesday; - case 3: - return DayOfWeek.Wednesday; - case 4: - return DayOfWeek.Thursday; - case 5: - return DayOfWeek.Friday; - case 6: - return DayOfWeek.Saturday; - default: - return 0; - } + 0 => DayOfWeek.Sunday, + 1 => DayOfWeek.Monday, + 2 => DayOfWeek.Tuesday, + 3 => DayOfWeek.Wednesday, + 4 => DayOfWeek.Thursday, + 5 => DayOfWeek.Friday, + 6 => DayOfWeek.Saturday, + _ => 0 + }; } /// <summary>Get the number of days since the game began (starting at 1 for the first day of spring in Y1).</summary> |