Browse Source

Merge branch 'master' into compiled-bindings-default

pull/7247/head
Dan Walmsley 3 years ago
committed by GitHub
parent
commit
8590bc7dbb
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlMetadataRemover.cs
  2. 53
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs
  3. 34
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs

5
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlMetadataRemover.cs

@ -1,4 +1,3 @@
using System.Linq;
using XamlX.Ast;
using XamlX.Transform;
@ -8,8 +7,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
if (node is AvaloniaXamlIlTargetTypeMetadataNode targetType)
return targetType.Value;
while (node is AvaloniaXamlIlTargetTypeMetadataNode targetType)
node = targetType.Value;
return node;
}

53
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs

@ -128,13 +128,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
break;
}
case SelectorGrammar.ChildSyntax child:
result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.SelectorType.Child);
result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.CombinatorSelectorType.Child);
break;
case SelectorGrammar.DescendantSyntax descendant:
result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.SelectorType.Descendant);
result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.CombinatorSelectorType.Descendant);
break;
case SelectorGrammar.TemplateSyntax template:
result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.SelectorType.Template);
result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.CombinatorSelectorType.Template);
break;
case SelectorGrammar.NotSyntax not:
result = new XamlIlNotSelector(result, Create(not.Argument, typeResolver));
@ -186,18 +186,50 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
=> TypeReferenceResolver.ResolveType(context, $"{p}:{n}", true, node, true));
pn.Values[0] = selector;
return new AvaloniaXamlIlTargetTypeMetadataNode(on,
var templateType = GetLastTemplateTypeFromSelector(selector);
var styleNode = new AvaloniaXamlIlTargetTypeMetadataNode(on,
new XamlAstClrTypeReference(selector, selector.TargetType, false),
AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style);
return templateType switch
{
null => styleNode,
_ => new AvaloniaXamlIlTargetTypeMetadataNode(styleNode,
new XamlAstClrTypeReference(styleNode, templateType, false),
AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.ControlTemplate)
};
}
}
private static IXamlType GetLastTemplateTypeFromSelector(XamlIlSelectorNode node)
{
while (node is not null)
{
if (node is XamlIlCombinatorSelector
{
SelectorType: XamlIlCombinatorSelector.CombinatorSelectorType.Template
} templateSelector)
{
if (templateSelector.Previous is XamlIlNestingSelector nestingSelector)
{
return nestingSelector.TargetType;
}
if (templateSelector.Previous is XamlIlTypeSelector typeSelector)
{
return typeSelector.TargetType;
}
return null;
}
node = node.Previous;
}
return null;
}
}
abstract class XamlIlSelectorNode : XamlAstNode, IXamlAstValueNode, IXamlAstEmitableNode<IXamlILEmitter, XamlILNodeEmitResult>
{
protected XamlIlSelectorNode Previous { get; }
internal XamlIlSelectorNode Previous { get; }
public abstract IXamlType TargetType { get; }
public XamlIlSelectorNode(XamlIlSelectorNode previous,
@ -289,19 +321,20 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
class XamlIlCombinatorSelector : XamlIlSelectorNode
{
private readonly SelectorType _type;
private readonly CombinatorSelectorType _type;
public enum SelectorType
public enum CombinatorSelectorType
{
Child,
Descendant,
Template
}
public XamlIlCombinatorSelector(XamlIlSelectorNode previous, SelectorType type) : base(previous)
public XamlIlCombinatorSelector(XamlIlSelectorNode previous, CombinatorSelectorType type) : base(previous)
{
_type = type;
}
public CombinatorSelectorType SelectorType => _type;
public override IXamlType TargetType => null;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{

34
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs

@ -754,6 +754,40 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
}
}
[Fact]
public void ResolvesRelativeSourceBindingFromStyleSelector()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<TextBox xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
InnerLeftContent='Hello'>
<TextBox.Styles>
<Style Selector='TextBox'>
<Setter Property='Template'>
<ControlTemplate>
<StackPanel>
<ContentPresenter x:Name='Content' />
<TextPresenter x:Name='PART_TextPresenter' />
</StackPanel>
</ControlTemplate>
</Setter>
<Style Selector='^ /template/ ContentPresenter#Content'>
<Setter Property='Content' Value='{CompiledBinding InnerLeftContent, RelativeSource={RelativeSource TemplatedParent}}' />
</Style>
</Style>
</TextBox.Styles>
</TextBox>";
var textBox = AvaloniaRuntimeXamlLoader.Parse<TextBox>(xaml);
textBox.Measure(new Size(10, 10));
var result = textBox.GetTemplateChildren().OfType<ContentPresenter>().First();
Assert.Equal(textBox.InnerLeftContent, result.Content);
}
}
[Fact]
public void ResolvesElementNameInTemplate()
{

Loading…
Cancel
Save