Преглед на файлове

Improve exception handling slightly

Equbuxu преди 2 години
родител
ревизия
4f7a66f082

+ 4 - 2
src/PixiEditor/Exceptions/CorruptedFileException.cs

@@ -1,7 +1,9 @@
-namespace PixiEditor.Exceptions;
+using System.IO;
+
+namespace PixiEditor.Exceptions;
 
 [Serializable]
-internal class CorruptedFileException : Exception
+internal class CorruptedFileException : RecoverableException
 {
     public CorruptedFileException()
         : base("The file you've chosen might be corrupted.")

+ 21 - 0
src/PixiEditor/Exceptions/InvalidFileFormatException.cs

@@ -0,0 +1,21 @@
+using System.Runtime.Serialization;
+
+namespace PixiEditor.Exceptions;
+
+internal class InvalidFileFormatException : RecoverableException
+{
+    public string FilePath { get; set; }
+
+    public InvalidFileFormatException() { }
+
+    public InvalidFileFormatException(string message) : base(message) { }
+
+    public InvalidFileFormatException(string message, string filePath) : base(message)
+    {
+        FilePath = filePath;
+    }
+
+    public InvalidFileFormatException(string message, Exception innerException) : base(message, innerException) { }
+
+    protected InvalidFileFormatException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+}

+ 21 - 0
src/PixiEditor/Exceptions/MissingFileException.cs

@@ -0,0 +1,21 @@
+using System.Runtime.Serialization;
+
+namespace PixiEditor.Exceptions;
+
+internal class MissingFileException : RecoverableException
+{
+    public string FilePath { get; set; }
+
+    public MissingFileException() { }
+
+    public MissingFileException(string message) : base(message) { }
+
+    public MissingFileException(string message, string filePath) : base(message)
+    {
+        FilePath = filePath;
+    }
+
+    public MissingFileException(string message, Exception innerException) : base(message, innerException) { }
+
+    protected MissingFileException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+}

+ 14 - 0
src/PixiEditor/Exceptions/RecoverableException.cs

@@ -0,0 +1,14 @@
+using System.Runtime.Serialization;
+
+namespace PixiEditor.Exceptions;
+
+public class RecoverableException : Exception
+{
+    public RecoverableException() { }
+
+    public RecoverableException(string message) : base(message) { }
+
+    public RecoverableException(string message, Exception innerException) : base(message, innerException) { }
+
+    protected RecoverableException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+}

+ 25 - 6
src/PixiEditor/Models/Commands/Templates/Providers/Parsers/AsepriteKeysParser.cs

@@ -1,6 +1,7 @@
 using System.IO;
 using System.Text;
 using System.Xml;
+using PixiEditor.Exceptions;
 
 namespace PixiEditor.Models.Commands.Templates.Parsers;
 
@@ -30,12 +31,12 @@ public class AsepriteKeysParser : KeysParser
     {
         if (!File.Exists(path))
         {
-            throw new FileNotFoundException("File not found", path);
+            throw new MissingFileException("File not found", path);
         }
 
         if (Path.GetExtension(path) != ".aseprite-keys")
         {
-            throw new ArgumentException("File is not aseprite-keys file", nameof(path));
+            throw new InvalidFileFormatException("File is not aseprite-keys file", path);
         }
         
         return LoadAndParse(path, applyDefaults);
@@ -44,15 +45,33 @@ public class AsepriteKeysParser : KeysParser
     private ShortcutsTemplate LoadAndParse(string path, bool applyDefaults)
     {
         XmlDocument doc = new XmlDocument();
-        doc.Load(path);
+
+        try
+        {
+            doc.Load(path);
+        }
+        catch (Exception e) when (e is DirectoryNotFoundException or FileNotFoundException or PathTooLongException)
+        {
+            throw new MissingFileException("File not found", e);
+        }
+        catch (Exception e)
+        {
+            throw new RecoverableException("Error while reading the file", e);
+        }
         
         List<KeyDefinition> keyDefinitions = new List<KeyDefinition>(); // DefaultShortcut is actually mapped shortcut.
 
         LoadCommands(doc, keyDefinitions, applyDefaults);
         LoadTools(doc, keyDefinitions, applyDefaults);
-        
-        ShortcutsTemplate template = ShortcutsTemplate.FromKeyDefinitions(keyDefinitions);
-        return template;
+
+        try
+        {
+            return ShortcutsTemplate.FromKeyDefinitions(keyDefinitions);
+        }
+        catch (Exception e)
+        {
+            throw new InvalidFileFormatException("The file contains an invalid shortcut", e);
+        }
     }
 
     private void LoadCommands(XmlDocument document, List<KeyDefinition> keyDefinitions, bool applyDefaults)

+ 2 - 1
src/PixiEditor/Models/DataHolders/RecentlyOpenedDocument.cs

@@ -9,6 +9,7 @@ using PixiEditor.Helpers;
 using PixiEditor.Models.IO;
 using PixiEditor.Parser;
 using PixiEditor.Parser.Skia;
+using PixiEditor.Exceptions;
 
 namespace PixiEditor.Models.DataHolders;
 
@@ -126,7 +127,7 @@ internal class RecentlyOpenedDocument : NotifyableObject
             {
                 bitmap = Importer.ImportWriteableBitmap(FilePath);
             }
-            catch
+            catch (RecoverableException)
             {
                 corrupt = true;
                 return null;

+ 6 - 10
src/PixiEditor/Models/IO/Importer.cs

@@ -59,6 +59,10 @@ internal class Importer : NotifyableObject
         {
             throw new CorruptedFileException("The file appears to be corrupted");
         }
+        catch (Exception e)
+        {
+            throw new RecoverableException("Error while importing the bitmap", e);
+        }
     }
 
     public static DocumentViewModel ImportDocument(string path)
@@ -111,17 +115,9 @@ internal class Importer : NotifyableObject
     {
         if (!IsSupportedFile(path))
         {
-            throw new ArgumentException($"The file type '{Path.GetExtension(path)}' is not supported");
-        }
-        
-        try
-        {
-            return Path.GetExtension(path) != ".pixi" ? ImportWriteableBitmap(path) : PixiParser.Deserialize(path).ToDocument().PreviewBitmap;
-        }
-        catch (InvalidFileException)
-        {
-            throw new CorruptedFileException();
+            throw new InvalidFileFormatException($"The file type '{Path.GetExtension(path)}' is not supported");
         }
+        return Path.GetExtension(path) != ".pixi" ? ImportWriteableBitmap(path) : PixiParser.Deserialize(path).ToDocument().PreviewBitmap;
     }
 
     public static bool IsSupportedFile(string path)

+ 4 - 2
src/PixiEditor/Models/IO/JascPalFile/JascFileException.cs

@@ -1,6 +1,8 @@
-namespace PixiEditor.Models.IO.JascPalFile;
+using PixiEditor.Exceptions;
 
-internal class JascFileException : Exception
+namespace PixiEditor.Models.IO.JascPalFile;
+
+internal class JascFileException : RecoverableException
 {
     public JascFileException(string message) : base(message)
     {

+ 3 - 6
src/PixiEditor/ViewModels/ImportFilePopupViewModel.cs

@@ -3,6 +3,7 @@ using PixiEditor.Helpers;
 using PixiEditor.Models.IO;
 using System;
 using System.IO;
+using System.Runtime.InteropServices;
 using System.Windows;
 using System.Windows.Media.Imaging;
 
@@ -79,11 +80,7 @@ internal class ImportFilePopupViewModel : ViewModelBase
                 ImportHeight = bitmap.PixelHeight;
                 ImportWidth = bitmap.PixelWidth;
             }
-            catch (NotSupportedException)
-            {
-                throw new CorruptedFileException();
-            }
-            catch (FileFormatException)
+            catch (Exception e) when (e is NotSupportedException or FileFormatException or COMException)
             {
                 throw new CorruptedFileException();
             }
@@ -106,4 +103,4 @@ internal class ImportFilePopupViewModel : ViewModelBase
         ((Window)parameter).DialogResult = true;
         CloseButton(parameter);
     }
-}
+}

+ 21 - 13
src/PixiEditor/ViewModels/SettingsWindowViewModel.cs

@@ -11,6 +11,7 @@ using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Commands.Templates;
 using PixiEditor.Models.UserPreferences;
 using PixiEditor.Views.Dialogs;
+using PixiEditor.Exceptions;
 
 namespace PixiEditor.ViewModels;
 
@@ -100,18 +101,8 @@ internal class SettingsWindowViewModel : ViewModelBase
         if (dialog.ShowDialog().GetValueOrDefault())
         {
             List<Shortcut> shortcuts = new List<Shortcut>();
-            try
-            {
-                if (!TryImport(dialog, ref shortcuts))
-                {
-                    return;
-                }
-            }
-            catch (Exception e)
-            {
-                NoticeDialog.Show("Shortcuts file was not in a valid format", "Invalid file");
+            if (!TryImport(dialog, ref shortcuts))
                 return;
-            }
             
             CommandController.Current.ResetShortcuts();
             CommandController.Current.Import(shortcuts, false);
@@ -126,7 +117,16 @@ internal class SettingsWindowViewModel : ViewModelBase
     {
         if (dialog.FileName.EndsWith(".pixisc") || dialog.FileName.EndsWith(".json"))
         {
-            shortcuts = ShortcutFile.LoadTemplate(dialog.FileName)?.Shortcuts.ToList();
+            try
+            {
+                shortcuts = ShortcutFile.LoadTemplate(dialog.FileName)?.Shortcuts.ToList();
+            }
+            catch (Exception)
+            {
+                NoticeDialog.Show(title: "Error", message: "Error while reading the file");
+                return false;
+            }
+
             if (shortcuts is null)
             {
                 NoticeDialog.Show("Shortcuts file was not in a valid format", "Invalid file");
@@ -143,7 +143,15 @@ internal class SettingsWindowViewModel : ViewModelBase
                 return false;
             }
 
-            shortcuts = provider.KeysParser.Parse(dialog.FileName, false)?.Shortcuts.ToList();
+            try
+            {
+                shortcuts = provider.KeysParser.Parse(dialog.FileName, false)?.Shortcuts.ToList();
+            }
+            catch (RecoverableException e)
+            {
+                NoticeDialog.Show(title: "Error", message: e.Message);
+                return false;
+            }
         }
 
         return true;

+ 3 - 2
src/PixiEditor/ViewModels/SubViewModels/Main/LayersViewModel.cs

@@ -6,6 +6,7 @@ using System.Windows.Media.Imaging;
 using Microsoft.Win32;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.DrawingApi.Core.Numerics;
+using PixiEditor.Exceptions;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Dialogs;
@@ -357,9 +358,9 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
         {
             bitmap = Importer.ImportWriteableBitmap(path);
         }
-        catch (Exception e)
+        catch (RecoverableException e)
         {
-            NoticeDialog.Show("Error while importing the image", "Error");
+            NoticeDialog.Show(title: "Error", message: e.Message);
             return;
         }
 

+ 3 - 2
src/PixiEditor/Views/Dialogs/ImportShortcutTemplatePopup.xaml.cs

@@ -1,5 +1,6 @@
 using System.Windows;
 using System.Windows.Input;
+using PixiEditor.Exceptions;
 using PixiEditor.Models.Commands;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Commands.Templates;
@@ -50,9 +51,9 @@ internal partial class ImportShortcutTemplatePopup : Window
         {
             CommandController.Current.Import(defaults.GetInstalledShortcuts().Shortcuts);
         }
-        catch
+        catch (RecoverableException e)
         {
-            NoticeDialog.Show($"The file was not in a correct format", "Error");
+            NoticeDialog.Show(title: "Error", message: e.Message);
             return;
         }