Ver código fonte

Merge pull request #2558 from AvaloniaUI/xamlil-fixes

Various xaml compiler fixes
Nikita Tsukanov 6 anos atrás
pai
commit
4e92b8ca6d

+ 2 - 1
src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs

@@ -150,7 +150,8 @@ namespace Avalonia.Build.Tasks
                             classType = typeSystem.TargetAssembly.FindType(tn.Text);
                             if (classType == null)
                                 throw new XamlIlParseException($"Unable to find type `{tn.Text}`", classDirective);
-                            initialRoot.Type = new XamlIlAstClrTypeReference(classDirective, classType, false);
+                            compiler.OverrideRootType(parsed,
+                                new XamlIlAstClrTypeReference(classDirective, classType, false));
                             initialRoot.Children.Remove(classDirective);
                         }
                         

+ 21 - 3
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs

@@ -112,13 +112,31 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
                 rootType = new XamlIlAstClrTypeReference(rootObject, overrideRootType, false);
             }
 
-            rootObject.Type = rootType;
+            OverrideRootType(parsed, rootType);
 
             Transform(parsed);
             Compile(parsed, tb, _contextType, PopulateName, BuildName, "__AvaloniaXamlIlNsInfo", baseUri, fileSource);
             
         }
-        
-        
+
+        public void OverrideRootType(XamlIlDocument doc, IXamlIlAstTypeReference newType)
+        {
+            var root = (XamlIlAstObjectNode)doc.Root;
+            var oldType = root.Type;
+            if (oldType.Equals(newType))
+                return;
+
+            root.Type = newType;
+            foreach (var child in root.Children.OfType<XamlIlAstXamlPropertyValueNode>())
+            {
+                if (child.Property is XamlIlAstNamePropertyReference prop)
+                {
+                    if (prop.DeclaringType.Equals(oldType))
+                        prop.DeclaringType = newType;
+                    if (prop.TargetType.Equals(oldType))
+                        prop.TargetType = newType;
+                }
+            }
+        }
     }
 }

+ 14 - 4
src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs

@@ -4,6 +4,7 @@ using System.Linq;
 using System.Reflection;
 using Avalonia.Controls;
 using Avalonia.Data;
+using Portable.Xaml;
 using Portable.Xaml.Markup;
 // ReSharper disable UnusedMember.Global
 // ReSharper disable UnusedParameter.Global
@@ -17,19 +18,24 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
         {
             var resourceNodes = provider.GetService<IAvaloniaXamlIlParentStackProvider>().Parents
                 .OfType<IResourceNode>().ToList();
-
-            return sp => builder(new DeferredParentServiceProvider(sp, resourceNodes));
+            var rootObject = provider.GetService<IRootObjectProvider>().RootObject;
+            return sp => builder(new DeferredParentServiceProvider(sp, resourceNodes, rootObject));
         }
 
-        class DeferredParentServiceProvider : IAvaloniaXamlIlParentStackProvider, IServiceProvider
+        class DeferredParentServiceProvider :
+            IAvaloniaXamlIlParentStackProvider,
+            IServiceProvider,
+            IRootObjectProvider
         {
             private readonly IServiceProvider _parentProvider;
             private readonly List<IResourceNode> _parentResourceNodes;
 
-            public DeferredParentServiceProvider(IServiceProvider parentProvider, List<IResourceNode> parentResourceNodes)
+            public DeferredParentServiceProvider(IServiceProvider parentProvider, List<IResourceNode> parentResourceNodes,
+                object rootObject)
             {
                 _parentProvider = parentProvider;
                 _parentResourceNodes = parentResourceNodes;
+                RootObject = rootObject;
             }
 
             public IEnumerable<object> Parents => GetParents();
@@ -46,8 +52,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
             {
                 if (serviceType == typeof(IAvaloniaXamlIlParentStackProvider))
                     return this;
+                if (serviceType == typeof(IRootObjectProvider))
+                    return this;
                 return _parentProvider?.GetService(serviceType);
             }
+
+            public object RootObject { get; }
         }
 
 

+ 1 - 1
src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github

@@ -1 +1 @@
-Subproject commit 3b3c1f93a566080d417b9782f9cc4ea67cd62344
+Subproject commit 1e3ffc315401f0b2eb96a0e79b25c2fc19a80d78

+ 2 - 1
tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj

@@ -32,7 +32,8 @@
     <EmbeddedResource Include="Xaml\Style2.xaml">
       <SubType>Designer</SubType>
     </EmbeddedResource>
-    <AvaloniaResource Include="Xaml\XamlIlClassWithPrecompiledXaml.xaml"/>
+    <AvaloniaResource Include="Xaml\XamlIlClassWithPrecompiledXaml.xaml" />
+    <AvaloniaResource Include="Xaml\XamlIlClassWithCustomProperty.xaml" />
   </ItemGroup>
   <Import Project="..\..\build\BuildTargets.targets" />
 </Project>

+ 6 - 0
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithCustomProperty.xaml

@@ -0,0 +1,6 @@
+<UserControl xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+             x:Class='Avalonia.Markup.Xaml.UnitTests.XamlIlClassWithCustomProperty'
+             Test="123">
+
+</UserControl>

+ 79 - 0
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs

@@ -5,8 +5,12 @@ using System.Globalization;
 using System.Linq;
 using System.Runtime.CompilerServices;
 using Avalonia.Controls;
+using Avalonia.Controls.Presenters;
 using Avalonia.Data.Converters;
+using Avalonia.Input;
+using Avalonia.Interactivity;
 using Avalonia.Media;
+using Avalonia.Threading;
 using Avalonia.UnitTests;
 using Avalonia.VisualTree;
 using JetBrains.Annotations;
@@ -117,6 +121,81 @@ namespace Avalonia.Markup.Xaml.UnitTests
                 Assert.Equal(Brushes.Red.Color, ((ISolidColorBrush)canvas.Background).Color);
             }
         }
+
+        [Fact]
+        public void Event_Handlers_Should_Work_For_Templates()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var w =new XamlIlBugTestsEventHandlerCodeBehind();
+                w.ApplyTemplate();
+                w.Show();
+
+                Dispatcher.UIThread.RunJobs();
+                var itemsPresenter = ((ItemsControl)w.Content).GetVisualChildren().FirstOrDefault();
+                var item = itemsPresenter
+                    .GetVisualChildren().First()
+                    .GetVisualChildren().First()
+                    .GetVisualChildren().First();
+                ((Control)item).RaiseEvent(new PointerPressedEventArgs {ClickCount = 20});
+                Assert.Equal(20, w.Args.ClickCount);
+            }
+        }
+        
+        [Fact]
+        public void Custom_Properties_Should_Work_With_XClass()
+        {
+            var precompiled = new XamlIlClassWithCustomProperty();
+            Assert.Equal("123", precompiled.Test);
+            var loaded = (XamlIlClassWithCustomProperty)AvaloniaXamlLoader.Parse(@"
+<UserControl xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+             x:Class='Avalonia.Markup.Xaml.UnitTests.XamlIlClassWithCustomProperty'
+             Test='321'>
+
+</UserControl>");
+            Assert.Equal("321", loaded.Test);
+            
+        }
+    }
+    
+    public class XamlIlBugTestsEventHandlerCodeBehind : Window
+    {
+        public PointerPressedEventArgs Args;
+        public void HandlePointerPressed(object sender, PointerPressedEventArgs args)
+        {
+            Args = args;
+        }
+
+        public XamlIlBugTestsEventHandlerCodeBehind()
+        {
+            new AvaloniaXamlLoader().Load(@"
+<Window x:Class='Avalonia.Markup.Xaml.UnitTests.XamlIlBugTestsEventHandlerCodeBehind'
+  xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+  xmlns='https://github.com/avaloniaui'
+  xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests;assembly=Avalonia.Markup.Xaml.UnitTests'
+>
+  <ItemsControl>
+    <ItemsControl.ItemTemplate>
+      <DataTemplate>
+        <Button PointerPressed='HandlePointerPressed' Content='{Binding .}' />
+      </DataTemplate>
+    </ItemsControl.ItemTemplate>
+  </ItemsControl>
+</Window>
+", typeof(XamlIlBugTestsEventHandlerCodeBehind).Assembly, this);
+            ((ItemsControl)Content).Items = new[] {"123"};
+        }
+    }
+
+    public class XamlIlClassWithCustomProperty : UserControl
+    {
+        public string Test { get; set; }
+
+        public XamlIlClassWithCustomProperty()
+        {
+            AvaloniaXamlLoader.Load(this);
+        }
     }
 
     public class XamlIlBugTestsBrushToColorConverter : IMultiValueConverter