Browse Source

Updated XamlIl, allow types to import IServiceProvider, preserve entire parent stack

pull/2322/head
Nikita Tsukanov 7 years ago
parent
commit
11af891f03
  1. 2
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
  2. 7
      src/Avalonia.Themes.Default/DatePicker.xaml
  3. 1
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  4. 5
      src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs
  5. 9
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
  6. 47
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlConstructorServiceProviderTransformer.cs
  7. 2
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs
  8. 12
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs
  9. 4
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs
  10. 5
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
  11. 19
      src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
  12. 2
      src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github

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

@ -137,7 +137,7 @@ 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); initialRoot.Type = new XamlIlAstClrTypeReference(classDirective, classType, false);
} }

7
src/Avalonia.Themes.Default/DatePicker.xaml

@ -63,11 +63,8 @@
Grid.ColumnSpan="4" Grid.ColumnSpan="4"
Grid.RowSpan="3" Grid.RowSpan="3"
FontSize="{DynamicResource FontSizeSmall}" FontSize="{DynamicResource FontSizeSmall}"
Foreground="{DynamicResource ThemeBorderHighBrush}"> Foreground="{DynamicResource ThemeBorderHighBrush}"
<TextBlock.Text> Text="{Binding Source={x:Static sys:DateTime.Today}, Path=Day}"/>
<Binding Source="{x:Static sys:DateTime.Today}" Path="Day"/>
</TextBlock.Text>
</TextBlock>
<Ellipse HorizontalAlignment="Center" VerticalAlignment="Center" Fill="{DynamicResource ThemeControlLowBrush}" StrokeThickness="0" Grid.ColumnSpan="4" Width="3" Height="3"/> <Ellipse HorizontalAlignment="Center" VerticalAlignment="Center" Fill="{DynamicResource ThemeControlLowBrush}" StrokeThickness="0" Grid.ColumnSpan="4" Width="3" Height="3"/>
</Grid> </Grid>

1
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -55,6 +55,7 @@
<Compile Include="Templates\TemplateLoader.cs" /> <Compile Include="Templates\TemplateLoader.cs" />
<Compile Include="Templates\TreeDataTemplate.cs" /> <Compile Include="Templates\TreeDataTemplate.cs" />
<Compile Include="XamlIl\AvaloniaXamlIlRuntimeCompiler.cs" /> <Compile Include="XamlIl\AvaloniaXamlIlRuntimeCompiler.cs" />
<Compile Include="XamlIl\CompilerExtensions\Transformers\AvaloniaXamlIlConstructorServiceProviderTransformer.cs" />
<Compile Include="XamlIl\CompilerExtensions\Transformers\AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs" /> <Compile Include="XamlIl\CompilerExtensions\Transformers\AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs" />
<Compile Include="XamlIl\CompilerExtensions\Transformers\AvaloniaXamlIlDesignPropertiesTransformer.cs" /> <Compile Include="XamlIl\CompilerExtensions\Transformers\AvaloniaXamlIlDesignPropertiesTransformer.cs" />
<Compile Include="XamlIl\CompilerExtensions\Transformers\AvaloniaXamlIlMetadataRemover.cs" /> <Compile Include="XamlIl\CompilerExtensions\Transformers\AvaloniaXamlIlMetadataRemover.cs" />

5
src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs

@ -25,6 +25,11 @@ namespace Avalonia.Markup.Xaml.Styling
_baseUri = baseUri; _baseUri = baseUri;
} }
public StyleInclude(IServiceProvider serviceProvider)
{
_baseUri = serviceProvider.GetContextBaseUri();
}
/// <inheritdoc/> /// <inheritdoc/>
public event EventHandler<ResourcesChangedEventArgs> ResourcesChanged public event EventHandler<ResourcesChangedEventArgs> ResourcesChanged
{ {

9
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs

@ -33,7 +33,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{ {
new AvaloniaXamlIlSelectorTransformer(), new AvaloniaXamlIlSelectorTransformer(),
new AvaloniaXamlIlSetterTransformer(), new AvaloniaXamlIlSetterTransformer(),
new AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer(), new AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer(),
new AvaloniaXamlIlConstructorServiceProviderTransformer()
} }
); );
// After everything else // After everything else
@ -79,10 +80,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
var originalType = XamlIlTypeReferenceResolver.ResolveType(CreateTransformationContext(parsed, true), var originalType = XamlIlTypeReferenceResolver.ResolveType(CreateTransformationContext(parsed, true),
(XamlIlAstXmlTypeReference)rootObject.Type, true); (XamlIlAstXmlTypeReference)rootObject.Type, true);
if (!originalType.IsAssignableFrom(overrideRootType)) if (!originalType.Type.IsAssignableFrom(overrideRootType))
throw new XamlIlLoadException( throw new XamlIlLoadException(
$"Unable to substitute {originalType.GetFqn()} with {overrideRootType.GetFqn()}", rootObject); $"Unable to substitute {originalType.Type.GetFqn()} with {overrideRootType.GetFqn()}", rootObject);
rootObject.Type = new XamlIlAstClrTypeReference(rootObject, overrideRootType); rootObject.Type = new XamlIlAstClrTypeReference(rootObject, overrideRootType, false);
} }
Transform(parsed); Transform(parsed);

47
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());
}
}
}
}

2
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs

@ -33,7 +33,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
targetType = parentScope.TargetType; targetType = parentScope.TargetType;
else else
targetType = new XamlIlAstClrTypeReference(node, targetType = new XamlIlAstClrTypeReference(node,
context.Configuration.TypeSystem.GetType("Avalonia.Controls.Control")); context.Configuration.TypeSystem.GetType("Avalonia.Controls.Control"), false);
} }

12
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 selectorType = pn.Property.GetClrProperty().PropertyType;
var initialNode = new XamlIlSelectorInitialNode(node, selectorType); var initialNode = new XamlIlSelectorInitialNode(node, selectorType);
XamlIlSelectorNode Create(IEnumerable<SelectorGrammar.ISyntax> syntax, XamlIlSelectorNode Create(IEnumerable<SelectorGrammar.ISyntax> syntax,
Func<string, string, IXamlIlType> typeResolver) Func<string, string, XamlIlAstClrTypeReference> typeResolver)
{ {
XamlIlSelectorNode result = initialNode; XamlIlSelectorNode result = initialNode;
XamlIlOrSelectorNode results = null; XamlIlOrSelectorNode results = null;
@ -47,10 +47,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{ {
case SelectorGrammar.OfTypeSyntax ofType: 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; break;
case SelectorGrammar.IsSyntax @is: 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; break;
case SelectorGrammar.ClassSyntax @class: case SelectorGrammar.ClassSyntax @class:
result = new XamlIlStringSelector(result, XamlIlStringSelector.Type.Class, @class.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) 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; pn.Values[0] = selector;
return new AvaloniaXamlIlTargetTypeMetadataNode(on, return new AvaloniaXamlIlTargetTypeMetadataNode(on,
new XamlIlAstClrTypeReference(selector, selector.TargetType), new XamlIlAstClrTypeReference(selector, selector.TargetType, false),
AvaloniaXamlIlTargetTypeMetadataNode.ScopeType.Style); AvaloniaXamlIlTargetTypeMetadataNode.ScopeType.Style);
} }
@ -140,7 +140,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
IXamlIlType selectorType = null) : base(info ?? previous) IXamlIlType selectorType = null) : base(info ?? previous)
{ {
Previous = 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; } public IXamlIlAstTypeReference Type { get; }

4
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, 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<IXamlIlAstValueNode> property.Values = new List<IXamlIlAstValueNode>
{ {
avaloniaPropertyNode avaloniaPropertyNode
@ -62,7 +62,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
valueProperty.Values = new List<IXamlIlAstValueNode> valueProperty.Values = new List<IXamlIlAstValueNode>
{ {
new XamlIlAstRuntimeCastNode(converted, converted, new XamlIlAstRuntimeCastNode(converted, converted,
new XamlIlAstClrTypeReference(converted, context.Configuration.WellKnownTypes.Object)) new XamlIlAstClrTypeReference(converted, context.Configuration.WellKnownTypes.Object, false))
}; };
} }

5
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs

@ -43,8 +43,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
xmlOwner += ":"; xmlOwner += ":";
xmlOwner += parsedPropertyName.owner; xmlOwner += parsedPropertyName.owner;
var t = XamlIlTypeReferenceResolver.ResolveType(context, xmlOwner, lineInfo, true); var tref = XamlIlTypeReferenceResolver.ResolveType(context, xmlOwner, false, lineInfo, true);
var tref = new XamlIlAstClrTypeReference(lineInfo, t);
forgedReference = new XamlIlAstNamePropertyReference(lineInfo, forgedReference = new XamlIlAstNamePropertyReference(lineInfo,
tref, parsedPropertyName.name, tref); tref, parsedPropertyName.name, tref);
} }
@ -62,7 +61,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{ {
public XamlIlAvaloniaPropertyNode(IXamlIlLineInfo lineInfo, IXamlIlType type, IXamlIlProperty property) : base(lineInfo) public XamlIlAvaloniaPropertyNode(IXamlIlLineInfo lineInfo, IXamlIlType type, IXamlIlProperty property) : base(lineInfo)
{ {
Type = new XamlIlAstClrTypeReference(this, type); Type = new XamlIlAstClrTypeReference(this, type, false);
Property = property; Property = property;
} }

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

@ -15,32 +15,31 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
public static Func<IServiceProvider, object> DeferredTransformationFactoryV1(Func<IServiceProvider, object> builder, public static Func<IServiceProvider, object> DeferredTransformationFactoryV1(Func<IServiceProvider, object> builder,
IServiceProvider provider) IServiceProvider provider)
{ {
// We need to preserve the first IResourceNode from the parent XAML, var resourceNodes = provider.GetService<IAvaloniaXamlIlParentStackProvider>().Parents
// so Static/DynamicResource extensions can get it .OfType<IResourceNode>().ToList();
var resourceNode = provider.GetService<IAvaloniaXamlIlParentStackProvider>().Parents.OfType<IResourceNode>()
.FirstOrDefault();
return sp => builder(new DeferredParentServiceProvider(sp, resourceNode)); return sp => builder(new DeferredParentServiceProvider(sp, resourceNodes));
} }
class DeferredParentServiceProvider : IAvaloniaXamlIlParentStackProvider, IServiceProvider class DeferredParentServiceProvider : IAvaloniaXamlIlParentStackProvider, IServiceProvider
{ {
private readonly IServiceProvider _parentProvider; private readonly IServiceProvider _parentProvider;
private readonly IResourceNode _parentResourceNode; private readonly List<IResourceNode> _parentResourceNodes;
public DeferredParentServiceProvider(IServiceProvider parentProvider, IResourceNode parentResourceNode) public DeferredParentServiceProvider(IServiceProvider parentProvider, List<IResourceNode> parentResourceNodes)
{ {
_parentProvider = parentProvider; _parentProvider = parentProvider;
_parentResourceNode = parentResourceNode; _parentResourceNodes = parentResourceNodes;
} }
public IEnumerable<object> Parents => GetParents(); public IEnumerable<object> Parents => GetParents();
IEnumerable<object> GetParents() IEnumerable<object> GetParents()
{ {
if(_parentResourceNode == null) if(_parentResourceNodes == null)
yield break; yield break;
yield return _parentResourceNode; foreach (var p in _parentResourceNodes)
yield return p;
} }
public object GetService(Type serviceType) public object GetService(Type serviceType)

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

@ -1 +1 @@
Subproject commit b318b6dcc67370f7ebea1e3c6741a0b6d4dd5db1 Subproject commit 1b3fda73e4cece31a4fec22ce146640ed5f2fd4c
Loading…
Cancel
Save