From 354496b9b24fb25849b180d0e80481e4f79d428f Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 19 Feb 2019 13:56:05 +0100 Subject: [PATCH 1/3] Throw an exception if selector class not found. Fixes #2316. --- .../Markup/Parsers/SelectorParser.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs index 8d1216e1dc..8137ac3f48 100644 --- a/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs +++ b/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; + } } } From a12631104a665c0d49900212025467d0e7fa5352 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 19 Feb 2019 13:56:34 +0100 Subject: [PATCH 2/3] Add guards to selector construction methods. --- src/Avalonia.Styling/Styling/Selectors.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Avalonia.Styling/Styling/Selectors.cs b/src/Avalonia.Styling/Styling/Selectors.cs index 4284c7e798..deb677e04c 100644 --- a/src/Avalonia.Styling/Styling/Selectors.cs +++ b/src/Avalonia.Styling/Styling/Selectors.cs @@ -28,6 +28,9 @@ namespace Avalonia.Styling /// The selector. public static Selector Class(this Selector previous, string name) { + Contract.Requires(name != null); + Contract.Requires(!string.IsNullOrWhiteSpace(name)); + var tac = previous as TypeNameAndClassSelector; if (tac != null) @@ -59,6 +62,8 @@ namespace Avalonia.Styling /// The selector. public static Selector Is(this Selector previous, Type type) { + Contract.Requires(type != null); + return TypeNameAndClassSelector.Is(previous, type); } @@ -81,6 +86,9 @@ namespace Avalonia.Styling /// The selector. public static Selector Name(this Selector previous, string name) { + Contract.Requires(name != null); + Contract.Requires(!string.IsNullOrWhiteSpace(name)); + var tac = previous as TypeNameAndClassSelector; if (tac != null) @@ -113,6 +121,8 @@ namespace Avalonia.Styling /// The selector. public static Selector OfType(this Selector previous, Type type) { + Contract.Requires(type != null); + return TypeNameAndClassSelector.OfType(previous, type); } @@ -137,6 +147,8 @@ namespace Avalonia.Styling /// The selector. public static Selector PropertyEquals(this Selector previous, AvaloniaProperty property, object value) { + Contract.Requires(property != null); + return new PropertyEqualsSelector(previous, property, value); } @@ -149,6 +161,8 @@ namespace Avalonia.Styling /// The selector. public static Selector PropertyEquals(this Selector previous, AvaloniaProperty property, object value) { + Contract.Requires(property != null); + return new PropertyEqualsSelector(previous, property, value); } From d9911732967691048ff9432f7570055213bc8abc Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 19 Feb 2019 14:03:13 +0100 Subject: [PATCH 3/3] Added tests for #2316. --- .../Parsers/SelectorParserTests.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Markup.UnitTests/Parsers/SelectorParserTests.cs b/tests/Avalonia.Markup.UnitTests/Parsers/SelectorParserTests.cs index dba4573473..1b1a96a7e2 100644 --- a/tests/Avalonia.Markup.UnitTests/Parsers/SelectorParserTests.cs +++ b/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(() => target.Parse("NotFound")); + } + + [Fact] + public void Throws_If_Is_Type_Not_Found() + { + var target = new SelectorParser((ns, type) => null); + Assert.Throws(() => target.Parse(":is(NotFound)")); + } } }