Browse Source

Merge branch 'master' into issue2613

pull/2645/head
FoggyFinder 7 years ago
committed by GitHub
parent
commit
648770741e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      src/Avalonia.Build.Tasks/Program.cs
  2. 7
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs
  3. 2
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  4. 61
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
  5. 42
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs

11
src/Avalonia.Build.Tasks/Program.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.IO; using System.IO;
using System.Linq;
using Microsoft.Build.Framework; using Microsoft.Build.Framework;
namespace Avalonia.Build.Tasks namespace Avalonia.Build.Tasks
@ -11,8 +12,14 @@ namespace Avalonia.Build.Tasks
{ {
if (args.Length != 3) if (args.Length != 3)
{ {
Console.Error.WriteLine("input references output"); if (args.Length == 1)
return 1; args = new[] {"original.dll", "references", "out.dll"}
.Select(x => Path.Combine(args[0], x)).ToArray();
else
{
Console.Error.WriteLine("input references output");
return 1;
}
} }
return new CompileAvaloniaXamlTask() return new CompileAvaloniaXamlTask()

7
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs

@ -16,8 +16,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
if (!(node is XamlIlAstObjectNode on if (!(node is XamlIlAstObjectNode on
&& on.Type.GetClrType().FullName == "Avalonia.Styling.Setter")) && on.Type.GetClrType().FullName == "Avalonia.Styling.Setter"))
return node; return node;
var parent = context.ParentNodes().OfType<XamlIlAstObjectNode>() var parent = context.ParentNodes().OfType<XamlIlAstObjectNode>()
.FirstOrDefault(x => x.Type.GetClrType().FullName == "Avalonia.Styling.Style"); .FirstOrDefault(p => p.Type.GetClrType().FullName == "Avalonia.Styling.Style");
if (parent == null) if (parent == null)
throw new XamlIlParseException( throw new XamlIlParseException(
"Avalonia.Styling.Setter is only valid inside Avalonia.Styling.Style", node); "Avalonia.Styling.Setter is only valid inside Avalonia.Styling.Style", node);
@ -53,8 +55,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
.OfType<XamlIlAstXamlPropertyValueNode>().FirstOrDefault(p => p.Property.GetClrProperty().Name == "Value"); .OfType<XamlIlAstXamlPropertyValueNode>().FirstOrDefault(p => p.Property.GetClrProperty().Name == "Value");
if (valueProperty?.Values?.Count == 1 && valueProperty.Values[0] is XamlIlAstTextNode) if (valueProperty?.Values?.Count == 1 && valueProperty.Values[0] is XamlIlAstTextNode)
{ {
var propType = avaloniaPropertyNode.Property.Getter?.ReturnType var propType = avaloniaPropertyNode.AvaloniaPropertyType;
?? avaloniaPropertyNode.Property.Setters.First().Parameters[0];
if (!XamlIlTransformHelpers.TryGetCorrectlyTypedValue(context, valueProperty.Values[0], if (!XamlIlTransformHelpers.TryGetCorrectlyTypedValue(context, valueProperty.Values[0],
propType, out var converted)) propType, out var converted))
throw new XamlIlParseException( throw new XamlIlParseException(

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

@ -10,6 +10,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlIlType BindingPriority { get; } public IXamlIlType BindingPriority { get; }
public IXamlIlType AvaloniaObjectExtensions { get; } public IXamlIlType AvaloniaObjectExtensions { get; }
public IXamlIlType AvaloniaProperty { get; } public IXamlIlType AvaloniaProperty { get; }
public IXamlIlType AvaloniaPropertyT { get; }
public IXamlIlType IBinding { get; } public IXamlIlType IBinding { get; }
public IXamlIlMethod AvaloniaObjectBindMethod { get; } public IXamlIlMethod AvaloniaObjectBindMethod { get; }
public IXamlIlMethod AvaloniaObjectSetValueMethod { get; } public IXamlIlMethod AvaloniaObjectSetValueMethod { get; }
@ -26,6 +27,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
IAvaloniaObject = ctx.Configuration.TypeSystem.GetType("Avalonia.IAvaloniaObject"); IAvaloniaObject = ctx.Configuration.TypeSystem.GetType("Avalonia.IAvaloniaObject");
AvaloniaObjectExtensions = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaObjectExtensions"); AvaloniaObjectExtensions = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaObjectExtensions");
AvaloniaProperty = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty"); AvaloniaProperty = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty");
AvaloniaPropertyT = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty`1");
BindingPriority = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.BindingPriority"); BindingPriority = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.BindingPriority");
IBinding = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.IBinding"); IBinding = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.IBinding");
IDisposable = ctx.Configuration.TypeSystem.GetType("System.IDisposable"); IDisposable = ctx.Configuration.TypeSystem.GetType("System.IDisposable");

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

@ -44,7 +44,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return true; return true;
} }
public static XamlIlAvaloniaPropertyNode CreateNode(XamlIlAstTransformationContext context, public static IXamlIlAvaloniaPropertyNode CreateNode(XamlIlAstTransformationContext context,
string propertyName, IXamlIlAstTypeReference selectorTypeReference, IXamlIlLineInfo lineInfo) string propertyName, IXamlIlAstTypeReference selectorTypeReference, IXamlIlLineInfo lineInfo)
{ {
XamlIlAstNamePropertyReference forgedReference; XamlIlAstNamePropertyReference forgedReference;
@ -63,8 +63,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
xmlOwner += parsedPropertyName.owner; xmlOwner += parsedPropertyName.owner;
var tref = XamlIlTypeReferenceResolver.ResolveType(context, xmlOwner, false, lineInfo, true); var tref = XamlIlTypeReferenceResolver.ResolveType(context, xmlOwner, false, lineInfo, true);
forgedReference = new XamlIlAstNamePropertyReference(lineInfo,
tref, parsedPropertyName.name, tref); var propertyFieldName = parsedPropertyName.name + "Property";
var found = tref.Type.GetAllFields()
.FirstOrDefault(f => f.IsStatic && f.IsPublic && f.Name == propertyFieldName);
if (found == null)
throw new XamlIlParseException(
$"Unable to find {propertyFieldName} field on type {tref.Type.GetFullName()}", lineInfo);
return new XamlIlAvaloniaPropertyFieldNode(context.GetAvaloniaTypes(), lineInfo, found);
} }
var clrProperty = var clrProperty =
@ -75,13 +81,20 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
clrProperty); clrProperty);
} }
} }
interface IXamlIlAvaloniaPropertyNode : IXamlIlAstValueNode
{
IXamlIlType AvaloniaPropertyType { get; }
}
class XamlIlAvaloniaPropertyNode : XamlIlAstNode, IXamlIlAstValueNode, IXamlIlAstEmitableNode class XamlIlAvaloniaPropertyNode : XamlIlAstNode, IXamlIlAstValueNode, IXamlIlAstEmitableNode, IXamlIlAvaloniaPropertyNode
{ {
public XamlIlAvaloniaPropertyNode(IXamlIlLineInfo lineInfo, IXamlIlType type, XamlIlAstClrProperty property) : base(lineInfo) public XamlIlAvaloniaPropertyNode(IXamlIlLineInfo lineInfo, IXamlIlType type, XamlIlAstClrProperty property) : base(lineInfo)
{ {
Type = new XamlIlAstClrTypeReference(this, type, false); Type = new XamlIlAstClrTypeReference(this, type, false);
Property = property; Property = property;
AvaloniaPropertyType = Property.Getter?.ReturnType
?? Property.Setters.First().Parameters[0];
} }
public XamlIlAstClrProperty Property { get; } public XamlIlAstClrProperty Property { get; }
@ -93,6 +106,46 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
throw new XamlIlLoadException(Property.Name + " is not an AvaloniaProperty", this); throw new XamlIlLoadException(Property.Name + " is not an AvaloniaProperty", this);
return XamlIlNodeEmitResult.Type(0, Type.GetClrType()); return XamlIlNodeEmitResult.Type(0, Type.GetClrType());
} }
public IXamlIlType AvaloniaPropertyType { get; }
}
class XamlIlAvaloniaPropertyFieldNode : XamlIlAstNode, IXamlIlAstValueNode, IXamlIlAstEmitableNode, IXamlIlAvaloniaPropertyNode
{
private readonly IXamlIlField _field;
public XamlIlAvaloniaPropertyFieldNode(AvaloniaXamlIlWellKnownTypes types,
IXamlIlLineInfo lineInfo, IXamlIlField field) : base(lineInfo)
{
_field = field;
var avaloniaPropertyType = field.FieldType;
while (avaloniaPropertyType != null)
{
if (avaloniaPropertyType.GenericTypeDefinition?.Equals(types.AvaloniaPropertyT) == true)
{
AvaloniaPropertyType = avaloniaPropertyType.GenericArguments[0];
return;
}
avaloniaPropertyType = avaloniaPropertyType.BaseType;
}
throw new XamlIlParseException(
$"{field.Name}'s type {field.FieldType} doesn't inherit from AvaloniaProperty<T>, make sure to use typed properties",
lineInfo);
}
public IXamlIlAstTypeReference Type => new XamlIlAstClrTypeReference(this, _field.FieldType, false);
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
{
codeGen.Ldsfld(_field);
return XamlIlNodeEmitResult.Type(0, _field.FieldType);
}
public IXamlIlType AvaloniaPropertyType { get; }
} }
interface IXamlIlAvaloniaProperty interface IXamlIlAvaloniaProperty

42
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs

@ -207,6 +207,33 @@ namespace Avalonia.Markup.Xaml.UnitTests
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'/>", typeof(XamlIlTests).Assembly); xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'/>", typeof(XamlIlTests).Assembly);
Assert.Equal(Design.GetDataContext(loaded), SomeStaticProperty); Assert.Equal(Design.GetDataContext(loaded), SomeStaticProperty);
} }
[Fact]
public void Attached_Properties_From_Static_Types_Should_Work_In_Style_Setters_Bug_2561()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parsed = (Window)AvaloniaXamlLoader.Parse(@"
<Window
xmlns='https://github.com/avaloniaui'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests;assembly=Avalonia.Markup.Xaml.UnitTests'
>
<Window.Styles>
<Style Selector='TextBox'>
<Setter Property='local:XamlIlBugTestsStaticClassWithAttachedProperty.TestInt' Value='100'/>
</Style>
</Window.Styles>
<TextBox/>
</Window>
");
var tb = ((TextBox)parsed.Content);
parsed.Show();
tb.ApplyTemplate();
Assert.Equal(100, XamlIlBugTestsStaticClassWithAttachedProperty.GetTestInt(tb));
}
}
} }
public class XamlIlBugTestsEventHandlerCodeBehind : Window public class XamlIlBugTestsEventHandlerCodeBehind : Window
@ -272,4 +299,19 @@ namespace Avalonia.Markup.Xaml.UnitTests
{ {
} }
public static class XamlIlBugTestsStaticClassWithAttachedProperty
{
public static readonly AvaloniaProperty<int> TestIntProperty = AvaloniaProperty
.RegisterAttached<Control, int>("TestInt", typeof(XamlIlBugTestsStaticClassWithAttachedProperty));
public static void SetTestInt(Control control, int value)
{
control.SetValue(TestIntProperty, value);
}
public static int GetTestInt(Control control)
{
return (int)control.GetValue(TestIntProperty);
}
}
} }

Loading…
Cancel
Save