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

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

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

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

@ -55,6 +55,7 @@
<Compile Include="Templates\TemplateLoader.cs" />
<Compile Include="Templates\TreeDataTemplate.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\AvaloniaXamlIlDesignPropertiesTransformer.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;
}
public StyleInclude(IServiceProvider serviceProvider)
{
_baseUri = serviceProvider.GetContextBaseUri();
}
/// <inheritdoc/>
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 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);

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;
else
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 initialNode = new XamlIlSelectorInitialNode(node, selectorType);
XamlIlSelectorNode Create(IEnumerable<SelectorGrammar.ISyntax> syntax,
Func<string, string, IXamlIlType> typeResolver)
Func<string, string, XamlIlAstClrTypeReference> 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; }

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,
new XamlIlAstClrTypeReference(selector, selector.TargetType), property.Values[0]);
new XamlIlAstClrTypeReference(selector, selector.TargetType, false), property.Values[0]);
property.Values = new List<IXamlIlAstValueNode>
{
avaloniaPropertyNode
@ -62,7 +62,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
valueProperty.Values = new List<IXamlIlAstValueNode>
{
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 += 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;
}

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,
IServiceProvider provider)
{
// We need to preserve the first IResourceNode from the parent XAML,
// so Static/DynamicResource extensions can get it
var resourceNode = provider.GetService<IAvaloniaXamlIlParentStackProvider>().Parents.OfType<IResourceNode>()
.FirstOrDefault();
var resourceNodes = provider.GetService<IAvaloniaXamlIlParentStackProvider>().Parents
.OfType<IResourceNode>().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<IResourceNode> _parentResourceNodes;
public DeferredParentServiceProvider(IServiceProvider parentProvider, IResourceNode parentResourceNode)
public DeferredParentServiceProvider(IServiceProvider parentProvider, List<IResourceNode> parentResourceNodes)
{
_parentProvider = parentProvider;
_parentResourceNode = parentResourceNode;
_parentResourceNodes = parentResourceNodes;
}
public IEnumerable<object> Parents => GetParents();
IEnumerable<object> 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)

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

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