From fb8fefea00aacd603e68fbdbaecd27e4c451cc82 Mon Sep 17 00:00:00 2001
From: Jesse Plamondon-Willard <github@jplamondonw.com>
Date: Sun, 18 Jun 2017 22:11:48 -0400
Subject: show friendly error when parsing a manifest version fails (#308)

---
 .../Framework/Exceptions/SParseException.cs             | 17 +++++++++++++++++
 .../Framework/ModLoading/ModResolver.cs                 |  5 +++++
 .../Framework/Serialisation/ManifestFieldConverter.cs   | 12 ++++++++++--
 src/StardewModdingAPI/StardewModdingAPI.csproj          |  1 +
 4 files changed, 33 insertions(+), 2 deletions(-)
 create mode 100644 src/StardewModdingAPI/Framework/Exceptions/SParseException.cs

(limited to 'src')

diff --git a/src/StardewModdingAPI/Framework/Exceptions/SParseException.cs b/src/StardewModdingAPI/Framework/Exceptions/SParseException.cs
new file mode 100644
index 00000000..f7133ee7
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/Exceptions/SParseException.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace StardewModdingAPI.Framework.Exceptions
+{
+    /// <summary>A format exception which provides a user-facing error message.</summary>
+    internal class SParseException : FormatException
+    {
+        /*********
+        ** Public methods
+        *********/
+        /// <summary>Construct an instance.</summary>
+        /// <param name="message">The error message.</param>
+        /// <param name="ex">The underlying exception, if any.</param>
+        public SParseException(string message, Exception ex = null)
+            : base(message, ex) { }
+    }
+}
diff --git a/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs b/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs
index dc140483..045b175c 100644
--- a/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs
+++ b/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using StardewModdingAPI.Framework.Exceptions;
 using StardewModdingAPI.Framework.Models;
 using StardewModdingAPI.Framework.Serialisation;
 
@@ -45,6 +46,10 @@ namespace StardewModdingAPI.Framework.ModLoading
                     else if (string.IsNullOrWhiteSpace(manifest.EntryDll))
                         error = "its manifest doesn't set an entry DLL.";
                 }
+                catch (SParseException ex)
+                {
+                    error = $"parsing its manifest failed: {ex.Message}";
+                }
                 catch (Exception ex)
                 {
                     error = $"parsing its manifest failed:\n{ex.GetLogSummary()}";
diff --git a/src/StardewModdingAPI/Framework/Serialisation/ManifestFieldConverter.cs b/src/StardewModdingAPI/Framework/Serialisation/ManifestFieldConverter.cs
index 7a59f134..e6d62d50 100644
--- a/src/StardewModdingAPI/Framework/Serialisation/ManifestFieldConverter.cs
+++ b/src/StardewModdingAPI/Framework/Serialisation/ManifestFieldConverter.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
+using StardewModdingAPI.Framework.Exceptions;
 using StardewModdingAPI.Framework.Models;
 
 namespace StardewModdingAPI.Framework.Serialisation
@@ -50,10 +51,17 @@ namespace StardewModdingAPI.Framework.Serialisation
                         }
 
                     case JTokenType.String:
-                        return new SemanticVersion(token.Value<string>());
+                        {
+                            string str = token.Value<string>();
+                            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.");
+                            return version;
+                        }
 
                     default:
-                        throw new FormatException($"Can't parse {token.Type} token as a semantic version, must be an object or string.");
+                        throw new SParseException($"Can't parse semantic version from {token.Type}, must be an object or string.");
                 }
             }
 
diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj
index 465a5ea7..77d3b12b 100644
--- a/src/StardewModdingAPI/StardewModdingAPI.csproj
+++ b/src/StardewModdingAPI/StardewModdingAPI.csproj
@@ -151,6 +151,7 @@
     <Compile Include="Framework\Reflection\PrivateProperty.cs" />
     <Compile Include="Framework\RequestExitDelegate.cs" />
     <Compile Include="Framework\SContentManager.cs" />
+    <Compile Include="Framework\Exceptions\SParseException.cs" />
     <Compile Include="Framework\Serialisation\JsonHelper.cs" />
     <Compile Include="Framework\Serialisation\SelectiveStringEnumConverter.cs" />
     <Compile Include="Framework\Serialisation\ManifestFieldConverter.cs" />
-- 
cgit