diff options
author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2022-04-13 20:24:14 -0400 |
---|---|---|
committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2022-04-13 20:24:14 -0400 |
commit | f39da383a17b368e92fd243cf155b27ba42671f3 (patch) | |
tree | 56c215dfb34da270a7714afd141e76a94c69a2c0 /src/SMAPI/Framework/ModHelpers | |
parent | 6e9e8aef1ef97e1a4ef4410ce300cb1c47eca986 (diff) | |
download | SMAPI-f39da383a17b368e92fd243cf155b27ba42671f3.tar.gz SMAPI-f39da383a17b368e92fd243cf155b27ba42671f3.tar.bz2 SMAPI-f39da383a17b368e92fd243cf155b27ba42671f3.zip |
enable nullable annotations in SMAPI where no logic changes are needed (#837)
Diffstat (limited to 'src/SMAPI/Framework/ModHelpers')
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/ContentHelper.cs | 9 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/DataHelper.cs | 28 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/GameContentHelper.cs | 8 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/ModContentHelper.cs | 6 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs | 13 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs | 8 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs | 26 |
7 files changed, 50 insertions, 48 deletions
diff --git a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs index 12ef0439..b610b395 100644 --- a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -114,6 +112,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <inheritdoc /> public T Load<T>(string key, ContentSource source = ContentSource.ModFolder) + where T : notnull { IAssetName assetName = this.ContentCore.ParseAssetName(key, allowLocales: source == ContentSource.GameContent); @@ -140,7 +139,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <inheritdoc /> [Pure] - public string NormalizeAssetName(string assetName) + public string NormalizeAssetName(string? assetName) { return this.ModContentManager.AssertAndNormalizeAssetName(assetName); } @@ -171,6 +170,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <inheritdoc /> public bool InvalidateCache<T>() + where T : notnull { this.Monitor.Log($"Requested cache invalidation for all assets of type {typeof(T)}. This is an expensive operation and should be avoided if possible."); return this.ContentCore.InvalidateCache((_, _, type) => typeof(T).IsAssignableFrom(type)).Any(); @@ -184,7 +184,8 @@ namespace StardewModdingAPI.Framework.ModHelpers } /// <inheritdoc /> - public IAssetData GetPatchHelper<T>(T data, string assetName = null) + public IAssetData GetPatchHelper<T>(T data, string? assetName = null) + where T : notnull { if (data == null) throw new ArgumentNullException(nameof(data), "Can't get a patch helper for a null value."); diff --git a/src/SMAPI/Framework/ModHelpers/DataHelper.cs b/src/SMAPI/Framework/ModHelpers/DataHelper.cs index 86a34ee8..92b3b398 100644 --- a/src/SMAPI/Framework/ModHelpers/DataHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/DataHelper.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using System.IO; @@ -42,19 +40,21 @@ namespace StardewModdingAPI.Framework.ModHelpers ** JSON file ****/ /// <inheritdoc /> - public TModel ReadJsonFile<TModel>(string path) where TModel : class + public TModel? ReadJsonFile<TModel>(string path) + where TModel : class { if (!PathUtilities.IsSafeRelativePath(path)) throw new InvalidOperationException($"You must call {nameof(IModHelper.Data)}.{nameof(this.ReadJsonFile)} with a relative path."); path = Path.Combine(this.ModFolderPath, PathUtilities.NormalizePath(path)); - return this.JsonHelper.ReadJsonFileIfExists(path, out TModel data) + return this.JsonHelper.ReadJsonFileIfExists(path, out TModel? data) ? data : null; } /// <inheritdoc /> - public void WriteJsonFile<TModel>(string path, TModel data) where TModel : class + public void WriteJsonFile<TModel>(string path, TModel? data) + where TModel : class { if (!PathUtilities.IsSafeRelativePath(path)) throw new InvalidOperationException($"You must call {nameof(IMod.Helper)}.{nameof(IModHelper.Data)}.{nameof(this.WriteJsonFile)} with a relative path (without directory climbing)."); @@ -71,7 +71,8 @@ namespace StardewModdingAPI.Framework.ModHelpers ** Save file ****/ /// <inheritdoc /> - public TModel ReadSaveData<TModel>(string key) where TModel : class + public TModel? ReadSaveData<TModel>(string key) + where TModel : class { if (Context.LoadStage == LoadStage.None) throw new InvalidOperationException($"Can't use {nameof(IMod.Helper)}.{nameof(IModHelper.Data)}.{nameof(this.ReadSaveData)} when a save file isn't loaded."); @@ -82,14 +83,15 @@ namespace StardewModdingAPI.Framework.ModHelpers string internalKey = this.GetSaveFileKey(key); foreach (IDictionary<string, string> dataField in this.GetDataFields(Context.LoadStage)) { - if (dataField.TryGetValue(internalKey, out string value)) + if (dataField.TryGetValue(internalKey, out string? value)) return this.JsonHelper.Deserialize<TModel>(value); } return null; } /// <inheritdoc /> - public void WriteSaveData<TModel>(string key, TModel model) where TModel : class + public void WriteSaveData<TModel>(string key, TModel? model) + where TModel : class { if (Context.LoadStage == LoadStage.None) throw new InvalidOperationException($"Can't use {nameof(IMod.Helper)}.{nameof(IModHelper.Data)}.{nameof(this.WriteSaveData)} when a save file isn't loaded."); @@ -97,7 +99,7 @@ namespace StardewModdingAPI.Framework.ModHelpers throw new InvalidOperationException($"Can't use {nameof(IMod.Helper)}.{nameof(IModHelper.Data)}.{nameof(this.WriteSaveData)} when connected to a remote host. (Save files are stored on the main player's computer.)"); string internalKey = this.GetSaveFileKey(key); - string data = model != null + string? data = model != null ? this.JsonHelper.Serialize(model, Formatting.None) : null; @@ -114,16 +116,18 @@ namespace StardewModdingAPI.Framework.ModHelpers ** Global app data ****/ /// <inheritdoc /> - public TModel ReadGlobalData<TModel>(string key) where TModel : class + public TModel? ReadGlobalData<TModel>(string key) + where TModel : class { string path = this.GetGlobalDataPath(key); - return this.JsonHelper.ReadJsonFileIfExists(path, out TModel data) + return this.JsonHelper.ReadJsonFileIfExists(path, out TModel? data) ? data : null; } /// <inheritdoc /> - public void WriteGlobalData<TModel>(string key, TModel data) where TModel : class + public void WriteGlobalData<TModel>(string key, TModel? data) + where TModel : class { string path = this.GetGlobalDataPath(key); if (data != null) diff --git a/src/SMAPI/Framework/ModHelpers/GameContentHelper.cs b/src/SMAPI/Framework/ModHelpers/GameContentHelper.cs index 6d0c2f5f..4c1cde02 100644 --- a/src/SMAPI/Framework/ModHelpers/GameContentHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/GameContentHelper.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Linq; using StardewModdingAPI.Framework.Content; @@ -71,6 +69,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <inheritdoc /> public T Load<T>(string key) + where T : notnull { IAssetName assetName = this.ContentCore.ParseAssetName(key, allowLocales: true); return this.Load<T>(assetName); @@ -78,6 +77,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <inheritdoc /> public T Load<T>(IAssetName assetName) + where T : notnull { try { @@ -105,6 +105,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <inheritdoc /> public bool InvalidateCache<T>() + where T : notnull { this.Monitor.Log($"Requested cache invalidation for all assets of type {typeof(T)}. This is an expensive operation and should be avoided if possible."); return this.ContentCore.InvalidateCache((_, _, type) => typeof(T).IsAssignableFrom(type)).Any(); @@ -118,7 +119,8 @@ namespace StardewModdingAPI.Framework.ModHelpers } /// <inheritdoc /> - public IAssetData GetPatchHelper<T>(T data, string assetName = null) + public IAssetData GetPatchHelper<T>(T data, string? assetName = null) + where T : notnull { if (data == null) throw new ArgumentNullException(nameof(data), "Can't get a patch helper for a null value."); diff --git a/src/SMAPI/Framework/ModHelpers/ModContentHelper.cs b/src/SMAPI/Framework/ModHelpers/ModContentHelper.cs index b149ed82..fc47f269 100644 --- a/src/SMAPI/Framework/ModHelpers/ModContentHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModContentHelper.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using Microsoft.Xna.Framework.Content; using StardewModdingAPI.Framework.Content; @@ -57,6 +55,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <inheritdoc /> public T Load<T>(string relativePath) + where T : notnull { relativePath = this.RelativePathCache.GetAssetName(relativePath); @@ -80,7 +79,8 @@ namespace StardewModdingAPI.Framework.ModHelpers } /// <inheritdoc /> - public IAssetData GetPatchHelper<T>(T data, string relativePath = null) + public IAssetData GetPatchHelper<T>(T data, string? relativePath = null) + where T : notnull { if (data == null) throw new ArgumentNullException(nameof(data), "Can't get a patch helper for a null value."); diff --git a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs index e277e6fa..84899610 100644 --- a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Collections.Generic; using StardewModdingAPI.Framework.Reflection; @@ -47,7 +45,7 @@ namespace StardewModdingAPI.Framework.ModHelpers } /// <inheritdoc /> - public IModInfo Get(string uniqueID) + public IModInfo? Get(string uniqueID) { return this.Registry.Get(uniqueID); } @@ -59,7 +57,7 @@ namespace StardewModdingAPI.Framework.ModHelpers } /// <inheritdoc /> - public object GetApi(string uniqueID) + public object? GetApi(string uniqueID) { // validate ready if (!this.Registry.AreAllModsInitialized) @@ -69,17 +67,18 @@ namespace StardewModdingAPI.Framework.ModHelpers } // get raw API - IModMetadata mod = this.Registry.Get(uniqueID); + IModMetadata? mod = this.Registry.Get(uniqueID); if (mod?.Api != null && this.AccessedModApis.Add(mod.Manifest.UniqueID)) this.Monitor.Log($"Accessed mod-provided API for {mod.DisplayName}."); return mod?.Api; } /// <inheritdoc /> - public TInterface GetApi<TInterface>(string uniqueID) where TInterface : class + public TInterface? GetApi<TInterface>(string uniqueID) + where TInterface : class { // get raw API - object api = this.GetApi(uniqueID); + object? api = this.GetApi(uniqueID); if (api == null) return null; diff --git a/src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs b/src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs index 96b074e2..a419327e 100644 --- a/src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Collections.Generic; using StardewModdingAPI.Framework.Networking; using StardewValley; @@ -41,9 +39,9 @@ namespace StardewModdingAPI.Framework.ModHelpers } /// <inheritdoc /> - public IMultiplayerPeer GetConnectedPlayer(long id) + public IMultiplayerPeer? GetConnectedPlayer(long id) { - return this.Multiplayer.Peers.TryGetValue(id, out MultiplayerPeer peer) + return this.Multiplayer.Peers.TryGetValue(id, out MultiplayerPeer? peer) ? peer : null; } @@ -55,7 +53,7 @@ namespace StardewModdingAPI.Framework.ModHelpers } /// <inheritdoc /> - public void SendMessage<TMessage>(TMessage message, string messageType, string[] modIDs = null, long[] playerIDs = null) + public void SendMessage<TMessage>(TMessage message, string messageType, string[]? modIDs = null, long[]? playerIDs = null) { this.Multiplayer.BroadcastModMessage( message: message, diff --git a/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs b/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs index 24cbd01c..af018c87 100644 --- a/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Reflection; using StardewModdingAPI.Framework.Reflection; @@ -39,7 +37,7 @@ namespace StardewModdingAPI.Framework.ModHelpers { return this.AssertAccessAllowed( this.Reflector.GetField<TValue>(obj, name, required) - ); + )!; } /// <inheritdoc /> @@ -47,7 +45,7 @@ namespace StardewModdingAPI.Framework.ModHelpers { return this.AssertAccessAllowed( this.Reflector.GetField<TValue>(type, name, required) - ); + )!; } /// <inheritdoc /> @@ -55,7 +53,7 @@ namespace StardewModdingAPI.Framework.ModHelpers { return this.AssertAccessAllowed( this.Reflector.GetProperty<TValue>(obj, name, required) - ); + )!; } /// <inheritdoc /> @@ -63,7 +61,7 @@ namespace StardewModdingAPI.Framework.ModHelpers { return this.AssertAccessAllowed( this.Reflector.GetProperty<TValue>(type, name, required) - ); + )!; } /// <inheritdoc /> @@ -71,7 +69,7 @@ namespace StardewModdingAPI.Framework.ModHelpers { return this.AssertAccessAllowed( this.Reflector.GetMethod(obj, name, required) - ); + )!; } /// <inheritdoc /> @@ -79,7 +77,7 @@ namespace StardewModdingAPI.Framework.ModHelpers { return this.AssertAccessAllowed( this.Reflector.GetMethod(type, name, required) - ); + )!; } @@ -90,7 +88,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <typeparam name="T">The field value type.</typeparam> /// <param name="field">The field being accessed.</param> /// <returns>Returns the same field instance for convenience.</returns> - private IReflectedField<T> AssertAccessAllowed<T>(IReflectedField<T> field) + private IReflectedField<T>? AssertAccessAllowed<T>(IReflectedField<T>? field) { this.AssertAccessAllowed(field?.FieldInfo); return field; @@ -100,7 +98,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <typeparam name="T">The property value type.</typeparam> /// <param name="property">The property being accessed.</param> /// <returns>Returns the same property instance for convenience.</returns> - private IReflectedProperty<T> AssertAccessAllowed<T>(IReflectedProperty<T> property) + private IReflectedProperty<T>? AssertAccessAllowed<T>(IReflectedProperty<T>? property) { this.AssertAccessAllowed(property?.PropertyInfo.GetMethod?.GetBaseDefinition()); this.AssertAccessAllowed(property?.PropertyInfo.SetMethod?.GetBaseDefinition()); @@ -110,7 +108,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <summary>Assert that mods can use the reflection helper to access the given member.</summary> /// <param name="method">The method being accessed.</param> /// <returns>Returns the same method instance for convenience.</returns> - private IReflectedMethod AssertAccessAllowed(IReflectedMethod method) + private IReflectedMethod? AssertAccessAllowed(IReflectedMethod? method) { this.AssertAccessAllowed(method?.MethodInfo.GetBaseDefinition()); return method; @@ -118,18 +116,18 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <summary>Assert that mods can use the reflection helper to access the given member.</summary> /// <param name="member">The member being accessed.</param> - private void AssertAccessAllowed(MemberInfo member) + private void AssertAccessAllowed(MemberInfo? member) { if (member == null) return; // get type which defines the member - Type declaringType = member.DeclaringType; + Type? declaringType = member.DeclaringType; if (declaringType == null) throw new InvalidOperationException($"Can't validate access to {member.MemberType} {member.Name} because it has no declaring type."); // should never happen // validate access - string rootNamespace = typeof(Program).Namespace; + string? rootNamespace = typeof(Program).Namespace; if (declaringType.Namespace == rootNamespace || declaringType.Namespace?.StartsWith(rootNamespace + ".") == true) throw new InvalidOperationException($"SMAPI blocked access by {this.ModName} to its internals through the reflection API. Accessing the SMAPI internals is strongly discouraged since they're subject to change, which means the mod can break without warning. (Detected access to {declaringType.FullName}.{member.Name}.)"); } |