From 0b48c1748b354458059c7607415288de072b01e9 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 12 Apr 2022 19:15:39 -0400 Subject: enable nullable annotations in the web project & related code (#837) --- .../Framework/Clients/Wiki/ChangeDescriptor.cs | 12 +- .../Framework/Clients/Wiki/WikiClient.cs | 159 +++++++++++---------- .../Clients/Wiki/WikiCompatibilityInfo.cs | 33 +++-- .../Clients/Wiki/WikiCompatibilityStatus.cs | 2 - .../Framework/Clients/Wiki/WikiModEntry.cs | 96 ++++++++++--- .../Framework/Clients/Wiki/WikiModList.cs | 23 ++- 6 files changed, 206 insertions(+), 119 deletions(-) (limited to 'src/SMAPI.Toolkit/Framework/Clients/Wiki') diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/ChangeDescriptor.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/ChangeDescriptor.cs index 910bf793..5978803e 100644 --- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/ChangeDescriptor.cs +++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/ChangeDescriptor.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -49,7 +47,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki /// Apply the change descriptors to a comma-delimited field. /// The raw field text. /// Returns the modified field. - public string ApplyToCopy(string rawField) + public string? ApplyToCopy(string? rawField) { // get list List values = !string.IsNullOrWhiteSpace(rawField) @@ -75,12 +73,12 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki { for (int i = values.Count - 1; i >= 0; i--) { - string value = this.FormatValue(values[i]?.Trim() ?? string.Empty); + string value = this.FormatValue(values[i].Trim()); if (this.Remove.Contains(value)) values.RemoveAt(i); - else if (this.Replace.TryGetValue(value, out string newValue)) + else if (this.Replace.TryGetValue(value, out string? newValue)) values[i] = newValue; } } @@ -88,7 +86,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki // add values if (this.Add.Any()) { - HashSet curValues = new HashSet(values.Select(p => p?.Trim() ?? string.Empty), StringComparer.OrdinalIgnoreCase); + HashSet curValues = new HashSet(values.Select(p => p.Trim()), StringComparer.OrdinalIgnoreCase); foreach (string add in this.Add) { if (!curValues.Contains(add)) @@ -121,7 +119,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki /// The raw change descriptor. /// The human-readable error message describing any invalid values that were ignored. /// Format a raw value into a normalized form if needed. - public static ChangeDescriptor Parse(string descriptor, out string[] errors, Func formatValue = null) + public static ChangeDescriptor Parse(string descriptor, out string[] errors, Func? formatValue = null) { // init formatValue ??= p => p; diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs index 86c3bd75..7f06d170 100644 --- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs +++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -53,8 +51,8 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki doc.LoadHtml(html); // fetch game versions - string stableVersion = doc.DocumentNode.SelectSingleNode("//div[@class='game-stable-version']")?.InnerText; - string betaVersion = doc.DocumentNode.SelectSingleNode("//div[@class='game-beta-version']")?.InnerText; + string? stableVersion = doc.DocumentNode.SelectSingleNode("//div[@class='game-stable-version']")?.InnerText; + string? betaVersion = doc.DocumentNode.SelectSingleNode("//div[@class='game-beta-version']")?.InnerText; if (betaVersion == stableVersion) betaVersion = null; @@ -65,7 +63,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki if (modNodes == null) throw new InvalidOperationException("Can't parse wiki compatibility list, no mod data overrides section found."); - foreach (var entry in this.ParseOverrideEntries(modNodes)) + foreach (WikiDataOverrideEntry entry in this.ParseOverrideEntries(modNodes)) { if (entry.Ids.Any() != true || !entry.HasChanges) continue; @@ -85,18 +83,17 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki } // build model - return new WikiModList - { - StableVersion = stableVersion, - BetaVersion = betaVersion, - Mods = mods - }; + return new WikiModList( + stableVersion: stableVersion, + betaVersion: betaVersion, + mods: mods + ); } /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. public void Dispose() { - this.Client?.Dispose(); + this.Client.Dispose(); } @@ -118,71 +115,68 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki int? nexusID = this.GetAttributeAsNullableInt(node, "data-nexus-id"); int? chucklefishID = this.GetAttributeAsNullableInt(node, "data-cf-id"); int? curseForgeID = this.GetAttributeAsNullableInt(node, "data-curseforge-id"); - string curseForgeKey = this.GetAttribute(node, "data-curseforge-key"); + string? curseForgeKey = this.GetAttribute(node, "data-curseforge-key"); int? modDropID = this.GetAttributeAsNullableInt(node, "data-moddrop-id"); - string githubRepo = this.GetAttribute(node, "data-github"); - string customSourceUrl = this.GetAttribute(node, "data-custom-source"); - string customUrl = this.GetAttribute(node, "data-url"); - string anchor = this.GetAttribute(node, "id"); - string contentPackFor = this.GetAttribute(node, "data-content-pack-for"); - string devNote = this.GetAttribute(node, "data-dev-note"); - string pullRequestUrl = this.GetAttribute(node, "data-pr"); + string? githubRepo = this.GetAttribute(node, "data-github"); + string? customSourceUrl = this.GetAttribute(node, "data-custom-source"); + string? customUrl = this.GetAttribute(node, "data-url"); + string? anchor = this.GetAttribute(node, "id"); + string? contentPackFor = this.GetAttribute(node, "data-content-pack-for"); + string? devNote = this.GetAttribute(node, "data-dev-note"); + string? pullRequestUrl = this.GetAttribute(node, "data-pr"); // parse stable compatibility - WikiCompatibilityInfo compatibility = new() - { - Status = this.GetAttributeAsEnum(node, "data-status") ?? WikiCompatibilityStatus.Ok, - BrokeIn = this.GetAttribute(node, "data-broke-in"), - UnofficialVersion = this.GetAttributeAsSemanticVersion(node, "data-unofficial-version"), - UnofficialUrl = this.GetAttribute(node, "data-unofficial-url"), - Summary = this.GetInnerHtml(node, "mod-summary")?.Trim() - }; + WikiCompatibilityInfo compatibility = new( + status: this.GetAttributeAsEnum(node, "data-status") ?? WikiCompatibilityStatus.Ok, + brokeIn: this.GetAttribute(node, "data-broke-in"), + unofficialVersion: this.GetAttributeAsSemanticVersion(node, "data-unofficial-version"), + unofficialUrl: this.GetAttribute(node, "data-unofficial-url"), + summary: this.GetInnerHtml(node, "mod-summary")?.Trim() + ); // parse beta compatibility - WikiCompatibilityInfo betaCompatibility = null; + WikiCompatibilityInfo? betaCompatibility = null; { WikiCompatibilityStatus? betaStatus = this.GetAttributeAsEnum(node, "data-beta-status"); if (betaStatus.HasValue) { - betaCompatibility = new WikiCompatibilityInfo - { - Status = betaStatus.Value, - BrokeIn = this.GetAttribute(node, "data-beta-broke-in"), - UnofficialVersion = this.GetAttributeAsSemanticVersion(node, "data-beta-unofficial-version"), - UnofficialUrl = this.GetAttribute(node, "data-beta-unofficial-url"), - Summary = this.GetInnerHtml(node, "mod-beta-summary") - }; + betaCompatibility = new WikiCompatibilityInfo( + status: betaStatus.Value, + brokeIn: this.GetAttribute(node, "data-beta-broke-in"), + unofficialVersion: this.GetAttributeAsSemanticVersion(node, "data-beta-unofficial-version"), + unofficialUrl: this.GetAttribute(node, "data-beta-unofficial-url"), + summary: this.GetInnerHtml(node, "mod-beta-summary") + ); } } // find data overrides - WikiDataOverrideEntry overrides = ids + WikiDataOverrideEntry? overrides = ids .Select(id => overridesById.TryGetValue(id, out overrides) ? overrides : null) .FirstOrDefault(p => p != null); // yield model - yield return new WikiModEntry - { - ID = ids, - Name = names, - Author = authors, - NexusID = nexusID, - ChucklefishID = chucklefishID, - CurseForgeID = curseForgeID, - CurseForgeKey = curseForgeKey, - ModDropID = modDropID, - GitHubRepo = githubRepo, - CustomSourceUrl = customSourceUrl, - CustomUrl = customUrl, - ContentPackFor = contentPackFor, - Compatibility = compatibility, - BetaCompatibility = betaCompatibility, - Warnings = warnings, - PullRequestUrl = pullRequestUrl, - DevNote = devNote, - Overrides = overrides, - Anchor = anchor - }; + yield return new WikiModEntry( + id: ids, + name: names, + author: authors, + nexusId: nexusID, + chucklefishId: chucklefishID, + curseForgeId: curseForgeID, + curseForgeKey: curseForgeKey, + modDropId: modDropID, + githubRepo: githubRepo, + customSourceUrl: customSourceUrl, + customUrl: customUrl, + contentPackFor: contentPackFor, + compatibility: compatibility, + betaCompatibility: betaCompatibility, + warnings: warnings, + pullRequestUrl: pullRequestUrl, + devNote: devNote, + overrides: overrides, + anchor: anchor + ); } } @@ -196,10 +190,10 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki { Ids = this.GetAttributeAsCsv(node, "data-id"), ChangeLocalVersions = this.GetAttributeAsChangeDescriptor(node, "data-local-version", - raw => SemanticVersion.TryParse(raw, out ISemanticVersion version) ? version.ToString() : raw + raw => SemanticVersion.TryParse(raw, out ISemanticVersion? version) ? version.ToString() : raw ), ChangeRemoteVersions = this.GetAttributeAsChangeDescriptor(node, "data-remote-version", - raw => SemanticVersion.TryParse(raw, out ISemanticVersion version) ? version.ToString() : raw + raw => SemanticVersion.TryParse(raw, out ISemanticVersion? version) ? version.ToString() : raw ), ChangeUpdateKeys = this.GetAttributeAsChangeDescriptor(node, "data-update-keys", @@ -212,7 +206,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki /// Get an attribute value. /// The element whose attributes to read. /// The attribute name. - private string GetAttribute(HtmlNode element, string name) + private string? GetAttribute(HtmlNode element, string name) { string value = element.GetAttributeValue(name, null); if (string.IsNullOrWhiteSpace(value)) @@ -225,9 +219,9 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki /// The element whose attributes to read. /// The attribute name. /// Format an raw entry value when applying changes. - private ChangeDescriptor GetAttributeAsChangeDescriptor(HtmlNode element, string name, Func formatValue) + private ChangeDescriptor? GetAttributeAsChangeDescriptor(HtmlNode element, string name, Func formatValue) { - string raw = this.GetAttribute(element, name); + string? raw = this.GetAttribute(element, name); return raw != null ? ChangeDescriptor.Parse(raw, out _, formatValue) : null; @@ -238,7 +232,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki /// The attribute name. private string[] GetAttributeAsCsv(HtmlNode element, string name) { - string raw = this.GetAttribute(element, name); + string? raw = this.GetAttribute(element, name); return !string.IsNullOrWhiteSpace(raw) ? raw.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim()).ToArray() : Array.Empty(); @@ -250,7 +244,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki /// The attribute name. private TEnum? GetAttributeAsEnum(HtmlNode element, string name) where TEnum : struct { - string raw = this.GetAttribute(element, name); + string? raw = this.GetAttribute(element, name); if (raw == null) return null; if (!Enum.TryParse(raw, true, out TEnum value) && Enum.IsDefined(typeof(TEnum), value)) @@ -261,10 +255,10 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki /// Get an attribute value and parse it as a semantic version. /// The element whose attributes to read. /// The attribute name. - private ISemanticVersion GetAttributeAsSemanticVersion(HtmlNode element, string name) + private ISemanticVersion? GetAttributeAsSemanticVersion(HtmlNode element, string name) { - string raw = this.GetAttribute(element, name); - return SemanticVersion.TryParse(raw, out ISemanticVersion version) + string? raw = this.GetAttribute(element, name); + return SemanticVersion.TryParse(raw, out ISemanticVersion? version) ? version : null; } @@ -274,7 +268,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki /// The attribute name. private int? GetAttributeAsNullableInt(HtmlNode element, string name) { - string raw = this.GetAttribute(element, name); + string? raw = this.GetAttribute(element, name); if (raw != null && int.TryParse(raw, out int value)) return value; return null; @@ -283,7 +277,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki /// Get the text of an element with the given class name. /// The metadata container. /// The field name. - private string GetInnerHtml(HtmlNode container, string className) + private string? GetInnerHtml(HtmlNode container, string className) { return container.Descendants().FirstOrDefault(p => p.HasClass(className))?.InnerHtml; } @@ -293,8 +287,22 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")] private class ResponseModel { + /********* + ** Accessors + *********/ /// The parse API results. - public ResponseParseModel Parse { get; set; } + public ResponseParseModel Parse { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The parse API results. + public ResponseModel(ResponseParseModel parse) + { + this.Parse = parse; + } } /// The inner response model for the MediaWiki parse API. @@ -303,8 +311,11 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")] private class ResponseParseModel { + /********* + ** Accessors + *********/ /// The parsed text. - public IDictionary Text { get; set; } + public IDictionary Text { get; } = new Dictionary(); } } } diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs index 30e76d04..71c90d0c 100644 --- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs +++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs @@ -1,5 +1,3 @@ -#nullable disable - namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki { /// Compatibility info for a mod. @@ -9,18 +7,37 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki ** Accessors *********/ /// The compatibility status. - public WikiCompatibilityStatus Status { get; set; } + public WikiCompatibilityStatus Status { get; } /// The human-readable summary of the compatibility status or workaround, without HTML formatting. - public string Summary { get; set; } + public string? Summary { get; } - /// The game or SMAPI version which broke this mod (if applicable). - public string BrokeIn { get; set; } + /// The game or SMAPI version which broke this mod, if applicable. + public string? BrokeIn { get; } /// The version of the latest unofficial update, if applicable. - public ISemanticVersion UnofficialVersion { get; set; } + public ISemanticVersion? UnofficialVersion { get; } /// The URL to the latest unofficial update, if applicable. - public string UnofficialUrl { get; set; } + public string? UnofficialUrl { get; } + + + /********* + ** Accessors + *********/ + /// Construct an instance. + /// The compatibility status. + /// The human-readable summary of the compatibility status or workaround, without HTML formatting. + /// The game or SMAPI version which broke this mod, if applicable. + /// The version of the latest unofficial update, if applicable. + /// The URL to the latest unofficial update, if applicable. + public WikiCompatibilityInfo(WikiCompatibilityStatus status, string? summary, string? brokeIn, ISemanticVersion? unofficialVersion, string? unofficialUrl) + { + this.Status = status; + this.Summary = summary; + this.BrokeIn = brokeIn; + this.UnofficialVersion = unofficialVersion; + this.UnofficialUrl = unofficialUrl; + } } } diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityStatus.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityStatus.cs index 2c222b71..5cdf489f 100644 --- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityStatus.cs +++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityStatus.cs @@ -1,5 +1,3 @@ -#nullable disable - namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki { /// The compatibility status for a mod. diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs index 91943ff9..fc50125f 100644 --- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs +++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs @@ -1,4 +1,4 @@ -#nullable disable +using System.Diagnostics.CodeAnalysis; namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki { @@ -8,64 +8,114 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki /********* ** Accessors *********/ - /// The mod's unique ID. If the mod has alternate/old IDs, they're listed in latest to newest order. - public string[] ID { get; set; } + /// The mod's unique ID. If the mod has alternate/old IDs, they're listed in latest to oldest order. + public string[] ID { get; } /// The mod's display name. If the mod has multiple names, the first one is the most canonical name. - public string[] Name { get; set; } + public string[] Name { get; } - /// The mod's author name. If the author has multiple names, the first one is the most canonical name. - public string[] Author { get; set; } + /// The mod's author name. If the author has multiple names, the first one is the most canonical name. + public string[] Author { get; } /// The mod ID on Nexus. - public int? NexusID { get; set; } + public int? NexusID { get; } /// The mod ID in the Chucklefish mod repo. - public int? ChucklefishID { get; set; } + public int? ChucklefishID { get; } /// The mod ID in the CurseForge mod repo. - public int? CurseForgeID { get; set; } + public int? CurseForgeID { get; } /// The mod key in the CurseForge mod repo (used in mod page URLs). - public string CurseForgeKey { get; set; } + public string? CurseForgeKey { get; } /// The mod ID in the ModDrop mod repo. - public int? ModDropID { get; set; } + public int? ModDropID { get; } /// The GitHub repository in the form 'owner/repo'. - public string GitHubRepo { get; set; } + public string? GitHubRepo { get; } /// The URL to a non-GitHub source repo. - public string CustomSourceUrl { get; set; } + public string? CustomSourceUrl { get; } /// The custom mod page URL (if applicable). - public string CustomUrl { get; set; } + public string? CustomUrl { get; } /// The name of the mod which loads this content pack, if applicable. - public string ContentPackFor { get; set; } + public string? ContentPackFor { get; } /// The mod's compatibility with the latest stable version of the game. - public WikiCompatibilityInfo Compatibility { get; set; } + public WikiCompatibilityInfo Compatibility { get; } /// The mod's compatibility with the latest beta version of the game (if any). - public WikiCompatibilityInfo BetaCompatibility { get; set; } + public WikiCompatibilityInfo? BetaCompatibility { get; } /// Whether a Stardew Valley or SMAPI beta which affects mod compatibility is in progress. If this is true, should be used for beta versions of SMAPI instead of . +#if NET5_0_OR_GREATER + [MemberNotNullWhen(true, nameof(WikiModEntry.BetaCompatibility))] +#endif public bool HasBetaInfo => this.BetaCompatibility != null; /// The human-readable warnings for players about this mod. - public string[] Warnings { get; set; } + public string[] Warnings { get; } /// The URL of the pull request which submits changes for an unofficial update to the author, if any. - public string PullRequestUrl { get; set; } + public string? PullRequestUrl { get; } - /// Special notes intended for developers who maintain unofficial updates or submit pull requests. - public string DevNote { get; set; } + /// Special notes intended for developers who maintain unofficial updates or submit pull requests. + public string? DevNote { get; } /// The data overrides to apply to the mod's manifest or remote mod page data, if any. - public WikiDataOverrideEntry Overrides { get; set; } + public WikiDataOverrideEntry? Overrides { get; } /// The link anchor for the mod entry in the wiki compatibility list. - public string Anchor { get; set; } + public string? Anchor { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The mod's unique ID. If the mod has alternate/old IDs, they're listed in latest to oldest order. + /// The mod's display name. If the mod has multiple names, the first one is the most canonical name. + /// The mod's author name. If the author has multiple names, the first one is the most canonical name. + /// The mod ID on Nexus. + /// The mod ID in the Chucklefish mod repo. + /// The mod ID in the CurseForge mod repo. + /// The mod ID in the CurseForge mod repo. + /// The mod ID in the ModDrop mod repo. + /// The GitHub repository in the form 'owner/repo'. + /// The URL to a non-GitHub source repo. + /// The custom mod page URL (if applicable). + /// The name of the mod which loads this content pack, if applicable. + /// The mod's compatibility with the latest stable version of the game. + /// The mod's compatibility with the latest beta version of the game (if any). + /// The human-readable warnings for players about this mod. + /// The URL of the pull request which submits changes for an unofficial update to the author, if any. + /// Special notes intended for developers who maintain unofficial updates or submit pull requests. + /// The data overrides to apply to the mod's manifest or remote mod page data, if any. + /// The link anchor for the mod entry in the wiki compatibility list. + public WikiModEntry(string[] id, string[] name, string[] author, int? nexusId, int? chucklefishId, int? curseForgeId, string? curseForgeKey, int? modDropId, string? githubRepo, string? customSourceUrl, string? customUrl, string? contentPackFor, WikiCompatibilityInfo compatibility, WikiCompatibilityInfo? betaCompatibility, string[] warnings, string? pullRequestUrl, string? devNote, WikiDataOverrideEntry? overrides, string? anchor) + { + this.ID = id; + this.Name = name; + this.Author = author; + this.NexusID = nexusId; + this.ChucklefishID = chucklefishId; + this.CurseForgeID = curseForgeId; + this.CurseForgeKey = curseForgeKey; + this.ModDropID = modDropId; + this.GitHubRepo = githubRepo; + this.CustomSourceUrl = customSourceUrl; + this.CustomUrl = customUrl; + this.ContentPackFor = contentPackFor; + this.Compatibility = compatibility; + this.BetaCompatibility = betaCompatibility; + this.Warnings = warnings; + this.PullRequestUrl = pullRequestUrl; + this.DevNote = devNote; + this.Overrides = overrides; + this.Anchor = anchor; + } } } diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModList.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModList.cs index 1787197a..24548078 100644 --- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModList.cs +++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModList.cs @@ -1,5 +1,3 @@ -#nullable disable - namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki { /// Metadata from the wiki's mod compatibility list. @@ -9,12 +7,27 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki ** Accessors *********/ /// The stable game version. - public string StableVersion { get; set; } + public string? StableVersion { get; } /// The beta game version (if any). - public string BetaVersion { get; set; } + public string? BetaVersion { get; } /// The mods on the wiki. - public WikiModEntry[] Mods { get; set; } + public WikiModEntry[] Mods { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The stable game version. + /// The beta game version (if any). + /// The mods on the wiki. + public WikiModList(string? stableVersion, string? betaVersion, WikiModEntry[] mods) + { + this.StableVersion = stableVersion; + this.BetaVersion = betaVersion; + this.Mods = mods; + } } } -- cgit