Browse Source

Merge pull request #2558 from AvaloniaUI/xamlil-fixes

Various xaml compiler fixes
pull/2580/head
Nikita Tsukanov 7 years ago
committed by GitHub
parent
commit
4e92b8ca6d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
  2. 24
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
  3. 18
      src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
  4. 2
      src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github
  5. 3
      tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
  6. 6
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithCustomProperty.xaml
  7. 79
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs

3
src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs

@ -150,7 +150,8 @@ namespace Avalonia.Build.Tasks
classType = typeSystem.TargetAssembly.FindType(tn.Text); classType = typeSystem.TargetAssembly.FindType(tn.Text);
if (classType == null) if (classType == null)
throw new XamlIlParseException($"Unable to find type `{tn.Text}`", classDirective); 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); initialRoot.Children.Remove(classDirective);
} }

24
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); rootType = new XamlIlAstClrTypeReference(rootObject, overrideRootType, false);
} }
rootObject.Type = rootType; OverrideRootType(parsed, rootType);
Transform(parsed); Transform(parsed);
Compile(parsed, tb, _contextType, PopulateName, BuildName, "__AvaloniaXamlIlNsInfo", baseUri, fileSource); 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;
}
}
}
} }
} }

18
src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs

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

2
src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github

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

3
tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj

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

6
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
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs

@ -5,8 +5,12 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Data.Converters; using Avalonia.Data.Converters;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Threading;
using Avalonia.UnitTests; using Avalonia.UnitTests;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using JetBrains.Annotations; using JetBrains.Annotations;
@ -117,6 +121,81 @@ namespace Avalonia.Markup.Xaml.UnitTests
Assert.Equal(Brushes.Red.Color, ((ISolidColorBrush)canvas.Background).Color); 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 public class XamlIlBugTestsBrushToColorConverter : IMultiValueConverter

Loading…
Cancel
Save