From 4da9e954df3846d01aa0536f4e8143466a1d62f3 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 11 Feb 2022 00:49:49 -0500 Subject: use Array.Empty to avoid unneeded array allocations --- src/SMAPI.Toolkit/Serialization/Models/Manifest.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/SMAPI.Toolkit/Serialization') diff --git a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs index 46b654a5..4ad97b6d 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Runtime.Serialization; using Newtonsoft.Json; @@ -68,7 +69,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models this.Description = description; this.Version = version; this.UniqueID = uniqueID; - this.UpdateKeys = new string[0]; + this.UpdateKeys = Array.Empty(); this.ContentPackFor = new ManifestContentPackFor { UniqueID = contentPackFor }; } @@ -77,8 +78,8 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models [OnDeserialized] public void OnDeserialized(StreamingContext context) { - this.Dependencies ??= new IManifestDependency[0]; - this.UpdateKeys ??= new string[0]; + this.Dependencies ??= Array.Empty(); + this.UpdateKeys ??= Array.Empty(); } } } -- cgit From a593eda30f82af474887d91458b0e9158f66fefc Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Apr 2022 18:24:59 -0400 Subject: use target-typed new --- src/SMAPI.Toolkit/Serialization/JsonHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI.Toolkit/Serialization') diff --git a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs index 00db9903..5c465f3c 100644 --- a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs +++ b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs @@ -14,7 +14,7 @@ namespace StardewModdingAPI.Toolkit.Serialization ** Accessors *********/ /// The JSON settings to use when serializing and deserializing files. - public JsonSerializerSettings JsonSettings { get; } = new JsonSerializerSettings + public JsonSerializerSettings JsonSettings { get; } = new() { Formatting = Formatting.Indented, ObjectCreationHandling = ObjectCreationHandling.Replace, // avoid issue where default ICollection values are duplicated each time the config is loaded -- cgit From 0539bb8f3705e5c50d0e5790e2af97f39aed04b8 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Apr 2022 18:25:00 -0400 Subject: simplify with newer pattern features --- src/SMAPI.Toolkit/Serialization/JsonHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI.Toolkit/Serialization') diff --git a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs index 5c465f3c..91c2e9d3 100644 --- a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs +++ b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs @@ -48,7 +48,7 @@ namespace StardewModdingAPI.Toolkit.Serialization { json = File.ReadAllText(fullPath); } - catch (Exception ex) when (ex is DirectoryNotFoundException || ex is FileNotFoundException) + catch (Exception ex) when (ex is DirectoryNotFoundException or FileNotFoundException) { result = default(TModel); return false; -- cgit From 2e7c233f6c9bf6430672b39f970a3324deba79dd Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Apr 2022 21:48:55 -0400 Subject: enable nullable annotations by default (#837) This adds `#nullable disable` to all existing code (except where null is impossible like enum files), so it can be migrated incrementally. --- .../Serialization/Converters/ManifestContentPackForConverter.cs | 2 ++ .../Serialization/Converters/ManifestDependencyArrayConverter.cs | 2 ++ src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs | 2 ++ src/SMAPI.Toolkit/Serialization/Converters/SimpleReadOnlyConverter.cs | 2 ++ src/SMAPI.Toolkit/Serialization/InternalExtensions.cs | 2 ++ src/SMAPI.Toolkit/Serialization/JsonHelper.cs | 2 ++ src/SMAPI.Toolkit/Serialization/Models/Manifest.cs | 2 ++ src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs | 2 ++ src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs | 2 ++ src/SMAPI.Toolkit/Serialization/SParseException.cs | 2 ++ 10 files changed, 20 insertions(+) (limited to 'src/SMAPI.Toolkit/Serialization') diff --git a/src/SMAPI.Toolkit/Serialization/Converters/ManifestContentPackForConverter.cs b/src/SMAPI.Toolkit/Serialization/Converters/ManifestContentPackForConverter.cs index 5cabe9d8..d2dc0d22 100644 --- a/src/SMAPI.Toolkit/Serialization/Converters/ManifestContentPackForConverter.cs +++ b/src/SMAPI.Toolkit/Serialization/Converters/ManifestContentPackForConverter.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using Newtonsoft.Json; using StardewModdingAPI.Toolkit.Serialization.Models; diff --git a/src/SMAPI.Toolkit/Serialization/Converters/ManifestDependencyArrayConverter.cs b/src/SMAPI.Toolkit/Serialization/Converters/ManifestDependencyArrayConverter.cs index 7b88d6b7..2c3c2ee7 100644 --- a/src/SMAPI.Toolkit/Serialization/Converters/ManifestDependencyArrayConverter.cs +++ b/src/SMAPI.Toolkit/Serialization/Converters/ManifestDependencyArrayConverter.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs b/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs index cf69104d..9205cebe 100644 --- a/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs +++ b/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; diff --git a/src/SMAPI.Toolkit/Serialization/Converters/SimpleReadOnlyConverter.cs b/src/SMAPI.Toolkit/Serialization/Converters/SimpleReadOnlyConverter.cs index ccc5158b..c923350c 100644 --- a/src/SMAPI.Toolkit/Serialization/Converters/SimpleReadOnlyConverter.cs +++ b/src/SMAPI.Toolkit/Serialization/Converters/SimpleReadOnlyConverter.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; diff --git a/src/SMAPI.Toolkit/Serialization/InternalExtensions.cs b/src/SMAPI.Toolkit/Serialization/InternalExtensions.cs index 10f88dde..1fce5f9d 100644 --- a/src/SMAPI.Toolkit/Serialization/InternalExtensions.cs +++ b/src/SMAPI.Toolkit/Serialization/InternalExtensions.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using Newtonsoft.Json.Linq; diff --git a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs index 91c2e9d3..9700e712 100644 --- a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs +++ b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs index 4ad97b6d..a5dbf604 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.Runtime.Serialization; diff --git a/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs b/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs index 1eb80889..ea5f0e6c 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs @@ -1,3 +1,5 @@ +#nullable disable + namespace StardewModdingAPI.Toolkit.Serialization.Models { /// Indicates which mod can read the content pack represented by the containing manifest. diff --git a/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs b/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs index 00f168f4..f52dd5ee 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs @@ -1,3 +1,5 @@ +#nullable disable + namespace StardewModdingAPI.Toolkit.Serialization.Models { /// A mod dependency listed in a mod manifest. diff --git a/src/SMAPI.Toolkit/Serialization/SParseException.cs b/src/SMAPI.Toolkit/Serialization/SParseException.cs index 5f58b5b8..1581e027 100644 --- a/src/SMAPI.Toolkit/Serialization/SParseException.cs +++ b/src/SMAPI.Toolkit/Serialization/SParseException.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; namespace StardewModdingAPI.Toolkit.Serialization -- cgit From e58e8a22836081ec4baffa5a9b4b093a329f3d88 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 7 Apr 2022 01:38:02 -0400 Subject: enable nullable annotations for manifests (#837) --- src/SMAPI.Toolkit/Serialization/Models/Manifest.cs | 102 +++++++++++++++------ .../Serialization/Models/ManifestContentPackFor.cs | 33 ++++++- .../Serialization/Models/ManifestDependency.cs | 44 +++++++-- 3 files changed, 138 insertions(+), 41 deletions(-) (limited to 'src/SMAPI.Toolkit/Serialization') diff --git a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs index a5dbf604..01010602 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs @@ -1,8 +1,6 @@ -#nullable disable - using System; using System.Collections.Generic; -using System.Runtime.Serialization; +using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; using StardewModdingAPI.Toolkit.Serialization.Converters; @@ -15,48 +13,45 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models ** Accessors *********/ /// The mod name. - public string Name { get; set; } + public string Name { get; } /// A brief description of the mod. - public string Description { get; set; } + public string Description { get; } /// The mod author's name. - public string Author { get; set; } + public string Author { get; } /// The mod version. - public ISemanticVersion Version { get; set; } + public ISemanticVersion Version { get; } /// The minimum SMAPI version required by this mod, if any. - public ISemanticVersion MinimumApiVersion { get; set; } + public ISemanticVersion? MinimumApiVersion { get; } /// The name of the DLL in the directory that has the Entry method. Mutually exclusive with . - public string EntryDll { get; set; } + public string? EntryDll { get; } /// The mod which will read this as a content pack. Mutually exclusive with . [JsonConverter(typeof(ManifestContentPackForConverter))] - public IManifestContentPackFor ContentPackFor { get; set; } + public IManifestContentPackFor? ContentPackFor { get; } /// The other mods that must be loaded before this mod. [JsonConverter(typeof(ManifestDependencyArrayConverter))] - public IManifestDependency[] Dependencies { get; set; } + public IManifestDependency[] Dependencies { get; } /// The namespaced mod IDs to query for updates (like Nexus:541). - public string[] UpdateKeys { get; set; } + public string[] UpdateKeys { get; private set; } /// The unique mod ID. - public string UniqueID { get; set; } + public string UniqueID { get; } /// Any manifest fields which didn't match a valid field. [JsonExtensionData] - public IDictionary ExtraFields { get; set; } + public IDictionary ExtraFields { get; set; } = new Dictionary(); /********* ** Public methods *********/ - /// Construct an instance. - public Manifest() { } - /// Construct an instance for a transitional content pack. /// The unique mod ID. /// The mod name. @@ -64,24 +59,71 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models /// A brief description of the mod. /// The mod version. /// The modID which will read this as a content pack. - public Manifest(string uniqueID, string name, string author, string description, ISemanticVersion version, string contentPackFor = null) + public Manifest(string uniqueID, string name, string author, string description, ISemanticVersion version, string? contentPackFor = null) + : this( + uniqueId: uniqueID, + name: name, + author: author, + description: description, + version: version, + minimumApiVersion: null, + entryDll: null, + contentPackFor: contentPackFor != null + ? new ManifestContentPackFor(contentPackFor, null) + : null, + dependencies: null, + updateKeys: null + ) + { } + + /// Construct an instance for a transitional content pack. + /// The unique mod ID. + /// The mod name. + /// The mod author's name. + /// A brief description of the mod. + /// The mod version. + /// The minimum SMAPI version required by this mod, if any. + /// The name of the DLL in the directory that has the Entry method. Mutually exclusive with . + /// The modID which will read this as a content pack. + /// The other mods that must be loaded before this mod. + /// The namespaced mod IDs to query for updates (like Nexus:541). + [JsonConstructor] + public Manifest(string uniqueId, string name, string author, string description, ISemanticVersion version, ISemanticVersion? minimumApiVersion, string? entryDll, IManifestContentPackFor? contentPackFor, IManifestDependency[]? dependencies, string[]? updateKeys) { - this.Name = name; - this.Author = author; - this.Description = description; + this.UniqueID = this.NormalizeWhitespace(uniqueId); + this.Name = this.NormalizeWhitespace(name); + this.Author = this.NormalizeWhitespace(author); + this.Description = this.NormalizeWhitespace(description); this.Version = version; - this.UniqueID = uniqueID; - this.UpdateKeys = Array.Empty(); - this.ContentPackFor = new ManifestContentPackFor { UniqueID = contentPackFor }; + this.MinimumApiVersion = minimumApiVersion; + this.EntryDll = this.NormalizeWhitespace(entryDll); + this.ContentPackFor = contentPackFor; + this.Dependencies = dependencies ?? Array.Empty(); + this.UpdateKeys = updateKeys ?? Array.Empty(); + } + + /// Override the update keys loaded from the mod info. + /// The new update keys to set. + internal void OverrideUpdateKeys(params string[] updateKeys) + { + this.UpdateKeys = updateKeys; } - /// Normalize the model after it's deserialized. - /// The deserialization context. - [OnDeserialized] - public void OnDeserialized(StreamingContext context) + + /********* + ** Private methods + *********/ + /// Normalize whitespace in a raw string. + /// The input to strip. +#if NET5_0_OR_GREATER + [return: NotNullIfNotNull("input")] +#endif + private string? NormalizeWhitespace(string? input) { - this.Dependencies ??= Array.Empty(); - this.UpdateKeys ??= Array.Empty(); + return input + ?.Trim() + .Replace("\r", "") + .Replace("\n", ""); } } } diff --git a/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs b/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs index ea5f0e6c..f7dc8aa8 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs @@ -1,4 +1,4 @@ -#nullable disable +using System.Diagnostics.CodeAnalysis; namespace StardewModdingAPI.Toolkit.Serialization.Models { @@ -9,9 +9,36 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models ** Accessors *********/ /// The unique ID of the mod which can read this content pack. - public string UniqueID { get; set; } + public string UniqueID { get; } /// The minimum required version (if any). - public ISemanticVersion MinimumVersion { get; set; } + public ISemanticVersion? MinimumVersion { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The unique ID of the mod which can read this content pack. + /// The minimum required version (if any). + public ManifestContentPackFor(string uniqueId, ISemanticVersion? minimumVersion) + { + this.UniqueID = this.NormalizeWhitespace(uniqueId); + this.MinimumVersion = minimumVersion; + } + + + /********* + ** Private methods + *********/ + /// Normalize whitespace in a raw string. + /// The input to strip. +#if NET5_0_OR_GREATER + [return: NotNullIfNotNull("input")] +#endif + private string? NormalizeWhitespace(string? input) + { + return input?.Trim(); + } } } diff --git a/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs b/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs index f52dd5ee..e7acf71d 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs @@ -1,4 +1,5 @@ -#nullable disable +using System.Diagnostics.CodeAnalysis; +using Newtonsoft.Json; namespace StardewModdingAPI.Toolkit.Serialization.Models { @@ -9,13 +10,13 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models ** Accessors *********/ /// The unique mod ID to require. - public string UniqueID { get; set; } + public string UniqueID { get; } /// The minimum required version (if any). - public ISemanticVersion MinimumVersion { get; set; } + public ISemanticVersion? MinimumVersion { get; } /// Whether the dependency must be installed to use the mod. - public bool IsRequired { get; set; } + public bool IsRequired { get; } /********* @@ -26,12 +27,39 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models /// The minimum required version (if any). /// Whether the dependency must be installed to use the mod. public ManifestDependency(string uniqueID, string minimumVersion, bool required = true) + : this( + uniqueID: uniqueID, + minimumVersion: !string.IsNullOrWhiteSpace(minimumVersion) + ? new SemanticVersion(minimumVersion) + : null, + required: required + ) + { } + + /// Construct an instance. + /// The unique mod ID to require. + /// The minimum required version (if any). + /// Whether the dependency must be installed to use the mod. + [JsonConstructor] + public ManifestDependency(string uniqueID, ISemanticVersion? minimumVersion, bool required = true) { - this.UniqueID = uniqueID; - this.MinimumVersion = !string.IsNullOrWhiteSpace(minimumVersion) - ? new SemanticVersion(minimumVersion) - : null; + this.UniqueID = this.NormalizeWhitespace(uniqueID); + this.MinimumVersion = minimumVersion; this.IsRequired = required; } + + + /********* + ** Private methods + *********/ + /// Normalize whitespace in a raw string. + /// The input to strip. +#if NET5_0_OR_GREATER + [return: NotNullIfNotNull("input")] +#endif + private string? NormalizeWhitespace(string? input) + { + return input?.Trim(); + } } } -- cgit From 6b05296e71c32abd158f354eeeaf1e135e72e6e2 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 7 Apr 2022 01:51:50 -0400 Subject: migrate mod build package to .NET 5 to allow full nullable annotations (#837) --- src/SMAPI.Toolkit/Serialization/Models/Manifest.cs | 2 -- src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs | 2 -- src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs | 2 -- 3 files changed, 6 deletions(-) (limited to 'src/SMAPI.Toolkit/Serialization') diff --git a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs index 01010602..3ab5edfb 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs @@ -115,9 +115,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models *********/ /// Normalize whitespace in a raw string. /// The input to strip. -#if NET5_0_OR_GREATER [return: NotNullIfNotNull("input")] -#endif private string? NormalizeWhitespace(string? input) { return input diff --git a/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs b/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs index f7dc8aa8..dcdbcf74 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs @@ -33,9 +33,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models *********/ /// Normalize whitespace in a raw string. /// The input to strip. -#if NET5_0_OR_GREATER [return: NotNullIfNotNull("input")] -#endif private string? NormalizeWhitespace(string? input) { return input?.Trim(); diff --git a/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs b/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs index e7acf71d..64725818 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs @@ -54,9 +54,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models *********/ /// Normalize whitespace in a raw string. /// The input to strip. -#if NET5_0_OR_GREATER [return: NotNullIfNotNull("input")] -#endif private string? NormalizeWhitespace(string? input) { return input?.Trim(); -- cgit From d706a25053cdc5d9f1ccc2c09dc3913f835c3f78 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 7 Apr 2022 02:33:23 -0400 Subject: enable nullable annotations for most of the SMAPI toolkit (#837) --- .../Converters/ManifestContentPackForConverter.cs | 6 ++---- .../Converters/ManifestDependencyArrayConverter.cs | 10 ++++------ .../Converters/SemanticVersionConverter.cs | 14 +++++++------- .../Converters/SimpleReadOnlyConverter.cs | 22 ++++++++++------------ .../Serialization/InternalExtensions.cs | 8 +++----- src/SMAPI.Toolkit/Serialization/JsonHelper.cs | 17 +++++++++-------- .../Serialization/Models/ManifestDependency.cs | 2 +- src/SMAPI.Toolkit/Serialization/SParseException.cs | 4 +--- 8 files changed, 37 insertions(+), 46 deletions(-) (limited to 'src/SMAPI.Toolkit/Serialization') diff --git a/src/SMAPI.Toolkit/Serialization/Converters/ManifestContentPackForConverter.cs b/src/SMAPI.Toolkit/Serialization/Converters/ManifestContentPackForConverter.cs index d2dc0d22..faaeedea 100644 --- a/src/SMAPI.Toolkit/Serialization/Converters/ManifestContentPackForConverter.cs +++ b/src/SMAPI.Toolkit/Serialization/Converters/ManifestContentPackForConverter.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using Newtonsoft.Json; using StardewModdingAPI.Toolkit.Serialization.Models; @@ -35,7 +33,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters /// The object type. /// The object being read. /// The calling serializer. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { return serializer.Deserialize(reader); } @@ -44,7 +42,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters /// The JSON writer. /// The value. /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { throw new InvalidOperationException("This converter does not write JSON."); } diff --git a/src/SMAPI.Toolkit/Serialization/Converters/ManifestDependencyArrayConverter.cs b/src/SMAPI.Toolkit/Serialization/Converters/ManifestDependencyArrayConverter.cs index 2c3c2ee7..c499a2c6 100644 --- a/src/SMAPI.Toolkit/Serialization/Converters/ManifestDependencyArrayConverter.cs +++ b/src/SMAPI.Toolkit/Serialization/Converters/ManifestDependencyArrayConverter.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using Newtonsoft.Json; @@ -37,13 +35,13 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters /// The object type. /// The object being read. /// The calling serializer. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { List result = new List(); foreach (JObject obj in JArray.Load(reader).Children()) { - string uniqueID = obj.ValueIgnoreCase(nameof(ManifestDependency.UniqueID)); - string minVersion = obj.ValueIgnoreCase(nameof(ManifestDependency.MinimumVersion)); + string uniqueID = obj.ValueIgnoreCase(nameof(ManifestDependency.UniqueID))!; // will be validated separately if null + string? minVersion = obj.ValueIgnoreCase(nameof(ManifestDependency.MinimumVersion)); bool required = obj.ValueIgnoreCase(nameof(ManifestDependency.IsRequired)) ?? true; result.Add(new ManifestDependency(uniqueID, minVersion, required)); } @@ -54,7 +52,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters /// The JSON writer. /// The value. /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { throw new InvalidOperationException("This converter does not write JSON."); } diff --git a/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs b/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs index 9205cebe..c32c3185 100644 --- a/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs +++ b/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -41,15 +39,17 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters /// The object type. /// The object being read. /// The calling serializer. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { string path = reader.Path; switch (reader.TokenType) { case JsonToken.StartObject: return this.ReadObject(JObject.Load(reader)); + case JsonToken.String: return this.ReadString(JToken.Load(reader).Value(), path); + default: throw new SParseException($"Can't parse {nameof(ISemanticVersion)} from {reader.TokenType} node (path: {reader.Path})."); } @@ -59,7 +59,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters /// The JSON writer. /// The value. /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { writer.WriteValue(value?.ToString()); } @@ -75,7 +75,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters int major = obj.ValueIgnoreCase(nameof(ISemanticVersion.MajorVersion)); int minor = obj.ValueIgnoreCase(nameof(ISemanticVersion.MinorVersion)); int patch = obj.ValueIgnoreCase(nameof(ISemanticVersion.PatchVersion)); - string prereleaseTag = obj.ValueIgnoreCase(nameof(ISemanticVersion.PrereleaseTag)); + string? prereleaseTag = obj.ValueIgnoreCase(nameof(ISemanticVersion.PrereleaseTag)); return new SemanticVersion(major, minor, patch, prereleaseTag: prereleaseTag); } @@ -83,11 +83,11 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters /// Read a JSON string. /// The JSON string value. /// The path to the current JSON node. - private ISemanticVersion ReadString(string str, string path) + private ISemanticVersion? ReadString(string str, string path) { if (string.IsNullOrWhiteSpace(str)) return null; - if (!SemanticVersion.TryParse(str, allowNonStandard: this.AllowNonStandard, out ISemanticVersion version)) + if (!SemanticVersion.TryParse(str, allowNonStandard: this.AllowNonStandard, out ISemanticVersion? version)) throw new SParseException($"Can't parse semantic version from invalid value '{str}', should be formatted like 1.2, 1.2.30, or 1.2.30-beta (path: {path})."); return version; } diff --git a/src/SMAPI.Toolkit/Serialization/Converters/SimpleReadOnlyConverter.cs b/src/SMAPI.Toolkit/Serialization/Converters/SimpleReadOnlyConverter.cs index c923350c..1c59f5e7 100644 --- a/src/SMAPI.Toolkit/Serialization/Converters/SimpleReadOnlyConverter.cs +++ b/src/SMAPI.Toolkit/Serialization/Converters/SimpleReadOnlyConverter.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -27,21 +25,12 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters return objectType == typeof(T) || Nullable.GetUnderlyingType(objectType) == typeof(T); } - /// Writes the JSON representation of the object. - /// The JSON writer. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new InvalidOperationException("This converter does not write JSON."); - } - /// Reads the JSON representation of the object. /// The JSON reader. /// The object type. /// The object being read. /// The calling serializer. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { string path = reader.Path; switch (reader.TokenType) @@ -60,6 +49,15 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters } } + /// Writes the JSON representation of the object. + /// The JSON writer. + /// The value. + /// The calling serializer. + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) + { + throw new InvalidOperationException("This converter does not write JSON."); + } + /********* ** Protected methods diff --git a/src/SMAPI.Toolkit/Serialization/InternalExtensions.cs b/src/SMAPI.Toolkit/Serialization/InternalExtensions.cs index 1fce5f9d..78297035 100644 --- a/src/SMAPI.Toolkit/Serialization/InternalExtensions.cs +++ b/src/SMAPI.Toolkit/Serialization/InternalExtensions.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using Newtonsoft.Json.Linq; @@ -12,12 +10,12 @@ namespace StardewModdingAPI.Toolkit.Serialization /// The value type. /// The JSON object to search. /// The field name. - public static T ValueIgnoreCase(this JObject obj, string fieldName) + public static T? ValueIgnoreCase(this JObject obj, string fieldName) { - JToken token = obj.GetValue(fieldName, StringComparison.OrdinalIgnoreCase); + JToken? token = obj.GetValue(fieldName, StringComparison.OrdinalIgnoreCase); return token != null ? token.Value() - : default(T); + : default; } } } diff --git a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs index 9700e712..7d1804e5 100644 --- a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs +++ b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs @@ -1,7 +1,6 @@ -#nullable disable - using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -38,7 +37,7 @@ namespace StardewModdingAPI.Toolkit.Serialization /// Returns false if the file doesn't exist, else true. /// The given is empty or invalid. /// The file contains invalid JSON. - public bool ReadJsonFileIfExists(string fullPath, out TModel result) + public bool ReadJsonFileIfExists(string fullPath, [NotNullWhen(true)] out TModel? result) { // validate if (string.IsNullOrWhiteSpace(fullPath)) @@ -52,7 +51,7 @@ namespace StardewModdingAPI.Toolkit.Serialization } catch (Exception ex) when (ex is DirectoryNotFoundException or FileNotFoundException) { - result = default(TModel); + result = default; return false; } @@ -60,7 +59,7 @@ namespace StardewModdingAPI.Toolkit.Serialization try { result = this.Deserialize(json); - return true; + return result != null; } catch (Exception ex) { @@ -90,7 +89,7 @@ namespace StardewModdingAPI.Toolkit.Serialization throw new ArgumentException("The file path is empty or invalid.", nameof(fullPath)); // create directory if needed - string dir = Path.GetDirectoryName(fullPath); + string dir = Path.GetDirectoryName(fullPath)!; if (dir == null) throw new ArgumentException("The file path is invalid.", nameof(fullPath)); if (!Directory.Exists(dir)) @@ -108,7 +107,8 @@ namespace StardewModdingAPI.Toolkit.Serialization { try { - return JsonConvert.DeserializeObject(json, this.JsonSettings); + return JsonConvert.DeserializeObject(json, this.JsonSettings) + ?? throw new InvalidOperationException($"Couldn't deserialize model type '{typeof(TModel)}' from empty or null JSON."); } catch (JsonReaderException) { @@ -117,7 +117,8 @@ namespace StardewModdingAPI.Toolkit.Serialization { try { - return JsonConvert.DeserializeObject(json.Replace('“', '"').Replace('”', '"'), this.JsonSettings); + return JsonConvert.DeserializeObject(json.Replace('“', '"').Replace('”', '"'), this.JsonSettings) + ?? throw new InvalidOperationException($"Couldn't deserialize model type '{typeof(TModel)}' from empty or null JSON."); } catch { /* rethrow original error */ } } diff --git a/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs b/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs index 64725818..5d1b73b1 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs @@ -26,7 +26,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models /// The unique mod ID to require. /// The minimum required version (if any). /// Whether the dependency must be installed to use the mod. - public ManifestDependency(string uniqueID, string minimumVersion, bool required = true) + public ManifestDependency(string uniqueID, string? minimumVersion, bool required = true) : this( uniqueID: uniqueID, minimumVersion: !string.IsNullOrWhiteSpace(minimumVersion) diff --git a/src/SMAPI.Toolkit/Serialization/SParseException.cs b/src/SMAPI.Toolkit/Serialization/SParseException.cs index 1581e027..c2b3f68e 100644 --- a/src/SMAPI.Toolkit/Serialization/SParseException.cs +++ b/src/SMAPI.Toolkit/Serialization/SParseException.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; namespace StardewModdingAPI.Toolkit.Serialization @@ -13,7 +11,7 @@ namespace StardewModdingAPI.Toolkit.Serialization /// Construct an instance. /// The error message. /// The underlying exception, if any. - public SParseException(string message, Exception ex = null) + public SParseException(string message, Exception? ex = null) : base(message, ex) { } } } -- cgit From 238045ba9c5937f684cad3c55a8f9b9c2733e45f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 7 Apr 2022 22:19:48 -0400 Subject: reverse mod build package migration to .NET 5 (#837) The migrated package didn't work consistently in VIsual Studio, so this suppresses nullable annotations in .NET Standard instead. --- src/SMAPI.Toolkit/Serialization/JsonHelper.cs | 7 ++++++- src/SMAPI.Toolkit/Serialization/Models/Manifest.cs | 2 ++ src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs | 2 ++ src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src/SMAPI.Toolkit/Serialization') diff --git a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs index 7d1804e5..3c9308f2 100644 --- a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs +++ b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs @@ -37,7 +37,12 @@ namespace StardewModdingAPI.Toolkit.Serialization /// Returns false if the file doesn't exist, else true. /// The given is empty or invalid. /// The file contains invalid JSON. - public bool ReadJsonFileIfExists(string fullPath, [NotNullWhen(true)] out TModel? result) + public bool ReadJsonFileIfExists(string fullPath, +#if NET5_0_OR_GREATER + [NotNullWhen(true)] +#endif + out TModel? result + ) { // validate if (string.IsNullOrWhiteSpace(fullPath)) diff --git a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs index 3ab5edfb..01010602 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs @@ -115,7 +115,9 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models *********/ /// Normalize whitespace in a raw string. /// The input to strip. +#if NET5_0_OR_GREATER [return: NotNullIfNotNull("input")] +#endif private string? NormalizeWhitespace(string? input) { return input diff --git a/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs b/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs index dcdbcf74..f7dc8aa8 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/ManifestContentPackFor.cs @@ -33,7 +33,9 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models *********/ /// Normalize whitespace in a raw string. /// The input to strip. +#if NET5_0_OR_GREATER [return: NotNullIfNotNull("input")] +#endif private string? NormalizeWhitespace(string? input) { return input?.Trim(); diff --git a/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs b/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs index 5d1b73b1..fa254ea7 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/ManifestDependency.cs @@ -54,7 +54,9 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models *********/ /// Normalize whitespace in a raw string. /// The input to strip. +#if NET5_0_OR_GREATER [return: NotNullIfNotNull("input")] +#endif private string? NormalizeWhitespace(string? input) { return input?.Trim(); -- cgit From 761f2d952b073b78a06453768992b7b0fd4c6463 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 10 Apr 2022 21:34:18 -0400 Subject: enable nullable annotations in mod data models (#837) --- src/SMAPI.Toolkit/Serialization/Models/Manifest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI.Toolkit/Serialization') diff --git a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs index 01010602..da3ad608 100644 --- a/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs +++ b/src/SMAPI.Toolkit/Serialization/Models/Manifest.cs @@ -46,7 +46,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Models /// Any manifest fields which didn't match a valid field. [JsonExtensionData] - public IDictionary ExtraFields { get; set; } = new Dictionary(); + public IDictionary ExtraFields { get; } = new Dictionary(); /********* -- cgit