Przeglądaj źródła

Merge pull request #2317 from AvaloniaUI/fixes/2316-selectorparser-null-type

Throw if selector class not found.
Steven Kirk 6 lat temu
rodzic
commit
d21901dcef

+ 14 - 0
src/Avalonia.Styling/Styling/Selectors.cs

@@ -28,6 +28,9 @@ namespace Avalonia.Styling
         /// <returns>The selector.</returns>
         public static Selector Class(this Selector previous, string name)
         {
+            Contract.Requires<ArgumentNullException>(name != null);
+            Contract.Requires<ArgumentException>(!string.IsNullOrWhiteSpace(name));
+
             var tac = previous as TypeNameAndClassSelector;
 
             if (tac != null)
@@ -59,6 +62,8 @@ namespace Avalonia.Styling
         /// <returns>The selector.</returns>
         public static Selector Is(this Selector previous, Type type)
         {
+            Contract.Requires<ArgumentNullException>(type != null);
+
             return TypeNameAndClassSelector.Is(previous, type);
         }
 
@@ -81,6 +86,9 @@ namespace Avalonia.Styling
         /// <returns>The selector.</returns>
         public static Selector Name(this Selector previous, string name)
         {
+            Contract.Requires<ArgumentNullException>(name != null);
+            Contract.Requires<ArgumentException>(!string.IsNullOrWhiteSpace(name));
+
             var tac = previous as TypeNameAndClassSelector;
 
             if (tac != null)
@@ -113,6 +121,8 @@ namespace Avalonia.Styling
         /// <returns>The selector.</returns>
         public static Selector OfType(this Selector previous, Type type)
         {
+            Contract.Requires<ArgumentNullException>(type != null);
+
             return TypeNameAndClassSelector.OfType(previous, type);
         }
 
@@ -137,6 +147,8 @@ namespace Avalonia.Styling
         /// <returns>The selector.</returns>
         public static Selector PropertyEquals<T>(this Selector previous, AvaloniaProperty<T> property, object value)
         {
+            Contract.Requires<ArgumentNullException>(property != null);
+
             return new PropertyEqualsSelector(previous, property, value);
         }
 
@@ -149,6 +161,8 @@ namespace Avalonia.Styling
         /// <returns>The selector.</returns>
         public static Selector PropertyEquals(this Selector previous, AvaloniaProperty property, object value)
         {
+            Contract.Requires<ArgumentNullException>(property != null);
+
             return new PropertyEqualsSelector(previous, property, value);
         }
 

+ 15 - 2
src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs

@@ -50,10 +50,10 @@ namespace Avalonia.Markup.Parsers
                 {
 
                     case SelectorGrammar.OfTypeSyntax ofType:
-                        result = result.OfType(_typeResolver(ofType.Xmlns, ofType.TypeName));
+                        result = result.OfType(Resolve(ofType.Xmlns, ofType.TypeName));
                         break;
                     case SelectorGrammar.IsSyntax @is:
-                        result = result.Is(_typeResolver(@is.Xmlns, @is.TypeName));
+                        result = result.Is(Resolve(@is.Xmlns, @is.TypeName));
                         break;
                     case SelectorGrammar.ClassSyntax @class:
                         result = result.Class(@class.Class);
@@ -113,5 +113,18 @@ namespace Avalonia.Markup.Parsers
 
             return result;
         }
+
+        private Type Resolve(string xmlns, string typeName)
+        {
+            var result = _typeResolver(xmlns, typeName);
+
+            if (result == null)
+            {
+                var type = string.IsNullOrWhiteSpace(xmlns) ? typeName : xmlns + ':' + typeName;
+                throw new InvalidOperationException($"Could not resolve type '{type}'");
+            }
+
+            return result;
+        }
     }
 }

+ 14 - 2
tests/Avalonia.Markup.UnitTests/Parsers/SelectorParserTests.cs

@@ -1,8 +1,6 @@
 using System;
 using Avalonia.Controls;
-using Avalonia.Controls.Primitives;
 using Avalonia.Markup.Parsers;
-using Avalonia.Styling;
 using Xunit;
 
 namespace Avalonia.Markup.UnitTests.Parsers
@@ -15,5 +13,19 @@ namespace Avalonia.Markup.UnitTests.Parsers
             var target = new SelectorParser((ns, type) => typeof(TextBlock));
             var result = target.Parse("TextBlock[IsPointerOver=True]");
         }
+
+        [Fact]
+        public void Throws_If_OfType_Type_Not_Found()
+        {
+            var target = new SelectorParser((ns, type) => null);
+            Assert.Throws<InvalidOperationException>(() => target.Parse("NotFound"));
+        }
+
+        [Fact]
+        public void Throws_If_Is_Type_Not_Found()
+        {
+            var target = new SelectorParser((ns, type) => null);
+            Assert.Throws<InvalidOperationException>(() => target.Parse(":is(NotFound)"));
+        }
     }
 }