From 0b5a82884e2cfa24499f5f05fc84e0dd52c734dd Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Fri, 28 Nov 2025 11:19:04 +0000 Subject: [PATCH 1/2] fix some query error and print out more detailed exceptions in query parser (#20170) --- .../Transformers/AvaloniaXamlIlQueryTransformer.cs | 2 +- .../Avalonia.Markup/Markup/Parsers/ContainerQueryGrammar.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlQueryTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlQueryTransformer.cs index 4068032376..3095af4a19 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlQueryTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlQueryTransformer.cs @@ -98,7 +98,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers } catch (Exception e) { - throw new XamlParseException("Unable to parse query: " + e.Message, node); + throw new XamlParseException("Unable to parse query: " + e, node); } var query = Create(parsed); diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/ContainerQueryGrammar.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/ContainerQueryGrammar.cs index 7573646651..0c34fa4637 100644 --- a/src/Markup/Avalonia.Markup/Markup/Parsers/ContainerQueryGrammar.cs +++ b/src/Markup/Avalonia.Markup/Markup/Parsers/ContainerQueryGrammar.cs @@ -84,7 +84,7 @@ namespace Avalonia.Markup.Parsers if (identifier.SequenceEqual(MinWidthKeyword.AsSpan()) || identifier.SequenceEqual(MaxWidthKeyword.AsSpan()) || identifier.SequenceEqual(WidthKeyword.AsSpan())) { if (!r.TakeIf(':')) - throw new ExpressionParseException(r.Position, "Expected ':' after 'orientation'."); + throw new ExpressionParseException(r.Position, $"Expected ':' after '{identifier}'."); double val = ParseDecimal(ref r); var syntax = new WidthSyntax() @@ -101,7 +101,7 @@ namespace Avalonia.Markup.Parsers if (identifier.SequenceEqual(MinHeightKeyword.AsSpan()) || identifier.SequenceEqual(MaxHeightKeyword.AsSpan()) || identifier.SequenceEqual(HeightKeyword.AsSpan())) { if (!r.TakeIf(':')) - throw new ExpressionParseException(r.Position, "Expected ':' after 'orientation'."); + throw new ExpressionParseException(r.Position, $"Expected ':' after '{identifier}'."); double val = ParseDecimal(ref r); var syntax = new HeightSyntax() From 51987447d3e8571cd453efaef94c4fe91383968c Mon Sep 17 00:00:00 2001 From: Alexander Prokhorov Date: Fri, 28 Nov 2025 20:57:07 +0300 Subject: [PATCH 2/2] Fixed ReversibleStackPanel not invalidating arrange on ReverseOrder change (#20172) * Added unit tests for ReversibleStackPanel (#20171) * Invalidates_Arrange_On_Reverse_Order_Change fails. * Fixed ReversibleStackPanel not invalidating arrange on ReverseOrder change (#20171) --- .../Notifications/ReversibleStackPanel.cs | 5 ++ .../ReversibleStackPanelTests.cs | 48 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 tests/Avalonia.Controls.UnitTests/ReversibleStackPanelTests.cs diff --git a/src/Avalonia.Controls/Notifications/ReversibleStackPanel.cs b/src/Avalonia.Controls/Notifications/ReversibleStackPanel.cs index b64d94ff9b..69df8209b9 100644 --- a/src/Avalonia.Controls/Notifications/ReversibleStackPanel.cs +++ b/src/Avalonia.Controls/Notifications/ReversibleStackPanel.cs @@ -24,6 +24,11 @@ namespace Avalonia.Controls set => SetValue(ReverseOrderProperty, value); } + static ReversibleStackPanel() + { + AffectsArrange(ReverseOrderProperty); + } + /// protected override Size ArrangeOverride(Size finalSize) { diff --git a/tests/Avalonia.Controls.UnitTests/ReversibleStackPanelTests.cs b/tests/Avalonia.Controls.UnitTests/ReversibleStackPanelTests.cs new file mode 100644 index 0000000000..2291ff7d8c --- /dev/null +++ b/tests/Avalonia.Controls.UnitTests/ReversibleStackPanelTests.cs @@ -0,0 +1,48 @@ +using Avalonia.UnitTests; +using Xunit; + +namespace Avalonia.Controls.UnitTests +{ + public class ReversibleStackPanelTests : ScopedTestBase + { + [Fact] + public void Arranges_In_Reverse_Order() + { + var target = new ReversibleStackPanel + { + ReverseOrder = true, + Children = + { + new Border { Height = 30, Width = 10 }, + new Border { Height = 50 }, + } + }; + + target.Measure(Size.Infinity); + target.Arrange(new Rect(target.DesiredSize)); + + Assert.Equal(new Rect(0, 50, 10, 30), target.Children[0].Bounds); + Assert.Equal(new Rect(0, 0, 10, 50), target.Children[1].Bounds); + } + + [Fact] + public void Invalidates_Arrange_On_Reverse_Order_Change() + { + var target = new ReversibleStackPanel + { + Children = + { + new Border(), + new Border(), + } + }; + + target.Measure(Size.Infinity); + target.Arrange(new Rect(target.DesiredSize)); + target.ReverseOrder = true; + + Assert.True(target.IsMeasureValid); + Assert.False(target.IsArrangeValid); + } + } +}