fix version parsing issues in new toolkit code (#532)

This commit is contained in:
Jesse Plamondon-Willard 2018-06-05 23:03:26 -04:00
parent 3c06a496a0
commit 6eba10948b
7 changed files with 48 additions and 46 deletions

View File

@ -3,7 +3,6 @@ using System.Diagnostics.CodeAnalysis;
using Newtonsoft.Json; using Newtonsoft.Json;
using NUnit.Framework; using NUnit.Framework;
using StardewModdingAPI.Framework; using StardewModdingAPI.Framework;
using StardewModdingAPI.Toolkit.Serialisation.Models;
namespace StardewModdingAPI.Tests.Utilities namespace StardewModdingAPI.Tests.Utilities
{ {
@ -272,22 +271,6 @@ namespace StardewModdingAPI.Tests.Utilities
Assert.IsTrue(version.IsOlderThan(new SemanticVersion("1.2.30")), "The game version should be considered older than the later semantic versions."); Assert.IsTrue(version.IsOlderThan(new SemanticVersion("1.2.30")), "The game version should be considered older than the later semantic versions.");
} }
/****
** LegacyManifestVersion
****/
[Test(Description = "Assert that the LegacyManifestVersion subclass correctly parses legacy manifest versions.")]
[TestCase(1, 0, 0, null, ExpectedResult = "1.0")]
[TestCase(3000, 4000, 5000, null, ExpectedResult = "3000.4000.5000")]
[TestCase(1, 2, 3, "", ExpectedResult = "1.2.3")]
[TestCase(1, 2, 3, " ", ExpectedResult = "1.2.3")]
[TestCase(1, 2, 3, "0", ExpectedResult = "1.2.3")] // special case: drop '0' tag for legacy manifest versions
[TestCase(1, 2, 3, "some-tag.4", ExpectedResult = "1.2.3-some-tag.4")]
[TestCase(1, 2, 3, "some-tag.4 ", ExpectedResult = "1.2.3-some-tag.4")]
public string LegacyManifestVersion(int major, int minor, int patch, string tag)
{
return new LegacyManifestVersion(major, minor, patch, tag).ToString();
}
/********* /*********
** Private methods ** Private methods

View File

@ -21,7 +21,7 @@ namespace StardewModdingAPI.Framework.Models
public ManifestContentPackFor(Toolkit.Serialisation.Models.ManifestContentPackFor contentPackFor) public ManifestContentPackFor(Toolkit.Serialisation.Models.ManifestContentPackFor contentPackFor)
{ {
this.UniqueID = contentPackFor.UniqueID; this.UniqueID = contentPackFor.UniqueID;
this.MinimumVersion = new SemanticVersion(contentPackFor.MinimumVersion); this.MinimumVersion = contentPackFor.MinimumVersion != null ? new SemanticVersion(contentPackFor.MinimumVersion) : null;
} }
/// <summary>Construct an instance.</summary> /// <summary>Construct an instance.</summary>

View File

@ -0,0 +1,40 @@
using Newtonsoft.Json.Linq;
using StardewModdingAPI.Toolkit.Serialisation;
using StardewModdingAPI.Toolkit.Serialisation.Converters;
namespace StardewModdingAPI.Framework.Serialisation
{
/// <summary>Handles deserialisation of <see cref="ISemanticVersion"/>.</summary>
internal class SemanticVersionConverter : SimpleReadOnlyConverter<ISemanticVersion>
{
/*********
** Protected methods
*********/
/// <summary>Read a JSON object.</summary>
/// <param name="obj">The JSON object to read.</param>
/// <param name="path">The path to the current JSON node.</param>
protected override ISemanticVersion ReadObject(JObject obj, string path)
{
int major = obj.ValueIgnoreCase<int>("MajorVersion");
int minor = obj.ValueIgnoreCase<int>("MinorVersion");
int patch = obj.ValueIgnoreCase<int>("PatchVersion");
string build = obj.ValueIgnoreCase<string>("Build");
if (build == "0")
build = null; // '0' from incorrect examples in old SMAPI documentation
return new SemanticVersion(major, minor, patch, build);
}
/// <summary>Read a JSON string.</summary>
/// <param name="str">The JSON string value.</param>
/// <param name="path">The path to the current JSON node.</param>
protected override ISemanticVersion ReadString(string str, string path)
{
if (string.IsNullOrWhiteSpace(str))
return null;
if (!SemanticVersion.TryParse(str, 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;
}
}
}

View File

@ -159,7 +159,8 @@ namespace StardewModdingAPI
new StringEnumConverter<SButton>(), new StringEnumConverter<SButton>(),
new ColorConverter(), new ColorConverter(),
new PointConverter(), new PointConverter(),
new RectangleConverter() new RectangleConverter(),
new Framework.Serialisation.SemanticVersionConverter()
}; };
foreach (JsonConverter converter in converters) foreach (JsonConverter converter in converters)
this.JsonHelper.JsonSettings.Converters.Add(converter); this.JsonHelper.JsonSettings.Converters.Add(converter);

View File

@ -121,6 +121,7 @@
<Compile Include="Framework\Models\ManifestContentPackFor.cs" /> <Compile Include="Framework\Models\ManifestContentPackFor.cs" />
<Compile Include="Framework\Models\ManifestDependency.cs" /> <Compile Include="Framework\Models\ManifestDependency.cs" />
<Compile Include="Framework\ModHelpers\InputHelper.cs" /> <Compile Include="Framework\ModHelpers\InputHelper.cs" />
<Compile Include="Framework\Serialisation\SemanticVersionConverter.cs" />
<Compile Include="IInputHelper.cs" /> <Compile Include="IInputHelper.cs" />
<Compile Include="Framework\Input\SInputState.cs" /> <Compile Include="Framework\Input\SInputState.cs" />
<Compile Include="Framework\Input\InputStatus.cs" /> <Compile Include="Framework\Input\InputStatus.cs" />

View File

@ -18,7 +18,10 @@ namespace StardewModdingAPI.Toolkit.Serialisation.Converters
int minor = obj.ValueIgnoreCase<int>("MinorVersion"); int minor = obj.ValueIgnoreCase<int>("MinorVersion");
int patch = obj.ValueIgnoreCase<int>("PatchVersion"); int patch = obj.ValueIgnoreCase<int>("PatchVersion");
string build = obj.ValueIgnoreCase<string>("Build"); string build = obj.ValueIgnoreCase<string>("Build");
return new LegacyManifestVersion(major, minor, patch, build); if (build == "0")
build = null; // '0' from incorrect examples in old SMAPI documentation
return new SemanticVersion(major, minor, patch, build);
} }
/// <summary>Read a JSON string.</summary> /// <summary>Read a JSON string.</summary>

View File

@ -1,26 +0,0 @@
using Newtonsoft.Json;
namespace StardewModdingAPI.Toolkit.Serialisation.Models
{
/// <summary>An implementation of <see cref="ISemanticVersion"/> that hamdles the legacy <see cref="Manifest"/> version format.</summary>
public class LegacyManifestVersion : SemanticVersion
{
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="majorVersion">The major version incremented for major API changes.</param>
/// <param name="minorVersion">The minor version incremented for backwards-compatible changes.</param>
/// <param name="patchVersion">The patch version for backwards-compatible bug fixes.</param>
/// <param name="build">An optional build tag.</param>
[JsonConstructor]
public LegacyManifestVersion(int majorVersion, int minorVersion, int patchVersion, string build = null)
: base(
majorVersion,
minorVersion,
patchVersion,
build != "0" ? build : null // '0' from incorrect examples in old SMAPI documentation
)
{ }
}
}