From 11af891f036cb78a4f534ee701ea2945e804e8a5 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 22 Apr 2019 13:50:33 +0300 Subject: [PATCH] Updated XamlIl, allow types to import IServiceProvider, preserve entire parent stack --- .../XamlCompilerTaskExecutor.cs | 2 +- src/Avalonia.Themes.Default/DatePicker.xaml | 7 +-- .../Avalonia.Markup.Xaml.csproj | 1 + .../Styling/StyleInclude.cs | 5 ++ .../AvaloniaXamlIlCompiler.cs | 9 ++-- ...IlConstructorServiceProviderTransformer.cs | 47 +++++++++++++++++++ ...olTemplateTargetTypeMetadataTransformer.cs | 2 +- .../AvaloniaXamlIlSelectorTransformer.cs | 12 ++--- .../AvaloniaXamlIlSetterTransformer.cs | 4 +- .../XamlIlAvaloniaPropertyHelper.cs | 5 +- .../XamlIl/Runtime/XamlIlRuntimeHelpers.cs | 19 ++++---- .../Avalonia.Markup.Xaml/XamlIl/xamlil.github | 2 +- 12 files changed, 82 insertions(+), 33 deletions(-) create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlConstructorServiceProviderTransformer.cs diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs index 2dfac41523..68f87b0eea 100644 --- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs +++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs @@ -137,7 +137,7 @@ 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); + initialRoot.Type = new XamlIlAstClrTypeReference(classDirective, classType, false); } diff --git a/src/Avalonia.Themes.Default/DatePicker.xaml b/src/Avalonia.Themes.Default/DatePicker.xaml index c7caccf329..7adb1c2d5f 100644 --- a/src/Avalonia.Themes.Default/DatePicker.xaml +++ b/src/Avalonia.Themes.Default/DatePicker.xaml @@ -63,11 +63,8 @@ Grid.ColumnSpan="4" Grid.RowSpan="3" FontSize="{DynamicResource FontSizeSmall}" - Foreground="{DynamicResource ThemeBorderHighBrush}"> - - - - + Foreground="{DynamicResource ThemeBorderHighBrush}" + Text="{Binding Source={x:Static sys:DateTime.Today}, Path=Day}"/> diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index a3d206edb7..c0ebdea7b5 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -55,6 +55,7 @@ + diff --git a/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs b/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs index 9273011cb9..01ec9753bd 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs @@ -25,6 +25,11 @@ namespace Avalonia.Markup.Xaml.Styling _baseUri = baseUri; } + public StyleInclude(IServiceProvider serviceProvider) + { + _baseUri = serviceProvider.GetContextBaseUri(); + } + /// public event EventHandler ResourcesChanged { diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs index 8484ae4ec6..8bb2494706 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs @@ -33,7 +33,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions { new AvaloniaXamlIlSelectorTransformer(), new AvaloniaXamlIlSetterTransformer(), - new AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer(), + new AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer(), + new AvaloniaXamlIlConstructorServiceProviderTransformer() } ); // After everything else @@ -79,10 +80,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions var originalType = XamlIlTypeReferenceResolver.ResolveType(CreateTransformationContext(parsed, true), (XamlIlAstXmlTypeReference)rootObject.Type, true); - if (!originalType.IsAssignableFrom(overrideRootType)) + if (!originalType.Type.IsAssignableFrom(overrideRootType)) throw new XamlIlLoadException( - $"Unable to substitute {originalType.GetFqn()} with {overrideRootType.GetFqn()}", rootObject); - rootObject.Type = new XamlIlAstClrTypeReference(rootObject, overrideRootType); + $"Unable to substitute {originalType.Type.GetFqn()} with {overrideRootType.GetFqn()}", rootObject); + rootObject.Type = new XamlIlAstClrTypeReference(rootObject, overrideRootType, false); } Transform(parsed); diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlConstructorServiceProviderTransformer.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlConstructorServiceProviderTransformer.cs new file mode 100644 index 0000000000..2baec04c6e --- /dev/null +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlConstructorServiceProviderTransformer.cs @@ -0,0 +1,47 @@ +using System.Linq; +using XamlIl.Ast; +using XamlIl.Transform; +using XamlIl.TypeSystem; + +namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers +{ + public class AvaloniaXamlIlConstructorServiceProviderTransformer : IXamlIlAstTransformer + { + public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) + { + if (node is XamlIlAstObjectNode on && on.Arguments.Count == 0) + { + var ctors = on.Type.GetClrType().Constructors; + if (!ctors.Any(c => c.IsPublic && !c.IsStatic && c.Parameters.Count == 0)) + { + var sp = context.Configuration.TypeMappings.ServiceProvider; + if (ctors.Any(c => + c.IsPublic && !c.IsStatic && c.Parameters.Count == 1 && c.Parameters[0] + .Equals(sp))) + { + on.Arguments.Add(new InjectServiceProviderNode(sp, on)); + } + } + } + + return node; + } + + class InjectServiceProviderNode : XamlIlAstNode, IXamlIlAstValueNode,IXamlIlAstNodeNeedsParentStack, + IXamlIlAstEmitableNode + { + public InjectServiceProviderNode(IXamlIlType type, IXamlIlLineInfo lineInfo) : base(lineInfo) + { + Type = new XamlIlAstClrTypeReference(lineInfo, type, false); + } + + public IXamlIlAstTypeReference Type { get; } + public bool NeedsParentStack => true; + public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen) + { + codeGen.Ldloc(context.ContextLocal); + return XamlIlNodeEmitResult.Type(0, Type.GetClrType()); + } + } + } +} diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs index edc9d6a389..d2eb9a5b66 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs @@ -33,7 +33,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers targetType = parentScope.TargetType; else targetType = new XamlIlAstClrTypeReference(node, - context.Configuration.TypeSystem.GetType("Avalonia.Controls.Control")); + context.Configuration.TypeSystem.GetType("Avalonia.Controls.Control"), false); } diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs index 1a646e50c2..608223a77c 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs @@ -37,7 +37,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers var selectorType = pn.Property.GetClrProperty().PropertyType; var initialNode = new XamlIlSelectorInitialNode(node, selectorType); XamlIlSelectorNode Create(IEnumerable syntax, - Func typeResolver) + Func typeResolver) { XamlIlSelectorNode result = initialNode; XamlIlOrSelectorNode results = null; @@ -47,10 +47,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers { case SelectorGrammar.OfTypeSyntax ofType: - result = new XamlIlTypeSelector(result, typeResolver(ofType.Xmlns, ofType.TypeName), true); + result = new XamlIlTypeSelector(result, typeResolver(ofType.Xmlns, ofType.TypeName).Type, true); break; case SelectorGrammar.IsSyntax @is: - result = new XamlIlTypeSelector(result, typeResolver(@is.Xmlns, @is.TypeName), false); + result = new XamlIlTypeSelector(result, typeResolver(@is.Xmlns, @is.TypeName).Type, false); break; case SelectorGrammar.ClassSyntax @class: result = new XamlIlStringSelector(result, XamlIlStringSelector.Type.Class, @class.Class); @@ -118,11 +118,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers } var selector = Create(parsed, (p, n) - => XamlIlTypeReferenceResolver.ResolveType(context, $"{p}:{n}", node, true)); + => XamlIlTypeReferenceResolver.ResolveType(context, $"{p}:{n}", true, node, true)); pn.Values[0] = selector; return new AvaloniaXamlIlTargetTypeMetadataNode(on, - new XamlIlAstClrTypeReference(selector, selector.TargetType), + new XamlIlAstClrTypeReference(selector, selector.TargetType, false), AvaloniaXamlIlTargetTypeMetadataNode.ScopeType.Style); } @@ -140,7 +140,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers IXamlIlType selectorType = null) : base(info ?? previous) { Previous = previous; - Type = selectorType == null ? previous.Type : new XamlIlAstClrTypeReference(this, selectorType); + Type = selectorType == null ? previous.Type : new XamlIlAstClrTypeReference(this, selectorType, false); } public IXamlIlAstTypeReference Type { get; } diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs index beec47afa4..5327935266 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs @@ -43,7 +43,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers var avaloniaPropertyNode = XamlIlAvaloniaPropertyHelper.CreateNode(context, propertyName, - new XamlIlAstClrTypeReference(selector, selector.TargetType), property.Values[0]); + new XamlIlAstClrTypeReference(selector, selector.TargetType, false), property.Values[0]); property.Values = new List { avaloniaPropertyNode @@ -62,7 +62,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers valueProperty.Values = new List { new XamlIlAstRuntimeCastNode(converted, converted, - new XamlIlAstClrTypeReference(converted, context.Configuration.WellKnownTypes.Object)) + new XamlIlAstClrTypeReference(converted, context.Configuration.WellKnownTypes.Object, false)) }; } diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs index 0d7d88588d..27c39aa8b9 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs @@ -43,8 +43,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions xmlOwner += ":"; xmlOwner += parsedPropertyName.owner; - var t = XamlIlTypeReferenceResolver.ResolveType(context, xmlOwner, lineInfo, true); - var tref = new XamlIlAstClrTypeReference(lineInfo, t); + var tref = XamlIlTypeReferenceResolver.ResolveType(context, xmlOwner, false, lineInfo, true); forgedReference = new XamlIlAstNamePropertyReference(lineInfo, tref, parsedPropertyName.name, tref); } @@ -62,7 +61,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions { public XamlIlAvaloniaPropertyNode(IXamlIlLineInfo lineInfo, IXamlIlType type, IXamlIlProperty property) : base(lineInfo) { - Type = new XamlIlAstClrTypeReference(this, type); + Type = new XamlIlAstClrTypeReference(this, type, false); Property = property; } diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs index 433c641717..f91e221ac0 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs @@ -15,32 +15,31 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime public static Func DeferredTransformationFactoryV1(Func builder, IServiceProvider provider) { - // We need to preserve the first IResourceNode from the parent XAML, - // so Static/DynamicResource extensions can get it - var resourceNode = provider.GetService().Parents.OfType() - .FirstOrDefault(); + var resourceNodes = provider.GetService().Parents + .OfType().ToList(); - return sp => builder(new DeferredParentServiceProvider(sp, resourceNode)); + return sp => builder(new DeferredParentServiceProvider(sp, resourceNodes)); } class DeferredParentServiceProvider : IAvaloniaXamlIlParentStackProvider, IServiceProvider { private readonly IServiceProvider _parentProvider; - private readonly IResourceNode _parentResourceNode; + private readonly List _parentResourceNodes; - public DeferredParentServiceProvider(IServiceProvider parentProvider, IResourceNode parentResourceNode) + public DeferredParentServiceProvider(IServiceProvider parentProvider, List parentResourceNodes) { _parentProvider = parentProvider; - _parentResourceNode = parentResourceNode; + _parentResourceNodes = parentResourceNodes; } public IEnumerable Parents => GetParents(); IEnumerable GetParents() { - if(_parentResourceNode == null) + if(_parentResourceNodes == null) yield break; - yield return _parentResourceNode; + foreach (var p in _parentResourceNodes) + yield return p; } public object GetService(Type serviceType) diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github b/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github index b318b6dcc6..1b3fda73e4 160000 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github @@ -1 +1 @@ -Subproject commit b318b6dcc67370f7ebea1e3c6741a0b6d4dd5db1 +Subproject commit 1b3fda73e4cece31a4fec22ce146640ed5f2fd4c